From 9e8516002b9ced0bada5064b2dc775d022adea73 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 30 Oct 2021 22:28:57 +0200 Subject: [PATCH] Part: fixes #0004774: Datum plane or line is not available in sketch in another body via binder --- src/Mod/Part/App/Tools.cpp | 66 ++++++++++++++++++++++++++++ src/Mod/Part/App/Tools.h | 18 ++++++++ src/Mod/Part/Gui/ViewProviderExt.cpp | 10 ++++- 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index d95e49eaf4f2..7c6792a2efd8 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -25,6 +25,11 @@ # include # include # include +# include +# include +# include +# include +# include # include # include # include @@ -590,3 +595,64 @@ void Part::Tools::applyTransformationOnNormals(const TopLoc_Location& loc, std:: } } } + +Handle (Poly_Triangulation) Part::Tools::triangulationOfFace(const TopoDS_Face& face) +{ + TopLoc_Location loc; + Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(face, loc); + if (!mesh.IsNull()) + return mesh; + + // If no triangulation exists then the shape is probably infinite + BRepAdaptor_Surface adapt(face); + double u1 = adapt.FirstUParameter(); + double u2 = adapt.LastUParameter(); + double v1 = adapt.FirstVParameter(); + double v2 = adapt.LastVParameter(); + + // recreate a face with a clear boundary + u1 = std::max(-50.0, u1); + u2 = std::min( 50.0, u2); + v1 = std::max(-50.0, v1); + v2 = std::min( 50.0, v2); + + Handle(Geom_Surface) surface = BRep_Tool::Surface(face); + BRepBuilderAPI_MakeFace mkBuilder(surface, u1, u2, v1, v2 +#if OCC_VERSION_HEX >= 0x060502 + , Precision::Confusion() +#endif + ); + + TopoDS_Shape shape = mkBuilder.Shape(); + shape.Location(loc); + + BRepMesh_IncrementalMesh(shape, 0.1); + return BRep_Tool::Triangulation(TopoDS::Face(shape), loc); +} + +Handle(Poly_Polygon3D) Part::Tools::polygonOfEdge(const TopoDS_Edge& edge, TopLoc_Location& loc) +{ + BRepAdaptor_Curve adapt(edge); + double u = adapt.FirstParameter(); + double v = adapt.LastParameter(); + Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(edge, loc); + if (!aPoly.IsNull() && !Precision::IsInfinite(u) && !Precision::IsInfinite(v)) + return aPoly; + + // recreate an edge with a clear range + u = std::max(-50.0, u); + v = std::min( 50.0, v); + + double uv; + Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, uv, uv); + + BRepBuilderAPI_MakeEdge mkBuilder(curve, u, v); + TopoDS_Shape shape = mkBuilder.Shape(); + // why do we have to set the inverted location here? + TopLoc_Location inv = loc.Inverted(); + shape.Location(inv); + + BRepMesh_IncrementalMesh(shape, 0.1); + TopLoc_Location tmp; + return BRep_Tool::Polygon3D(TopoDS::Edge(shape), tmp); +} diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index 425032a12d92..3bb543804e99 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include class gp_Lin; class gp_Pln; @@ -177,6 +179,22 @@ class PartExport Tools * \param normals */ static void applyTransformationOnNormals(const TopLoc_Location& loc, std::vector& normals); + /*! + * \brief triangulationOfInfinite + * Returns the triangulation of the face of the tessellated shape. In case the face has infinite lengths + * the triangulation of a limited parameter range is computed. + * \param edge + * \param loc + */ + static Handle (Poly_Triangulation) triangulationOfFace(const TopoDS_Face& face); + /*! + * \brief polygonOfEdge + * Returns the polygon of the edge of the tessellated shape. In case the edge has infinite length + * the polygon of a limited parameter range is computed. + * \param edge + * \param loc + */ + static Handle(Poly_Polygon3D) polygonOfEdge(const TopoDS_Edge& edge, TopLoc_Location& loc); }; } //namespace Part diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index daf355e9095b..b5025dee0c79 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -985,6 +985,9 @@ void ViewProviderPartExt::updateVisual() TopExp::MapShapes(cShape, TopAbs_FACE, faceMap); for (int i=1; i <= faceMap.Extent(); i++) { Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(faceMap(i)), aLoc); + if (mesh.IsNull()) { + mesh = Part::Tools::triangulationOfFace(TopoDS::Face(faceMap(i))); + } // Note: we must also count empty faces if (!mesh.IsNull()) { numTriangles += mesh->NbTriangles(); @@ -1024,7 +1027,7 @@ void ViewProviderPartExt::updateVisual() // a free edge. int hash = aEdge.HashCode(INT_MAX); if (faceEdges.find(hash) == faceEdges.end()) { - Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); + Handle(Poly_Polygon3D) aPoly = Part::Tools::polygonOfEdge(aEdge, aLoc); if (!aPoly.IsNull()) { int nbNodesInEdge = aPoly->NbNodes(); numNodes += nbNodesInEdge; @@ -1058,6 +1061,9 @@ void ViewProviderPartExt::updateVisual() const TopoDS_Face &actFace = TopoDS::Face(faceMap(i)); // get the mesh of the shape Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); + if (mesh.IsNull()) { + mesh = Part::Tools::triangulationOfFace(actFace); + } if (mesh.IsNull()) { parts[ii] = 0; continue; @@ -1220,7 +1226,7 @@ void ViewProviderPartExt::updateVisual() // handling of the free edge that are not associated to a face int hash = aEdge.HashCode(INT_MAX); if (faceEdges.find(hash) == faceEdges.end()) { - Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); + Handle(Poly_Polygon3D) aPoly = Part::Tools::polygonOfEdge(aEdge, aLoc); if (!aPoly.IsNull()) { if (!aLoc.IsIdentity()) { identity = false;