From 013b7a763d928187e220df28db27bff1cd6f642f Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 9 Apr 2019 17:03:24 +0200 Subject: [PATCH] Some fixes to make sure that non-planar faces get explicitly triangulated --- src/ifcgeom/IfcGeom.h | 2 +- src/ifcgeom/IfcGeomFaces.cpp | 2 -- src/ifcgeom/IfcGeomFunctions.cpp | 19 ++++++++++++++++--- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index c6e3c7692d..efa9f715a3 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -317,7 +317,7 @@ public: void remove_collinear_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol=-1.); bool wire_to_sequence_of_point(const TopoDS_Wire&, TColgp_SequenceOfPnt&); void sequence_of_point_to_wire(const TColgp_SequenceOfPnt&, TopoDS_Wire&, bool closed); - bool approximate_plane_through_wire(const TopoDS_Wire&, gp_Pln&); + bool approximate_plane_through_wire(const TopoDS_Wire&, gp_Pln&, double eps=-1.); bool flatten_wire(TopoDS_Wire&); bool triangulate_wire(const TopoDS_Wire&, TopTools_ListOfShape&); bool wire_intersections(const TopoDS_Wire & wire, TopTools_ListOfShape & wires); diff --git a/src/ifcgeom/IfcGeomFaces.cpp b/src/ifcgeom/IfcGeomFaces.cpp index 6ba4746f42..b44121e657 100644 --- a/src/ifcgeom/IfcGeomFaces.cpp +++ b/src/ifcgeom/IfcGeomFaces.cpp @@ -199,8 +199,6 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) { for (; exp.More(); exp.Next(), count++) { if (count < 2) { edges[count] = TopoDS::Edge(exp.Current()); - } else { - break; } } diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index f5afab6017..676ddae0e8 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -3077,12 +3077,15 @@ bool IfcGeom::Kernel::is_identity_transform(IfcUtil::IfcBaseClass* l) { } } -bool IfcGeom::Kernel::approximate_plane_through_wire(const TopoDS_Wire& wire, gp_Pln& plane) { +bool IfcGeom::Kernel::approximate_plane_through_wire(const TopoDS_Wire& wire, gp_Pln& plane, double eps) { // Newell's Method is used for the normal calculation // as a simple edge cross product can give opposite results // for a concave face boundary. // Reference: Graphics Gems III p. 231 + const double eps_ = eps < 1. ? getValue(GV_PRECISION) : eps; + const double eps2 = eps_ * eps_; + double x = 0, y = 0, z = 0; gp_Pnt current, previous, first; gp_XYZ center; @@ -3122,8 +3125,18 @@ bool IfcGeom::Kernel::approximate_plane_through_wire(const TopoDS_Wire& wire, gp if (n < 3) { return false; } - + plane = gp_Pln(center / n, gp_Dir(x, y, z)); + + exp.Init(wire); + for (; exp.More(); exp.Next()) { + const TopoDS_Vertex& v = exp.CurrentVertex(); + current = BRep_Tool::Pnt(v); + if (plane.SquareDistance(current) > eps2) { + return false; + } + } + return true; } @@ -3161,7 +3174,7 @@ bool IfcGeom::Kernel::triangulate_wire(const TopoDS_Wire& wire, TopTools_ListOfS typedef std::pair uv_node; gp_Pln pln; - if (!approximate_plane_through_wire(wire, pln)) { + if (!approximate_plane_through_wire(wire, pln, std::numeric_limits::infinity())) { return false; }