1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

0025378: Building of triangulation for distored surfaces can take very long using BRepMesh_IncrementalMesh

New parameter MinSize has been introduced to BRepMesh and GCPnts_TangentialDeflection;

Check length of remaining part of curve for min size parameter instead of distance between two points to avoid large gaps in case highly distorted BSpline surfaces;

Produce fine mesh for sphere and fix other surface;

Test cases for issue CR25378

Correction of test cases for issue CR25378
This commit is contained in:
oan
2014-12-11 17:15:42 +03:00
committed by bugmaster
parent 949df2b64b
commit 74da0216d7
31 changed files with 788 additions and 243 deletions

View File

@@ -105,6 +105,12 @@ public:
return myMeshData->GetElement (theIndex);
}
//! Returns tool used to build mesh consistent to Delaunay criteria.
inline const BRepMesh_CircleTool& Circles() const
{
return myCircles;
}
//! Test is the given triangle contains the given vertex.
//! If theEdgeOn != 0 the vertex lies onto the edge index
//! returned through this parameter.

View File

@@ -43,7 +43,8 @@ BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator(
const Handle(BRepMesh_FaceAttribute)& theFaceAttribute,
const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces,
const Standard_Real theLinDeflection,
const Standard_Real theAngDeflection)
const Standard_Real theAngDeflection,
const Standard_Real theMinSize)
: mySurface(theFaceAttribute->Surface())
{
Standard_Real aPreciseAngDef = 0.5 * theAngDeflection;
@@ -52,6 +53,7 @@ BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator(
aPreciseLinDef *= 0.5;
mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef;
mySquareMinSize = Max(mySquareEdgeDef, theMinSize * theMinSize);
Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge);
if (isSameParam)
@@ -67,7 +69,7 @@ BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator(
Standard_Real aFirstParam, aLastParam;
BRep_Tool::Range(theEdge, theFaceAttribute->Face(), aFirstParam, aLastParam);
myTool = new BRepMesh_GeomTool(myCOnS, aFirstParam, aLastParam,
aPreciseLinDef, aPreciseAngDef, aMinPntNb);
aPreciseLinDef, aPreciseAngDef, aMinPntNb, theMinSize);
if (aCurveType == GeomAbs_BSplineCurve)
{
@@ -83,7 +85,7 @@ BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator(
const Standard_Real& anEndInt = anIntervals.Value( aIntIt + 1 );
BRepMesh_GeomTool aDetalizator(myCOnS, aStartInt, anEndInt,
aPreciseLinDef, aPreciseAngDef, aMinPntNb);
aPreciseLinDef, aPreciseAngDef, aMinPntNb, theMinSize);
Standard_Integer aNbAddNodes = aDetalizator.NbPoints();
for ( Standard_Integer aNodeIt = 1; aNodeIt <= aNbAddNodes; ++aNodeIt )
@@ -191,16 +193,19 @@ void BRepMesh_EdgeTessellator::splitSegment(
P3dF = theSurf->Value(uvf.X(), uvf.Y());
P3dL = theSurf->Value(uvl.X(), uvl.Y());
if(P3dF.SquareDistance(P3dL) < mySquareEdgeDef)
if(P3dF.SquareDistance(P3dL) < mySquareMinSize)
return;
uvm = gp_Pnt2d((uvf.XY() + uvl.XY())*0.5);
midP3dFromSurf = theSurf->Value(uvm.X(), uvm.Y());
gp_XYZ Vec1 = midP3dFromSurf.XYZ() - P3dF.XYZ();
if(Vec1.SquareModulus() < mySquareMinSize)
return;
gp_XYZ aVec = P3dL.XYZ() - P3dF.XYZ();
aVec.Normalize();
gp_XYZ Vec1 = midP3dFromSurf.XYZ() - P3dF.XYZ();
Standard_Real aModulus = Vec1.Dot(aVec);
gp_XYZ aProj = aVec * aModulus;
gp_XYZ aDist = Vec1 - aProj;

View File

@@ -47,7 +47,8 @@ public:
const Handle(BRepMesh_FaceAttribute)& theFaceAttribute,
const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces,
const Standard_Real theLinDeflection,
const Standard_Real theAngDeflection);
const Standard_Real theAngDeflection,
const Standard_Real theMinSize);
//! Returns number of dicretization points.
virtual Standard_Integer NbPoints() const
@@ -81,6 +82,7 @@ private:
Handle(BRepAdaptor_HSurface) mySurface;
BRepAdaptor_Curve myCOnS;
Standard_Real mySquareEdgeDef;
Standard_Real mySquareMinSize;
};
DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool)

View File

