ifcgeom: keep one copy of same-identity duplicate loops via set semantics

Adopt the reviewer's suggestion on #9396: instead of counting how many
skips each duplicate identity has earned, record which duplicate
identities have already built once. The first occurrence builds, the
rest are skipped. Distinct-identity loops that only become duplicates
after point mapping behave as before. Set semantics are also robust if
the helper is ever driven over the same shell twice, where a consumed
counter would under-build.
This commit is contained in:
Petru Conduraru
2026-08-31 17:46:40 +03:00
committed by Thomas Krijnen
parent 1207338fa9
commit e4190a1636
2 changed files with 9 additions and 8 deletions
@@ -108,7 +108,7 @@ ifcopenshell::geom::open_cascade_kernel::faceset_helper::faceset_helper(
vertex_mapping_.clear(); vertex_mapping_.clear();
duplicates_.clear(); duplicates_.clear();
duplicate_skips_remaining_.clear(); duplicate_identities_built_.clear();
edge_use.clear(); edge_use.clear();
@@ -176,7 +176,6 @@ ifcopenshell::geom::open_cascade_kernel::faceset_helper::faceset_helper(
if (edge_sets.find(edge_set_key) != edge_sets.end()) { if (edge_sets.find(edge_set_key) != edge_sets.end()) {
duplicate_faces++; duplicate_faces++;
duplicates_.insert(loop->identity()); duplicates_.insert(loop->identity());
duplicate_skips_remaining_[loop->identity()]++;
continue; continue;
} }
edge_sets.insert(edge_set_key); edge_sets.insert(edge_set_key);
@@ -253,12 +252,14 @@ bool ifcopenshell::geom::open_cascade_kernel::faceset_helper::wire(const ifcopen
} }
bool ifcopenshell::geom::open_cascade_kernel::faceset_helper::wires(const ifcopenshell::geom::taxonomy::loop::ptr loop, NCollection_List<TopoDS_Shape>& wires) { bool ifcopenshell::geom::open_cascade_kernel::faceset_helper::wires(const ifcopenshell::geom::taxonomy::loop::ptr loop, NCollection_List<TopoDS_Shape>& wires) {
// Skip only the redundant occurrences, keep one copy of the face. // A loop whose edge set duplicates another's is skipped. When the duplicates
auto it = duplicate_skips_remaining_.find(loop->identity()); // share one identity (the same IfcFace listed repeatedly, #418), set semantics
if (it != duplicate_skips_remaining_.end() && it->second > 0) { // keep exactly one copy: the first occurrence builds, the rest are skipped.
--it->second; if (duplicates_.find(loop->identity()) != duplicates_.end()) {
if (!duplicate_identities_built_.insert(loop->identity()).second) {
return false; return false;
} }
}
TopoDS_Wire wire; TopoDS_Wire wire;
BRep_Builder builder; BRep_Builder builder;
builder.MakeWire(wire); builder.MakeWire(wire);
@@ -86,7 +86,7 @@ private:
private: private:
open_cascade_kernel* kernel_; open_cascade_kernel* kernel_;
std::set<int> duplicates_; std::set<int> duplicates_;
std::map<int, int> duplicate_skips_remaining_; std::set<int> duplicate_identities_built_;
std::map<int, int> vertex_mapping_; std::map<int, int> vertex_mapping_;
std::map<std::pair<int, int>, TopoDS_Edge> edges_; std::map<std::pair<int, int>, TopoDS_Edge> edges_;
double eps_; double eps_;