Ut11, Ut12, Ut21, Ut22: Real)
is static protected;
+
+ GetSingleSolutionFlag (me) returns Boolean
+ ---Purpose: Returns single solution flag value.
+ is static;
+
+ SetSingleSolutionFlag (me: in out;
+ theFlag: Boolean)
+ ---Purpose: Sets single solution flag value.
+ is static;
myECC: ECC from Extrema;
myDone: Boolean;
myIsPar: Boolean;
+ myIsFindSingleSolution: Boolean;
mypoints: SequenceOfPOnCurv from Extrema;
mySqDist: SequenceOfReal from TColStd;
mynbext: Integer;
#include <Adaptor3d_Curve.hxx>
#include <Extrema_CurveTool.hxx>
-
//=======================================================================
//function : Extrema_ExtCC
//purpose :
//=======================================================================
-
Extrema_ExtCC::Extrema_ExtCC (const Standard_Real TolC1,
- const Standard_Real TolC2) :
- myDone (Standard_False)
+ const Standard_Real TolC2)
+: myIsFindSingleSolution(Standard_False),
+ myDone (Standard_False)
{
myC[0] = 0; myC[1] = 0;
myTol[0] = TolC1; myTol[1] = TolC2;
//purpose :
//=======================================================================
-Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1,
- const Adaptor3d_Curve& C2,
- const Standard_Real U1,
- const Standard_Real U2,
- const Standard_Real V1,
- const Standard_Real V2,
- const Standard_Real TolC1,
- const Standard_Real TolC2)
-: myECC(C1, C2, U1, U2, V1, V2),
+Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1,
+ const Adaptor3d_Curve& C2,
+ const Standard_Real U1,
+ const Standard_Real U2,
+ const Standard_Real V1,
+ const Standard_Real V2,
+ const Standard_Real TolC1,
+ const Standard_Real TolC2)
+: myIsFindSingleSolution(Standard_False),
+ myECC(C1, C2, U1, U2, V1, V2),
myDone (Standard_False)
{
SetCurve (1, C1, U1, U2);
//=======================================================================
Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1,
- const Adaptor3d_Curve& C2,
- const Standard_Real TolC1,
- const Standard_Real TolC2)
-: myECC(C1, C2),
+ const Adaptor3d_Curve& C2,
+ const Standard_Real TolC1,
+ const Standard_Real TolC2)
+: myIsFindSingleSolution(Standard_False),
+ myECC(C1, C2),
myDone (Standard_False)
{
SetCurve (1, C1, C1.FirstParameter(), C1.LastParameter());
myECC.SetParams(*((Adaptor3d_Curve*)myC[0]),
*((Adaptor3d_Curve*)myC[1]), myInf[0], mySup[0], myInf[1], mySup[1]);
myECC.SetTolerance(Min(myTol[0], myTol[1]));
+ myECC.SetSingleSolutionFlag(GetSingleSolutionFlag());
myDone = Standard_False;
mypoints.Clear();
mySqDist.Clear();
}
}
}
+
+//=======================================================================
+//function : SetSingleSolutionFlag
+//purpose :
+//=======================================================================
+void Extrema_ExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag)
+{
+ myIsFindSingleSolution = theFlag;
+}
+
+//=======================================================================
+//function : GetSingleSolutionFlag
+//purpose :
+//=======================================================================
+Standard_Boolean Extrema_ExtCC::GetSingleSolutionFlag() const
+{
+ return myIsFindSingleSolution;
+}
Period2 : Real from Standard = 0.0)
is static protected;
+
+ GetSingleSolutionFlag (me) returns Boolean
+ ---Purpose: Returns single solution flag value.
+ is static;
+
+ SetSingleSolutionFlag (me: in out;
+ theFlag: Boolean)
+ ---Purpose: Sets single solution flag value.
+ is static;
fields
myDone: Boolean;
myIsPar: Boolean;
+ myIsFindSingleSolution: Boolean;
mypoints: SequenceOfPOnCurv2d from Extrema;
mySqDist: SequenceOfReal from TColStd;
mynbext: Integer;
Extrema_ExtCC2d::Extrema_ExtCC2d()
+: myIsFindSingleSolution(Standard_False)
{
}
-Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d& C1,
- const Adaptor2d_Curve2d& C2,
- const Standard_Real TolC1,
- const Standard_Real TolC2)
+Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d& C1,
+ const Adaptor2d_Curve2d& C2,
+ const Standard_Real TolC1,
+ const Standard_Real TolC2)
+: myIsFindSingleSolution(Standard_False)
{
Initialize(C2, Extrema_Curve2dTool::FirstParameter(C2), Extrema_Curve2dTool::LastParameter(C2), TolC1, TolC2);
Perform(C1, Extrema_Curve2dTool::FirstParameter(C1), Extrema_Curve2dTool::LastParameter(C1));
}
Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d& C1,
- const Adaptor2d_Curve2d& C2,
- const Standard_Real U1,
- const Standard_Real U2,
- const Standard_Real V1,
- const Standard_Real V2,
- const Standard_Real TolC1,
- const Standard_Real TolC2)
+ const Adaptor2d_Curve2d& C2,
+ const Standard_Real U1,
+ const Standard_Real U2,
+ const Standard_Real V1,
+ const Standard_Real V2,
+ const Standard_Real TolC1,
+ const Standard_Real TolC2)
+: myIsFindSingleSolution(Standard_False)
{
Initialize(C2, V1, V2, TolC1, TolC2);
Perform(C1, U1, U2);
case GeomAbs_BezierCurve:
case GeomAbs_OtherCurve:
case GeomAbs_BSplineCurve: {
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
- Standard_Real Period2 = 0.;
- if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
- Results(Xtrem, U11, U12, U21, U22, 2*M_PI,Period2);
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
+ Standard_Real Period2 = 0.;
+ if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
+ Results(aParamSolver, U11, U12, U21, U22, 2*M_PI,Period2);
}
break;
case GeomAbs_Line: {
Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 2*M_PI);
}
break;
- case GeomAbs_Ellipse: {
- //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)));
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
- Results(Xtrem, U11, U12, U21, U22,2*M_PI, 2*M_PI);
+ case GeomAbs_Ellipse:
+ {
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
+ Results(aParamSolver, U11, U12, U21, U22,2*M_PI, 2*M_PI);
}
break;
case GeomAbs_Parabola: {
//Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
- Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 0.);
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
+ Results(aParamSolver, U11, U12, U21, U22, 2*M_PI, 0.);
}
break;
case GeomAbs_Hyperbola: {
//Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)));
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
- Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 0.);
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
+ Results(aParamSolver, U11, U12, U21, U22, 2*M_PI, 0.);
}
break;
case GeomAbs_BezierCurve:
case GeomAbs_OtherCurve:
case GeomAbs_BSplineCurve: {
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
Standard_Real Period2 = 0.;
if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
- Results(Xtrem, U11, U12, U21, U22, 2*M_PI,Period2);
+ Results(aParamSolver, U11, U12, U21, U22, 2*M_PI,Period2);
}
break;
case GeomAbs_Line: {
case GeomAbs_Ellipse: {
//inverse = Standard_True;
//Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Parabola(C1));
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
- Results(Xtrem, U11, U12, U21, U22, 0., 2*M_PI);
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
+ Results(aParamSolver, U11, U12, U21, U22, 0., 2*M_PI);
}
break;
case GeomAbs_Parabola: {
//Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Parabola(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
- Results(Xtrem, U11, U12, U21, U22, 0., 0.);
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
+ Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
}
break;
case GeomAbs_Hyperbola: {
//inverse = Standard_True;
//Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Parabola(C1));
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
- Results(Xtrem, U11, U12, U21, U22, 0., 0.);
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
+ Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
}
break;
case GeomAbs_BezierCurve:
case GeomAbs_OtherCurve:
case GeomAbs_BSplineCurve: {
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
Standard_Real Period2 = 0.;
if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
- Results(Xtrem, U11, U12, U21, U22, 0., Period2);
+ Results(aParamSolver, U11, U12, U21, U22, 0., Period2);
}
break;
case GeomAbs_Line: {
case GeomAbs_Ellipse: {
//inverse = Standard_True;
//Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Hyperbola(C1));
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
- Results(Xtrem, U11, U12, U21, U22, 0., 2*M_PI );
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
+ Results(aParamSolver, U11, U12, U21, U22, 0., 2*M_PI );
}
break;
case GeomAbs_Parabola: {
//Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
- Results(Xtrem, U11, U12, U21, U22, 0., 0.);
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
+ Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
}
break;
case GeomAbs_Hyperbola: {
//Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(C1), Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)));
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
- Results(Xtrem, U11, U12, U21, U22, 0., 0.);
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
+ Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
}
break;
case GeomAbs_OtherCurve:
case GeomAbs_BezierCurve:
case GeomAbs_BSplineCurve: {
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
Standard_Real Period2 = 0.;
if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
- Results(Xtrem, U11, U12, U21, U22, 0., Period2);
+ Results(aParamSolver, U11, U12, U21, U22, 0., Period2);
}
break;
case GeomAbs_Line: {
case GeomAbs_BezierCurve:
case GeomAbs_OtherCurve:
case GeomAbs_BSplineCurve: {
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
Standard_Real Period1 = 0.;
if (Extrema_Curve2dTool::IsPeriodic(C1)) Period1 = Extrema_Curve2dTool::Period(C1);
Standard_Real Period2 = 0.;
if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
- Results(Xtrem, U11, U12, U21, U22, Period1, Period2);
+ Results(aParamSolver, U11, U12, U21, U22, Period1, Period2);
}
break;
case GeomAbs_BezierCurve:
case GeomAbs_OtherCurve:
case GeomAbs_BSplineCurve: {
- Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
- Xtrem.Perform();
+ Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+ aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+ aParamSolver.Perform();
Standard_Real Period2 = 0.;
if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
- Results(Xtrem, U11, U12, U21, U22, 0., Period2);
+ Results(aParamSolver, U11, U12, U21, U22, 0., Period2);
}
break;
case GeomAbs_Line: {
if (!myDone) StdFail_NotDone::Raise();
return myIsPar;
}
+
+//=======================================================================
+//function : SetSingleSolutionFlag
+//purpose :
+//=======================================================================
+void Extrema_ExtCC2d::SetSingleSolutionFlag(const Standard_Boolean theFlag)
+{
+ myIsFindSingleSolution = theFlag;
+}
+
+//=======================================================================
+//function : GetSingleSolutionFlag
+//purpose :
+//=======================================================================
+Standard_Boolean Extrema_ExtCC2d::GetSingleSolutionFlag() const
+{
+ return myIsFindSingleSolution;
+}
OutOfRange
-- if N < 1 or N > NbExt(me)
is static;
+
+ GetSingleSolutionFlag (me) returns Boolean
+ ---Purpose: Returns single solution flag value.
+ is static;
+
+ SetSingleSolutionFlag (me: in out;
+ theFlag: Boolean)
+ ---Purpose: Sets single solution flag value.
+ is static;
fields
+ myIsFindSingleSolution: Boolean;
myCurveMinTol : Real from Standard;
myLowBorder : Vector from math;
myUppBorder : Vector from math;
myPoints2 : SequenceOfReal from TColStd;
myC : Address from Standard [2];
myDone : Boolean;
+
end GenExtCC;
//purpose :
//=======================================================================
Extrema_GenExtCC::Extrema_GenExtCC()
-: myCurveMinTol(Precision::PConfusion()),
+: myIsFindSingleSolution(Standard_False),
+ myCurveMinTol(Precision::PConfusion()),
myLowBorder(1,2),
myUppBorder(1,2),
myDone(Standard_False)
//=======================================================================
Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
const Curve2& C2)
-: myCurveMinTol(Precision::PConfusion()),
+: myIsFindSingleSolution(Standard_False),
+ myCurveMinTol(Precision::PConfusion()),
myLowBorder(1,2),
myUppBorder(1,2),
myDone(Standard_False)
const Standard_Real Usup,
const Standard_Real Vinf,
const Standard_Real Vsup)
-: myCurveMinTol(Precision::PConfusion()),
+: myIsFindSingleSolution(Standard_False),
+ myCurveMinTol(Precision::PConfusion()),
myLowBorder(1,2),
myUppBorder(1,2),
myDone(Standard_False)
Curve2 &C2 = *(Curve2*)myC[1];
Standard_Integer aNbInter[2];
- aNbInter[0] = C1.NbIntervals(GeomAbs_C2);
- aNbInter[1] = C2.NbIntervals(GeomAbs_C2);
+ GeomAbs_Shape aContinuity = GeomAbs_C2;
+ aNbInter[0] = C1.NbIntervals(aContinuity);
+ aNbInter[1] = C2.NbIntervals(aContinuity);
+
+ if (aNbInter[0] * aNbInter[1] > 100)
+ {
+ aContinuity = GeomAbs_C1;
+ aNbInter[0] = C1.NbIntervals(aContinuity);
+ aNbInter[1] = C2.NbIntervals(aContinuity);
+ }
+
TColStd_Array1OfReal anIntervals1(1, aNbInter[0] + 1);
TColStd_Array1OfReal anIntervals2(1, aNbInter[1] + 1);
- C1.Intervals(anIntervals1, GeomAbs_C2);
- C2.Intervals(anIntervals2, GeomAbs_C2);
+ C1.Intervals(anIntervals1, aContinuity);
+ C2.Intervals(anIntervals2, aContinuity);
Extrema_GlobOptFuncCCC2 aFunc (C1, C2);
math_GlobOptMin aFinder(&aFunc, myLowBorder, myUppBorder);
+ aFinder.SetContinuity(aContinuity == GeomAbs_C2 ? 2 : 1);
Standard_Real aDiscTol = 1.0e-2;
Standard_Real aValueTol = 1.0e-2;
Standard_Real aSameTol = myCurveMinTol / (aDiscTol);
aSecondBorderInterval(2) = anIntervals2(j + 1);
aFinder.SetLocalParams(aFirstBorderInterval, aSecondBorderInterval);
- aFinder.Perform();
+ aFinder.Perform(GetSingleSolutionFlag());
// check that solution found on current interval is not worse than previous
aCurrF = aFinder.GetF();
P1.SetValues(myPoints1(N), Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)));
P2.SetValues(myPoints2(N), Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
-}
\ No newline at end of file
+}
+
+//=======================================================================
+//function : SetSingleSolutionFlag
+//purpose :
+//=======================================================================
+void Extrema_GenExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag)
+{
+ myIsFindSingleSolution = theFlag;
+}
+
+//=======================================================================
+//function : GetSingleSolutionFlag
+//purpose :
+//=======================================================================
+Standard_Boolean Extrema_GenExtCC::GetSingleSolutionFlag() const
+{
+ return myIsFindSingleSolution;
+}
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
+
+#include <algorithm>
+
#include <ProjLib_CompProjectedCurve.ixx>
#include <ProjLib_HCompProjectedCurve.hxx>
#include <gp_XY.hxx>
+#include <Adaptor2d_HCurve2d.hxx>
+#include <Adaptor3d_HCurve.hxx>
+#include <Adaptor3d_HSurface.hxx>
#include <gp_Mat2d.hxx>
#include <Extrema_ExtPS.hxx>
#include <Precision.hxx>
#include <ProjLib_PrjResolve.hxx>
#include <GeomAbs_CurveType.hxx>
#include <GeomLib.hxx>
+#include <Adaptor3d_CurveOnSurface.hxx>
+#include <Geom2d_Line.hxx>
+#include <Geom2dAdaptor_HCurve.hxx>
+#include <Extrema_ExtCC.hxx>
+#include <NCollection_Vector.hxx>
#define FuncTol 1.e-10
}
#endif
+// Structure to perform splits computation.
+// This structure is not thread-safe since operations under mySplits should be performed in a critical section.
+// myPeriodicDir - 0 for U periodicity and 1 for V periodicity.
+struct SplitDS
+{
+ SplitDS(const Handle(Adaptor3d_HCurve) &theCurve,
+ const Handle(Adaptor3d_HSurface) &theSurface,
+ NCollection_Vector<Standard_Real> &theSplits)
+ : myCurve(theCurve),
+ mySurface(theSurface),
+ mySplits(theSplits)
+ { }
+
+ // Assignment operator is forbidden.
+ void operator=(const SplitDS &theSplitDS);
+
+ const Handle(Adaptor3d_HCurve) myCurve;
+ const Handle(Adaptor3d_HSurface) mySurface;
+ NCollection_Vector<Standard_Real> &mySplits;
+
+ Standard_Real myPerMinParam;
+ Standard_Real myPerMaxParam;
+ Standard_Integer myPeriodicDir;
+
+ Extrema_ExtCC *myExtCC;
+ Extrema_ExtPS *myExtPS;
+};
+
+ //! Compute split points in the parameter space of the curve.
+ static void BuildCurveSplits(const Handle(Adaptor3d_HCurve) &theCurve,
+ const Handle(Adaptor3d_HSurface) &theSurface,
+ const Standard_Real theTolU,
+ const Standard_Real theTolV,
+ NCollection_Vector<Standard_Real> &theSplits);
+
+ //! Perform splitting on a specified direction. Sub-method in BuildCurveSplits.
+ static void SplitOnDirection(SplitDS & theSplitDS);
+
+ //! Perform recursive search of the split points.
+ static void FindSplitPoint(SplitDS & theSplitDS,
+ const Standard_Real theMinParam,
+ const Standard_Real theMaxParam);
+
+
+//=======================================================================
+//function : Comparator
+//purpose : used in sort algorithm
+//=======================================================================
+inline Standard_Boolean Comparator(const Standard_Real theA,
+ const Standard_Real theB)
+{
+ return theA < theB;
+}
//=======================================================================
//function : d1
void ProjLib_CompProjectedCurve::Init()
{
myTabInt.Nullify();
+ NCollection_Vector<Standard_Real> aSplits;
Standard_Real Tol;// Tolerance for ExactBound
- Standard_Integer i, Nend = 0;
- Standard_Boolean FromLastU=Standard_False;
-
- //new part (to discard far solutions)
- Standard_Real TolC = Precision::Confusion(), TolS = Precision::Confusion();
- Extrema_ExtCS CExt(myCurve->Curve(),
- mySurface->Surface(),
- TolC,
- TolS);
- if (CExt.IsDone() && CExt.NbExt())
+ Standard_Integer i, Nend = 0, aSplitIdx = 0;
+ Standard_Boolean FromLastU = Standard_False,
+ isSplitsComputed = Standard_False;
+
+ const Standard_Real aTol3D = Precision::Confusion();
+ Extrema_ExtCS CExt(myCurve->Curve(), mySurface->Surface(), aTol3D, aTol3D);
+ if (CExt.IsDone() && CExt.NbExt())
{
- // Search for the minimum solution
- Nend = CExt.NbExt();
+ // Search for the minimum solution.
+ // Avoid usage of extrema result that can be wrong for extrusion.
if(myMaxDist > 0 &&
- // Avoid usage of extrema result that can be wrong for extrusion
+
mySurface->GetType() != GeomAbs_SurfaceOfExtrusion)
{
Standard_Real min_val2;
min_val2 = CExt.SquareDistance(1);
+
+ Nend = CExt.NbExt();
for(i = 2; i <= Nend; i++)
- if (CExt.SquareDistance(i) < min_val2) min_val2 = CExt.SquareDistance(i);
+ {
+ if (CExt.SquareDistance(i) < min_val2)
+ min_val2 = CExt.SquareDistance(i);
+ }
if (min_val2 > myMaxDist * myMaxDist)
- return;
+ return; // No near solution -> exit.
}
}
- // end of new part
Standard_Real FirstU, LastU, Step, SearchStep, WalkStep, t;
SearchStep = 10*MinStep;
Step = SearchStep;
- //Initialization of aPrjPS
- Standard_Real Uinf = mySurface->FirstUParameter();
- Standard_Real Usup = mySurface->LastUParameter();
- Standard_Real Vinf = mySurface->FirstVParameter();
- Standard_Real Vsup = mySurface->LastVParameter();
-
+ gp_Pnt2d aLowBorder(mySurface->FirstUParameter(),mySurface->FirstVParameter());
+ gp_Pnt2d aUppBorder(mySurface->LastUParameter(), mySurface->LastVParameter());
+ gp_Pnt2d aTol(myTolU, myTolV);
ProjLib_PrjResolve aPrjPS(myCurve->Curve(), mySurface->Surface(), 1);
t = FirstU;
ParT=P1.Parameter();
P2.Parameter(ParU, ParV);
- aPrjPS.Perform(ParT, ParU, ParV, gp_Pnt2d(myTolU, myTolV),
- gp_Pnt2d(mySurface->FirstUParameter(),mySurface->FirstVParameter()),
- gp_Pnt2d(mySurface->LastUParameter(), mySurface->LastVParameter()),
- FuncTol, Standard_True);
+ aPrjPS.Perform(ParT, ParU, ParV, aTol, aLowBorder, aUppBorder, FuncTol, Standard_True);
+
if ( aPrjPS.IsDone() && P1.Parameter() > Max(FirstU,t-Step+Precision::PConfusion())
&& P1.Parameter() <= t)
{
}
}
if (!initpoint)
- {
+ {
myCurve->D0(t,CPoint);
#ifdef OCCT_DEBUG_CHRONO
InitChron(chr_init_point);
gp_Vec2d D;
if ((mySurface->IsUPeriodic() &&
- Abs(Usup - Uinf - mySurface->UPeriod()) < Precision::Confusion()) ||
+ Abs(aUppBorder.X() - aLowBorder.X() - mySurface->UPeriod()) < Precision::Confusion()) ||
(mySurface->IsVPeriodic() &&
- Abs(Vsup - Vinf - mySurface->VPeriod()) < Precision::Confusion()))
+ Abs(aUppBorder.Y() - aLowBorder.Y() - mySurface->VPeriod()) < Precision::Confusion()))
{
- if((Abs(U - Uinf) < mySurface->UResolution(Precision::PConfusion())) &&
+ if((Abs(U - aLowBorder.X()) < mySurface->UResolution(Precision::PConfusion())) &&
mySurface->IsUPeriodic())
{
d1(t, U, V, D, myCurve, mySurface);
- if (D.X() < 0 ) U = Usup;
+ if (D.X() < 0 ) U = aUppBorder.X();
}
- else if((Abs(U - Usup) < mySurface->UResolution(Precision::PConfusion())) &&
+ else if((Abs(U - aUppBorder.X()) < mySurface->UResolution(Precision::PConfusion())) &&
mySurface->IsUPeriodic())
{
d1(t, U, V, D, myCurve, mySurface);
- if (D.X() > 0) U = Uinf;
+ if (D.X() > 0) U = aLowBorder.X();
}
- if((Abs(V - Vinf) < mySurface->VResolution(Precision::PConfusion())) &&
+ if((Abs(V - aLowBorder.Y()) < mySurface->VResolution(Precision::PConfusion())) &&
mySurface->IsVPeriodic())
{
d1(t, U, V, D, myCurve, mySurface);
- if (D.Y() < 0) V = Vsup;
+ if (D.Y() < 0) V = aUppBorder.Y();
}
- else if((Abs(V - Vsup) <= mySurface->VResolution(Precision::PConfusion())) &&
+ else if((Abs(V - aUppBorder.Y()) <= mySurface->VResolution(Precision::PConfusion())) &&
mySurface->IsVPeriodic())
{
d1(t, U, V, D, myCurve, mySurface);
- if (D.Y() > 0) V = Vinf;
+ if (D.Y() > 0) V = aLowBorder.Y();
}
}
-
if (myMaxDist > 0)
{
// Here we are going to stop if the distance between projection and
}
if (!new_part) break;
-
//We have found a new continuous part
Handle(TColgp_HSequenceOfPnt) hSeq = new TColgp_HSequenceOfPnt();
mySequence->Append(hSeq);
if (t > LastU) t = LastU;
Standard_Real prevStep = Step;
Standard_Real U0, V0;
- gp_Pnt2d aLowBorder(mySurface->FirstUParameter(),mySurface->FirstVParameter());
- gp_Pnt2d aUppBorder(mySurface->LastUParameter(), mySurface->LastVParameter());
- gp_Pnt2d aTol(myTolU, myTolV);
+
//Here we are trying to prolong continuous part
while (t <= LastU && new_part)
{
Triple.SetZ(V);
}
+ // Protection from case when the whole curve lies on a seam.
+ if (!isSplitsComputed)
+ {
+ Standard_Boolean isUPossible = Standard_False;
+ if (mySurface->IsUPeriodic() &&
+ (Abs(Triple.Y() - mySurface->FirstUParameter() ) > Precision::PConfusion() &&
+ Abs(Triple.Y() - mySurface->LastUParameter() ) > Precision::PConfusion()))
+ {
+ isUPossible = Standard_True;
+ }
+
+ Standard_Boolean isVPossible = Standard_False;
+ if (mySurface->IsVPeriodic() &&
+ (Abs(Triple.Z() - mySurface->FirstVParameter() ) > Precision::PConfusion() &&
+ Abs(Triple.Z() - mySurface->LastVParameter() ) > Precision::PConfusion()))
+ {
+ isVPossible = Standard_True;
+ }
+
+ if (isUPossible || isVPossible)
+ {
+ // When point is good conditioned.
+ BuildCurveSplits(myCurve, mySurface, myTolU, myTolV, aSplits);
+ isSplitsComputed = Standard_True;
+ }
+ }
+
if((Triple.X() - mySequence->Value(myNbCurves)->Value(mySequence->Value(myNbCurves)->Length()).X()) > 1.e-10)
mySequence->Value(myNbCurves)->Append(Triple);
if (t == LastU) {t = LastU + 1; break;}//return;
Step = WalkStep;
t += Step;
- if (t > (LastU-MinStep/2) )
+ if (t > (LastU-MinStep/2))
{
- Step =Step+LastU-t;
+ Step = Step + LastU - t;
t = LastU;
- }
+ }
+
+ // We assume at least one point of cache inside of a split.
+ const Standard_Integer aSize = aSplits.Size();
+ for(Standard_Integer anIdx = aSplitIdx; anIdx < aSize; ++anIdx)
+ {
+ const Standard_Real aParam = aSplits(anIdx);
+ if (Abs(aParam - Triple.X() ) < Precision::PConfusion())
+ {
+ // The current point is equal to a split point.
+ new_part = Standard_False;
+
+ // Move split index to avoid check of the whole list.
+ ++aSplitIdx;
+ break;
+ }
+ else if (aParam < t + Precision::PConfusion() )
+ {
+ // The next point crosses the split point.
+ t = aParam;
+ Step = t - prevTriple.X();
+ }
+ } // for(Standard_Integer anIdx = aSplitIdx; anIdx < aSize; ++anIdx)
}
}
}
- // Sequence postproceeding
+
+ // Sequence post-proceeding.
Standard_Integer j;
// 1. Removing poor parts
{
return GeomAbs_OtherCurve;
}
+
+//=======================================================================
+//function : BuildCurveSplits
+//purpose :
+//=======================================================================
+void BuildCurveSplits(const Handle(Adaptor3d_HCurve) &theCurve,
+ const Handle(Adaptor3d_HSurface) &theSurface,
+ const Standard_Real theTolU,
+ const Standard_Real theTolV,
+ NCollection_Vector<Standard_Real> &theSplits)
+{
+ SplitDS aDS(theCurve, theSurface, theSplits);
+
+ Extrema_ExtPS anExtPS;
+ anExtPS.Initialize(theSurface->Surface(),
+ theSurface->FirstUParameter(), theSurface->LastUParameter(),
+ theSurface->FirstVParameter(), theSurface->LastVParameter(),
+ theTolU, theTolV);
+ aDS.myExtPS = &anExtPS;
+
+ if (theSurface->IsUPeriodic())
+ {
+ aDS.myPeriodicDir = 0;
+ SplitOnDirection(aDS);
+ }
+ if (theSurface->IsVPeriodic())
+ {
+ aDS.myPeriodicDir = 1;
+ SplitOnDirection(aDS);
+ }
+
+ std::sort(aDS.mySplits.begin(), aDS.mySplits.end(), Comparator);
+}
+
+//=======================================================================
+//function : SplitOnDirection
+//purpose : This method compute points in the parameter space of the curve
+// on which curve should be split since period jump is happen.
+//=======================================================================
+void SplitOnDirection(SplitDS & theSplitDS)
+{
+ // Algorithm:
+ // Create 3D curve which is correspond to the periodic bound in 2d space.
+ // Run curve / curve extrema and run extrema point / surface to check that
+ // the point will be projected to the periodic bound.
+ // In this method assumed that the points cannot be closer to each other that 1% of the parameter space.
+
+ gp_Pnt2d aStartPnt(theSplitDS.mySurface->FirstUParameter(), theSplitDS.mySurface->FirstVParameter());
+ gp_Dir2d aDir(theSplitDS.myPeriodicDir, (Standard_Integer)!theSplitDS.myPeriodicDir);
+
+ theSplitDS.myPerMinParam = !theSplitDS.myPeriodicDir ? theSplitDS.mySurface->FirstUParameter():
+ theSplitDS.mySurface->FirstVParameter();
+ theSplitDS.myPerMaxParam = !theSplitDS.myPeriodicDir ? theSplitDS.mySurface->LastUParameter():
+ theSplitDS.mySurface->LastVParameter();
+ Standard_Real aLast2DParam = theSplitDS.myPeriodicDir ?
+ theSplitDS.mySurface->LastUParameter() - theSplitDS.mySurface->FirstUParameter():
+ theSplitDS.mySurface->LastVParameter() - theSplitDS.mySurface->FirstVParameter();
+
+ // Create line which is represent periodic border.
+ Handle(Geom2d_Curve) aC2GC = new Geom2d_Line(aStartPnt, aDir);
+ Handle(Geom2dAdaptor_HCurve) aC = new Geom2dAdaptor_HCurve(aC2GC, 0, aLast2DParam);
+ Adaptor3d_CurveOnSurface aCOnS(aC, theSplitDS.mySurface);
+
+ Extrema_ExtCC anExtCC;
+ anExtCC.SetCurve(1, aCOnS);
+ anExtCC.SetCurve(2, theSplitDS.myCurve->Curve());
+ anExtCC.SetRange(1, 0, aLast2DParam);
+ anExtCC.SetSingleSolutionFlag(Standard_True);
+ theSplitDS.myExtCC = &anExtCC;
+
+ FindSplitPoint(theSplitDS,
+ theSplitDS.myCurve->FirstParameter(), // Initial curve range.
+ theSplitDS.myCurve->LastParameter());
+}
+
+
+//=======================================================================
+//function : FindSplitPoint
+//purpose :
+//=======================================================================
+void FindSplitPoint(SplitDS &theSplitDS,
+ const Standard_Real theMinParam,
+ const Standard_Real theMaxParam)
+{
+ // Make extrema copy to avoid dependencies between different levels of the recursion.
+ Extrema_ExtCC anExtCC(*theSplitDS.myExtCC);
+ anExtCC.SetRange(2, theMinParam, theMaxParam);
+ anExtCC.Perform();
+
+ if (anExtCC.IsDone())
+ {
+ const Standard_Integer aNbExt = anExtCC.NbExt();
+ for (Standard_Integer anIdx = 1; anIdx <= aNbExt; ++anIdx)
+ {
+ Extrema_POnCurv aPOnC1, aPOnC2;
+ anExtCC.Points(anIdx, aPOnC1, aPOnC2);
+
+ theSplitDS.myExtPS->Perform(aPOnC2.Value());
+ if (!theSplitDS.myExtPS->IsDone())
+ return;
+
+ // Find point with the minimal Euclidean distance to avoid
+ // false positive points detection.
+ Standard_Integer aMinIdx = -1;
+ Standard_Real aMinSqDist = RealLast();
+ const Standard_Integer aNbPext = theSplitDS.myExtPS->NbExt();
+ for(Standard_Integer aPIdx = 1; aPIdx <= aNbPext; ++aPIdx)
+ {
+ const Standard_Real aCurrSqDist = theSplitDS.myExtPS->SquareDistance(aPIdx);
+
+ if (aCurrSqDist < aMinSqDist)
+ {
+ aMinSqDist = aCurrSqDist;
+ aMinIdx = aPIdx;
+ }
+ }
+
+ // Check that is point will be projected to the periodic border.
+ const Extrema_POnSurf &aPOnS = theSplitDS.myExtPS->Point(aMinIdx);
+ Standard_Real U, V, aProjParam;
+ aPOnS.Parameter(U, V);
+ aProjParam = theSplitDS.myPeriodicDir ? V : U;
+
+
+ if (Abs(aProjParam - theSplitDS.myPerMinParam) < Precision::PConfusion() ||
+ Abs(aProjParam - theSplitDS.myPerMaxParam) < Precision::PConfusion() )
+ {
+ const Standard_Real aParam = aPOnC2.Parameter();
+ const Standard_Real aCFParam = theSplitDS.myCurve->FirstParameter();
+ const Standard_Real aCLParam = theSplitDS.myCurve->LastParameter();
+
+ if (aParam > aCFParam + Precision::PConfusion() &&
+ aParam < aCLParam - Precision::PConfusion() )
+ {
+ // Add only inner points.
+ theSplitDS.mySplits.Append(aParam);
+ }
+
+ const Standard_Real aDeltaCoeff = 0.01;
+ const Standard_Real aDelta = (theMaxParam - theMinParam +
+ aCLParam - aCFParam) * aDeltaCoeff;
+
+ if (aParam - aDelta > theMinParam + Precision::PConfusion())
+ {
+ FindSplitPoint(theSplitDS,
+ theMinParam, aParam - aDelta); // Curve parameters.
+ }
+
+ if (aParam + aDelta < theMaxParam - Precision::PConfusion())
+ {
+ FindSplitPoint(theSplitDS,
+ aParam + aDelta, theMaxParam); // Curve parameters.
+ }
+ }
+
+ } // for (Standard_Integer anIdx = 1; anIdx <= aNbExt; ++anIdx)
+ }
+}
myTmp(1, myN),
myV(1, myN),
myMaxV(1, myN),
- myExpandCoeff(1, myN)
+ myExpandCoeff(1, myN),
+ myCont(2)
{
Standard_Integer i;
myFunc = theFunc;
myC = theC;
+ myIsFindSingleSolution = Standard_False;
myZ = -1;
mySolCount = 0;
//purpose : Compute Global extremum point
//=======================================================================
// In this algo indexes started from 1, not from 0.
-void math_GlobOptMin::Perform()
+void math_GlobOptMin::Perform(const Standard_Boolean isFindSingleSolution)
{
Standard_Integer i;
myE1 = minLength * myTol;
myE2 = maxLength * myTol;
- if (myC > 1.0)
- myE3 = - maxLength * myTol / 4.0;
+
+ myIsFindSingleSolution = isFindSingleSolution;
+ if (isFindSingleSolution)
+ {
+ // Run local optimization
+ // if current value better than optimal.
+ myE3 = 0.0;
+ }
else
- myE3 = - maxLength * myTol * myC / 4.0;
+ {
+ if (myC > 1.0)
+ myE3 = - maxLength * myTol / 4.0;
+ else
+ myE3 = - maxLength * myTol * myC / 4.0;
+ }
computeGlobalExtremum(myN);
Standard_Integer i;
//Newton method
- if (dynamic_cast<math_MultipleVarFunctionWithHessian*>(myFunc))
+ if (myCont >= 2 &&
+ dynamic_cast<math_MultipleVarFunctionWithHessian*>(myFunc))
{
math_MultipleVarFunctionWithHessian* myTmp =
dynamic_cast<math_MultipleVarFunctionWithHessian*> (myFunc);
} else
// BFGS method used.
- if (dynamic_cast<math_MultipleVarFunctionWithGradient*>(myFunc))
+ if (myCont >= 1 &&
+ dynamic_cast<math_MultipleVarFunctionWithGradient*>(myFunc))
{
math_MultipleVarFunctionWithGradient* myTmp =
dynamic_cast<math_MultipleVarFunctionWithGradient*> (myFunc);
aStepBestValue = (isInside && (val < d))? val : d;
aStepBestPoint = (isInside && (val < d))? myTmp : myX;
- // Solutions are close to each other.
- if (Abs(aStepBestValue - myF) < mySameTol * 0.01)
+ // Solutions are close to each other
+ // and it is allowed to have more than one solution.
+ if (Abs(aStepBestValue - myF) < mySameTol * 0.01 &&
+ !myIsFindSingleSolution)
{
if (!isStored(aStepBestPoint))
{
}
}
- // New best solution.
- if ((aStepBestValue - myF) * myZ > mySameTol * 0.01)
+ // New best solution:
+ // new point is out of (mySameTol * 0.01) surrounding or
+ // new point is better than old + single point search.
+ Standard_Real aFunctionalDelta = (aStepBestValue - myF) * myZ;
+ if (aFunctionalDelta > mySameTol * 0.01 ||
+ (aFunctionalDelta > 0.0 && myIsFindSingleSolution))
{
mySolCount = 0;
myF = aStepBestValue;
Standard_EXPORT ~math_GlobOptMin();
- Standard_EXPORT void Perform();
+ //! @param isFindSingleSolution - defines whether to find single solution or all solutions.
+ Standard_EXPORT void Perform(const Standard_Boolean isFindSingleSolution = Standard_False);
//! Get best functional value.
Standard_EXPORT Standard_Real GetF();
Standard_Boolean isDone();
+ //! Get continuity of local borders splits.
+ inline Standard_Integer GetContinuity() const { return myCont; }
+
+ //! Set continuity of local borders splits.
+ inline void SetContinuity(const Standard_Integer theCont) { myCont = theCont; }
+
private:
math_GlobOptMin & operator = (const math_GlobOptMin & theOther);
// function values |val1 - val2| * 0.01 < mySameTol is equal,
// default value is 1.0e-7.
Standard_Real myC; //Lipschitz constant, default 9
+ Standard_Boolean myIsFindSingleSolution; // Default value is false.
// Output.
Standard_Boolean myDone;
math_Vector myMaxV; // Max Steps array.
math_Vector myExpandCoeff; // Define expand coefficient between neighboring indiced dimensions.
+ // Continuity of local borders.
+ Standard_Integer myCont;
+
Standard_Real myF; // Current value of Global optimum.
};
--- /dev/null
+puts "================"
+puts "0027299"
+puts "================"
+puts ""
+##############################################################
+# Incorrect result of the normal projection algorithm
+# Exception during the exectuion
+##############################################################
+
+restore [locate_data_file bug27299_1.brep] aShape
+explode aShape
+
+nproject result aShape_1 aShape_2
+
+# Visual check.
+donly result
+smallview
+fit
+display aShape_2
+xwd ${imagedir}/${test_image}.png
--- /dev/null
+puts "================"
+puts "0027299"
+puts "================"
+puts ""
+##############################################################
+# Incorrect result of the normal projection algorithm
+# Exception during the exectuion
+##############################################################
+
+restore [locate_data_file bug27299_1.brep] aShape
+explode aShape
+
+# To make task non-symmetry.
+ttranslate aShape_1 0 0 135.123
+
+nproject result aShape_1 aShape_2
+
+# Visual check.
+donly result
+smallview
+fit
+display aShape_2
+xwd ${imagedir}/${test_image}.png
--- /dev/null
+puts "================"
+puts "0027299"
+puts "================"
+puts ""
+##############################################################
+# Incorrect result of the normal projection algorithm
+# Exception during the exectuion
+##############################################################
+
+restore [locate_data_file bug27299_2.brep] aShape
+explode aShape
+
+nproject result aShape_1 aShape_2
+
+# Visual check.
+donly result
+smallview
+fit
+display aShape_2
+xwd ${imagedir}/${test_image}.png