@@ -86,15 +86,16 @@ IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscret, Standard_Transient)
//purpose :
//=======================================================================
BRepMesh_FastDiscret::BRepMesh_FastDiscret(
const Standard_Real theDefle,
const Standard_Real theAngl,
const Bnd_Box& theBox,
const Standard_Boolean theWithShare,
const Standard_Boolean theInshape,
const Standard_Boolean theRelative,
const Standard_Boolean theShapetrigu,
const Standard_Boolean isInParallel,
const Standard_Boolean isInternalVerticesMode)
const Standard_Real theDefle,
const Standard_Real theAngl,
const Bnd_Box& theBox,
const Standard_Boolean theWithShare,
const Standard_Boolean theInshape,
const Standard_Boolean theRelative,
const Standard_Boolean theShapetrigu,
const Standard_Boolean isInParallel,
const Standard_Real theMinSize,
const Standard_Boolean isInternalVerticesMode)
: myAngle (theAngl),
myDeflection (theDefle),
myWithShare (theWithShare),
@@ -104,6 +105,7 @@ BRepMesh_FastDiscret::BRepMesh_FastDiscret(
myInshape (theInshape),
myBoundaryVertices(new BRepMesh::DMapOfVertexInteger),
myBoundaryPoints(new BRepMesh::DMapOfIntegerPnt),
myMinSize(theMinSize),
myInternalVerticesMode(isInternalVerticesMode)
{
if ( myRelative )
@@ -124,6 +126,7 @@ BRepMesh_FastDiscret::BRepMesh_FastDiscret(
const Standard_Boolean theRelative,
const Standard_Boolean theShapetrigu,
const Standard_Boolean isInParallel,
const Standard_Real theMinSize,
const Standard_Boolean isInternalVerticesMode)
: myAngle (theAngl),
myDeflection (theDefle),
@@ -134,6 +137,7 @@ BRepMesh_FastDiscret::BRepMesh_FastDiscret(
myInshape (theInshape),
myBoundaryVertices(new BRepMesh::DMapOfVertexInteger),
myBoundaryPoints(new BRepMesh::DMapOfIntegerPnt),
myMinSize(theMinSize),
myInternalVerticesMode(isInternalVerticesMode)
{
if ( myRelative )
@@ -198,7 +202,7 @@ void BRepMesh_FastDiscret::Process(const TopoDS_Face& theFace) const
{
OCC_CATCH_SIGNALS
BRepMesh_FastDiscretFace aTool(GetAngle(), myInternalVerticesMode);
BRepMesh_FastDiscretFace aTool(GetAngle(), myMinSize, myInternalVerticesMode);
aTool.Perform(anAttribute);
}
catch (Standard_Failure)
@@ -868,7 +872,7 @@ void BRepMesh_FastDiscret::update(
if (aEdgeTool.IsNull())
{
aEdgeTool = new BRepMesh_EdgeTessellator(theEdge, myAttribute,
mySharedFaces, theDefEdge, myAngle);
mySharedFaces, theDefEdge, myAngle, myMinSize);
}
Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl;

View File

@@ -58,16 +58,16 @@ class BRepMesh_FastDiscret : public Standard_Transient
{
public:
Standard_EXPORT BRepMesh_FastDiscret(
const Standard_Real defle,
const Standard_Real angle,
const Bnd_Box& B,
const Standard_Boolean withShare = Standard_True,
const Standard_Boolean inshape = Standard_False,
const Standard_Boolean relative = Standard_False,
const Standard_Boolean shapetrigu = Standard_False,
const Standard_Boolean isInParallel = Standard_False,
const Standard_Boolean isInternalVerticesMode = Standard_True);
Standard_EXPORT BRepMesh_FastDiscret(const Standard_Real defle,
const Standard_Real angle,
const Bnd_Box& B,
const Standard_Boolean withShare = Standard_True,
const Standard_Boolean inshape = Standard_False,
const Standard_Boolean relative = Standard_False,
const Standard_Boolean shapetrigu = Standard_False,
const Standard_Boolean isInParallel = Standard_False,
const Standard_Real theMinSize = Precision::Confusion(),
const Standard_Boolean isInternalVerticesMode = Standard_True);
//! if the boolean <relative> is True, the <br>
//! deflection used for the polygonalisation of <br>
@@ -81,17 +81,17 @@ public:
//! <br>
//! if <inshape> is True, the calculated <br>
//! triangulation will be stored in the shape. <br>
Standard_EXPORT BRepMesh_FastDiscret(
const TopoDS_Shape& shape,
const Standard_Real defle,
const Standard_Real angle,
const Bnd_Box& B,
const Standard_Boolean withShare = Standard_True,
const Standard_Boolean inshape = Standard_False,
const Standard_Boolean relative = Standard_False,
const Standard_Boolean shapetrigu = Standard_False,
const Standard_Boolean isInParallel = Standard_False,
const Standard_Boolean isInternalVerticesMode = Standard_True);
Standard_EXPORT BRepMesh_FastDiscret(const TopoDS_Shape& shape,
const Standard_Real defle,
const Standard_Real angle,
const Bnd_Box& B,
const Standard_Boolean withShare = Standard_True,
const Standard_Boolean inshape = Standard_False,
const Standard_Boolean relative = Standard_False,
const Standard_Boolean shapetrigu = Standard_False,
const Standard_Boolean isInParallel = Standard_False,
const Standard_Real theMinSize = Precision::Confusion(),
const Standard_Boolean isInternalVerticesMode = Standard_True);
//! Build triangulation on the whole shape.
Standard_EXPORT void Perform(const TopoDS_Shape& shape);
@@ -366,6 +366,8 @@ private:
// Fast access to attributes of current face
Handle(BRepMesh_FaceAttribute) myAttribute;
TopTools_IndexedDataMapOfShapeListOfShape mySharedFaces;
Standard_Real myMinSize;
Standard_Boolean myInternalVerticesMode;
};

View File

@@ -33,6 +33,7 @@
#include <Geom_Surface.hxx>
#include <Geom_BSplineSurface.hxx>
#include <GCPnts_TangentialDeflection.hxx>
#include <GCPnts_AbscissaPoint.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
@@ -143,12 +144,12 @@ namespace
//=======================================================================
BRepMesh_FastDiscretFace::BRepMesh_FastDiscretFace(
const Standard_Real theAngle,
const Standard_Real theMinSize,
const Standard_Boolean isInternalVerticesMode)
: myAngle(theAngle),
myInternalVerticesMode(isInternalVerticesMode)
myInternalVerticesMode(isInternalVerticesMode),
myMinSize(theMinSize)
{
myAllocator = new NCollection_IncAllocator(
BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
}
//=======================================================================
@@ -175,7 +176,9 @@ void BRepMesh_FastDiscretFace::initDataStructure()
const Standard_Real deltaX = myAttribute->GetDeltaX();
const Standard_Real deltaY = myAttribute->GetDeltaY();
myStructure = new BRepMesh_DataStructureOfDelaun(myAllocator);
Handle(NCollection_IncAllocator) aAllocator =
new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
myStructure = new BRepMesh_DataStructureOfDelaun(aAllocator);
myStructure->Data()->SetCellSize ( uCellSize / deltaX, vCellSize / deltaY);
myStructure->Data()->SetTolerance( aTolU / deltaX, aTolV / deltaY);
@@ -367,25 +370,19 @@ void BRepMesh_FastDiscretFace::add(const Handle(BRepMesh_FaceAttribute)& theAttr
if ( !isaline && myStructure->ElementsOfDomain().Extent() > 0 )
{
BRepMesh::ListOfVertex aNewVertices;
if ( !rajout )
if (!rajout)
{
aDef = control(aNewVertices, trigu, Standard_True);
if( aDef > myAttribute->GetDefFace() || aDef < 0.)
rajout = Standard_True;
rajout = (aDef > myAttribute->GetDefFace() || aDef < 0.);
}
if ( !rajout && useUVParam )
if (!rajout && useUVParam)
{
if ( myVParam.Extent() > 2 &&
(gFace->IsUClosed() ||
gFace->IsVClosed()))
{
rajout = Standard_True;
}
rajout = (myVParam.Extent() > 2 &&
(gFace->IsUClosed() || gFace->IsVClosed()));
}
if ( rajout )
if (rajout)
{
insertInternalVertices(aNewVertices, trigu);
@@ -572,42 +569,38 @@ void BRepMesh_FastDiscretFace::insertInternalVertices(
void BRepMesh_FastDiscretFace::insertInternalVerticesSphere(
BRepMesh::ListOfVertex& theNewVertices)
{
const Standard_Real umax = myAttribute->GetUMax();
const Standard_Real umin = myAttribute->GetUMin();
const Standard_Real vmax = myAttribute->GetVMax();
const Standard_Real vmin = myAttribute->GetVMin();
Standard_Real aRange[] = {
myAttribute->GetVMin(), myAttribute->GetVMax(),
myAttribute->GetUMin(), myAttribute->GetUMax()
};
gp_Sphere S = myAttribute->Surface()->Sphere();
const Standard_Real R = S.Radius();
gp_Sphere aSphere = myAttribute->Surface()->Sphere();
// Calculate parameters for iteration in V direction
Standard_Real Dv = 1.0 - (myAttribute->GetDefFace() / R);
if (Dv < 0.0) Dv = 0.0;
Standard_Real oldDv = 2.0 * ACos(Dv);
Dv = .7 * oldDv; //.7 ~= sqrt(2.) - Dv is hypotenuse of triangle when oldDv is legs
const Standard_Real sv = vmax - vmin;
Dv = sv / ((Standard_Integer)(sv / Dv) + 1);
const Standard_Real pasvmax = vmax - Dv*0.5;
Standard_Real aStep = 0.7 * GCPnts_TangentialDeflection::ArcAngularStep(
aSphere.Radius(), myAttribute->GetDefFace(), myAngle, myMinSize);
//Du can be defined from relation: 2*r*Sin(Du/2) = 2*R*Sin(Dv/2), r = R*Cos(v)
//here approximate relation r*Du = R*Dv is used
Standard_Real Du, pasu, pasv; //, ru;
const Standard_Real su = umax - umin;
Standard_Boolean Shift = Standard_False;
for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv)
Standard_Real aDd[2] = {aStep, aStep};
Standard_Real aPasMax[2] = {0., 0.};
for (Standard_Integer i = 0; i < 2; ++i)
{
const Standard_Real aMax = aRange[2 * i + 1];
const Standard_Real aDiff = aMax - aRange[2 * i + 0];
aDd[i] = aDiff / ((Standard_Integer)(aDiff / aDd[i]) + 1);
aPasMax[i] = aMax - Precision::PConfusion();
}
const Standard_Real aHalfDu = aDd[1] * 0.5;
Standard_Boolean Shift = Standard_False;
Standard_Real aPasV = aRange[0] + aDd[0];
for (; aPasV < aPasMax[0]; aPasV += aDd[0])
{
// Calculate parameters for iteration in U direction
// 1.-.365*pasv*pasv is simple approximation of Cos(pasv)
// with condition that it gives ~.1 when pasv = pi/2
Du = Dv / (1. - .365*pasv*pasv);
Du = su / ((Standard_Integer)(su / Du) + 1);
Shift = !Shift;
const Standard_Real d = (Shift) ? Du*.5 : 0.;
const Standard_Real pasumax = umax - Du*0.5 + d;
for (pasu = umin + Du - d; pasu < pasumax; pasu += Du)
const Standard_Real d = (Shift) ? aHalfDu : 0.;
Standard_Real aPasU = aRange[2] + d;
for (; aPasU < aPasMax[1]; aPasU += aDd[1])
{
tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), S, theNewVertices);
tryToInsertAnalyticVertex(gp_Pnt2d(aPasU, aPasV), aSphere, theNewVertices);
}
}
}
@@ -624,21 +617,20 @@ void BRepMesh_FastDiscretFace::insertInternalVerticesCylinder(
const Standard_Real vmax = myAttribute->GetVMax();
const Standard_Real vmin = myAttribute->GetVMin();
gp_Cylinder S = myAttribute->Surface()->Cylinder();
const Standard_Real R = S.Radius();
gp_Cylinder aCylinder = myAttribute->Surface()->Cylinder();
const Standard_Real aRadius = aCylinder.Radius();
// Calculate parameters for iteration in U direction
Standard_Real Du = 1.0 - (myAttribute->GetDefFace() / R);
if (Du < 0.0) Du = 0.0;
Du = 2.0 * ACos(Du);
if (Du > myAngle) Du = myAngle;
Standard_Real Du = GCPnts_TangentialDeflection::ArcAngularStep(
aRadius, myAttribute->GetDefFace(), myAngle, myMinSize);
const Standard_Real su = umax - umin;
const Standard_Integer nbU = (Standard_Integer)(su / Du);
Du = su / (nbU + 1);
// Calculate parameters for iteration in V direction
const Standard_Real sv = vmax - vmin;
Standard_Integer nbV = (Standard_Integer)(nbU*sv / (su*R));
Standard_Integer nbV = (Standard_Integer)(nbU*sv / (su*aRadius));
nbV = Min(nbV, 100 * nbU);
Standard_Real Dv = sv / (nbV + 1);
@@ -647,7 +639,7 @@ void BRepMesh_FastDiscretFace::insertInternalVerticesCylinder(
{
for (pasu = umin + Du; pasu < pasumax; pasu += Du)
{
tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), S, theNewVertices);
tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), aCylinder, theNewVertices);
}
}
}
@@ -664,16 +656,17 @@ void BRepMesh_FastDiscretFace::insertInternalVerticesCone(
const Standard_Real vmax = myAttribute->GetVMax();
const Standard_Real vmin = myAttribute->GetVMin();
Standard_Real R, RefR, SAng;
gp_Cone C = myAttribute->Surface()->Cone();
RefR = C.RefRadius();
SAng = C.SemiAngle();
R = Max(Abs(RefR + vmin*Sin(SAng)), Abs(RefR + vmax*Sin(SAng)));
Standard_Real Du, Dv, pasu, pasv;
Du = Max(1.0e0 - (myAttribute->GetDefFace() / R), 0.0e0);
Du = (2.0 * ACos(Du));
gp_Cone aCone = myAttribute->Surface()->Cone();
Standard_Real RefR = aCone.RefRadius();
Standard_Real SAng = aCone.SemiAngle();
Standard_Real aRadius = Max(Abs(RefR + vmin*Sin(SAng)), Abs(RefR + vmax*Sin(SAng)));
Standard_Real Du = GCPnts_TangentialDeflection::ArcAngularStep(
aRadius, myAttribute->GetDefFace(), myAngle, myMinSize);
Standard_Real Dv, pasu, pasv;
Standard_Integer nbU = (Standard_Integer)((umax - umin) / Du);
Standard_Integer nbV = (Standard_Integer)(nbU*(vmax - vmin) / ((umax - umin)*R));
Standard_Integer nbV = (Standard_Integer)(nbU*(vmax - vmin) / ((umax - umin)*aRadius));
Du = (umax - umin) / (nbU + 1);
Dv = (vmax - vmin) / (nbV + 1);
@@ -682,7 +675,7 @@ void BRepMesh_FastDiscretFace::insertInternalVerticesCone(
{
for (pasu = umin + Du; pasu < pasumax; pasu += Du)
{
tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), C, theNewVertices);
tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), aCone, theNewVertices);
}
}
}
@@ -711,20 +704,21 @@ void BRepMesh_FastDiscretFace::insertInternalVerticesTorus(
BRepMesh::SequenceOfReal ParamU, ParamV;
Standard_Real Du, Dv;//, pasu, pasv;
Dv = Max(1.0e0 - (aDefFace / r), 0.0e0);
Standard_Real oldDv = 2.0 * ACos(Dv);
oldDv = Min(oldDv, myAngle);
Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
Standard_Real oldDv = GCPnts_TangentialDeflection::ArcAngularStep(
r, aDefFace, myAngle, myMinSize);
Standard_Real Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
Dv = oldDv;
Standard_Real Du;
Standard_Integer nbV = Max((Standard_Integer)((vmax - vmin) / Dv), 2);
Dv = (vmax - vmin) / (nbV + 1);
Standard_Real ru = R + r;
if (ru > 1.e-16)
{
Du = 2.0 * ACos(Max(1.0 - (aDefFace / ru), 0.0));
if (myAngle < Du) Du = myAngle;
Du = GCPnts_TangentialDeflection::ArcAngularStep(
ru, aDefFace, myAngle, myMinSize);
Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
if (aa < gp::Resolution())
return;
@@ -854,9 +848,12 @@ void BRepMesh_FastDiscretFace::insertInternalVerticesBSpline(
if (aDelta[i] < 1.)
aMinDiff /= aDelta[i];
aMinDiff = Max(myMinSize, aMinDiff);
Standard_Real aRangeDiff = aRange[i][0] - aRange[i][1];
Standard_Real aDiffMaxLim = 0.1 * aRangeDiff;
Standard_Real aDiff = Min(aDiffMaxLim, Max(0.005 * aRangeDiff, 2. * aRes));
Standard_Real aDiffMinLim = Max(0.005 * aRangeDiff, 2. * aRes);
Standard_Real aDiff = Max(myMinSize, Min(aDiffMaxLim, aDiffMinLim));
filterParameters(isU ? myUParam : myVParam, aMinDiff, aDiff, aParams[i]);
}
@@ -893,17 +890,17 @@ void BRepMesh_FastDiscretFace::insertInternalVerticesBSpline(
for (Standard_Integer i = aStartIndex; i <= aEndIndex; ++i)
{
const Standard_Real aParam1 = aParams1(i);
Handle(Geom_Curve) aIso = isU ?
aBSpline->UIso(aParam1) : aBSpline->VIso(aParam1);
GeomAdaptor_Curve aIso(isU ?
aBSpline->UIso(aParam1) : aBSpline->VIso(aParam1));
Standard_Real aPrevParam2 = aParams2(1);
gp_Pnt aPrevPnt2 = aIso->Value(aPrevParam2);
gp_Pnt aPrevPnt2 = aIso.Value(aPrevParam2);
for (Standard_Integer j = 2; j <= aParams2.Length();)
{
Standard_Real aParam2 = aParams2(j);
gp_Pnt aPnt2 = aIso->Value(aParam2);
gp_Pnt aPnt2 = aIso.Value(aParam2);
Standard_Real aMidParam = 0.5 * (aPrevParam2 + aParam2);
gp_Pnt aMidPnt = aIso->Value(aMidParam);
gp_Pnt aMidPnt = aIso.Value(aMidParam);
// 23.03.2010 skl for OCC21645 - change precision for comparison
Standard_Real aDist;
@@ -915,7 +912,7 @@ void BRepMesh_FastDiscretFace::insertInternalVerticesBSpline(
else
aDist = aPrevPnt2.Distance(aMidPnt);
if (aDist > aDefFace)
if (aDist > aDefFace && aDist > myMinSize)
{
// insertion
aParams2.InsertBefore(j, aMidParam);
@@ -942,15 +939,25 @@ void BRepMesh_FastDiscretFace::insertInternalVerticesBSpline(
Standard_Real aAngle = N2.Angle(N1);
if (aSt1 < 1 && aSt2 < 1 && aAngle > myAngle)
{
// insertion
aParams2.InsertBefore(j, aMidParam);
Standard_Real aLen = GCPnts_AbscissaPoint::Length(aIso,
aPrevParam2, aMidParam, aDefFace);
if (aLen > myMinSize)
{
// insertion
aParams2.InsertBefore(j, aMidParam);
continue;
}
}
else
aPrevParam2 = aParam2;
aPrevPnt2 = aPnt2;
if (!isU && j < aParams2.Length())
{
aPrevParam2 = aParam2;
aPrevPnt2 = aPnt2;
++j;
}
// Update point parameter.
aStPnt1.SetX(aPrevParam2);
++j;
}
}
}
@@ -982,7 +989,7 @@ void BRepMesh_FastDiscretFace::insertInternalVerticesBSpline(
void BRepMesh_FastDiscretFace::insertInternalVerticesOther(
BRepMesh::ListOfVertex& theNewVertices)
{
const Standard_Real aAngle = 0.35;
const Standard_Real aAngle = myAngle;//0.35;
const Standard_Real aRange[2][2] = {
{ myAttribute->GetUMax(), myAttribute->GetUMin() },
{ myAttribute->GetVMax(), myAttribute->GetVMin() }
@@ -1015,7 +1022,7 @@ void BRepMesh_FastDiscretFace::insertInternalVerticesOther(
Standard_Real aLastParam = Min(aRange2[0], aIso.LastParameter());
aDiscretIso[aIsoIt].Initialize(aIso, aFirstParam, aLastParam,
aAngle, 0.7 * aDefFace, 2);
aAngle, 0.7 * aDefFace, 2, Precision::PConfusion(), myMinSize);
const Standard_Integer aPointsNb = aDiscretIso[aIsoIt].NbPoints();
if (aPointsNb > aMaxPointsNb)
@@ -1056,6 +1063,68 @@ void BRepMesh_FastDiscretFace::insertInternalVerticesOther(
}
}
//=======================================================================
//function : checkDeflectionAndInsert
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_FastDiscretFace::checkDeflectionAndInsert(
const gp_Pnt& thePnt3d,
const gp_XY& theUV,
const Standard_Boolean isDeflectionCheckOnly,
const Standard_Real theTriangleDeflection,
const Standard_Real theFaceDeflection,
const BRepMesh_CircleTool& theCircleTool,
BRepMesh::ListOfVertex& theVertices,
Standard_Real& theMaxTriangleDeflection)
{
if (theTriangleDeflection > theMaxTriangleDeflection)
theMaxTriangleDeflection = theTriangleDeflection;
if (theTriangleDeflection < theFaceDeflection)
return Standard_True;
if (myMinSize > Precision::Confusion())
{
// Iterator in the list of indexes of circles containing the node
BRepMesh::ListOfInteger& aCirclesList =
const_cast<BRepMesh_CircleTool&>(theCircleTool).Select(
myAttribute->Scale(theUV, Standard_True));
Handle(NCollection_IncAllocator) aAllocator =
new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
BRepMesh::MapOfInteger aUsedNodes(10, aAllocator);
BRepMesh::ListOfInteger::Iterator aCircleIt(aCirclesList);
for (; aCircleIt.More(); aCircleIt.Next())
{
const BRepMesh_Triangle& aTriangle =
myStructure->GetElement(aCircleIt.Value());
Standard_Integer aNodes[3];
myStructure->ElementNodes(aTriangle, aNodes);
for (Standard_Integer i = 0; i < 3; ++i)
{
const Standard_Integer aNodeId = aNodes[i];
if (aUsedNodes.Contains(aNodeId))
continue;
aUsedNodes.Add(aNodeId);
const BRepMesh_Vertex& aNode = myStructure->GetNode(aNodeId);
const gp_Pnt& aPoint = myAttribute->GetPoint(aNode);
if (thePnt3d.SquareDistance(aPoint) < myMinSize * myMinSize)
return Standard_True;
}
}
}
if (isDeflectionCheckOnly)
return Standard_False;
insertVertex(thePnt3d, theUV, theVertices);
return Standard_True;
}
//=======================================================================
//function : control
//purpose :
@@ -1064,19 +1133,6 @@ Standard_Real BRepMesh_FastDiscretFace::control(
BRepMesh::ListOfVertex& theNewVertices,
BRepMesh_Delaun& theTrigu,
const Standard_Boolean theIsFirst)
#define CHECK_DEF_AND_INSERT_CURRENT(isSkipped) \
if (aSqDef > aMaxSqDef) \
aMaxSqDef = aSqDef; \
\
(isSkipped) = Standard_False; \
if (aSqDef > aSqDefFace) \
{ \
(isSkipped) = theIsFirst; \
if (!(isSkipped)) \
insertVertex(pDef, mi2d, theNewVertices); \
} \
{
Standard_Integer aTrianglesNb = myStructure->ElementsOfDomain().Extent();
if (aTrianglesNb < 1)
@@ -1099,6 +1155,7 @@ if (aSqDef > aSqDefFace) \
NCollection_DataMap<Standard_Integer, gp_Dir> aNorMap;
BRepMesh::MapOfIntegerInteger aStatMap;
NCollection_Map<BRepMesh_OrientedEdge> aCouples(3 * aTrianglesNb);
const BRepMesh_CircleTool& aCircles = theTrigu.Circles();
// Perform refinement passes
// Define the number of iterations
@@ -1185,7 +1242,9 @@ if (aSqDef > aSqDefFace) \
aSqDef = Abs(normal * (pDef.XYZ() - p[0]));
aSqDef *= aSqDef;
CHECK_DEF_AND_INSERT_CURRENT(isSkipped);
isSkipped = !checkDeflectionAndInsert(pDef, mi2d, theIsFirst,
aSqDef, aSqDefFace, aCircles, theNewVertices, aMaxSqDef);
if (isSkipped)
break;
}
@@ -1221,7 +1280,8 @@ if (aSqDef > aSqDefFace) \
gp_Lin aLin(p[i], gp_Vec(p[i], p[j]));
aSqDef = aLin.SquareDistance(pDef);
CHECK_DEF_AND_INSERT_CURRENT(isSkipped);
isSkipped = !checkDeflectionAndInsert(pDef, mi2d, theIsFirst,
aSqDef, aSqDefFace, aCircles, theNewVertices, aMaxSqDef);
}
}

View File

@@ -56,6 +56,7 @@ public:
//! vertices mode.
Standard_EXPORT BRepMesh_FastDiscretFace(
const Standard_Real theAngle,
const Standard_Real theMinSize,
const Standard_Boolean isInternalVerticesMode);
Standard_EXPORT void Perform(const Handle(BRepMesh_FaceAttribute)& theAttribute);
@@ -152,6 +153,32 @@ private:
const Standard_Integer theLastNodeId,
const TopAbs_Orientation theOrientation);
//! Inserts new node into a mesh in case if smoothed region build
//! using the given node has better deflection metrics than source state.
//! @param thePnt3d 3d point corresponded to the vertex.
//! @param theUV UV point corresponded to the vertex.
//! @param isDeflectionCheckOnly if TRUE new node will not be added to a mesh
//! even if deflection parameter is better.
//! @param theTriangleDeflection deflection of a triangle from real geometry.
//! @param theFaceDeflection deflection to be achieved.
//! @param theCircleTool tool used for fast extraction of triangles
//! touched by the given point.
//! @param[out] theVertices list of vertices to be updated.
//! @param[in out] theMaxTriangleDeflection maximal deflection of a mesh.
//! @return TRUE in case if the given deflection of triangle is fine and
//! there is no necessity to insert new node or new node was being inserted
//! successfully, FALSE in case if new configuration is better but
//! isDeflectionCheckOnly flag is set.
Standard_Boolean checkDeflectionAndInsert(
const gp_Pnt& thePnt3d,
const gp_XY& theUV,
const Standard_Boolean isDeflectionCheckOnly,
const Standard_Real theTriangleDeflection,
const Standard_Real theFaceDeflection,
const BRepMesh_CircleTool& theCircleTool,
BRepMesh::ListOfVertex& theVertices,
Standard_Real& theMaxTriangleDeflection);
private:
Standard_Real myAngle;
@@ -160,9 +187,10 @@ private:
BRepMesh::IMapOfReal myVParam;
// Fast access to attributes of current face
Handle(NCollection_IncAllocator) myAllocator;
Handle(BRepMesh_FaceAttribute) myAttribute;
Handle(BRepMesh_DataStructureOfDelaun) myStructure;
Standard_Real myMinSize;
};
DEFINE_STANDARD_HANDLE (BRepMesh_FastDiscretFace, Standard_Transient)

View File

@@ -35,12 +35,14 @@ BRepMesh_GeomTool::BRepMesh_GeomTool(
const Standard_Real theLastParam,
const Standard_Real theLinDeflection,
const Standard_Real theAngDeflection,
const Standard_Integer theMinPointsNb)
const Standard_Integer theMinPointsNb,
const Standard_Real theMinSize)
: myEdge(&theCurve.Edge()),
myIsoType(GeomAbs_NoneIso)
{
myDiscretTool.Initialize(theCurve, theFirstParam, theLastParam,
theAngDeflection, theLinDeflection, theMinPointsNb);
theAngDeflection, theLinDeflection, theMinPointsNb,
Precision::PConfusion(), theMinSize);
}
//=======================================================================
@@ -55,7 +57,8 @@ BRepMesh_GeomTool::BRepMesh_GeomTool(
const Standard_Real theLastParam,
const Standard_Real theLinDeflection,
const Standard_Real theAngDeflection,
const Standard_Integer theMinPointsNb)
const Standard_Integer theMinPointsNb,
const Standard_Real theMinSize)
: myEdge(NULL),
myIsoType(theIsoType)
{
@@ -63,7 +66,8 @@ BRepMesh_GeomTool::BRepMesh_GeomTool(
theFirstParam, theLastParam);
myDiscretTool.Initialize(aIso, theFirstParam, theLastParam,
theAngDeflection, theLinDeflection, theMinPointsNb);
theAngDeflection, theLinDeflection, theMinPointsNb,
Precision::PConfusion(), theMinSize);
}
//=======================================================================

