myCircles ( theVertices.Length(), theOldMesh->Allocator() )
{
if ( theVertices.Length() > 2 )
+ {
Init( theVertices );
+ }
}
//=======================================================================
: myMeshData( theOldMesh ),
myCircles ( theVertexIndices.Length(), theOldMesh->Allocator() )
{
- if ( theVertexIndices.Length() > 2 )
- {
- Bnd_Box2d aBox;
- Standard_Integer anIndex = theVertexIndices.Lower();
- Standard_Integer anUpper = theVertexIndices.Upper();
- for ( ; anIndex <= anUpper; ++anIndex )
- aBox.Add( gp_Pnt2d( GetVertex( theVertexIndices( anIndex) ).Coord() ) );
+ perform( theVertexIndices );
+}
- perform( aBox, theVertexIndices );
- }
+//=======================================================================
+//function : BRepMesh_Delaun
+//purpose : Creates the triangulation with and existent Mesh data structure
+//=======================================================================
+BRepMesh_Delaun::BRepMesh_Delaun (const Handle (BRepMesh_DataStructureOfDelaun)& theOldMesh,
+ BRepMesh::Array1OfInteger& theVertexIndices,
+ const Standard_Integer theCellsCountU,
+ const Standard_Integer theCellsCountV)
+ : myMeshData (theOldMesh),
+ myCircles (theVertexIndices.Length (), theOldMesh->Allocator ())
+{
+ perform (theVertexIndices, theCellsCountU, theCellsCountV);
}
//=======================================================================
//=======================================================================
void BRepMesh_Delaun::Init(BRepMesh::Array1OfVertexOfDelaun& theVertices)
{
- Bnd_Box2d aBox;
Standard_Integer aLowerIdx = theVertices.Lower();
Standard_Integer anUpperIdx = theVertices.Upper();
BRepMesh::Array1OfInteger aVertexIndexes( aLowerIdx, anUpperIdx );
Standard_Integer anIndex = aLowerIdx;
for ( ; anIndex <= anUpperIdx; ++anIndex )
{
- aBox.Add( gp_Pnt2d( theVertices( anIndex ).Coord() ) );
aVertexIndexes( anIndex ) = myMeshData->AddNode( theVertices( anIndex ) );
}
- perform( aBox, aVertexIndexes );
+ perform( aVertexIndexes );
}
//=======================================================================
//function : perform
//purpose : Create super mesh and run triangulation procedure
//=======================================================================
-void BRepMesh_Delaun::perform(Bnd_Box2d& theBndBox,
- BRepMesh::Array1OfInteger& theVertexIndexes)
+void BRepMesh_Delaun::perform (BRepMesh::Array1OfInteger& theVertexIndices,
+ const Standard_Integer theCellsCountU /* = -1 */,
+ const Standard_Integer theCellsCountV /* = -1 */)
{
- theBndBox.Enlarge( Precision );
- superMesh( theBndBox );
+ if (theVertexIndices.Length () <= 2)
+ {
+ return;
+ }
+
+ Bnd_Box2d aBox;
+ Standard_Integer anIndex = theVertexIndices.Lower ();
+ Standard_Integer anUpper = theVertexIndices.Upper ();
+ for (; anIndex <= anUpper; ++anIndex)
+ {
+ aBox.Add (gp_Pnt2d (GetVertex (theVertexIndices (anIndex)).Coord ()));
+ }
+
+ aBox.Enlarge (Precision);
+
+ Standard_Integer aScaler = 2;
+ if ( myMeshData->NbNodes() > 100 )
+ {
+ aScaler = 5;
+ }
+ else if( myMeshData->NbNodes() > 1000 )
+ {
+ aScaler = 7;
+ }
+
+ superMesh (aBox, Max (theCellsCountU, aScaler),
+ Max (theCellsCountV, aScaler));
ComparatorOfIndexedVertexOfDelaun aCmp(myMeshData);
- std::make_heap(theVertexIndexes.begin(), theVertexIndexes.end(), aCmp);
- std::sort_heap(theVertexIndexes.begin(), theVertexIndexes.end(), aCmp);
+ std::make_heap(theVertexIndices.begin(), theVertexIndices.end(), aCmp);
+ std::sort_heap(theVertexIndices.begin(), theVertexIndices.end(), aCmp);
- compute( theVertexIndexes );
+ compute( theVertexIndices );
}
//=======================================================================
//function : superMesh
//purpose : Build the super mesh
//=======================================================================
-void BRepMesh_Delaun::superMesh( const Bnd_Box2d& theBox )
+void BRepMesh_Delaun::superMesh (const Bnd_Box2d& theBox,
+ const Standard_Integer theCellsCountU,
+ const Standard_Integer theCellsCountV)
{
Standard_Real aMinX, aMinY, aMaxX, aMaxY;
theBox.Get( aMinX, aMinY, aMaxX, aMaxY );
Standard_Real aDelta = aDeltaX + aDeltaY;
myCircles.SetMinMaxSize( gp_XY( aMinX, aMinY ), gp_XY( aMaxX, aMaxY ) );
-
- Standard_Integer aScaler = 2;
- if ( myMeshData->NbNodes() > 100 )
- aScaler = 5;
- else if( myMeshData->NbNodes() > 1000 )
- aScaler = 7;
-
- myCircles.SetCellSize( aDeltaX / aScaler,
- aDeltaY / aScaler );
+ myCircles.SetCellSize( aDeltaX / theCellsCountU, aDeltaY / theCellsCountV);
mySupVert[0] = myMeshData->AddNode(
BRepMesh_Vertex( ( aMinX + aMaxX ) / 2, aMaxY + aDeltaMax, BRepMesh_Free ) );
Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
BRepMesh::Array1OfInteger& theVertexIndices);
+ //! Creates the triangulation with an existant Mesh data structure.
+ Standard_EXPORT BRepMesh_Delaun (const Handle (BRepMesh_DataStructureOfDelaun)& theOldMesh,
+ BRepMesh::Array1OfInteger& theVertexIndices,
+ const Standard_Integer theCellsCountU,
+ const Standard_Integer theCellsCountV);
+
//! Initializes the triangulation with an array of vertices.
Standard_EXPORT void Init (BRepMesh::Array1OfVertexOfDelaun& theVertices);
//! that have number of connected elements less or equal 1.
BRepMesh::HMapOfInteger getEdgesByType (const BRepMesh_DegreeOfFreedom theEdgeType) const;
- //! Create super mesh and run triangulation procedure.
- void perform (Bnd_Box2d& theBndBox,
- BRepMesh::Array1OfInteger& theVertexIndices);
+ //! Run triangulation procedure.
+ void perform (BRepMesh::Array1OfInteger& theVertexIndices,
+ const Standard_Integer theCellsCountU = -1,
+ const Standard_Integer theCellsCountV = -1);
//! Build the super mesh.
- void superMesh (const Bnd_Box2d& theBox);
+ void superMesh (const Bnd_Box2d& theBox,
+ const Standard_Integer theCellsCountU,
+ const Standard_Integer theCellsCountV);
//! Computes the triangulation and adds the vertices,
//! edges and triangles to the Mesh data structure.
#include <BRepAdaptor_HSurface.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <Adaptor3d_IsoCurve.hxx>
+#include <Adaptor3d_HCurve.hxx>
#include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
#include <BRep_PointRepresentation.hxx>
private:
const TopoDS_Vertex& myVertex;
};
+
+ void ComputeErrFactors (const Standard_Real theDeflection,
+ const Handle(Adaptor3d_HSurface)& theFace,
+ Standard_Real& theErrFactorU,
+ Standard_Real& theErrFactorV)
+ {
+ theErrFactorU = theDeflection * 10.;
+ theErrFactorV = theDeflection * 10.;
+
+ switch (theFace->GetType ())
+ {
+ case GeomAbs_Cylinder:
+ case GeomAbs_Cone:
+ case GeomAbs_Sphere:
+ case GeomAbs_Torus:
+ break;
+
+ case GeomAbs_SurfaceOfExtrusion:
+ case GeomAbs_SurfaceOfRevolution:
+ {
+ Handle (Adaptor3d_HCurve) aCurve = theFace->BasisCurve ();
+ if (aCurve->GetType () == GeomAbs_BSplineCurve && aCurve->Degree () > 2)
+ {
+ theErrFactorV /= (aCurve->Degree () * aCurve->NbKnots ());
+ }
+ break;
+ }
+ case GeomAbs_BezierSurface:
+ {
+ if (theFace->UDegree () > 2)
+ {
+ theErrFactorU /= (theFace->UDegree ());
+ }
+ if (theFace->VDegree () > 2)
+ {
+ theErrFactorV /= (theFace->VDegree ());
+ }
+ break;
+ }
+ case GeomAbs_BSplineSurface:
+ {
+ if (theFace->UDegree () > 2)
+ {
+ theErrFactorU /= (theFace->UDegree () * theFace->NbUKnots ());
+ }
+ if (theFace->VDegree () > 2)
+ {
+ theErrFactorV /= (theFace->VDegree () * theFace->NbVKnots ());
+ }
+ break;
+ }
+
+ case GeomAbs_Plane:
+ default:
+ theErrFactorU = theErrFactorV = 1.;
+ }
+ }
+
+ void AdjustCellsCounts (const Handle(Adaptor3d_HSurface)& theFace,
+ const Standard_Integer theNbVertices,
+ Standard_Integer& theCellsCountU,
+ Standard_Integer& theCellsCountV)
+ {
+ const GeomAbs_SurfaceType aType = theFace->GetType ();
+ if (aType == GeomAbs_OtherSurface)
+ {
+ // fallback to the default behavior
+ theCellsCountU = theCellsCountV = -1;
+ return;
+ }
+
+ Standard_Real aSqNbVert = theNbVertices;
+ if (aType == GeomAbs_Plane)
+ {
+ theCellsCountU = theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ }
+ else if (aType == GeomAbs_Cylinder || aType == GeomAbs_Cone)
+ {
+ theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ }
+ else if (aType == GeomAbs_SurfaceOfExtrusion || aType == GeomAbs_SurfaceOfRevolution)
+ {
+ Handle (Adaptor3d_HCurve) aCurve = theFace->BasisCurve ();
+ if (aCurve->GetType () == GeomAbs_Line ||
+ (aCurve->GetType () == GeomAbs_BSplineCurve && aCurve->Degree () < 2))
+ {
+ // planar, cylindrical, conical cases
+ if (aType == GeomAbs_SurfaceOfExtrusion)
+ theCellsCountU = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ else
+ theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ }
+ if (aType == GeomAbs_SurfaceOfExtrusion)
+ {
+ // V is always a line
+ theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ }
+ }
+ else if (aType == GeomAbs_BezierSurface || aType == GeomAbs_BSplineSurface)
+ {
+ if (theFace->UDegree () < 2)
+ {
+ theCellsCountU = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ }
+ if (theFace->VDegree () < 2)
+ {
+ theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ }
+ }
+
+ theCellsCountU = Max (theCellsCountU, 2);
+ theCellsCountV = Max (theCellsCountV, 2);
+ }
}
for ( Standard_Integer i = 1; i <= nbVertices; ++i )
tabvert_corr(i) = i;
- BRepMesh_Delaun trigu(myStructure, tabvert_corr);
+ Handle (Adaptor3d_HSurface) aSurface (myAttribute->Surface ());
+ GeomAbs_SurfaceType aType = aSurface->GetType ();
+
+ while (aType == GeomAbs_OffsetSurface)
+ {
+ aSurface = aSurface->BasisSurface ();
+ aType = aSurface->GetType ();
+ }
+
+ // For better meshing performance we try to estimate the acceleration circles grid structure sizes:
+ // For each parametric direction (U, V) we estimate firstly an approximate distance between the future points -
+ // this estimation takes into account the required face deflection and the complexity of the face.
+ // Particularly, the complexity of the faces based on BSpline curves and surfaces requires much more points.
+ // At the same time, for planar faces and linear parts of the arbitrary surfaces usually no intermediate points
+ // are necessary.
+ // The general idea for each parametric direction:
+ // cells_count = 2 ^ log10 ( estimated_points_count )
+ // For linear parametric direction we fall back to the initial vertex count:
+ // cells_count = 2 ^ log10 ( initial_vertex_count )
+
+ Standard_Real anErrFactorU, anErrFactorV;
+ ComputeErrFactors(myAttribute->GetDefFace (), aSurface, anErrFactorU, anErrFactorV);
+
+ Standard_Integer aCellsCountU, aCellsCountV;
+ if (aType == GeomAbs_Torus)
+ {
+ aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
+ (myAttribute->GetUMax() - myAttribute->GetUMin()) / myAttribute->GetDeltaX())));
+ aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
+ (myAttribute->GetVMax() - myAttribute->GetVMin()) / myAttribute->GetDeltaY())));
+ }
+ else if (aType == GeomAbs_Cylinder)
+ {
+ aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
+ (myAttribute->GetUMax() - myAttribute->GetUMin()) / myAttribute->GetDeltaX() /
+ (myAttribute->GetVMax() - myAttribute->GetVMin()))));
+ aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
+ (myAttribute->GetVMax() - myAttribute->GetVMin()) / anErrFactorV)));
+ }
+ else
+ {
+ aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
+ (myAttribute->GetUMax() - myAttribute->GetUMin()) / myAttribute->GetDeltaX() / anErrFactorU)));
+ aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
+ (myAttribute->GetVMax() - myAttribute->GetVMin()) / myAttribute->GetDeltaY() / anErrFactorV)));
+ }
+
+ AdjustCellsCounts(aSurface, nbVertices, aCellsCountU, aCellsCountV);
+
+ BRepMesh_Delaun trigu(myStructure, tabvert_corr, aCellsCountU, aCellsCountV);
//removed all free edges from triangulation
const Standard_Integer nbLinks = myStructure->NbLinks();
}
}
- const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
- GeomAbs_SurfaceType thetype = gFace->GetType();
-
Standard_Boolean rajout =
- (thetype == GeomAbs_Sphere || thetype == GeomAbs_Torus);
+ (aType == GeomAbs_Sphere || aType == GeomAbs_Torus);
// Check the necessity to fill the map of parameters
- const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus ||
- thetype == GeomAbs_BezierSurface ||
- thetype == GeomAbs_BSplineSurface);
+ const Standard_Boolean useUVParam = (aType == GeomAbs_Torus ||
+ aType == GeomAbs_BezierSurface ||
+ aType == GeomAbs_BSplineSurface);
const Standard_Real umax = myAttribute->GetUMax();
const Standard_Real umin = myAttribute->GetUMin();
aDef = control(trigu, Standard_True);
rajout = (aDef > myAttribute->GetDefFace() || aDef < 0.);
}
- if (thetype != GeomAbs_Plane)
+ if (aType != GeomAbs_Plane)
{
if (!rajout && useUVParam)
{
rajout = (myVParam.Extent() > 2 &&
- (gFace->IsUClosed() || gFace->IsVClosed()));
+ (aSurface->IsUClosed() || aSurface->IsVClosed()));
}
if (rajout)