From 73a572f26cc025cb710a871269cc07fb5519cb86 Mon Sep 17 00:00:00 2001 From: oan Date: Mon, 16 Jan 2023 14:59:31 +0300 Subject: [PATCH] #32471 Mesh - Deflection of the triangulation is not recomputed for planar face Correction fix for CR32741 to provide binary compatibility with Products 750 --- src/BRepLib/BRepLib.cxx | 168 +++++++++++++++++++ src/BRepLib/BRepLib.hxx | 4 + src/BRepMesh/BRepMesh_ModelPostProcessor.cxx | 51 +++++- src/Poly/FILES | 2 + src/Poly/Poly_Triangulation.hxx | 9 + src/Poly/Poly_TriangulationParameters.cxx | 18 ++ src/Poly/Poly_TriangulationParameters.hxx | 93 ++++++++++ 7 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 src/Poly/Poly_TriangulationParameters.cxx create mode 100644 src/Poly/Poly_TriangulationParameters.hxx diff --git a/src/BRepLib/BRepLib.cxx b/src/BRepLib/BRepLib.cxx index 7ac087cc3d..23e2e9e3e4 100644 --- a/src/BRepLib/BRepLib.cxx +++ b/src/BRepLib/BRepLib.cxx @@ -2444,6 +2444,174 @@ Standard_Boolean BRepLib:: return aRetVal; } +//======================================================================= +//function : UpdateDeflection +//purpose : +//======================================================================= +namespace +{ + //! Tool to estimate deflection of the given UV point + //! with regard to its representation in 3D space. + struct EvalDeflection + { + BRepAdaptor_Surface Surface; + + //! Initializes tool with the given face. + EvalDeflection (const TopoDS_Face& theFace) + : Surface (theFace) + { + } + + //! Evaluates deflection of the given 2d point from its 3d representation. + Standard_Real Eval (const gp_Pnt2d& thePoint2d, const gp_Pnt& thePoint3d) + { + gp_Pnt aPnt; + Surface.D0 (thePoint2d.X (), thePoint2d.Y (), aPnt); + return (thePoint3d.XYZ () - aPnt.XYZ ()).SquareModulus (); + } + }; + + //! Represents link of triangulation. + struct Link + { + Standard_Integer Node[2]; + + //! Constructor + Link (const Standard_Integer theNode1, const Standard_Integer theNode2) + { + Node[0] = theNode1; + Node[1] = theNode2; + } + + //! Computes a hash code for the this link + Standard_Integer HashCode (const Standard_Integer theUpperBound) const + { + return ::HashCode (Node[0] + Node[1], theUpperBound); + } + + //! Returns true if this link has the same nodes as the other. + Standard_Boolean IsEqual (const Link& theOther) const + { + return ((Node[0] == theOther.Node[0] && Node[1] == theOther.Node[1]) || + (Node[0] == theOther.Node[1] && Node[1] == theOther.Node[0])); + } + + //! Alias for IsEqual. + Standard_Boolean operator ==(const Link& theOther) const + { + return IsEqual (theOther); + } + }; + + //! Computes a hash code for the given link + inline Standard_Integer HashCode (const Link& theLink, const Standard_Integer theUpperBound) + { + return theLink.HashCode (theUpperBound); + } +} + +void BRepLib::UpdateDeflection (const TopoDS_Shape& theShape) +{ + TopExp_Explorer anExpFace (theShape, TopAbs_FACE); + for (; anExpFace.More(); anExpFace.Next()) + { + const TopoDS_Face& aFace = TopoDS::Face (anExpFace.Current()); + const Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aFace); + if (aSurf.IsNull()) + { + continue; + } + + TopLoc_Location aLoc; + const Handle(Poly_Triangulation)& aPT = BRep_Tool::Triangulation (aFace, aLoc); + if (aPT.IsNull() || !aPT->HasUVNodes()) + { + continue; + } + + // Collect all nodes of degenerative edges and skip elements + // build upon them due to huge distortions introduced by passage + // from UV space to 3D. + NCollection_Map aDegNodes; + TopExp_Explorer anExpEdge (aFace, TopAbs_EDGE); + for (; anExpEdge.More(); anExpEdge.Next()) + { + const TopoDS_Edge& aEdge = TopoDS::Edge (anExpEdge.Current()); + if (BRep_Tool::Degenerated (aEdge)) + { + const Handle(Poly_PolygonOnTriangulation)& aPolygon = BRep_Tool::PolygonOnTriangulation (aEdge, aPT, aLoc); + if (aPolygon.IsNull ()) + { + continue; + } + + for (Standard_Integer aNodeIt = aPolygon->Nodes().Lower(); aNodeIt <= aPolygon->Nodes().Upper(); ++aNodeIt) + { + aDegNodes.Add (aPolygon->Nodes().Value (aNodeIt)); + } + } + } + + EvalDeflection aTool (aFace); + NCollection_Map aLinks; + Standard_Real aSqDeflection = 0.; + const gp_Trsf& aTrsf = aLoc.Transformation(); + for (Standard_Integer aTriIt = 1; aTriIt <= aPT->NbTriangles(); ++aTriIt) + { + const Poly_Triangle& aTriangle = aPT->Triangle (aTriIt); + + int aNode[3]; + aTriangle.Get (aNode[0], aNode[1], aNode[2]); + if (aDegNodes.Contains (aNode[0]) || + aDegNodes.Contains (aNode[1]) || + aDegNodes.Contains (aNode[2])) + { + continue; + } + + const gp_Pnt aP3d[3] = { + aPT->Node (aNode[0]).Transformed (aTrsf), + aPT->Node (aNode[1]).Transformed (aTrsf), + aPT->Node (aNode[2]).Transformed (aTrsf) + }; + + const gp_Pnt2d aP2d[3] = { + aPT->UVNode (aNode[0]), + aPT->UVNode (aNode[1]), + aPT->UVNode (aNode[2]) + }; + + // Check midpoint of triangle. + const gp_Pnt aMid3d_t = (aP3d[0].XYZ() + aP3d[1].XYZ() + aP3d[2].XYZ()) / 3.; + const gp_Pnt2d aMid2d_t = (aP2d[0].XY () + aP2d[1].XY () + aP2d[2].XY ()) / 3.; + + aSqDeflection = Max (aSqDeflection, aTool.Eval (aMid2d_t, aMid3d_t)); + + for (Standard_Integer i = 0; i < 3; ++i) + { + const Standard_Integer j = (i + 1) % 3; + const Link aLink (aNode[i], aNode[j]); + if (!aLinks.Add (aLink)) + { + // Do not estimate boundary links due to high distortions at the edge. + const gp_Pnt& aP3d1 = aP3d[i]; + const gp_Pnt& aP3d2 = aP3d[j]; + + const gp_Pnt2d& aP2d1 = aP2d[i]; + const gp_Pnt2d& aP2d2 = aP2d[j]; + + const gp_Pnt aMid3d_l = (aP3d1.XYZ() + aP3d2.XYZ()) / 2.; + const gp_Pnt2d aMid2d_l = (aP2d1.XY () + aP2d2.XY ()) / 2.; + + aSqDeflection = Max (aSqDeflection, aTool.Eval (aMid2d_l, aMid3d_l)); + } + } + } + + aPT->Deflection (Sqrt (aSqDeflection)); + } +} + //======================================================================= //function : SortFaces //purpose : diff --git a/src/BRepLib/BRepLib.hxx b/src/BRepLib/BRepLib.hxx index d19127a3aa..fcb5d530f4 100644 --- a/src/BRepLib/BRepLib.hxx +++ b/src/BRepLib/BRepLib.hxx @@ -229,6 +229,10 @@ public: //! Returns TRUE if any correction is done. Standard_EXPORT static Standard_Boolean EnsureNormalConsistency (const TopoDS_Shape& S, const Standard_Real theAngTol = 0.001, const Standard_Boolean ForceComputeNormals = Standard_False); + //! Updates value of deflection in Poly_Triangulation of faces + //! by the maximum deviation measured on existing triangulation. + Standard_EXPORT static void UpdateDeflection (const TopoDS_Shape& S); + //! Calculates the bounding sphere around the set of vertexes from the theLV list. //! Returns the center (theNewCenter) and the radius (theNewTol) of this sphere. //! This can be used to construct the new vertex which covers the given set of diff --git a/src/BRepMesh/BRepMesh_ModelPostProcessor.cxx b/src/BRepMesh/BRepMesh_ModelPostProcessor.cxx index 99ccd0d20a..8715c2b287 100644 --- a/src/BRepMesh/BRepMesh_ModelPostProcessor.cxx +++ b/src/BRepMesh/BRepMesh_ModelPostProcessor.cxx @@ -19,6 +19,8 @@ #include #include #include +#include +#include IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_ModelPostProcessor, IMeshTools_ModelAlgo) @@ -157,6 +159,47 @@ namespace Handle(IMeshData_Model) myModel; }; + + //! Estimates and updates deflection of triangulations for corresponding faces. + class DeflectionEstimator + { + public: + //! Constructor + DeflectionEstimator (const Handle(IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParams) + : myModel (theModel) + , myParams (new Poly_TriangulationParameters ( + theParams.Deflection, theParams.Angle, theParams.MinSize)) + { + } + + //! Main functor. + void operator()(const Standard_Integer theFaceIndex) const + { + const IMeshData::IFaceHandle& aDFace = myModel->GetFace (theFaceIndex); + if (aDFace->IsSet (IMeshData_Failure) || + aDFace->IsSet (IMeshData_Reused)) + { + return; + } + + BRepLib::UpdateDeflection (aDFace->GetFace()); + + TopLoc_Location aLoc; + const Handle(Poly_Triangulation)& aTriangulation = + BRep_Tool::Triangulation (aDFace->GetFace(), aLoc); + + if (!aTriangulation.IsNull()) + { + aTriangulation->Parameters (myParams); + } + } + + private: + + Handle(IMeshData_Model) myModel; + Handle(Poly_TriangulationParameters) myParams; + }; } //======================================================================= @@ -181,7 +224,7 @@ BRepMesh_ModelPostProcessor::~BRepMesh_ModelPostProcessor() //======================================================================= Standard_Boolean BRepMesh_ModelPostProcessor::performInternal( const Handle(IMeshData_Model)& theModel, - const IMeshTools_Parameters& /*theParameters*/) + const IMeshTools_Parameters& theParameters) { if (theModel.IsNull()) { @@ -189,6 +232,10 @@ Standard_Boolean BRepMesh_ModelPostProcessor::performInternal( } // TODO: Force single threaded solution due to data races on edges sharing the same TShape - OSD_Parallel::For(0, theModel->EdgesNb(), PolygonCommitter(theModel), Standard_True/*!theParameters.InParallel*/); + OSD_Parallel::For (0, theModel->EdgesNb(), PolygonCommitter (theModel), Standard_True/*!theParameters.InParallel*/); + + // Estimate deflection here due to BRepLib::EstimateDeflection requires + // existence of both Poly_Triangulation and Poly_PolygonOnTriangulation. + OSD_Parallel::For (0, theModel->FacesNb(), DeflectionEstimator (theModel, theParameters), !theParameters.InParallel); return Standard_True; } diff --git a/src/Poly/FILES b/src/Poly/FILES index 3d22dcd6b9..3ee889bab1 100755 --- a/src/Poly/FILES +++ b/src/Poly/FILES @@ -29,5 +29,7 @@ Poly_PolygonOnTriangulation.lxx Poly_Triangle.cxx Poly_Triangle.hxx Poly_Triangle.lxx +Poly_TriangulationParameters.hxx +Poly_TriangulationParameters.cxx Poly_Triangulation.cxx Poly_Triangulation.hxx diff --git a/src/Poly/Poly_Triangulation.hxx b/src/Poly/Poly_Triangulation.hxx index 80670786f6..91f054a999 100644 --- a/src/Poly/Poly_Triangulation.hxx +++ b/src/Poly/Poly_Triangulation.hxx @@ -34,6 +34,8 @@ class Standard_NullObject; class Poly_Triangulation; +class Poly_TriangulationParameters; + DEFINE_STANDARD_HANDLE(Poly_Triangulation, Standard_Transient) //! Provides a triangulation for a surface, a set of surfaces, or @@ -106,6 +108,12 @@ public: //! Deallocates the UV nodes. Standard_EXPORT void RemoveUVNodes(); + //! Returns initial set of parameters used to generate this triangulation. + const Handle(Poly_TriangulationParameters)& Parameters() const { return myParams; } + + //! Updates initial set of parameters used to generate this triangulation. + void Parameters (const Handle(Poly_TriangulationParameters)& theParams) { myParams = theParams; } + //! Returns the number of nodes for this triangulation. Standard_Integer NbNodes() const { return myNodes.Length(); } @@ -204,6 +212,7 @@ protected: Poly_Array1OfTriangle myTriangles; Handle(TShort_HArray1OfShortReal) myNormals; + Handle(Poly_TriangulationParameters) myParams; }; #endif // _Poly_Triangulation_HeaderFile diff --git a/src/Poly/Poly_TriangulationParameters.cxx b/src/Poly/Poly_TriangulationParameters.cxx new file mode 100644 index 0000000000..55b7ec025c --- /dev/null +++ b/src/Poly/Poly_TriangulationParameters.cxx @@ -0,0 +1,18 @@ +// Created on: 2021-07-20 +// Copyright (c) 2021 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +IMPLEMENT_STANDARD_RTTIEXT (Poly_TriangulationParameters, Standard_Transient) diff --git a/src/Poly/Poly_TriangulationParameters.hxx b/src/Poly/Poly_TriangulationParameters.hxx new file mode 100644 index 0000000000..176d0abba7 --- /dev/null +++ b/src/Poly/Poly_TriangulationParameters.hxx @@ -0,0 +1,93 @@ +// Created on: 2021-07-20 +// Copyright (c) 2021 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Poly_TriangulationParameters_HeaderFile +#define _Poly_TriangulationParameters_HeaderFile + +#include +#include + +//! Represents initial set of parameters triangulation is built for. +class Poly_TriangulationParameters : public Standard_Transient +{ +public: + + //! Constructor. + //! Initializes object with the given parameters. + //! @param theDeflection linear deflection + //! @param theAngle angular deflection + //! @param theMinSize minimum size + Poly_TriangulationParameters (const Standard_Real theDeflection = -1., + const Standard_Real theAngle = -1., + const Standard_Real theMinSize = -1.) + : myDeflection (theDeflection) + , myAngle (theAngle) + , myMinSize (theMinSize) + { + } + + //! Destructor. + virtual ~Poly_TriangulationParameters() + { + } + + //! Returns true if linear deflection is defined. + Standard_Boolean HasDeflection() const + { + return !(myDeflection < 0.); + } + + //! Returns true if angular deflection is defined. + Standard_Boolean HasAngle() const + { + return !(myAngle < 0.); + } + + //! Returns true if minimum size is defined. + Standard_Boolean HasMinSize() const + { + return !(myMinSize < 0.); + } + + //! Returns linear deflection or -1 if undefined. + Standard_Real Deflection() const + { + return myDeflection; + } + + //! Returns angular deflection or -1 if undefined. + Standard_Real Angle() const + { + return myAngle; + } + + //! Returns minimum size or -1 if undefined. + Standard_Real MinSize() const + { + return myMinSize; + } + + DEFINE_STANDARD_RTTIEXT (Poly_TriangulationParameters, Standard_Transient) + +private: + + Standard_Real myDeflection; + Standard_Real myAngle; + Standard_Real myMinSize; +}; + +DEFINE_STANDARD_HANDLE (Poly_TriangulationParameters, Standard_Transient) + +#endif -- 2.39.5