//=======================================================================
Approx_ComputeCLine::Approx_ComputeCLine
- (const MultiLine& Line,
- const Standard_Integer degreemin,
- const Standard_Integer degreemax,
- const Standard_Real Tolerance3d,
- const Standard_Real Tolerance2d,
- const Standard_Boolean cutting,
- const AppParCurves_Constraint FirstC,
- const AppParCurves_Constraint LastC)
+(const MultiLine& Line,
+const Standard_Integer degreemin,
+const Standard_Integer degreemax,
+const Standard_Real Tolerance3d,
+const Standard_Real Tolerance2d,
+const Standard_Boolean cutting,
+const AppParCurves_Constraint FirstC,
+const AppParCurves_Constraint LastC)
{
mydegremin = degreemin;
mydegremax = degreemax;
//=======================================================================
Approx_ComputeCLine::Approx_ComputeCLine
- (const Standard_Integer degreemin,
- const Standard_Integer degreemax,
- const Standard_Real Tolerance3d,
- const Standard_Real Tolerance2d,
- const Standard_Boolean cutting,
- const AppParCurves_Constraint FirstC,
- const AppParCurves_Constraint LastC)
+(const Standard_Integer degreemin,
+const Standard_Integer degreemax,
+const Standard_Real Tolerance3d,
+const Standard_Real Tolerance2d,
+const Standard_Boolean cutting,
+const AppParCurves_Constraint FirstC,
+const AppParCurves_Constraint LastC)
{
alldone = Standard_False;
mydegremin = degreemin;
void Approx_ComputeCLine::Perform(const MultiLine& Line)
{
Standard_Real UFirst, ULast;
- Standard_Boolean Finish = Standard_False,
- begin = Standard_True, Ok = Standard_False;
+ Standard_Boolean Finish = Standard_False,
+ begin = Standard_True, Ok = Standard_False;
Standard_Real thetol3d = Precision::Confusion(), thetol2d = Precision::Confusion();
UFirst = Line.FirstParameter();
- ULast = Line.LastParameter();
- Standard_Real TolU = Max((ULast-UFirst)*1.e-05, Precision::PApproximation());
- Standard_Real myfirstU = UFirst;
+ ULast = Line.LastParameter();
+ Standard_Real TolU = Max((ULast - UFirst)*1.e-03, Precision::Confusion());
+ Standard_Real myfirstU = UFirst;
Standard_Real mylastU = ULast;
Standard_Integer aMaxSegments = 0;
Standard_Integer aMaxSegments1 = myMaxSegments - 1;
+ Standard_Integer aNbCut = 0, aNbImp = 0, aNbComp = 5;
if (!mycut)
{
alldone = Compute(Line, UFirst, ULast, thetol3d, thetol2d);
- if (!alldone)
+ if (!alldone)
{
tolreached = Standard_False;
myfirstparam.Append(UFirst);
Tolers2d.Append(currenttol2d);
}
}
- else
+ else
{
// previous decision to be taken if we get worse with next cut (eap)
AppParCurves_MultiCurve KeptMultiCurve;
Standard_Real KeptUfirst = 0., KeptUlast = 0., KeptT3d = RealLast(), KeptT2d = 0.;
- while (!Finish)
+ while (!Finish)
{
-
+
// Gestion du decoupage de la multiline pour approximer:
- if (!begin)
+ if (!begin)
{
- if (Ok)
+ if (Ok)
{
// Calcul de la partie a approximer.
myfirstU = mylastU;
- mylastU = ULast;
- if (Abs(ULast-myfirstU) <= RealEpsilon()
+ mylastU = ULast;
+ aNbCut = 0;
+ aNbImp = 0;
+ if (Abs(ULast - myfirstU) <= RealEpsilon()
|| aMaxSegments >= myMaxSegments)
{
Finish = Standard_True;
if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d))
{
KeptMultiCurve = TheMultiCurve;
- KeptUfirst = myfirstU;
- KeptUlast = mylastU;
- KeptT3d = thetol3d;
- KeptT2d = thetol2d;
+ KeptUfirst = myfirstU;
+ KeptUlast = mylastU;
+ KeptT3d = thetol3d;
+ KeptT2d = thetol2d;
+ aNbImp++;
}
// cut an interval
- mylastU = (myfirstU + mylastU)/2;
+ mylastU = (myfirstU + mylastU) / 2;
+ aNbCut++;
}
}
// Calcul des parametres sur ce nouvel intervalle.
Ok = Compute(Line, myfirstU, mylastU, thetol3d, thetol2d);
- if(Ok)
+ if (Ok)
{
aMaxSegments++;
}
//cout << myfirstU << " - " << mylastU << " tol : " << thetol3d << " " << thetol2d << endl;
-
+ Standard_Boolean aStopCutting = Standard_False;
+ if (aNbCut >= aNbComp)
+ {
+ if (aNbCut > aNbImp)
+ {
+ aStopCutting = Standard_True;
+ }
+ }
// is new decision better?
- if (!Ok && (Abs(myfirstU-mylastU) <= TolU || aMaxSegments >= aMaxSegments1))
+ if (!Ok && (Abs(myfirstU - mylastU) <= TolU || aMaxSegments >= aMaxSegments1 || aStopCutting ))
{
- Ok = Standard_True; // stop interval cutting, approx the rest part
+ Ok = Standard_True; // stop interval cutting, approx the rest part
- if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d))
- {
- KeptMultiCurve = TheMultiCurve;
- KeptUfirst = myfirstU;
- KeptUlast = mylastU;
- KeptT3d = thetol3d;
- KeptT2d = thetol2d;
- }
+ if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d))
+ {
+ KeptMultiCurve = TheMultiCurve;
+ KeptUfirst = myfirstU;
+ KeptUlast = mylastU;
+ KeptT3d = thetol3d;
+ KeptT2d = thetol2d;
+ }
- mylastU = KeptUlast;
+ mylastU = KeptUlast;
- tolreached = Standard_False; // helas
- myMultiCurves.Append(KeptMultiCurve);
- aMaxSegments++;
- Tolers3d.Append (KeptT3d);
- Tolers2d.Append (KeptT2d);
- myfirstparam.Append (KeptUfirst);
- mylastparam.Append (KeptUlast);
- }
+ tolreached = Standard_False; // helas
+ myMultiCurves.Append(KeptMultiCurve);
+ aMaxSegments++;
+ Tolers3d.Append(KeptT3d);
+ Tolers2d.Append(KeptT2d);
+ myfirstparam.Append(KeptUfirst);
+ mylastparam.Append(KeptUlast);
+ }
begin = Standard_False;
} // while (!Finish)
//=======================================================================
Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line,
- const Standard_Real Ufirst,
- const Standard_Real Ulast,
- Standard_Real& TheTol3d,
- Standard_Real& TheTol2d)
+ const Standard_Real Ufirst,
+ const Standard_Real Ulast,
+ Standard_Real& TheTol3d,
+ Standard_Real& TheTol2d)
{
if (mydone) {
LSquare.Error(Fv, TheTol3d, TheTol2d);
if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
- // Stockage de la multicurve approximee.
- tolreached = Standard_True;
+ // Stockage de la multicurve approximee.
+ tolreached = Standard_True;
myMultiCurves.Append(LSquare.Value());
- myfirstparam.Append(Ufirst);
- mylastparam.Append(Ulast);
- Tolers3d.Append(TheTol3d);
- Tolers2d.Append(TheTol2d);
- return Standard_True;
+ myfirstparam.Append(Ufirst);
+ mylastparam.Append(Ulast);
+ Tolers3d.Append(TheTol3d);
+ Tolers2d.Append(TheTol2d);
+ return Standard_True;
}
}
if (deg == mydegremax) {
currenttol3d = TheTol3d;
currenttol2d = TheTol2d;
}
-
+
}
return Standard_False;
}
//=======================================================================
void Approx_ComputeCLine::Parameters(const Standard_Integer Index,
- Standard_Real& firstpar,
- Standard_Real& lastpar) const
+ Standard_Real& firstpar,
+ Standard_Real& lastpar) const
{
firstpar = myfirstparam.Value(Index);
- lastpar = mylastparam.Value(Index);
+ lastpar = mylastparam.Value(Index);
}
//=======================================================================
//=======================================================================
void Approx_ComputeCLine::SetDegrees(const Standard_Integer degreemin,
- const Standard_Integer degreemax)
+ const Standard_Integer degreemax)
{
mydegremin = degreemin;
mydegremax = degreemax;
//=======================================================================
void Approx_ComputeCLine::SetTolerances(const Standard_Real Tolerance3d,
- const Standard_Real Tolerance2d)
+ const Standard_Real Tolerance2d)
{
mytol3d = Tolerance3d;
mytol2d = Tolerance2d;
//=======================================================================
void Approx_ComputeCLine::SetConstraints(const AppParCurves_Constraint FirstC,
- const AppParCurves_Constraint LastC)
+ const AppParCurves_Constraint LastC)
{
myfirstC = FirstC;
- mylastC = LastC;
+ mylastC = LastC;
}
//=======================================================================
//purpose : Changes the max number of segments, which is allowed for cutting.
//=======================================================================
-void Approx_ComputeCLine:: SetMaxSegments(const Standard_Integer theMaxSegments)
+void Approx_ComputeCLine::SetMaxSegments(const Standard_Integer theMaxSegments)
{
myMaxSegments = theMaxSegments;
}
//=======================================================================
void Approx_ComputeCLine::Error(const Standard_Integer Index,
- Standard_Real& tol3d,
- Standard_Real& tol2d) const
+ Standard_Real& tol3d,
+ Standard_Real& tol2d) const
{
tol3d = Tolers3d.Value(Index);
tol2d = Tolers2d.Value(Index);
#include <TColgp_HArray1OfPnt2d.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
+#include <Geom2dConvert.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <GeomLib.hxx>
#include <Extrema_ExtPC.hxx>
#include <NCollection_DataMap.hxx>
+#include <ElSLib.hxx>
+#include <ElCLib.hxx>
//=======================================================================
//function : ComputeTolU
//purpose :
//=======================================================================
static void TrimC3d(Handle(Adaptor3d_HCurve)& myCurve,
- Standard_Boolean* IsTrimmed,
- const Standard_Real dt,
- const gp_Pnt& Pole,
+ Standard_Boolean* IsTrimmed,
+ const Standard_Real dt,
+ const gp_Pnt& Pole,
Standard_Integer* SingularCase,
- const Standard_Integer NumberOfSingularCase)
+ const Standard_Integer NumberOfSingularCase,
+ const Standard_Real TolConf)
{
Standard_Real f = myCurve->FirstParameter();
Standard_Real l = myCurve->LastParameter();
gp_Pnt P = myCurve->Value(f);
- if(P.Distance(Pole) < Precision::Confusion()) {
+ if(P.Distance(Pole) <= TolConf) {
IsTrimmed[0] = Standard_True;
f = f+dt;
myCurve = myCurve->Trim(f, l, Precision::Confusion());
}
P = myCurve->Value(l);
- if(P.Distance(Pole) < Precision::Confusion()) {
+ if(P.Distance(Pole) <= TolConf) {
IsTrimmed[1] = Standard_True;
l = l-dt;
myCurve = myCurve->Trim(f, l, Precision::Confusion());
}
}
gp_Lin2d BoundLin(thePole, theBoundDir); //one of the bounds of rectangle
+ Standard_Real ParOnLin = 0.;
+ if (theBoundDir.IsParallel(aDBnd, 100.*Precision::Angular()))
+ {
+ ParOnLin = ElCLib::Parameter(aLin, thePole);
+ }
+ else
+ {
+ Standard_Real U1x = BoundLin.Direction().X();
+ Standard_Real U1y = BoundLin.Direction().Y();
+ Standard_Real U2x = aLin.Direction().X();
+ Standard_Real U2y = aLin.Direction().Y();
+ Standard_Real Uo21x = aLin.Location().X() - BoundLin.Location().X();
+ Standard_Real Uo21y = aLin.Location().Y() - BoundLin.Location().Y();
- Standard_Real U1x = BoundLin.Direction().X();
- Standard_Real U1y = BoundLin.Direction().Y();
- Standard_Real U2x = aLin.Direction().X();
- Standard_Real U2y = aLin.Direction().Y();
- Standard_Real Uo21x = aLin.Location().X() - BoundLin.Location().X();
- Standard_Real Uo21y = aLin.Location().Y() - BoundLin.Location().Y();
-
- Standard_Real D = U1y*U2x-U1x*U2y;
-
- Standard_Real ParOnLin = (Uo21y * U1x - Uo21x * U1y)/D; //parameter of intersection point
+ Standard_Real D = U1y*U2x - U1x*U2y;
+
+ ParOnLin = (Uo21y * U1x - Uo21x * U1y) / D; //parameter of intersection point
+ }
Handle(Geom2d_Line) aSegLine = new Geom2d_Line(aLin);
aSegment = (FirstOrLast == 0)?
GeomAbs_SurfaceType SType = mySurface->GetType();
GeomAbs_CurveType CType = myCurve->GetType();
Standard_Boolean isAnalyticalSurf = Standard_True;
+ Standard_Boolean IsTrimmed[2] = { Standard_False, Standard_False };
+ Standard_Integer SingularCase[2];
+ const Standard_Real eps = 0.01;
+ Standard_Real TolConf = Precision::Confusion();
+ Standard_Real dt = (LastPar - FirstPar) * eps;
+ Standard_Real U1 = 0.0, U2 = 0.0, V1 = 0.0, V2 = 0.0;
+ U1 = mySurface->FirstUParameter();
+ U2 = mySurface->LastUParameter();
+ V1 = mySurface->FirstVParameter();
+ V2 = mySurface->LastVParameter();
switch (SType)
{
// periodique en V !)
P.SetInBounds(myCurve->FirstParameter());
}
+ else
+ {
+ const Standard_Real Vmax = M_PI / 2.;
+ const Standard_Real Vmin = -Vmax;
+ const Standard_Real minang = 1.e-5 * M_PI;
+ gp_Sphere aSph = mySurface->Sphere();
+ Standard_Real anR = aSph.Radius();
+ Standard_Real f = myCurve->FirstParameter();
+ Standard_Real l = myCurve->LastParameter();
+
+ gp_Pnt Pf = myCurve->Value(f);
+ gp_Pnt Pl = myCurve->Value(l);
+ gp_Pnt aLoc = aSph.Position().Location();
+ Standard_Real maxdist = Max(Pf.Distance(aLoc), Pl.Distance(aLoc));
+ TolConf = Max(anR * minang, Abs(anR - maxdist));
+
+ //Surface has pole at V = Vmin and Vmax
+ gp_Pnt Pole = mySurface->Value(U1, Vmin);
+ TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 3, TolConf);
+ Pole = mySurface->Value(U1, Vmax);
+ TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4, TolConf);
+ }
myResult = P;
}
break;
case GeomAbs_BSplineSurface:
{
isAnalyticalSurf = Standard_False;
- Standard_Boolean IsTrimmed[2] = {Standard_False, Standard_False};
- Standard_Integer SingularCase[2];
- Standard_Real f, l, dt;
- const Standard_Real eps = 0.01;
+ Standard_Real f, l;
f = myCurve->FirstParameter();
l = myCurve->LastParameter();
dt = (l - f) * eps;
- Standard_Real U1 = 0.0, U2=0.0, V1=0.0, V2=0.0;
const Adaptor3d_Surface& S = mySurface->Surface();
U1 = S.FirstUParameter();
U2 = S.LastUParameter();
{
//Surface has pole at U = Umin
gp_Pnt Pole = mySurface->Value(U1, V1);
- TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 1);
+ TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 1, TolConf);
}
if(IsoIsDeg(S, U2, GeomAbs_IsoU, 0., myTolerance))
{
//Surface has pole at U = Umax
gp_Pnt Pole = mySurface->Value(U2, V1);
- TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 2);
+ TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 2, TolConf);
}
if(IsoIsDeg(S, V1, GeomAbs_IsoV, 0., myTolerance))
{
//Surface has pole at V = Vmin
gp_Pnt Pole = mySurface->Value(U1, V1);
- TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 3);
+ TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 3, TolConf);
}
if(IsoIsDeg(S, V2, GeomAbs_IsoV, 0., myTolerance))
{
//Surface has pole at V = Vmax
gp_Pnt Pole = mySurface->Value(U1, V2);
- TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4);
+ TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4, TolConf);
}
ProjLib_ComputeApproxOnPolarSurface polar;
default:
{
isAnalyticalSurf = Standard_False;
- Standard_Boolean IsTrimmed[2] = {Standard_False, Standard_False};
Standard_Real Vsingular[2] = {0.0 , 0.0}; //for surfaces of revolution
- Standard_Real f = 0.0, l = 0.0, dt = 0.0;
- const Standard_Real eps = 0.01;
+ Standard_Real f = 0.0, l = 0.0;
+ dt = 0.0;
if(mySurface->GetType() == GeomAbs_SurfaceOfRevolution)
{
Comp.SetDegree(myDegMin, myDegMax);
Comp.SetMaxSegments(myMaxSegments);
Comp.SetBndPnt(myBndPnt);
- Comp.Perform( myCurve, mySurface);
+ Comp.Perform(myCurve, mySurface);
if (Comp.Bezier().IsNull() && Comp.BSpline().IsNull())
return; // advanced projector has been failed too
myResult.Done();
-
- // set the type
- if ( SType == GeomAbs_Plane && CType == GeomAbs_BezierCurve)
+ Handle(Geom2d_BSplineCurve) aRes;
+ if (Comp.BSpline().IsNull())
{
- myResult.SetType(GeomAbs_BezierCurve);
- myResult.SetBezier(Comp.Bezier()) ;
+ aRes = Geom2dConvert::CurveToBSplineCurve(Comp.Bezier());
}
else
{
+ aRes = Comp.BSpline();
+ }
+ if ((IsTrimmed[0] || IsTrimmed[1]))
+ {
+ if (IsTrimmed[0])
+ {
+ //Add segment before start of curve
+ Standard_Real f = myCurve->FirstParameter();
+ ExtendC2d(aRes, f, -dt, U1, U2, V1, V2, 0, SingularCase[0]);
+ }
+ if (IsTrimmed[1])
+ {
+ //Add segment after end of curve
+ Standard_Real l = myCurve->LastParameter();
+ ExtendC2d(aRes, l, dt, U1, U2, V1, V2, 1, SingularCase[1]);
+ }
+ Handle(Geom2d_Curve) NewCurve2d;
+ GeomLib::SameRange(Precision::PConfusion(), aRes,
+ aRes->FirstParameter(), aRes->LastParameter(),
+ FirstPar, LastPar, NewCurve2d);
+ aRes = Handle(Geom2d_BSplineCurve)::DownCast(NewCurve2d);
+ myResult.SetBSpline(aRes);
myResult.SetType(GeomAbs_BSplineCurve);
- myResult.SetBSpline(Comp.BSpline()) ;
+ }
+ else
+ {
+ // set the type
+ if (SType == GeomAbs_Plane && CType == GeomAbs_BezierCurve)
+ {
+ myResult.SetType(GeomAbs_BezierCurve);
+ myResult.SetBezier(Comp.Bezier());
+ }
+ else
+ {
+ myResult.SetType(GeomAbs_BSplineCurve);
+ myResult.SetBSpline(Comp.BSpline());
+ }
}
// set the periodicity flag
if (SType == GeomAbs_Plane &&
- CType == GeomAbs_BSplineCurve &&
- myCurve->IsPeriodic() )
+ CType == GeomAbs_BSplineCurve &&
+ myCurve->IsPeriodic())
{
myResult.SetPeriodic();
}