From 87c70167bea759049a21f2e2697bdfd000a41ab2 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Oct 2021 11:37:18 +0200 Subject: [PATCH] Part: add convenience function to convert TColgp_Array1OfDir to std::vector --- src/Mod/Part/App/Tools.cpp | 88 ++++++++++++++++++++++++++++++++++++++ src/Mod/Part/App/Tools.h | 23 ++++++++++ 2 files changed, 111 insertions(+) diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index 74664dfa50..0a85e0c6df 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -420,6 +420,7 @@ void Part::Tools::getPointNormals(const std::vector& points, const TopoD void Part::Tools::getPointNormals(const TopoDS_Face& theFace, Handle(Poly_Triangulation) aPolyTri, TColgp_Array1OfDir& theNormals) { +#if OCC_VERSION_HEX < 0x070600 const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes(); if(aPolyTri->HasNormals()) @@ -500,4 +501,91 @@ void Part::Tools::getPointNormals(const TopoDS_Face& theFace, Handle(Poly_Triang } } } +#else + Standard_Integer numNodes = aPolyTri->NbNodes(); + + if(aPolyTri->HasNormals()) + { + for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) + { + theNormals(aNodeIter) = aPolyTri->Normal(aNodeIter); + } + + if(theFace.Orientation() == TopAbs_REVERSED) + { + for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) + { + theNormals.ChangeValue(aNodeIter).Reverse(); + } + } + } + else { + // take in face the surface location + Poly_Connect thePolyConnect(aPolyTri); + const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location())); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace); + const Standard_Real aTol = Precision::Confusion(); + Standard_Boolean hasNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull(); + Standard_Integer aTri[3]; + + for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) + { + // try to retrieve normal from real surface first, when UV coordinates are available + if (!hasNodesUV || GeomLib::NormEstim(aSurf, aPolyTri->UVNode(aNodeIter), aTol, theNormals(aNodeIter)) > 1) + { + // compute flat normals + gp_XYZ eqPlan(0.0, 0.0, 0.0); + + for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next()) + { + aPolyTri->Triangle(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]); + const gp_XYZ v1(aPolyTri->Node(aTri[1]).Coord() - aPolyTri->Node(aTri[0]).Coord()); + const gp_XYZ v2(aPolyTri->Node(aTri[2]).Coord() - aPolyTri->Node(aTri[1]).Coord()); + const gp_XYZ vv = v1 ^ v2; + const Standard_Real aMod = vv.Modulus(); + + if(aMod >= aTol) + { + eqPlan += vv / aMod; + } + } + + const Standard_Real aModMax = eqPlan.Modulus(); + theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ(); + } + + aPolyTri->SetNormal(aNodeIter, theNormals(aNodeIter)); + } + + if(theFace.Orientation() == TopAbs_REVERSED) + { + for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter) + { + theNormals.ChangeValue(aNodeIter).Reverse(); + } + } + } +#endif +} + +void Part::Tools::getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, std::vector& normals) +{ + TColgp_Array1OfDir dirs (1, aPoly->NbNodes()); + getPointNormals(face, aPoly, dirs); + normals.reserve(aPoly->NbNodes()); + + for (int i = dirs.Lower(); i <= dirs.Upper(); ++i) { + normals.emplace_back(dirs(i).XYZ()); + } +} + +void Part::Tools::applyTransformationOnNormals(const TopLoc_Location& loc, std::vector& normals) +{ + if (!loc.IsIdentity()) { + gp_Trsf myTransf = loc.Transformation(); + + for (auto& it : normals) { + it.Transform(myTransf); + } + } } diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index 43a01123b7..425032a12d 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -153,7 +154,29 @@ public: * \param vertexnormals */ static void getPointNormals(const std::vector& points, const TopoDS_Face& face, std::vector& vertexnormals); + /*! + * \brief getPointNormals + * Computes the exact surface normals for the points by using the UV coordinates of the mesh vertexes. + * \param face + * \param aPoly + * \param vertexnormals + */ static void getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, TColgp_Array1OfDir& normals); + /*! + * \brief getPointNormals + * Computes the exact surface normals for the points by using the UV coordinates of the mesh vertexes. + * \param face + * \param aPoly + * \param vertexnormals + */ + static void getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, std::vector& normals); + /*! + * \brief applyTransformationOnNormals + * Apply the transformation to the vectors + * \param loc + * \param normals + */ + static void applyTransformationOnNormals(const TopLoc_Location& loc, std::vector& normals); }; } //namespace Part