]> OCCT Git - occt.git/commitdiff
#32471 Mesh - Deflection of the triangulation is not recomputed for planar face
authoroan <oan@opencascade.com>
Mon, 16 Jan 2023 11:59:31 +0000 (14:59 +0300)
committeroan <oan@opencascade.com>
Mon, 16 Jan 2023 11:59:31 +0000 (14:59 +0300)
Correction fix for CR32741 to provide binary compatibility with Products 750

src/BRepLib/BRepLib.cxx
src/BRepLib/BRepLib.hxx
src/BRepMesh/BRepMesh_ModelPostProcessor.cxx
src/Poly/FILES
src/Poly/Poly_Triangulation.hxx
src/Poly/Poly_TriangulationParameters.cxx [new file with mode: 0644]
src/Poly/Poly_TriangulationParameters.hxx [new file with mode: 0644]

index 7ac087cc3ddbbc9812b26c7bfb05b82c9cc1cbc3..23e2e9e3e4aa014d9b619a1345f6ff64a9fa7048 100644 (file)
@@ -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<Standard_Integer> 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<Link> 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  : 
index d19127a3aa0346969a9b745236ae7a70b5eabebc..fcb5d530f415b9840c7b571e3e0d5c0709776137 100644 (file)
@@ -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
index 99ccd0d20acbc6b937e66b0a8be30ac711ba2339..8715c2b287164da379b071c6abe9f41c3d992d6c 100644 (file)
@@ -19,6 +19,8 @@
 #include <IMeshData_Edge.hxx>
 #include <IMeshData_PCurve.hxx>
 #include <OSD_Parallel.hxx>
+#include <BRepLib.hxx>
+#include <Poly_TriangulationParameters.hxx>
 
 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;
 }
index 3d22dcd6b98f50fc05f62c73263744756230ee99..3ee889bab1c92eafc0c7877be1dcebaf8b1fae62 100755 (executable)
@@ -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
index 80670786f66a2ddf40a322d5156ab9339a3bf2b7..91f054a99987afac4e1d1a4b92bd69eb394d1706 100644 (file)
@@ -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 (file)
index 0000000..55b7ec0
--- /dev/null
@@ -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 <Poly_TriangulationParameters.hxx>
+
+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 (file)
index 0000000..176d0ab
--- /dev/null
@@ -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 <Standard_Transient.hxx>
+#include <Standard_DefineHandle.hxx>
+
+//! 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