From a888a0ac0a72d7600f98bc6506ecd8b5ff7c2d4c Mon Sep 17 00:00:00 2001 From: marioalexis Date: Tue, 18 Jan 2022 01:02:53 -0300 Subject: [PATCH] Part: Implement Tools::getNormal function --- src/Mod/Part/App/Tools.cpp | 57 ++++++++++++++++++++++++++++++++++++++ src/Mod/Part/App/Tools.h | 22 +++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/Mod/Part/App/Tools.cpp b/src/Mod/Part/App/Tools.cpp index 7c6792a2ef..8c65fa75f0 100644 --- a/src/Mod/Part/App/Tools.cpp +++ b/src/Mod/Part/App/Tools.cpp @@ -29,8 +29,10 @@ # include # include # include +# include # include # include +# include # include # include # include @@ -39,6 +41,7 @@ # include # include # include +# include # include # include # include @@ -656,3 +659,57 @@ Handle(Poly_Polygon3D) Part::Tools::polygonOfEdge(const TopoDS_Edge& edge, TopLo TopLoc_Location tmp; return BRep_Tool::Polygon3D(TopoDS::Edge(shape), tmp); } + +// helper function to use in getNormal, here we pass the local properties +// of the surface given by the #LProp_SLProps objects +template +void getNormalBySLProp(T prop, double u, double v, Standard_Real lastU, Standard_Real lastV, + const Standard_Real tol, gp_Dir& dir, Standard_Boolean& done) +{ + if (prop.D1U().Magnitude() > tol && + prop.D1V().Magnitude() > tol && + prop.IsNormalDefined()) { + dir = prop.Normal(); + done = Standard_True; + } + // use an alternative method in case of a null normal + else { + CSLib_NormalStatus stat; + CSLib::Normal(prop.D1U(), prop.D1V(), prop.D2U(), prop.D2V(), prop.DUV(), + tol, done, stat, dir); + // at the right boundary, the normal is flipped with respect to the + // normal on surrounding points. + if (stat == CSLib_D1NuIsNull) { + if (Abs(lastV - v) < tol) + dir.Reverse(); + } + else if (stat == CSLib_D1NvIsNull || stat == CSLib_D1NuIsParallelD1Nv) { + if (Abs(lastU - u) < tol) + dir.Reverse(); + } + } +} + +void Part::Tools::getNormal(const Handle(Geom_Surface)& surf, double u, double v, + const Standard_Real tol, gp_Dir& dir, Standard_Boolean& done) +{ + GeomLProp_SLProps prop(surf, u, v, 1, tol); + Standard_Real u1,u2,v1,v2; + surf->Bounds(u1,u2,v1,v2); + + getNormalBySLProp(prop, u, v, u2, v2, tol, dir, done); +} + +void Part::Tools::getNormal(const TopoDS_Face& face, double u, double v, + const Standard_Real tol, gp_Dir& dir, Standard_Boolean& done) +{ + BRepAdaptor_Surface adapt(face); + BRepLProp_SLProps prop(adapt, u, v, 1, tol); + Standard_Real u2 = adapt.LastUParameter(); + Standard_Real v2 = adapt.LastVParameter(); + + getNormalBySLProp(prop, u, v, u2, v2, tol, dir, done); + + if (face.Orientation() == TopAbs_REVERSED) + dir.Reverse(); +} diff --git a/src/Mod/Part/App/Tools.h b/src/Mod/Part/App/Tools.h index 3bb543804e..9cfae6ed6b 100644 --- a/src/Mod/Part/App/Tools.h +++ b/src/Mod/Part/App/Tools.h @@ -195,6 +195,28 @@ public: * \param loc */ static Handle(Poly_Polygon3D) polygonOfEdge(const TopoDS_Edge& edge, TopLoc_Location& loc); + /*! + * \brief getNormal + * Returns the normal at the given parameters on the surface and the state of the calculation + * \param surf + * \param u + * \param v + * \param tol + * \param dir + * \param done + */ + static void getNormal(const Handle(Geom_Surface)& surf, double u, double v, const Standard_Real tol, gp_Dir& dir, Standard_Boolean& done); + /* \brief getNormal + * Returns the normal at the given parameters on the face and the state of the calculation. + * The orientation is taken into account + * \param face + * \param u + * \param v + * \param tol + * \param dir + * \param done + */ + static void getNormal(const TopoDS_Face& face, double u, double v, const Standard_Real tol, gp_Dir& dir, Standard_Boolean& done); }; } //namespace Part