diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index c563da8049..8b9a0c5a66 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -119,6 +119,7 @@ private: class faceset_helper { private: MAKE_TYPE_NAME(Kernel)* kernel_; + std::set duplicates_; std::map vertex_mapping_; std::map, TopoDS_Edge> edges_; double eps_; @@ -173,6 +174,9 @@ private: } bool wire(const IfcSchema::IfcPolyLoop* loop, TopoDS_Wire& wire) { + if (duplicates_.find(loop) != duplicates_.end()) { + return false; + } BRep_Builder builder; builder.MakeWire(wire); int count = 0; diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index e08964f845..1db328acc4 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -4173,19 +4173,36 @@ IfcGeom::Kernel::faceset_helper::faceset_helper(Kernel* kernel, const IfcSchema: } } + // @todo, there a tiny possibility that the duplicate faces are triggered + // for an internal boundary, that is also present as an external boundary. + // This will result in non-manifold configuration then, but this is deemed + // such as corner-case that it is not considered. IfcSchema::IfcPolyLoop::list::ptr loops = IfcParse::traverse((IfcUtil::IfcBaseClass*)l)->as(); - size_t loops_removed = 0, non_manifold = 0; + size_t loops_removed = 0, non_manifold = 0, duplicate_faces = 0; + + typedef std::array edge_t; + typedef std::set edge_set_t; + std::set edge_sets; for (auto& loop : *loops) { auto ps = loop->Polygon(); std::vector > segments; + edge_set_t segment_set; - loop_(ps, [&segments](int C, int D, bool) { + loop_(ps, [&segments, &segment_set](int C, int D, bool) { + segment_set.insert({ C, D }); segments.push_back({ C, D }); }); + if (edge_sets.find(segment_set) != edge_sets.end()) { + duplicate_faces++; + duplicates_.insert(loop); + continue; + } + edge_sets.insert(segment_set); + if (segments.size() >= 3) { for (auto& p : segments) { edge_use[p] ++; @@ -4206,6 +4223,6 @@ IfcGeom::Kernel::faceset_helper::faceset_helper(Kernel* kernel, const IfcSchema: } if (loops_removed || (non_manifold && l->declaration().is(IfcSchema::IfcClosedShell::Class()))) { - Logger::Warning(boost::lexical_cast(loops_removed) + " loops removed and " + boost::lexical_cast(non_manifold) + " non-manifold edges for:", l); + Logger::Warning(boost::lexical_cast(duplicate_faces) + " duplicate faces removed, " + boost::lexical_cast(loops_removed) + " loops removed and " + boost::lexical_cast(non_manifold) + " non-manifold edges for:", l); } } \ No newline at end of file