From 4f8b430040563e87c99112d34157e8bc32ecc252 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 30 Nov 2018 11:08:19 +0100 Subject: [PATCH] Improvements to faceset_helper in case of nearby verts --- src/ifcgeom/IfcGeom.h | 12 +++++++----- src/ifcgeom/IfcGeomFaces.cpp | 6 +++++- src/ifcgeom/IfcGeomFunctions.cpp | 31 +++++++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index 604ff34be4..3aebe1f66d 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -166,22 +166,24 @@ private: bool wire(const IfcSchema::IfcPolyLoop* loop, TopoDS_Wire& wire) { BRep_Builder builder; builder.MakeWire(wire); - bool valid; + int count = 0; auto ps = loop->Polygon(); - loop_(ps, [this, &builder, &wire, &valid](int A, int B, bool fwd) { + loop_(ps, [this, &builder, &wire, &count](int A, int B, bool fwd) { TopoDS_Edge e; if (edge(A, B, e)) { if (!fwd) { e.Reverse(); } builder.Add(wire, e); - valid = true; + count += 1; } }); - if (valid) { + if (count >= 3) { wire.Closed(true); + return true; + } else { + return false; } - return valid; } }; diff --git a/src/ifcgeom/IfcGeomFaces.cpp b/src/ifcgeom/IfcGeomFaces.cpp index 278cd33711..3b30fd9eb7 100644 --- a/src/ifcgeom/IfcGeomFaces.cpp +++ b/src/ifcgeom/IfcGeomFaces.cpp @@ -179,7 +179,11 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) { TopoDS_Wire wire; if (faceset_helper_ && loop->as()) { - faceset_helper_->wire(loop->as(), wire); + if (!faceset_helper_->wire(loop->as(), wire)) { + Logger::Message(Logger::LOG_WARNING, "Face boundary loop not included", loop); + delete mf; + return false; + } } else if (!convert_wire(loop, wire)) { Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop); delete mf; diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index cf6681c9bc..81141fdb6c 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -3506,6 +3506,8 @@ namespace { std::vector js = tree.select_box(b, false); for (int j : js) { if (visited.find(j) == visited.end()) { + // @todo, making this recursive removes the dependence on the initial ordering, but will + // likely result in empty results when all vertices are within 1 eps from another point. find_neighbours(tree, pnts, visited, j, eps); } } @@ -3527,7 +3529,7 @@ IfcGeom::Kernel::faceset_helper::faceset_helper(Kernel* kernel, const IfcSchema: BRep_Builder B; - const double eps = kernel->getValue(GV_PRECISION); + const double eps = kernel->getValue(GV_PRECISION) * 10.; IfcGeom::impl::tree tree; { int i = 0; @@ -3549,23 +3551,44 @@ IfcGeom::Kernel::faceset_helper::faceset_helper(Kernel* kernel, const IfcSchema: for (int v : vs) { if (v <= i) { auto pt = *(points->begin() + v); - vertex_mapping_.insert({pt->data().id(), i}); + vertex_mapping_[pt->data().id()] = i; } } } IfcSchema::IfcPolyLoop::list::ptr loops = IfcParse::traverse((IfcUtil::IfcBaseClass*)l)->as(); + size_t loops_removed = 0, non_manifold = 0; + for (auto& loop : *loops) { auto ps = loop->Polygon(); - loop_(ps, [&edge_use](int C, int D, bool) { - edge_use[{C, D}] ++; + + std::vector > segments; + + loop_(ps, [&segments](int C, int D, bool) { + segments.push_back({ C, D }); }); + + if (segments.size() >= 3) { + for (auto& p : segments) { + edge_use[p] ++; + } + } else { + loops_removed += 1; + } } for (auto& p : edge_use) { int a, b; std::tie(a, b) = p.first; edges_[p.first] = BRepBuilderAPI_MakeEdge(vertices[a], vertices[b]); + + if (p.second != 2) { + non_manifold += 1; + } + } + + if (loops_removed || non_manifold) { + Logger::Error(boost::lexical_cast(loops_removed) + " loops removed and " + boost::lexical_cast(non_manifold) + " non-manifold edges for:", l); } } \ No newline at end of file