From 61fba3f406d79fad1f4233ea1c877256aa4e8ad9 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 24 Sep 2017 13:48:16 +0200 Subject: [PATCH] Work on padded profile --- src/ifcconvert/IfcConvert.cpp | 6 +- src/ifcparse/Hdf5Settings.h | 24 ++ src/ifcparse/IfcHdf5File.cpp | 607 ++++++++++++++++++++-------------- src/ifcparse/IfcHdf5File.h | 15 +- src/ifcparse/IfcParse.cpp | 2 +- 5 files changed, 388 insertions(+), 266 deletions(-) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index ce8ea5013e..8e71229145 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -101,7 +101,7 @@ int main(int argc, char** argv) { ("input-file", boost::program_options::value(), "input IFC file") ("output-file", boost::program_options::value(), "output geometry file"); - std::string bounds; + std::string bounds, hdf5_profile; uint32_t hdf5_chunk_size; std::vector entity_vector; std::vector hdf5_ref_attributes; @@ -150,6 +150,7 @@ int main(int argc, char** argv) { ("bounds", boost::program_options::value(&bounds), "Specifies the bounding rectangle, for example 512x512, to which the " "output will be scaled. Only used when converting to SVG.") + ("hdf5-profile", boost::program_options::value(&hdf5_profile), "") ("hdf5-compress", "") ("hdf5-fix-cartesian-point", "") ("hdf5-fix-global-id", "") @@ -292,6 +293,9 @@ int main(int argc, char** argv) { if (vmap.count("hdf5-chunk-size") == 1) { settings.chunk_size() = hdf5_chunk_size; } + if (vmap.count("hdf5-profile") == 1) { + settings.profile() = IfcParse::Hdf5Settings::ProfileFromString(hdf5_profile); + } f.write_hdf5(output_filename, settings); exit_code = 0; } diff --git a/src/ifcparse/Hdf5Settings.h b/src/ifcparse/Hdf5Settings.h index 431bae7b3d..bc0cebd964 100644 --- a/src/ifcparse/Hdf5Settings.h +++ b/src/ifcparse/Hdf5Settings.h @@ -30,6 +30,26 @@ namespace IfcParse { bool compress_, fix_cartesian_point_, fix_global_id_, instantiate_select_, instantiate_inverse_; unsigned int chunk_size_; std::vector ref_attributes_; + + public: + enum Profile { + standard, + padded, + standard_referenced, + padded_referenced + }; + + static Profile ProfileFromString(const std::string& s) { + if (s == "standard") return standard; + if (s == "padded") return padded; + if (s == "standard-referenced") return standard_referenced; + if (s == "padded-referenced") return padded_referenced; + throw std::exception("Unrecognized profile"); + } + + private: + Profile profile_; + public: Hdf5Settings() : compress_(false) @@ -38,6 +58,7 @@ namespace IfcParse { , instantiate_select_(false) , instantiate_inverse_(false) , chunk_size_(false) + , profile_(standard) {} bool compress() const { return compress_; } @@ -55,6 +76,9 @@ namespace IfcParse { unsigned int chunk_size() const { return chunk_size_; } unsigned int& chunk_size() { return chunk_size_; } + Profile profile() const { return profile_; } + Profile& profile() { return profile_; } + const std::vector& ref_attributes() const { return ref_attributes_; } std::vector& ref_attributes() { return ref_attributes_; } }; diff --git a/src/ifcparse/IfcHdf5File.cpp b/src/ifcparse/IfcHdf5File.cpp index 63fb4be517..8d20d4eb9c 100644 --- a/src/ifcparse/IfcHdf5File.cpp +++ b/src/ifcparse/IfcHdf5File.cpp @@ -10,24 +10,24 @@ class type_mapper { public: - type_mapper(IfcParse::IfcFile& ifc_file, H5::H5File* hdf5_file); + type_mapper(IfcParse::IfcFile& ifc_file, H5::H5File* hdf5_file, const IfcParse::Hdf5Settings& settings); H5::DataType* commit(H5::DataType* dt, const std::string& name); - - H5::DataType* operator()(const IfcParse::parameter_type* pt); - H5::DataType* operator()(const IfcParse::select_type* pt); - H5::CompType* operator()(const IfcParse::entity* e); - H5::EnumType* operator()(const IfcParse::enumeration_type* en); + + H5::DataType* operator()(const IfcParse::parameter_type* pt, IfcEntityList::ptr instances = nullptr, int dims = 0, const hsize_t* max_length = nullptr); + H5::DataType* operator()(const IfcParse::select_type* pt, IfcEntityList::ptr instances = nullptr, int dims = 0, const hsize_t* max_length = nullptr); + H5::CompType* operator()(const IfcParse::entity* e, IfcEntityList::ptr instances = nullptr, int dims = 0, const hsize_t* max_length = nullptr); + H5::EnumType* operator()(const IfcParse::enumeration_type* en, IfcEntityList::ptr instances = nullptr, int dims = 0, const hsize_t* max_length = nullptr); void operator()(); std::pair make_select_leaf(const IfcParse::declaration* decl); private: + IfcParse::Hdf5Settings settings_; bool padded_; bool referenced_; - IfcParse::Hdf5Settings settings_; - + IfcParse::IfcFile& ifc_file_; H5::H5File* hdf5_file_; H5::Group schema_group_; @@ -359,6 +359,75 @@ public: } }; +class default_value_visitor { +private: + H5::DataType& datatype_; + +public: + default_value_visitor(H5::DataType& datatype) + : datatype_(datatype) + {} + + void operator()(void*& ptr) { + switch (datatype_.getClass()) { + case H5T_INTEGER: + write_number_of_size(ptr, datatype_.getSize(), 0); + break; + case H5T_FLOAT: + write_number_of_size(ptr, datatype_.getSize(), 0.); + break; + case H5T_STRING: + if (datatype_ == H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)) { + write(ptr, new char(0)); + } else { + write_string_of_size(ptr, datatype_.getSize(), ""); + } + break; + case H5T_COMPOUND: + { + H5::CompType* compound = (H5::CompType*) &datatype_; + for (int i = 0; i < compound->getNmembers(); ++i) { + H5::DataType attr_type = compound->getMemberDataType(i); + default_value_visitor visitor(attr_type); + visitor(ptr); + } + break; + } + case H5T_REFERENCE: + throw std::runtime_error("Not implemented"); + break; + case H5T_ENUM: + write_number_of_size(ptr, datatype_.getSize(), 0); + break; + case H5T_VLEN: + { + // H5::VarLenType* vlen = (H5::VarLenType*) &datatype_; + // Does this work? + write_vlen_t(ptr, 0, nullptr); + break; + } + case H5T_ARRAY: + { + H5::ArrayType* arr = (H5::ArrayType*) &datatype_; + size_t ndims = arr->getArrayNDims(); + hsize_t* array_dims = new hsize_t[ndims]; + arr->getArrayDims(array_dims); + if (ndims != 1) { + throw std::runtime_error("Not implemented"); + } + H5::DataType super = arr->getSuper(); + default_value_visitor visitor(super); + for (hsize_t i = 0; i < array_dims[0]; ++i) { + visitor(ptr); + } + break; + } + default: + throw std::runtime_error("Unexpected type encountered"); + } + } +}; + // template class write_visit { private: @@ -503,8 +572,8 @@ public: T t = v[i]; visit(ptr, elem_dt, t); } else { - // TODO: Figure this out. - // visit(ptr, elem_dt, T()); + default_value_visitor visitor(elem_dt); + visitor(ptr); } } } else { @@ -613,75 +682,6 @@ void IfcParse::IfcHdf5File::write_instance(void*& ptr, T& visitor, H5::DataType& } } -class default_value_visitor { -private: - H5::DataType& datatype_; - -public: - default_value_visitor(H5::DataType& datatype) - : datatype_(datatype) - {} - - void operator()(void*& ptr) { - switch (datatype_.getClass()) { - case H5T_INTEGER: - write_number_of_size(ptr, datatype_.getSize(), 0); - break; - case H5T_FLOAT: - write_number_of_size(ptr, datatype_.getSize(), 0.); - break; - case H5T_STRING: - if (datatype_ == H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)) { - write(ptr, new char(0)); - } else { - write_string_of_size(ptr, datatype_.getSize(), ""); - } - break; - case H5T_COMPOUND: - { - H5::CompType* compound = (H5::CompType*) &datatype_; - for (int i = 0; i < compound->getNmembers(); ++i) { - H5::DataType attr_type = compound->getMemberDataType(i); - default_value_visitor visitor(attr_type); - visitor(ptr); - } - break; - } - case H5T_REFERENCE: - throw std::runtime_error("Not implemented"); - break; - case H5T_ENUM: - write_number_of_size(ptr, datatype_.getSize(), 0); - break; - case H5T_VLEN: - { - // H5::VarLenType* vlen = (H5::VarLenType*) &datatype_; - // Does this work? - write_vlen_t(ptr, 0, nullptr); - break; - } - case H5T_ARRAY: - { - H5::ArrayType* arr = (H5::ArrayType*) &datatype_; - size_t ndims = arr->getArrayNDims(); - hsize_t* array_dims = new hsize_t[ndims]; - arr->getArrayDims(array_dims); - if (ndims != 1) { - throw std::runtime_error("Not implemented"); - } - H5::DataType super = arr->getSuper(); - default_value_visitor visitor(super); - for (hsize_t i = 0; i < array_dims[0]; ++i) { - visitor(ptr); - } - break; - } - default: - throw std::runtime_error("Unexpected type encountered"); - } - } -}; - void write_visit::visit(void*& ptr, H5::DataType& datatype, select_item& v) { pointer_increment_assert _(ptr, datatype.getSize()); @@ -765,12 +765,12 @@ std::string type_mapper::flatten_aggregate_name(const IfcParse::parameter_type* } } -type_mapper::type_mapper(IfcParse::IfcFile& ifc_file, H5::H5File* hdf5_file) +type_mapper::type_mapper(IfcParse::IfcFile& ifc_file, H5::H5File* hdf5_file, const IfcParse::Hdf5Settings& settings) : ifc_file_(ifc_file) , hdf5_file_(hdf5_file) - // TODO: Configure - , padded_(false) - , referenced_(false) + , settings_(settings) + , padded_(settings_.profile() == IfcParse::Hdf5Settings::padded || settings_.profile() == IfcParse::Hdf5Settings::padded_referenced) + , referenced_(settings_.profile() == IfcParse::Hdf5Settings::standard_referenced || settings_.profile() == IfcParse::Hdf5Settings::padded_referenced) { schema_group_ = hdf5_file_->openGroup(ifc_file_.schema()->name() + "_encoding"); @@ -826,37 +826,96 @@ H5::DataType* type_mapper::commit(H5::DataType* dt, const std::string& name) { return dt; } -H5::DataType* type_mapper::operator()(const IfcParse::parameter_type* pt) { - H5::DataType* h5_dt; +H5::DataType* type_mapper::operator()(const IfcParse::parameter_type* pt, IfcEntityList::ptr instances, int dims, const hsize_t* max_length) { + H5::DataType* h5_dt = nullptr; if (pt->as_aggregation_type()) { - if (padded_) { - // TODO: Determine dimensions + if (padded_ && dims && max_length) { // TODO: Check whether these pointers can safely be dereferenced - hsize_t dims = 1; - h5_dt = new H5::ArrayType(*(*this)(pt->as_aggregation_type()->type_of_element()), 1, &dims); + + // Zero dim arrays are not supported + hsize_t* max_length_copy = new hsize_t[dims]; + memcpy(max_length_copy, max_length, sizeof(hsize_t) * dims); + if (max_length_copy[0] == 0) max_length_copy[0] = 1; + + H5::DataType* element_dt = (*this)(pt->as_aggregation_type()->type_of_element(), nullptr, dims - 1, max_length + 1); + + std::vector< IfcParse::IfcHdf5File::compound_member > members; + members.push_back(std::make_pair(std::string("length"), new H5::PredType(H5::PredType::NATIVE_UINT32))); + members.push_back(std::make_pair(std::string("data"), new H5::ArrayType(*element_dt, 1, max_length_copy))); + h5_dt = create_compound(members); + + delete[] max_length_copy; } else { h5_dt = new H5::VarLenType((*this)(pt->as_aggregation_type()->type_of_element())); } } else if (pt->as_named_type()) { + // TODO: named types can also represent aggregations, can't they? + if (pt->as_named_type()->declared_type()->as_entity()) { return instance_reference_; // TFK: Do not copy, we want to retain path to simplify datatype identify checks later on // h5_dt = new H5::DataType(); // h5_dt->copy(*instance_reference_); } else { - IfcSchema::Type::Enum ty = pt->as_named_type()->declared_type()->type(); - if (!declared_types_[ty]) { - throw UnmetDependencyException(); - } else { - // TFK: Copy, as well be committed under different name? - h5_dt = new H5::DataType(); - h5_dt->copy(*declared_types_[ty]); + + if (padded_ && dims && max_length) { + auto decl = pt->as_named_type()->declared_type(); + while (decl->as_type_declaration()) { + const IfcParse::parameter_type* leaf_pt = decl->as_type_declaration()->declared_type(); + const IfcParse::named_type* nt = leaf_pt->as_named_type(); + if (nt) { + decl = nt->declared_type(); + } else { + break; + } + } + if ( + decl->as_type_declaration() && + decl->as_type_declaration()->declared_type()->as_simple_type() && + decl->as_type_declaration()->declared_type()->as_simple_type()->declared_type() == IfcParse::simple_type::string_type) + { + std::vector< IfcParse::IfcHdf5File::compound_member > members; + members.push_back(std::make_pair(std::string("length"), new H5::PredType(H5::PredType::NATIVE_UINT32))); + members.push_back(std::make_pair(std::string("data"), new H5::StrType(H5::PredType::C_S1, (size_t) max_length[0] + 1))); + h5_dt = create_compound(members); + } + } + + if (!h5_dt) { + IfcSchema::Type::Enum ty = pt->as_named_type()->declared_type()->type(); + if (!declared_types_[ty]) { + if (padded_) { + if (pt->as_named_type()->declared_type()->as_select_type()) { + // For padded ifc-hdf the select type is based on model population + return (*this)(pt->as_named_type()->declared_type()->as_select_type(), instances); + } else if (pt->as_named_type()->declared_type()->as_type_declaration()) { + return (*this)(pt->as_named_type()->declared_type()->as_type_declaration()->declared_type(), instances); + } else { + throw UnmetDependencyException(); + } + } else { + throw UnmetDependencyException(); + } + } else { + // TFK: Copy, as well be committed under different name? + h5_dt = new H5::DataType(); + h5_dt->copy(*declared_types_[ty]); + } } } } else if (pt->as_simple_type()) { - const H5::DataType* orig = default_types_[pt->as_simple_type()->declared_type()]; - h5_dt = new H5::DataType(); - h5_dt->copy(*orig); + // TODO: This branch has redundancies with pt->as_named_type + if (padded_ && dims && max_length && pt->as_simple_type()->declared_type() == IfcParse::simple_type::string_type) { + std::vector< IfcParse::IfcHdf5File::compound_member > members; + members.push_back(std::make_pair(std::string("length"), new H5::PredType(H5::PredType::NATIVE_UINT32))); + members.push_back(std::make_pair(std::string("data"), new H5::StrType(H5::PredType::C_S1, (size_t) max_length[0] + 1))); + h5_dt = create_compound(members); + } else { + // TFK: Copy, as well be committed under different name? + const H5::DataType* orig = default_types_[pt->as_simple_type()->declared_type()]; + h5_dt = new H5::DataType(); + h5_dt->copy(*orig); + } } else { throw UnmetDependencyException(); } @@ -905,12 +964,31 @@ std::pair type_mapper::make_select_leaf(const return std::make_pair(name, dt); } -H5::DataType* type_mapper::operator()(const IfcParse::select_type* pt) { - std::set leafs; - visit_select(pt, leafs); +H5::DataType* type_mapper::operator()(const IfcParse::select_type* pt, IfcEntityList::ptr instances, int, const hsize_t*) { + std::set leafs_schema; + visit_select(pt, leafs_schema); + + std::set leafs_model; + std::set* leafs = &leafs_schema; + + if (padded_) { + std::set instantiated; + std::for_each(instances->begin(), instances->end(), [&instantiated](IfcUtil::IfcBaseClass* inst) { + instantiated.insert(&inst->declaration()); + if (inst->declaration().as_entity()) { + auto entity = inst->declaration().as_entity(); + while (entity->supertype()) { + entity = entity->supertype(); + instantiated.insert(entity); + } + } + }); + std::set_intersection(leafs_schema.begin(), leafs_schema.end(), instantiated.begin(), instantiated.end(), std::inserter(leafs_model, leafs_model.end())); + leafs = &leafs_model; + } bool all_entity_instance_refs = true; - for (auto it = leafs.begin(); it != leafs.end(); ++it) { + for (auto it = leafs->begin(); it != leafs->end(); ++it) { if (!(*it)->as_entity()) { all_entity_instance_refs = false; break; @@ -925,7 +1003,7 @@ H5::DataType* type_mapper::operator()(const IfcParse::select_type* pt) { h5_attributes.push_back(std::make_pair(std::string("type_code"), &H5::PredType::NATIVE_INT16)); - for (auto it = leafs.begin(); it != leafs.end(); ++it) { + for (auto it = leafs->begin(); it != leafs->end(); ++it) { const IfcParse::declaration* decl = (*it); auto leaf_type = make_select_leaf(decl); @@ -941,7 +1019,116 @@ H5::DataType* type_mapper::operator()(const IfcParse::select_type* pt) { } } -H5::CompType* type_mapper::operator()(const IfcParse::entity* e) { +class apply_attribute_visitor_instance_list { +private: + const IfcEntityList::ptr& instances_; + int attribute_idx_; +public: + apply_attribute_visitor_instance_list(const IfcEntityList::ptr& instances, int attribute_idx) + : instances_(instances) + , attribute_idx_(attribute_idx) + {} + + template + typename T::return_type apply(T& t) const { + for (auto it = instances_->begin(); it != instances_->end(); ++it) { + apply_attribute_visitor((**it).data().getArgument(attribute_idx_), (**it).declaration().as_entity()->all_attributes()[attribute_idx_]).apply(t); + } + } +}; + +class all_null_visitor { +private: + bool all_null_; +public: + typedef void return_type; + + all_null_visitor() + : all_null_(true) + {} + + void operator()(const boost::none_t&) { + // Empty on purpose + } + + template + void operator()(const T&) { + all_null_ = false; + } + + bool all_null() const { + return all_null_; + } +}; + +class max_length_visitor { +private: + std::vector max_length_; + void contain(size_t dim, size_t count) { + if (dim == max_length_.size()) { + max_length_.push_back(count); + } else if (count > max_length_[dim]) { + max_length_[dim] = count; + } + } + +public: + typedef void return_type; + + void operator()(const IfcEntityList::ptr& aggregate) { + contain(0, aggregate->size()); + } + + void operator()(const IfcEntityListList::ptr& aggregate) { + contain(0, aggregate->size()); + for (auto it = aggregate->begin(); it != aggregate->end(); ++it) { + contain(1, it->size()); + } + } + + void operator()(const std::string& str) { + contain(0, str.size()); + } + + void operator()(const std::vector& aggregate) { + contain(0, aggregate.size()); + for (auto it = aggregate.begin(); it != aggregate.end(); ++it) { + contain(1, it->size()); + } + } + + template + void operator()(const std::vector< std::vector >& aggregate) { + contain(0, aggregate.size()); + for (auto it = aggregate.begin(); it != aggregate.end(); ++it) { + contain(1, it->size()); + } + } + + template + void operator()(const std::vector& aggregate) { + contain(0, aggregate.size()); + } + + template + void operator()(const T&) { + // Empty on purpose + } + + operator bool() const { + return !max_length_.empty(); + } + + int dims() const { + return (int)max_length_.size(); + } + + const hsize_t* max_length() const { + return max_length_.data(); + } +}; + +H5::CompType* type_mapper::operator()(const IfcParse::entity* e, IfcEntityList::ptr, int, const hsize_t*) { // List of entity instances of this type, no subtypes IfcEntityList::ptr incl_subtypes = ifc_file_.entitiesByType(e->name()); @@ -968,7 +1155,7 @@ H5::CompType* type_mapper::operator()(const IfcParse::entity* e) { bool has_optional_attributes = false; const size_t num_extra = has_optional_attributes ? 2 : 1; - // size_t num_all_null = 0; + size_t num_all_null = 0; std::vector attributes_all_null(attributes.size(), false); auto jt = attributes_derived_in_subtype.begin(); @@ -981,16 +1168,14 @@ H5::CompType* type_mapper::operator()(const IfcParse::entity* e) { has_optional_attributes = true; - /* apply_attribute_visitor_instance_list dispatch(instances, idx); all_null_visitor visitor; dispatch.apply(visitor); if (visitor.all_null()) { num_all_null += 1; attributes_all_null[idx] = true; - attributes_omitted.insert(std::make_pair(e->name(), idx)); + // attributes_omitted.insert(std::make_pair(e->name(), idx)); } - */ } } @@ -1016,14 +1201,35 @@ H5::CompType* type_mapper::operator()(const IfcParse::entity* e) { const int idx = std::distance(attributes.begin(), it); - if (attributes_all_null[idx]) { + if (padded_ && attributes_all_null[idx]) { continue; } - const std::string& name = (*it)->name(); - if (name == "InnerCurves") { - std::cerr << 1; + // TFK: Note the scope of max_length_visitor + max_length_visitor visitor; + const hsize_t* max_length = nullptr; + int dims = 0; + + if (padded_) { + apply_attribute_visitor_instance_list dispatch(instances, idx); + dispatch.apply(visitor); + if (visitor) { + max_length = visitor.max_length(); + dims = visitor.dims(); + } } + + IfcEntityList::ptr attribute_select_instances; + // What to with aggregates of select? + if (padded_ && (*it)->type_of_attribute()->as_named_type() && (*it)->type_of_attribute()->as_named_type()->declared_type()->as_select_type()) { + attribute_select_instances.reset(new IfcEntityList); + std::for_each(instances->begin(), instances->end(), [idx, attribute_select_instances](IfcUtil::IfcBaseClass* inst) { + IfcUtil::IfcBaseClass* attribute_value = *inst->data().getArgument(idx); + attribute_select_instances->push(attribute_value); + }); + } + + const std::string& name = (*it)->name(); const bool is_optional = (*it)->optional(); const H5::DataType* type; const std::string qualified_attr_name = e->name() + "." + name; @@ -1034,18 +1240,13 @@ H5::CompType* type_mapper::operator()(const IfcParse::entity* e) { // } else if (overridden_types.find("*." + name) != overridden_types.end()) { // type = overridden_types.find("*." + name)->second; } else { - type = (*this)((*it)->type_of_attribute()); + type = (*this)((*it)->type_of_attribute(), attribute_select_instances, dims, max_length); + if (type == nullptr) { + // This is for select types. Should this be handled elsewhere? + type = instance_reference_; + } } - /* - apply_attribute_visitor_instance_list dispatch(instances, idx); - max_length_visitor visitor; - dispatch.apply(visitor); - if (visitor) { - type = specify_length(type, visitor.max_length()); - } - */ - // TODO: Re-evaluate // if (false && visitor && visitor.max_length()[0] == 0) { // attributes_omitted.insert(std::make_pair(e->name(), idx)); @@ -1067,7 +1268,7 @@ H5::CompType* type_mapper::operator()(const IfcParse::entity* e) { return create_compound(h5_attributes); } -H5::EnumType* type_mapper::operator()(const IfcParse::enumeration_type* en) { +H5::EnumType* type_mapper::operator()(const IfcParse::enumeration_type* en, IfcEntityList::ptr, int, const hsize_t*) { return create_enumeration(en->enumeration_items()); } @@ -1078,26 +1279,32 @@ void type_mapper::operator()() { declared_types_[(*it)->type()] = commit((*this)(*it), (*it)->name()); } - const std::vector& ts = schema.type_declarations(); - std::set processed; - while (processed.size() < ts.size()) { - for (auto it = ts.begin(); it != ts.end(); ++it) { - auto pt = (*it)->declared_type(); - const std::string& name = (*it)->name(); - if (processed.find(*it) != processed.end()) continue; - try { - declared_types_[(*it)->type()] = commit((*this)(pt), name); - processed.insert(*it); - } catch (const UnmetDependencyException&) {} - } - } + if (!padded_) { + // For padded ifc-hdf files the width for declared types will depend on the data in the model. + // Therefore there is no point in having e.g. an IfcLabel type as part of the serialization. - for (auto it = schema.select_types().begin(); it != schema.select_types().end(); ++it) { - H5::DataType* dt = (*this)(*it); - if (dt) { - declared_types_[(*it)->type()] = commit(dt, (*it)->name()); - } else { - declared_types_[(*it)->type()] = instance_reference_; + const std::vector& ts = schema.type_declarations(); + std::set processed; + while (processed.size() < ts.size()) { + for (auto it = ts.begin(); it != ts.end(); ++it) { + auto pt = (*it)->declared_type(); + const std::string& name = (*it)->name(); + if (processed.find(*it) != processed.end()) continue; + try { + declared_types_[(*it)->type()] = commit((*this)(pt), name); + processed.insert(*it); + } catch (const UnmetDependencyException&) {} + } + } + + IfcEntityList::ptr _; + for (auto it = schema.select_types().begin(); it != schema.select_types().end(); ++it) { + H5::DataType* dt = (*this)(*it, _); + if (dt) { + declared_types_[(*it)->type()] = commit(dt, (*it)->name()); + } else { + declared_types_[(*it)->type()] = instance_reference_; + } } } @@ -1197,112 +1404,8 @@ H5::DataType* IfcParse::IfcHdf5File::commit(H5::DataType* dt, const std::string& return dt; } -class all_null_visitor { -private: - bool all_null_; -public: - typedef void return_type; - - all_null_visitor() - : all_null_(true) - {} - - void operator()(const boost::none_t&) { - // Empty on purpose - } - - template - void operator()(const T& other) { - all_null_ = false; - } - - bool all_null() const { - return all_null_; - } -}; - -class max_length_visitor { -private: - std::vector max_length_; - void contain(size_t dim, size_t count) { - if (dim == max_length_.size()) { - max_length_.push_back(count); - } else if (count > max_length_[dim]) { - max_length_[dim] = count; - } - } - -public: - typedef void return_type; - - void operator()(const IfcEntityList::ptr& aggregate) { - contain(0, aggregate->size()); - } - - void operator()(const IfcEntityListList::ptr& aggregate) { - contain(0, aggregate->size()); - for (auto it = aggregate->begin(); it != aggregate->end(); ++it) { - contain(1, it->size()); - } - } - - void operator()(const std::string& str) { - contain(0, str.size()); - } - - void operator()(const std::vector& aggregate) { - contain(0, aggregate.size()); - for (auto it = aggregate.begin(); it != aggregate.end(); ++it) { - contain(1, it->size()); - } - } - - template - void operator()(const std::vector< std::vector >& aggregate) { - contain(0, aggregate.size()); - for (auto it = aggregate.begin(); it != aggregate.end(); ++it) { - contain(1, it->size()); - } - } - - template - void operator()(const std::vector& aggregate) { - contain(0, aggregate.size()); - } - - template - void operator()(const T& other) { - } - - operator bool() const { - return !max_length_.empty(); - } - - const size_t* max_length() const { - return max_length_.data(); - } -}; - -class apply_attribute_visitor_instance_list { -private: - const IfcEntityList::ptr& instances_; - int attribute_idx_; -public: - apply_attribute_visitor_instance_list(const IfcEntityList::ptr& instances, int attribute_idx) - : instances_(instances) - , attribute_idx_(attribute_idx) - {} - - template - typename T::return_type apply(T& t) const { - for (auto it = instances_->begin(); it != instances_->end(); ++it) { - apply_attribute_visitor((**it).data().getArgument(attribute_idx_)).apply(t); - } - } -}; - -std::set< std::pair > attributes_omitted; -std::set< std::string > entities_with_optional_attrs; +// std::set< std::pair > attributes_omitted; +// std::set< std::string > entities_with_optional_attrs; /* template <> @@ -1663,7 +1766,7 @@ void IfcParse::IfcHdf5File::write_schema(const IfcParse::schema_definition& sche // init_default_types(); - mapper_ = new type_mapper(ifc_file, file); + mapper_ = new type_mapper(ifc_file, file, settings_); (*(type_mapper*)mapper_)(); }; @@ -1847,7 +1950,9 @@ void IfcParse::IfcHdf5File::write_population(IfcFile& f) { #endif sorted_instance_locator locator(this->ifcfile_); - write_visit/**/ visitor(false, false, locator, *((type_mapper*)mapper_)); + const bool padded = settings_.profile() == IfcParse::Hdf5Settings::padded || settings_.profile() == IfcParse::Hdf5Settings::padded_referenced; + const bool referenced = settings_.profile() == IfcParse::Hdf5Settings::standard_referenced || settings_.profile() == IfcParse::Hdf5Settings::padded_referenced; + write_visit/**/ visitor(padded, referenced, locator, *((type_mapper*)mapper_)); for (auto dsn_it = dataset_names.begin(); dsn_it != dataset_names.end(); ++dsn_it) { diff --git a/src/ifcparse/IfcHdf5File.h b/src/ifcparse/IfcHdf5File.h index ae52d6a71e..2894f4a8b1 100644 --- a/src/ifcparse/IfcHdf5File.h +++ b/src/ifcparse/IfcHdf5File.h @@ -31,17 +31,7 @@ namespace IfcParse { class IfcHdf5File { - public: - enum Profile { - standard, - padded, - standard_referenced, - padded_referenced - }; - private: - Profile profile_; - class allocator_t { private: // TODO: Change this? @@ -160,9 +150,8 @@ namespace IfcParse { typedef std::pair compound_member; - IfcHdf5File(IfcFile* f, const std::string& name, const Hdf5Settings& settings, Profile profile) - : profile_(profile) - , name_(name) + IfcHdf5File(IfcFile* f, const std::string& name, const Hdf5Settings& settings) + : name_(name) , schema_(*f->schema()) , ifcfile_(*f) , settings_(settings) diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index d6edeaaf67..5fede461fb 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -1552,5 +1552,5 @@ std::pair IfcFile::getUnit(IfcSchema::IfcUnitE } void IfcFile::write_hdf5(const std::string& name, const Hdf5Settings& settings) { - IfcHdf5File(this, name, settings, IfcHdf5File::standard); + IfcHdf5File(this, name, settings); } \ No newline at end of file