diff --git a/src/ifcgeom/schema/mapping.cpp b/src/ifcgeom/schema/mapping.cpp index 21a45afd1e..82ba02ba8b 100644 --- a/src/ifcgeom/schema/mapping.cpp +++ b/src/ifcgeom/schema/mapping.cpp @@ -75,12 +75,10 @@ namespace { if (loop) { loop->external = true; - face_ = taxonomy::face(); + face_.emplace(); face_->instance = loop->instance; face_->matrix = loop->matrix; - // @todo make sure loop is not freed - // this is accounted for below with as::upgraded_ - face_->children = { loop }; + face_->children = { loop->clone() }; } } @@ -107,22 +105,20 @@ namespace { class as { private: taxonomy::item* item_; - mutable bool upgraded_; public: - as(taxonomy::item* item) : item_(item), upgraded_(false) {} + as(taxonomy::item* item) : item_(item) {} operator T() const { if (!item_) { throw taxonomy::topology_error("item was nullptr"); } T* t = dynamic_cast(item_); if (t) { - return *t; + return T(*t); } else { { loop_to_face_upgrade upgrade(item_); if (upgrade) { - upgraded_ = true; return upgrade; } } @@ -130,10 +126,7 @@ namespace { } } ~as() { - if (!upgraded_) { - // @todo revisit this - delete item_; - } + delete item_; } }; @@ -204,7 +197,7 @@ namespace { auto filtered = new taxonomy::collection; for (auto& child : collection->children) { if (apply_predicate_to_collection(child, fn)) { - filtered->children.push_back(child); + filtered->children.push_back(child->clone()); } } if (filtered->children.empty()) { @@ -213,6 +206,18 @@ namespace { } return filtered; } + + // @nb traverses nested collections + template + taxonomy::collection* filter_in_place(taxonomy::collection* collection, Fn fn) { + for (auto it = --collection->children.end(); it >= collection->children.begin(); --it) { + if (!apply_predicate_to_collection(*it, fn)) { + delete *it; + collection->children.erase(it); + } + } + return collection; + } } taxonomy::item* mapping::map_impl(const IfcSchema::IfcRepresentation* inst) { @@ -232,14 +237,10 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcRepresentation* inst) { } */ - auto filtered = filter(items, [&use_body](taxonomy::item* i) { + return filter_in_place(items, [&use_body](taxonomy::item* i) { // @todo just filter loops for now. return (i->kind() != taxonomy::LOOP) == use_body; }); - - delete items; - - return filtered; } taxonomy::item* mapping::map_impl(const IfcSchema::IfcFaceBasedSurfaceModel* inst) { @@ -277,11 +278,14 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcFace* inst) { r->reverse(); } if (bound->declaration().is(IfcSchema::IfcFaceOuterBound::Class())) { + ((taxonomy::loop*)r)->external = true; + /* // Make a copy in case we need immutability later for e.g. caching auto s = r->clone(); ((taxonomy::loop*)s)->external = true; delete r; r = s; + */ } face->children.push_back(r); } diff --git a/src/ifcgeom/taxonomy.h b/src/ifcgeom/taxonomy.h index c22965865d..11ba421914 100644 --- a/src/ifcgeom/taxonomy.h +++ b/src/ifcgeom/taxonomy.h @@ -344,6 +344,11 @@ struct edge : public trimmed_curve { struct collection : public geom_item { std::vector children; + collection() {} + collection(const collection& other) { + std::transform(other.children.begin(), other.children.end(), std::back_inserter(children), std::mem_fun(&item::clone)); + } + template std::vector children_as() const { std::vector ts;