View File

@@ -21,6 +21,7 @@
#include <GeomAbs_IsoType.hxx>
#include <Handle_BRepAdaptor_HSurface.hxx>
#include <TopoDS_Edge.hxx>
#include <Precision.hxx>
class BRepAdaptor_Curve;
class BRepAdaptor_HSurface;
@@ -65,7 +66,8 @@ public:
const Standard_Real theLastParam,
const Standard_Real theLinDeflection,
const Standard_Real theAngDeflection,
const Standard_Integer theMinPointsNb = 2);
const Standard_Integer theMinPointsNb = 2,
const Standard_Real theMinSize = Precision::Confusion());
//! Constructor.
//! Initiates discretization of geometric curve corresponding
@@ -85,7 +87,8 @@ public:
const Standard_Real theLastParam,
const Standard_Real theLinDeflection,
const Standard_Real theAngDeflection,
const Standard_Integer theMinPointsNb = 2);
const Standard_Integer theMinPointsNb = 2,
const Standard_Real theMinSize = Precision::Confusion());
//! Adds point to already calculated points (or replaces existing).
//! @param thePoint point to be added.

View File

@@ -72,8 +72,9 @@ IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IncrementalMesh, BRepMesh_DiscretRoot)
//purpose :
//=======================================================================
BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh()
: myRelative (Standard_False),
myInParallel (Standard_False),
: myRelative (Standard_False),
myInParallel(Standard_False),
myMinSize (Precision::Confusion()),
myInternalVerticesMode(Standard_True)
{
}
@@ -90,6 +91,7 @@ BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh(
const Standard_Boolean isInParallel)
: myRelative (isRelative),
myInParallel(isInParallel),
myMinSize (Precision::Confusion()),
myInternalVerticesMode(Standard_True)
{
myDeflection = theLinDeflection;
@@ -144,9 +146,10 @@ void BRepMesh_IncrementalMesh::init()
BRepMesh_ShapeTool::BoxMaxDimension(aBox, myMaxShapeSize);
myMesh = new BRepMesh_FastDiscret(myDeflection, myAngle, aBox,
Standard_True, Standard_True, myRelative, Standard_True,
myInParallel, myInternalVerticesMode);
myMesh = new BRepMesh_FastDiscret(myDeflection,
myAngle, aBox, Standard_True, Standard_True,
myRelative, Standard_True, myInParallel, myMinSize,
myInternalVerticesMode);
myMesh->InitSharedFaces(myShape);
}
@@ -257,7 +260,7 @@ void BRepMesh_IncrementalMesh::discretizeFreeEdges()
BRepAdaptor_Curve aCurve(aEdge);
GCPnts_TangentialDeflection aDiscret(aCurve, aCurve.FirstParameter(),
aCurve.LastParameter(), myAngle, aEdgeDeflection, 2);
aCurve.LastParameter(), myAngle, aEdgeDeflection, 2, myMinSize);
Standard_Integer aNodesNb = aDiscret.NbPoints();
TColgp_Array1OfPnt aNodes (1, aNodesNb);

View File

@@ -103,6 +103,18 @@ public: //! @name accessing to parameters.
return myInParallel;
}
//! Sets min size parameter.
inline void SetMinSize(const Standard_Real theMinSize)
{
myMinSize = Max(theMinSize, Precision::Confusion());
}
//! Returns min size parameter.
inline Standard_Real GetMinSize() const
{
return myMinSize;
}
//! Enables/disables internal vertices mode.
inline void SetInternalVerticesMode(const Standard_Boolean isEnabled)
{
@@ -205,6 +217,7 @@ protected:
Standard_Real myMaxShapeSize;
Standard_Integer myStatus;
NCollection_Vector<TopoDS_Face> myFaces;
Standard_Real myMinSize;
Standard_Boolean myInternalVerticesMode;
};