From d8d82eb6ec964e8f64ce976bd8b6302ba9cf1f7e Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 6 Dec 2017 17:51:18 +0100 Subject: [PATCH] Work on LOD example --- src/hdf5_usecases/lod.cpp | 58 ++++++++++--- .../multifile_instance_locator.h | 24 ++++++ src/ifcparse/IfcHdf5File.cpp | 83 +++++++++++++++++-- 3 files changed, 146 insertions(+), 19 deletions(-) diff --git a/src/hdf5_usecases/lod.cpp b/src/hdf5_usecases/lod.cpp index 5c3698e1c7..c2a5a27960 100644 --- a/src/hdf5_usecases/lod.cpp +++ b/src/hdf5_usecases/lod.cpp @@ -94,20 +94,21 @@ void find_geometric_types(IfcParse::IfcFile& f, const std::string& tfn) { return a->data().id() < b->data().id(); }); - IfcSchema::IfcStyledItem::list::ptr styles = f.entitiesByType(); - - std::set geometric_types{ IfcSchema::Type::IfcStyledItem }; + std::set geometric_types{ IfcSchema::Type::IfcStyledItem, IfcSchema::Type::IfcMaterialDefinitionRepresentation, IfcSchema::Type::IfcStyledRepresentation }; std::set other_types; std::set geometric_instances; - std::for_each(styles->begin(), styles->end(), [&geometric_instances](IfcSchema::IfcStyledItem* style) { - geometric_instances.insert(style); - }); + for (auto ty : geometric_types) { + auto insts = f.entitiesByType(ty); + std::for_each(insts->begin(), insts->end(), [&geometric_instances](IfcUtil::IfcBaseClass* inst) { + geometric_instances.insert(inst); + }); + } int N, n; - auto vist_geometric = [&f, &geometric_types, &geometric_instances, N, &n](IfcUtil::IfcBaseEntity* def) { + auto vist_geometric = [&f, &geometric_types, &geometric_instances, &N, &n](IfcUtil::IfcBaseEntity* def) { auto refs = f.traverse(def); geometric_instances.insert(refs->begin(), refs->end()); std::for_each(refs->begin(), refs->end(), [&geometric_types](IfcUtil::IfcBaseClass* inst) { @@ -116,7 +117,7 @@ void find_geometric_types(IfcParse::IfcFile& f, const std::string& tfn) { } }); if (n++ % 1000 == 0) { - std::cerr << "\r" << n * 100 / N << std::flush; + std::cerr << "\r" << (n * 100 / N) << std::flush; } }; @@ -136,6 +137,16 @@ void find_geometric_types(IfcParse::IfcFile& f, const std::string& tfn) { fn = [&f, &geometric_instances, &other_types, &fn](IfcUtil::IfcBaseClass* root, IfcUtil::IfcBaseClass* inst) { if (geometric_instances.find(inst) == geometric_instances.end()) { auto ty = inst->declaration().type(); + if (ty == IfcSchema::Type::IfcExtrudedAreaSolid) { + std::cerr << inst->data().toString() << " reachded by " << root->data().toString() << std::endl; + } + + // Not referenced. Revit generates unused IfcExtrudedAreaSolids some times. + auto invs = f.getInverse(inst->data().id(), IfcSchema::Type::UNDEFINED, -1); + if (root == inst && invs->size() == 0) { + return; + } + other_types.insert(ty); auto refs = f.traverse(inst, 1); std::for_each(refs->begin() + 1, refs->end(), [&fn, root](IfcUtil::IfcBaseClass* inst) { @@ -170,6 +181,8 @@ void find_geometric_types(IfcParse::IfcFile& f, const std::string& tfn) { const size_t name = ty; str.write((char*)&name, sizeof(size_t)); } + + std::cin.get(); } int main(int argc, char** argv) { @@ -214,10 +227,21 @@ int main(int argc, char** argv) { } std::set property_types { - IfcSchema::Type::IfcRelDefines, IfcSchema::Type::IfcPropertySetDefinition, IfcSchema::Type::IfcTypeObject + IfcSchema::Type::IfcRelDefines, + IfcSchema::Type::IfcPropertySetDefinition, + IfcSchema::Type::IfcTypeObject, + IfcSchema::Type::IfcProperty, + IfcSchema::Type::IfcPhysicalQuantity, + IfcSchema::Type::IfcRelAssociatesClassification, + IfcSchema::Type::IfcRelAssociatesMaterial, + IfcSchema::Type::IfcMaterialList, + IfcSchema::Type::IfcMaterialLayerSetUsage, + IfcSchema::Type::IfcMaterialLayerSet, + IfcSchema::Type::IfcMaterialLayer, + IfcSchema::Type::IfcMaterial }; - std::vector new_defs, old_defs, old_prop_defs, old_geom_defs, all_old_defs, all_defs; + std::vector new_defs, old_defs, old_prop_defs, old_geom_defs, old_box_defs, all_old_defs, all_defs; std::for_each(only_geometric.begin(), only_geometric.end(), [&f, &old_geom_defs](IfcSchema::Type::Enum t) { auto insts = f.entitiesByType(t); @@ -312,6 +336,10 @@ int main(int argc, char** argv) { all_old_defs.insert(all_old_defs.end(), old_geom_defs.begin(), old_geom_defs.end()); all_defs.insert(all_defs.end(), all_old_defs.begin(), all_old_defs.end()); all_defs.insert(all_defs.end(), new_defs.begin(), new_defs.end()); + old_box_defs.insert(old_box_defs.end(), old_defs.begin(), old_defs.end()); + old_box_defs.insert(old_box_defs.end(), new_defs.begin(), new_defs.end()); + auto contexts = f.entitiesByType(); + old_box_defs.insert(old_box_defs.end(), contexts->begin(), contexts->end()); { int num_insts1 = std::distance(all_old_defs.begin(), all_old_defs.end()); @@ -329,6 +357,7 @@ int main(int argc, char** argv) { IfcParse::Hdf5Settings settings; settings.profile() = IfcParse::Hdf5Settings::padded; settings.compress() = true; + settings.chunk_size() = 256; H5::H5File hdf(argv[1] + std::string(".hdf"), H5F_ACC_TRUNC); H5::H5File geom_hdf(argv[1] + std::string("-geometry.hdf"), H5F_ACC_TRUNC); @@ -367,5 +396,14 @@ int main(int argc, char** argv) { IfcParse::instance_enumerator enumerator(&f.header(), old_prop_defs.begin(), old_prop_defs.end()); ifc_hdf5.write_population(prop_population, enumerator, locator); } + + { + // locator is setup with all_old_defs, need to switch to new_defs + old_defs for the cartesian points + // NB: also geom rep context + locator->next(box_population, old_box_defs.begin(), old_box_defs.end()); + + IfcParse::instance_enumerator enumerator(&f.header(), new_defs.begin(), new_defs.end()); + ifc_hdf5.write_population(box_population, enumerator, locator); + } } } \ No newline at end of file diff --git a/src/hdf5_usecases/multifile_instance_locator.h b/src/hdf5_usecases/multifile_instance_locator.h index b097524039..27f41e4293 100644 --- a/src/hdf5_usecases/multifile_instance_locator.h +++ b/src/hdf5_usecases/multifile_instance_locator.h @@ -202,6 +202,30 @@ public: ptr = static_cast(ptr) + sizeof(hdset_reg_ref_t); } + template + void next(H5::Group& group, ForwardIt insts_begin, ForwardIt insts_end) { + subsequent_group_ = &group; + + subsequent_population_.first = initial_population_.first; + subsequent_population_.second.clear(); + + std::for_each(this->begin(), this->end(), [this, &insts_begin, &insts_end](IfcSchema::Type::Enum t) { + std::vector by_type; + + std::for_each(insts_begin, insts_end, [t, &by_type](IfcUtil::IfcBaseClass* inst) { + if (inst->declaration().type() == t && inst->declaration().as_entity()) { + by_type.push_back((IfcUtil::IfcBaseEntity*) inst); + } + }); + + std::sort(by_type.begin(), by_type.end(), [](IfcUtil::IfcBaseEntity* i1, IfcUtil::IfcBaseEntity* i2) { + return i1->data().id() < i2->data().id(); + }); + + subsequent_population_.second.emplace_back(by_type); + }); + } + void next(const std::string& name, H5::Group& group, IfcParse::IfcFile* f) { subsequent_group_ = &group; root_ = name; diff --git a/src/ifcparse/IfcHdf5File.cpp b/src/ifcparse/IfcHdf5File.cpp index 5020767b60..1b1a62ab14 100644 --- a/src/ifcparse/IfcHdf5File.cpp +++ b/src/ifcparse/IfcHdf5File.cpp @@ -1844,16 +1844,30 @@ private: H5::H5File& file_; H5::Group& population_group_; std::vector dataset_names_; + std::vector dataset_paths_; + std::vector dataset_paths_warnings_emitted; std::map* name_mapping_; + std::map, size_t> cache_; public: - instance_resolver(H5::H5File& file, H5::Group& population_group, std::map* name_mapping = nullptr) + instance_resolver(H5::H5File& file, H5::Group& population_group, std::map* name_mapping = nullptr, std::map* path_mapping = nullptr) : file_(file) , population_group_(population_group) , name_mapping_(name_mapping) { dataset_names_ = read_attribute(population_group_, "iso_10303_26_data_set_names"); + if (name_mapping != nullptr) { + for (const auto& s : dataset_names_) { + auto it = path_mapping->find(s); + if (it == path_mapping->end()) { + dataset_paths_.push_back(""); + } else { + dataset_paths_.push_back(it->second); + } + } + } + dataset_paths_warnings_emitted.resize(dataset_names_.size()); } size_t instance_name(const std::string& path, int row) { @@ -1877,9 +1891,29 @@ public: pair[i] = read((uint8_t*)data + offset, &mt); } - const std::string& nm = dataset_names_[pair[0]]; + auto ppair = std::make_pair(pair[0], pair[1]); - H5::DataSet dataset = file_.openDataSet("population/" + nm + "_instances"); + auto cache_it = cache_.find(ppair); + if (cache_it != cache_.end()) { + return cache_it->second; + } + + std::string path; + if (dataset_paths_.empty()) { + const std::string& nm = dataset_names_[pair[0]]; + path = "population/" + nm + "_instances"; + } else { + path = dataset_paths_[pair[0]]; + if (path.empty()) { + if (!dataset_paths_warnings_emitted[pair[0]]) { + std::cerr << "No dataset loaded for '" << dataset_names_[pair[0]] << "'" << std::endl; + } + dataset_paths_warnings_emitted[pair[0]] = true; + return 0; + } + } + + H5::DataSet dataset = file_.openDataSet(path); H5::CompType datatype = dataset.getCompType(); H5::DataSpace dataspace = dataset.getSpace(); if (dataspace.getSimpleExtentNdims() != 1) { @@ -1906,6 +1940,8 @@ public: delete[] buffer; + cache_.insert(std::make_pair(ppair, inst_name)); + return inst_name; } else if (dt->getClass() == H5T_REFERENCE) { @@ -2155,6 +2191,7 @@ struct hdf5_output_info { std::ostream& output; std::map* name_mapping; + std::map* path_mapping; }; herr_t iterate(hid_t id, const char *path, const H5O_info_t *object_info, void *op_data) { @@ -2163,10 +2200,12 @@ herr_t iterate(hid_t id, const char *path, const H5O_info_t *object_info, void * if (object_info->type == H5O_TYPE_DATASET) { H5::Group population_group(id); - instance_resolver resolver(f, population_group, ((hdf5_output_info*)op_data)->name_mapping); + instance_resolver resolver(f, population_group, ((hdf5_output_info*)op_data)->name_mapping, ((hdf5_output_info*)op_data)->path_mapping); std::string name = path; + std::cerr << name << std::endl; + H5::DataSet dataset = population_group.openDataSet(name); H5::DataType datatype = dataset.getDataType(); H5::DataSpace dataspace = dataset.getSpace(); @@ -2218,13 +2257,15 @@ private: H5::H5File& file_; bool finished_schema_; std::map* offset_mapping_; + std::map* path_mapping_; int last_offset_; public: - file_structure(H5::H5File& file, std::map* offset_mapping = nullptr) + file_structure(H5::H5File& file, std::map* offset_mapping = nullptr, std::map* path_mapping = nullptr) : file_(file) , finished_schema_(false) , offset_mapping_(offset_mapping) + , path_mapping_(path_mapping) , last_offset_(1) {} @@ -2252,6 +2293,27 @@ public: offset_mapping_->insert({ds.getObjName(), last_offset_}); last_offset_ += dims; } + if (path_mapping_) { + /* + std::string datatype = ds.getDataType().getObjName(); + auto it = datatype.rfind('/'); + if (it != std::string::npos) { + datatype = datatype.substr(it + 1); + } + */ + + std::string name = ds.getObjName(); + std::string path = name; + auto it = path.rfind('/'); + if (it != std::string::npos) { + path = path.substr(it + 1); + } + it = path.find('_'); + if (it != std::string::npos) { + path = path.substr(0, it); + } + path_mapping_->insert({ path, name }); + } } void finished_schema() { finished_schema_ = true; } @@ -2306,6 +2368,11 @@ void IfcParse::IfcHdf5File::convert_to_spf(const std::string& name, std::ostream H5::H5File f(name, H5F_ACC_RDONLY); std::vector children; + std::map offset_mapping; + std::map path_mapping; + + file_structure fs(f, &offset_mapping, &path_mapping); + if (mount_points) { std::transform(mount_points->begin(), mount_points->end(), std::back_inserter(children), [&f](const std::string& directive) { @@ -2328,15 +2395,13 @@ void IfcParse::IfcHdf5File::convert_to_spf(const std::string& name, std::ostream }); } - std::map offset_mapping; - - file_structure fs(f, &offset_mapping); H5Ovisit(f.getId(), H5_INDEX_NAME, H5_ITER_NATIVE, find_datasets, &fs); + H5Ovisit(f.getId(), H5_INDEX_NAME, H5_ITER_NATIVE, find_groups, &fs); fs.finished_schema(); H5Ovisit(f.getId(), H5_INDEX_NAME, H5_ITER_NATIVE, find_groups, &fs); - hdf5_output_info info{ f, output, &offset_mapping }; + hdf5_output_info info{ f, output, &offset_mapping, &path_mapping }; for (auto it = fs.begin(); it != fs.end(); ++it) { auto& group = it->first; auto& schema_id = it->second->first;