From ee09f2404b84d0a119d0b7d2f83cd24919e62abb Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 6 Aug 2023 14:27:31 +0800 Subject: [PATCH] Filter duplicate edge indices #3546 --- src/ifcgeom/IfcGeomRepresentation.cpp | 6 ++--- src/ifcgeom/IfcGeomRepresentation.h | 2 +- .../OpenCascadeConversionResult.cpp | 22 +++++++++++++------ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/ifcgeom/IfcGeomRepresentation.cpp b/src/ifcgeom/IfcGeomRepresentation.cpp index d6380a5cdf..7678d0d28c 100644 --- a/src/ifcgeom/IfcGeomRepresentation.cpp +++ b/src/ifcgeom/IfcGeomRepresentation.cpp @@ -409,11 +409,9 @@ int IfcGeom::Representation::Triangulation::addVertex(int item_id, int material_ return i; } -void IfcGeom::Representation::Triangulation::addEdge(int n1, int n2, std::map, int>& edgecount, std::vector>& edges_temp) { +void IfcGeom::Representation::Triangulation::addEdge(int n1, int n2, std::map, int>& edgecount) { const Edge e = Edge((std::min)(n1, n2), (std::max)(n1, n2)); - if (edgecount.find(e) == edgecount.end()) edgecount[e] = 1; - else edgecount[e] ++; - edges_temp.push_back(e); + edgecount[e] ++; } const IfcGeom::ConversionResultShape* IfcGeom::Representation::BRep::item(int i) const { diff --git a/src/ifcgeom/IfcGeomRepresentation.h b/src/ifcgeom/IfcGeomRepresentation.h index 5250603bea..07f6962110 100644 --- a/src/ifcgeom/IfcGeomRepresentation.h +++ b/src/ifcgeom/IfcGeomRepresentation.h @@ -195,7 +195,7 @@ namespace IfcGeom { _edges.push_back(i1); } - void addEdge(int n1, int n2, std::map, int>& edgecount, std::vector >& edges_temp); + void addEdge(int n1, int n2, std::map, int>& edgecount); void resetWelds() { weld_offset_ += welds.size(); diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp index bc5b5d2860..7d58fc99f1 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp @@ -47,6 +47,10 @@ void ifcopenshell::geometry::OpenCascadeShape::Triangulate(ifcopenshell::geometr m(2, 0), m(2, 1), m(2, 2) ); } + + // When welding vertices, vertex coords will be shared among faces so we need to per-shape set + // to keep track of which edges were already emitted. + std::set> emitted_edges; // Triangulate the shape try { @@ -70,7 +74,6 @@ void ifcopenshell::geometry::OpenCascadeShape::Triangulate(ifcopenshell::geometr // Keep track of the number of times an edge is used // Manifold edges (i.e. edges used twice) are deemed invisible std::map, int> edgecount; - std::vector > edges_temp; std::vector coords; BRepGProp_Face prop(face); @@ -142,14 +145,19 @@ void ifcopenshell::geometry::OpenCascadeShape::Triangulate(ifcopenshell::geometr t->addFace(item_id, surface_style_id, dict[n1], dict[n2], dict[n3]); - t->addEdge(dict[n1], dict[n2], edgecount, edges_temp); - t->addEdge(dict[n2], dict[n3], edgecount, edges_temp); - t->addEdge(dict[n3], dict[n1], edgecount, edges_temp); + t->addEdge(dict[n1], dict[n2], edgecount); + t->addEdge(dict[n2], dict[n3], edgecount); + t->addEdge(dict[n3], dict[n1], edgecount); } - for (std::vector >::const_iterator jt = edges_temp.begin(); jt != edges_temp.end(); ++jt) { - if (edgecount[*jt] == 1) { + for (auto& p : edgecount) { + // @todo should be != 2? + if (p.second == 1 && emitted_edges.find(p.first) == emitted_edges.end()) { // non manifold edge, face boundary - t->registerEdge(jt->first, jt->second); + t->registerEdge(p.first.first, p.first.second); + if (settings.get().get()) { + // only relevant while welding, because otherwise vertices are not shared among distinct faces + emitted_edges.insert(p.first); + } } } }