diff --git a/src/hdf5_usecases/federate.cpp b/src/hdf5_usecases/federate.cpp index bd13579040..bf3c712ea1 100644 --- a/src/hdf5_usecases/federate.cpp +++ b/src/hdf5_usecases/federate.cpp @@ -25,6 +25,8 @@ #include #include +#include "multifile_instance_locator.h" + #pragma warning(disable:4100) class ifc_inst_cmp { @@ -157,189 +159,6 @@ public: } }; -class multifile_instance_locator : public IfcParse::abstract_instance_locator { -public: - typedef std::function mapping_t; - typedef std::pair< - std::vector, - std::vector< std::vector > - > population_t; - typedef std::vector::const_iterator full_const_iterator; - -private: - H5::H5File& root_file_; - - mapping_t mapping_; - std::set initial_population_set_; - - population_t initial_population_; - population_t subsequent_population_; - std::vector subsequent_minus_initial_; - - H5::Group& initial_group_; - H5::Group* subsequent_group_; - H5::H5File* subsequent_file_; - std::string root_; - -public: - - template - multifile_instance_locator(H5::H5File& root_file, H5::Group& group, mapping_t mapping, ForwardIterator b, ForwardIterator e) - : root_file_(root_file) - , mapping_(mapping) - , initial_group_(group) - , subsequent_group_(nullptr) - { - initial_population_set_.insert(b, e); - - std::set names_set; - std::for_each(b, e, [this, &names_set](IfcUtil::IfcBaseClass* inst) { - IfcSchema::Type::Enum ty = inst->declaration().type(); - if (names_set.find(ty) == names_set.end()) { - initial_population_.first.push_back(ty); - names_set.insert(ty); - } - }); - - std::sort(initial_population_.first.begin(), initial_population_.first.end()); - - std::for_each(this->begin(), this->end(), [this, &b, &e](IfcSchema::Type::Enum t) { - std::vector by_type; - - std::for_each(b, e, [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(); - }); - - initial_population_.second.emplace_back(by_type); - }); - } - - const_iterator begin() const { - if (subsequent_group_) { - return subsequent_population_.first.begin(); - } else { - return initial_population_.first.begin(); - } - } - - const_iterator end() const { - if (subsequent_group_) { - return subsequent_population_.first.end(); - } else { - return initial_population_.first.end(); - } - } - - full_const_iterator full_begin() const { - return subsequent_minus_initial_.begin(); - } - - full_const_iterator full_end() const { - return subsequent_minus_initial_.end(); - } - - const std::vector& instances(IfcSchema::Type::Enum t) { - if (subsequent_group_) { - return subsequent_population_.second[std::lower_bound(begin(), end(), t) - begin()]; - } else { - return initial_population_.second[std::lower_bound(begin(), end(), t) - begin()]; - } - } - - std::pair operator()(IfcUtil::IfcBaseClass* v) { - throw std::runtime_error("This locator can only be used in referenced profile"); - } - - void make_reference(IfcUtil::IfcBaseClass* v, void*& ptr) { - v = mapping_(v); - IfcSchema::Type::Enum t = v->declaration().type(); - - population_t* pop; - H5::Group* group; - boost::optional current_root; - - if (initial_population_set_.find(v) != initial_population_set_.end()) { - pop = &initial_population_; - group = &initial_group_; - current_root = boost::none; - } else { - pop = &subsequent_population_; - group = subsequent_group_; - current_root = root_; - } - - int a = std::lower_bound(pop->first.begin(), pop->first.end(), t) - pop->first.begin(); - auto& vec = pop->second[a]; - - hsize_t coord = std::lower_bound(vec.begin(), vec.end(), v, [](IfcUtil::IfcBaseClass* other, IfcUtil::IfcBaseClass* val) { - return other->data().id() < val->data().id(); - }) - vec.begin(); - - hsize_t dims = instances(v->declaration().type()).size(); - H5::DataSpace space(1, &dims); - space.selectElements(H5S_SELECT_SET, 1, &coord); - const std::string path = IfcSchema::Type::ToString(pop->first[a]); - - std::string full_path = group->getObjName() + "/" + path + "_instances"; - - root_file_.reference(ptr, full_path, space); - ptr = static_cast(ptr) + sizeof(hdset_reg_ref_t); - } - - void next(const std::string& name, H5::Group& group, IfcParse::IfcFile* f) { - subsequent_group_ = &group; - root_ = name; - - subsequent_population_.first.clear(); - subsequent_population_.second.clear(); - subsequent_minus_initial_.clear(); - - auto f_begin = f->begin(); - auto f_end = f->end(); - - std::set names_set; - std::for_each(f_begin, f_end, [this, &names_set](auto& pair) { - IfcUtil::IfcBaseClass* inst = mapping_(pair.second); - if (initial_population_set_.find(inst) == initial_population_set_.end()) { - IfcSchema::Type::Enum ty = inst->declaration().type(); - if (names_set.find(ty) == names_set.end()) { - subsequent_population_.first.push_back(ty); - names_set.insert(ty); - } - subsequent_minus_initial_.push_back(inst); - } - }); - - auto& names = subsequent_population_.first; - std::sort(names.begin(), names.end()); - - auto& vecs = subsequent_population_.second; - vecs.resize(names.size()); - - std::for_each(f_begin, f_end, [this, &names, &vecs](auto& pair) { - IfcUtil::IfcBaseClass* inst = mapping_(pair.second); - if (initial_population_set_.find(inst) == initial_population_set_.end() && inst->declaration().as_entity()) { - IfcSchema::Type::Enum ty = inst->declaration().type(); - auto a = std::lower_bound(names.begin(), names.end(), ty) - names.begin(); - auto& by_type = vecs[a]; - by_type.push_back((IfcUtil::IfcBaseEntity*) inst); - } - }); - - std::for_each(vecs.begin(), vecs.end(), [](auto& vec) { - std::sort(vec.begin(), vec.end(), [](IfcUtil::IfcBaseEntity* i1, IfcUtil::IfcBaseEntity* i2) { - return i1->data().id() < i2->data().id(); - }); - }); - } -}; - int main(int argc, char** argv) { std::set shared { diff --git a/src/hdf5_usecases/multifile_instance_locator.h b/src/hdf5_usecases/multifile_instance_locator.h new file mode 100644 index 0000000000..50c39370c4 --- /dev/null +++ b/src/hdf5_usecases/multifile_instance_locator.h @@ -0,0 +1,201 @@ +/******************************************************************************** + * * + * This file is part of IfcOpenShell. * + * * + * IfcOpenShell is free software: you can redistribute it and/or modify * + * it under the terms of the Lesser GNU General Public License as published by * + * the Free Software Foundation, either version 3.0 of the License, or * + * (at your option) any later version. * + * * + * IfcOpenShell is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * Lesser GNU General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see . * + * * + ********************************************************************************/ + + class multifile_instance_locator : public IfcParse::abstract_instance_locator { +public: + typedef std::function mapping_t; + typedef std::pair< + std::vector, + std::vector< std::vector > + > population_t; + typedef std::vector::const_iterator full_const_iterator; + +private: + H5::H5File& root_file_; + + mapping_t mapping_; + std::set initial_population_set_; + + population_t initial_population_; + population_t subsequent_population_; + std::vector subsequent_minus_initial_; + + H5::Group& initial_group_; + H5::Group* subsequent_group_; + H5::H5File* subsequent_file_; + std::string root_; + +public: + + template + multifile_instance_locator(H5::H5File& root_file, H5::Group& group, mapping_t mapping, ForwardIterator b, ForwardIterator e) + : root_file_(root_file) + , mapping_(mapping) + , initial_group_(group) + , subsequent_group_(nullptr) + { + initial_population_set_.insert(b, e); + + std::set names_set; + std::for_each(b, e, [this, &names_set](IfcUtil::IfcBaseClass* inst) { + IfcSchema::Type::Enum ty = inst->declaration().type(); + if (names_set.find(ty) == names_set.end()) { + initial_population_.first.push_back(ty); + names_set.insert(ty); + } + }); + + std::sort(initial_population_.first.begin(), initial_population_.first.end()); + + std::for_each(this->begin(), this->end(), [this, &b, &e](IfcSchema::Type::Enum t) { + std::vector by_type; + + std::for_each(b, e, [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(); + }); + + initial_population_.second.emplace_back(by_type); + }); + } + + const_iterator begin() const { + if (subsequent_group_) { + return subsequent_population_.first.begin(); + } else { + return initial_population_.first.begin(); + } + } + + const_iterator end() const { + if (subsequent_group_) { + return subsequent_population_.first.end(); + } else { + return initial_population_.first.end(); + } + } + + full_const_iterator full_begin() const { + return subsequent_minus_initial_.begin(); + } + + full_const_iterator full_end() const { + return subsequent_minus_initial_.end(); + } + + const std::vector& instances(IfcSchema::Type::Enum t) { + if (subsequent_group_) { + return subsequent_population_.second[std::lower_bound(begin(), end(), t) - begin()]; + } else { + return initial_population_.second[std::lower_bound(begin(), end(), t) - begin()]; + } + } + + std::pair operator()(IfcUtil::IfcBaseClass* v) { + throw std::runtime_error("This locator can only be used in referenced profile"); + } + + void make_reference(IfcUtil::IfcBaseClass* v, void*& ptr) { + v = mapping_(v); + IfcSchema::Type::Enum t = v->declaration().type(); + + population_t* pop; + H5::Group* group; + boost::optional current_root; + + if (initial_population_set_.find(v) != initial_population_set_.end()) { + pop = &initial_population_; + group = &initial_group_; + current_root = boost::none; + } else { + pop = &subsequent_population_; + group = subsequent_group_; + current_root = root_; + } + + int a = std::lower_bound(pop->first.begin(), pop->first.end(), t) - pop->first.begin(); + auto& vec = pop->second[a]; + + hsize_t coord = std::lower_bound(vec.begin(), vec.end(), v, [](IfcUtil::IfcBaseClass* other, IfcUtil::IfcBaseClass* val) { + return other->data().id() < val->data().id(); + }) - vec.begin(); + + hsize_t dims = instances(v->declaration().type()).size(); + H5::DataSpace space(1, &dims); + space.selectElements(H5S_SELECT_SET, 1, &coord); + const std::string path = IfcSchema::Type::ToString(pop->first[a]); + + std::string full_path = group->getObjName() + "/" + path + "_instances"; + + root_file_.reference(ptr, full_path, space); + ptr = static_cast(ptr) + sizeof(hdset_reg_ref_t); + } + + void next(const std::string& name, H5::Group& group, IfcParse::IfcFile* f) { + subsequent_group_ = &group; + root_ = name; + + subsequent_population_.first.clear(); + subsequent_population_.second.clear(); + subsequent_minus_initial_.clear(); + + auto f_begin = f->begin(); + auto f_end = f->end(); + + std::set names_set; + std::for_each(f_begin, f_end, [this, &names_set](auto& pair) { + IfcUtil::IfcBaseClass* inst = mapping_(pair.second); + if (initial_population_set_.find(inst) == initial_population_set_.end()) { + IfcSchema::Type::Enum ty = inst->declaration().type(); + if (names_set.find(ty) == names_set.end()) { + subsequent_population_.first.push_back(ty); + names_set.insert(ty); + } + subsequent_minus_initial_.push_back(inst); + } + }); + + auto& names = subsequent_population_.first; + std::sort(names.begin(), names.end()); + + auto& vecs = subsequent_population_.second; + vecs.resize(names.size()); + + std::for_each(f_begin, f_end, [this, &names, &vecs](auto& pair) { + IfcUtil::IfcBaseClass* inst = mapping_(pair.second); + if (initial_population_set_.find(inst) == initial_population_set_.end() && inst->declaration().as_entity()) { + IfcSchema::Type::Enum ty = inst->declaration().type(); + auto a = std::lower_bound(names.begin(), names.end(), ty) - names.begin(); + auto& by_type = vecs[a]; + by_type.push_back((IfcUtil::IfcBaseEntity*) inst); + } + }); + + std::for_each(vecs.begin(), vecs.end(), [](auto& vec) { + std::sort(vec.begin(), vec.end(), [](IfcUtil::IfcBaseEntity* i1, IfcUtil::IfcBaseEntity* i2) { + return i1->data().id() < i2->data().id(); + }); + }); + } +};