diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index c0e5944508..41284befed 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -29,6 +29,7 @@ # include # include # include +# include # include # include # include @@ -356,3 +357,60 @@ bool Part::Tools::getPolygon3D(const TopoDS_Edge& edge, std::vector& poi return true; } + +void Part::Tools::getPointNormals(const std::vector& points, const std::vector& facets, std::vector& vertexnormals) +{ + vertexnormals.resize(points.size()); + + for (const auto& it : facets) { + // Get the triangle + Standard_Integer n1,n2,n3; + it.Get(n1,n2,n3); + + // Calculate triangle normal + gp_Vec v1(points[n1].XYZ()); + gp_Vec v2(points[n2].XYZ()); + gp_Vec v3(points[n3].XYZ()); + gp_Vec n = (v2 - v1) ^ (v3 - v1); + + // add the triangle normal to the vertex normal for all points of this triangle + vertexnormals[n1] += n; + vertexnormals[n2] += n; + vertexnormals[n3] += n; + } + + for (auto& it : vertexnormals) + it.Normalize(); +} + +void Part::Tools::getPointNormals(const std::vector& points, const TopoDS_Face& face, std::vector& vertexnormals) +{ + if (points.size() != vertexnormals.size()) + return; + + Handle(Geom_Surface) hSurface = BRep_Tool::Surface(face); + if (hSurface.IsNull()) + return; + + // normalize all vertex normals + for (std::size_t i = 0; i < points.size(); i++) { + try { + GeomAPI_ProjectPointOnSurf ProPntSrf(points[i], hSurface); + Standard_Real u, v; + ProPntSrf.Parameters(1, u, v); + + GeomLProp_SLProps propOfFace(hSurface, u, v, 2, gp::Resolution()); + + gp_Dir normal = propOfFace.Normal(); + gp_Vec temp = normal; + if (temp * vertexnormals[i] < 0.0) + temp = -temp; + vertexnormals[i] = temp; + + } + catch (...) { + } + + vertexnormals[i].Normalize(); + } +} diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index 19ecf937fd..a487530a7d 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -134,6 +134,23 @@ public: * \return true if a polygon exists or false otherwise */ static bool getPolygon3D(const TopoDS_Edge& edge, std::vector& points); + /*! + * \brief getPointNormals + * Calculate the point normals of the given triangulation. + * \param points + * \param facets + * \param normals + */ + static void getPointNormals(const std::vector& points, const std::vector& facets, std::vector& vertexnormals); + /*! + * \brief getPointNormals + * Computes the more accurate surface normals for the points. If the calculation for a point fails then the precomputed + * point normal of the triangulation is used. + * \param points + * \param face + * \param vertexnormals + */ + static void getPointNormals(const std::vector& points, const TopoDS_Face& face, std::vector& vertexnormals); }; } //namespace Part