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 :
//! 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
#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)
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;
+ };
}
//=======================================================================
//=======================================================================
Standard_Boolean BRepMesh_ModelPostProcessor::performInternal(
const Handle(IMeshData_Model)& theModel,
- const IMeshTools_Parameters& /*theParameters*/)
+ const IMeshTools_Parameters& theParameters)
{
if (theModel.IsNull())
{
}
// 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;
}
Poly_Triangle.cxx
Poly_Triangle.hxx
Poly_Triangle.lxx
+Poly_TriangulationParameters.hxx
+Poly_TriangulationParameters.cxx
Poly_Triangulation.cxx
Poly_Triangulation.hxx
class Poly_Triangulation;
+class Poly_TriangulationParameters;
+
DEFINE_STANDARD_HANDLE(Poly_Triangulation, Standard_Transient)
//! Provides a triangulation for a surface, a set of surfaces, or
//! 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(); }
Poly_Array1OfTriangle myTriangles;
Handle(TShort_HArray1OfShortReal) myNormals;
+ Handle(Poly_TriangulationParameters) myParams;
};
#endif // _Poly_Triangulation_HeaderFile
--- /dev/null
+// 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)
--- /dev/null
+// 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