Files
OCCT/src/IntTools/IntTools_EdgeEdge.cxx
msv 0d0481c787 0026738: Make Boolean operations safely treating arguments when running with fuzzy option
When fuzzy option is in force prevent increasing tolerance of input shapes. Instead pass increased by fuzzy value the tolerances of sub-shapes everywhere where it is needed by intersection algorithms.

The following changes in API have been made:

- The methods SetFuzzyValue and FuzzyValue have been moved from the classes BOPAlgo_ArgumentAnalyzer, BOPAlgo_Builder, and BOPAlgo_PaveFiller to the base class BOPAlgo_Algo.
- The public method BOPDS_DS::VerticesOnIn has been renamed to SubShapesOnIn, and the new output parameter theCommonPB has been added.
- In BOPTools_AlgoTools, a new argument "theFuzzyValue" has been added in the methods ComputeVV and AreFacesSameDomain.
- In IntTools_Context, a new argument "theFuzzyValue" has been added in the methods ComputeVE and ComputeVF.
- The methods SetFuzzyValue and FuzzyValue have been added in the classes IntTools_EdgeEdge, IntTools_FaceFace.
- In the class IntTools_EdgeFace, the methods SetTolE, SetTolF, TolE, TolF have been removed, and the methods SetFuzzyValue, FuzzyValue have been added.
- The new argument "theTol" has been added in the method IntTools_WLineTool::DecompositionOfWLine.

Some improvements in algorithms have been made during fighting with regressions:

- Correct initialization of pave blocks for degenerated edges.
- In BOPAlgo_PaveFiller::MakeBlocks(), filter out paves on intersection curve that were put on the curve accidentally due to wide range of E-F intersection vertex.
- In the method IntTools_Tools::ComputeTolerance the margin added to the computed tolerance has been increased up to 0.001%.
- The method BOPAlgo_PaveFiller::PutPaveOnCurve has been corrected in order to use the original vertex tolerance instead of the value increased during putting it on other curves.
- The new method BOPDS_PaveBlock::RemoveExtPave has been added.
- The vertex tolerance computation in BOPTools_AlgoTools::CorrectCurveOnSurface has been improved, taking into account intersection segments between p-curves (to avoid regression on "bugs modalg_6 bug22794").
- Improve IsExistingPaveBlock to make more stable catching of coincidence of common block with section curve (against regression "bugs modalg_4 bug697_2" on Linux).

Test case for the bug has been added.

The following test cases have been updated as improvements:
boolean gdml_private ZH2 ZI7 ZJ7
boolean volumemaker C4

The test case bugs/modalg_4/pro19653 has been corrected to make it stable. See comment inside the script for details.

The test case bugs/modalg_6/bug25880 has been corrected to suppress wrong bfuse commands.

The test bugs/modalg_6/bug26954_3 has been corrected to compare the result with more precise reference value.

The "faulty" TODO in boolean/volumemaker/A8 has been made actual for Linux as well.

//Eliminate compilation error on Linux.
2016-11-08 16:42:44 +03:00

1527 lines
44 KiB
C++

// Created by: Eugeny MALTCHIKOV
// Copyright (c) 2013-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Bnd_Box.hxx>
#include <BndLib_Add3dCurve.hxx>
#include <BOPCol_MapOfInteger.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <ElCLib.hxx>
#include <Geom_BezierCurve.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_Line.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_OffsetCurve.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <gp_Dir.hxx>
#include <gp_Lin.hxx>
#include <IntTools_CommonPrt.hxx>
#include <IntTools_EdgeEdge.hxx>
#include <IntTools_Range.hxx>
#include <IntTools_Tools.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Iterator.hxx>
static
void BndBuildBox(const BRepAdaptor_Curve& theBAC,
const Standard_Real aT1,
const Standard_Real aT2,
const Standard_Real theTol,
Bnd_Box& theBox);
static
Standard_Real PointBoxDistance(const Bnd_Box& aB,
const gp_Pnt& aP);
static
Standard_Integer SplitRangeOnSegments(const Standard_Real aT1,
const Standard_Real aT2,
const Standard_Real theResolution,
const Standard_Integer theNbSeg,
IntTools_SequenceOfRanges& theSegments);
static
Standard_Integer DistPC(const Standard_Real aT1,
const Handle(Geom_Curve)& theC1,
const Standard_Real theCriteria,
GeomAPI_ProjectPointOnCurve& theProjector,
Standard_Real& aD,
Standard_Real& aT2,
const Standard_Integer iC = 1);
static
Standard_Integer DistPC(const Standard_Real aT1,
const Handle(Geom_Curve)& theC1,
const Standard_Real theCriteria,
GeomAPI_ProjectPointOnCurve& theProjector,
Standard_Real& aD,
Standard_Real& aT2,
Standard_Real& aDmax,
Standard_Real& aT1max,
Standard_Real& aT2max,
const Standard_Integer iC = 1);
static
Standard_Integer FindDistPC(const Standard_Real aT1A,
const Standard_Real aT1B,
const Handle(Geom_Curve)& theC1,
const Standard_Real theCriteria,
const Standard_Real theEps,
GeomAPI_ProjectPointOnCurve& theProjector,
Standard_Real& aDmax,
Standard_Real& aT1max,
Standard_Real& aT2max,
const Standard_Boolean bMaxDist = Standard_True);
static
Standard_Real ResolutionCoeff(const BRepAdaptor_Curve& theBAC,
const IntTools_Range& theRange);
static
Standard_Real Resolution(const Handle(Geom_Curve)& theCurve,
const GeomAbs_CurveType theCurveType,
const Standard_Real theResCoeff,
const Standard_Real theR3D);
static
Standard_Real CurveDeflection(const BRepAdaptor_Curve& theBAC,
const IntTools_Range& theRange);
static
Standard_Boolean IsClosed(const Handle(Geom_Curve)& theCurve,
const Standard_Real aT1,
const Standard_Real aT2,
const Standard_Real theTol,
const Standard_Real theRes);
static
Standard_Integer TypeToInteger(const GeomAbs_CurveType theCType);
//=======================================================================
//function : Prepare
//purpose :
//=======================================================================
void IntTools_EdgeEdge::Prepare()
{
GeomAbs_CurveType aCT1, aCT2;
Standard_Integer iCT1, iCT2;
//
myCurve1.Initialize(myEdge1);
myCurve2.Initialize(myEdge2);
//
if (myRange1.First() == 0. && myRange1.Last() == 0.) {
myRange1.SetFirst(myCurve1.FirstParameter());
myRange1.SetLast (myCurve1.LastParameter());
}
//
if (myRange2.First() == 0. && myRange2.Last() == 0.) {
myRange2.SetFirst(myCurve2.FirstParameter());
myRange2.SetLast (myCurve2.LastParameter());
}
//
aCT1 = myCurve1.GetType();
aCT2 = myCurve2.GetType();
//
iCT1 = TypeToInteger(aCT1);
iCT2 = TypeToInteger(aCT2);
//
if (iCT1 == iCT2) {
if (iCT1 != 0) {
//compute deflection
Standard_Real aC1, aC2;
//
aC2 = CurveDeflection(myCurve2, myRange2);
aC1 = (aC2 > Precision::Confusion()) ?
CurveDeflection(myCurve1, myRange1) : 1.;
//
if (aC1 < aC2) {
--iCT1;
}
}
}
//
if (iCT1 < iCT2) {
TopoDS_Edge tmpE = myEdge1;
myEdge1 = myEdge2;
myEdge2 = tmpE;
//
BRepAdaptor_Curve tmpC = myCurve1;
myCurve1 = myCurve2;
myCurve2 = tmpC;
//
IntTools_Range tmpR = myRange1;
myRange1 = myRange2;
myRange2 = tmpR;
//
mySwap = Standard_True;
}
//
Standard_Real aTolAdd = myFuzzyValue / 2.;
myTol1 = myCurve1.Tolerance() + aTolAdd;
myTol2 = myCurve2.Tolerance() + aTolAdd;
myTol = myTol1 + myTol2;
//
if (iCT1 != 0 || iCT2 != 0) {
Standard_Real f, l, aTM;
//
myGeom1 = BRep_Tool::Curve(myEdge1, f, l);
myGeom2 = BRep_Tool::Curve(myEdge2, f, l);
//
myResCoeff1 = ResolutionCoeff(myCurve1, myRange1);
myResCoeff2 = ResolutionCoeff(myCurve2, myRange2);
//
myRes1 = Resolution(myCurve1.Curve().Curve(), myCurve1.GetType(), myResCoeff1, myTol1);
myRes2 = Resolution(myCurve2.Curve().Curve(), myCurve2.GetType(), myResCoeff2, myTol2);
//
myPTol1 = 5.e-13;
aTM = Max(fabs(myRange1.First()), fabs(myRange1.Last()));
if (aTM > 999.) {
myPTol1 = 5.e-16 * aTM;
}
//
myPTol2 = 5.e-13;
aTM = Max(fabs(myRange2.First()), fabs(myRange2.Last()));
if (aTM > 999.) {
myPTol2 = 5.e-16 * aTM;
}
}
}
//=======================================================================
//function : Perform
//purpose :
//=======================================================================
void IntTools_EdgeEdge::Perform()
{
//1. Check data
CheckData();
if (myErrorStatus) {
return;
}
//
//2. Prepare Data
Prepare();
//
//3.1. Check Line/Line case
if (myCurve1.GetType() == GeomAbs_Line &&
myCurve2.GetType() == GeomAbs_Line) {
ComputeLineLine();
return;
}
//
if (myQuickCoincidenceCheck) {
if (IsCoincident()) {
Standard_Real aT11, aT12, aT21, aT22;
//
myRange1.Range(aT11, aT12);
myRange2.Range(aT21, aT22);
AddSolution(aT11, aT12, aT21, aT22, TopAbs_EDGE);
return;
}
}
//
IntTools_SequenceOfRanges aRanges1, aRanges2;
//
//3.2. Find ranges containig solutions
Standard_Boolean bSplit2;
FindSolutions(aRanges1, aRanges2, bSplit2);
//
//4. Merge solutions and save common parts
MergeSolutions(aRanges1, aRanges2, bSplit2);
}
//=======================================================================
//function : IsCoincident
//purpose :
//=======================================================================
Standard_Boolean IntTools_EdgeEdge::IsCoincident()
{
Standard_Integer i, iCnt, aNbSeg, aNbP2;
Standard_Real dT, aT1, aCoeff, aTresh, aD;
Standard_Real aT11, aT12, aT21, aT22;
GeomAPI_ProjectPointOnCurve aProjPC;
gp_Pnt aP1;
//
aTresh=0.5;
aNbSeg=23;
myRange1.Range(aT11, aT12);
myRange2.Range(aT21, aT22);
//
aProjPC.Init(myGeom2, aT21, aT22);
//
dT=(aT12-aT11)/aNbSeg;
//
iCnt=0;
for(i=0; i <= aNbSeg; ++i) {
aT1 = aT11+i*dT;
myGeom1->D0(aT1, aP1);
//
aProjPC.Perform(aP1);
aNbP2=aProjPC.NbPoints();
if (!aNbP2) {
continue;
}
//
aD=aProjPC.LowerDistance();
if(aD < myTol) {
++iCnt;
}
}
//
aCoeff=(Standard_Real)iCnt/((Standard_Real)aNbSeg+1);
return aCoeff > aTresh;
}
//=======================================================================
//function : FindSolutions
//purpose :
//=======================================================================
void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1,
IntTools_SequenceOfRanges& theRanges2,
Standard_Boolean& bSplit2)
{
Standard_Boolean bIsClosed2;
Standard_Real aT11, aT12, aT21, aT22;
Bnd_Box aB2;
//
bSplit2 = Standard_False;
myRange1.Range(aT11, aT12);
myRange2.Range(aT21, aT22);
//
bIsClosed2 = IsClosed(myGeom2, aT21, aT22, myTol2, myRes2);
//
if (bIsClosed2) {
Bnd_Box aB1;
BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
//
gp_Pnt aP = myGeom2->Value(aT21);
bIsClosed2 = !aB1.IsOut(aP);
}
//
if (!bIsClosed2) {
BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
FindSolutions(myRange1, myRange2, aB2, theRanges1, theRanges2);
return;
}
//
if (!CheckCoincidence(aT11, aT12, aT21, aT22, myTol, myRes1)) {
theRanges1.Append(myRange1);
theRanges2.Append(myRange2);
return;
}
//
Standard_Integer i, j, aNb1, aNb2;
IntTools_SequenceOfRanges aSegments1, aSegments2;
//
aNb1 = IsClosed(myGeom1, aT11, aT12, myTol1, myRes1) ? 2 : 1;
aNb2 = 2;
//
aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, aNb1, aSegments1);
aNb2 = SplitRangeOnSegments(aT21, aT22, myRes2, aNb2, aSegments2);
//
for (i = 1; i <= aNb1; ++i) {
const IntTools_Range& aR1 = aSegments1(i);
for (j = 1; j <= aNb2; ++j) {
const IntTools_Range& aR2 = aSegments2(j);
BndBuildBox(myCurve2, aR2.First(), aR2.Last(), myTol2, aB2);
FindSolutions(aR1, aR2, aB2, theRanges1, theRanges2);
}
}
//
bSplit2 = aNb2 > 1;
}
//=======================================================================
//function : FindSolutions
//purpose :
//=======================================================================
void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
const IntTools_Range& theR2,
const Bnd_Box& theBox2,
IntTools_SequenceOfRanges& theRanges1,
IntTools_SequenceOfRanges& theRanges2)
{
Standard_Boolean bOut, bStop, bThin;
Standard_Real aT11, aT12, aT21, aT22;
Standard_Real aTB11, aTB12, aTB21, aTB22;
Standard_Real aSmallStep1, aSmallStep2;
Standard_Integer iCom;
Bnd_Box aB1, aB2;
//
theR1.Range(aT11, aT12);
theR2.Range(aT21, aT22);
//
aB2 = theBox2;
//
bThin = Standard_False;
bStop = Standard_False;
iCom = 1;
//
do {
aTB11 = aT11;
aTB12 = aT12;
aTB21 = aT21;
aTB22 = aT22;
//
//1. Build box for first edge and find parameters
// of the second one in that box
BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
bOut = aB1.IsOut(aB2);
if (bOut) {
break;
}
//
bThin = ((aT12 - aT11) < myRes1) ||
(aB1.IsXThin(myTol) && aB1.IsYThin(myTol) && aB1.IsZThin(myTol));
//
bOut = !FindParameters(myCurve2, aTB21, aTB22, myTol2, myRes2, myPTol2,
myResCoeff2, aB1, aT21, aT22);
if (bOut || bThin) {
break;
}
//
//2. Build box for second edge and find parameters
// of the first one in that box
BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
bOut = aB1.IsOut(aB2);
if (bOut) {
break;
}
//
bThin = ((aT22 - aT21) < myRes2) ||
(aB2.IsXThin(myTol) && aB2.IsYThin(myTol) && aB2.IsZThin(myTol));
//
bOut = !FindParameters(myCurve1, aTB11, aTB12, myTol1, myRes1, myPTol1,
myResCoeff1, aB2, aT11, aT12);
//
if (bOut || bThin) {
break;
}
//
//3. Check if it makes sense to continue
aSmallStep1 = (aTB12 - aTB11) / 250.;
aSmallStep2 = (aTB22 - aTB21) / 250.;
//
if (aSmallStep1 < myRes1) {
aSmallStep1 = myRes1;
}
if (aSmallStep2 < myRes2) {
aSmallStep2 = myRes2;
}
//
if (((aT11 - aTB11) < aSmallStep1) && ((aTB12 - aT12) < aSmallStep1) &&
((aT21 - aTB21) < aSmallStep2) && ((aTB22 - aT22) < aSmallStep2)) {
bStop = Standard_True;
}
//
} while (!bStop);
//
if (bOut) {
//no intersection;
return;
}
//
if (!bThin) {
//check curves for coincidence on the ranges
iCom = CheckCoincidence(aT11, aT12, aT21, aT22, myTol, myRes1);
if (!iCom) {
bThin = Standard_True;
}
}
//
if (bThin) {
if (iCom != 0) {
//check intermediate points
Standard_Boolean bSol;
Standard_Real aT1;
gp_Pnt aP1;
GeomAPI_ProjectPointOnCurve aProjPC;
//
aT1 = (aT11 + aT12) * .5;
myGeom1->D0(aT1, aP1);
//
aProjPC.Init(myGeom2, aT21, aT22);
aProjPC.Perform(aP1);
//
if (aProjPC.NbPoints()) {
bSol = aProjPC.LowerDistance() <= myTol;
}
else {
Standard_Real aT2;
gp_Pnt aP2;
//
aT2 = (aT21 + aT22) * .5;
myGeom2->D0(aT2, aP2);
//
bSol = aP1.IsEqual(aP2, myTol);
}
//
if (!bSol) {
return;
}
}
//add common part
IntTools_Range aR1(aT11, aT12), aR2(aT21, aT22);
//
theRanges1.Append(aR1);
theRanges2.Append(aR2);
return;
}
//
if (!IsIntersection(aT11, aT12, aT21, aT22)) {
return;
}
//
//split ranges on segments and repeat
Standard_Integer i, aNb1;
IntTools_SequenceOfRanges aSegments1;
//
IntTools_Range aR2(aT21, aT22);
BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
//
aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, 3, aSegments1);
for (i = 1; i <= aNb1; ++i) {
const IntTools_Range& aR1 = aSegments1(i);
FindSolutions(aR1, aR2, aB2, theRanges1, theRanges2);
}
}
//=======================================================================
//function : FindParameters
//purpose :
//=======================================================================
Standard_Boolean IntTools_EdgeEdge::FindParameters(const BRepAdaptor_Curve& theBAC,
const Standard_Real aT1,
const Standard_Real aT2,
const Standard_Real theTol,
const Standard_Real theRes,
const Standard_Real thePTol,
const Standard_Real theResCoeff,
const Bnd_Box& theCBox,
Standard_Real& aTB1,
Standard_Real& aTB2)
{
Standard_Boolean bRet;
Standard_Integer aC, i, k;
Standard_Real aCf, aDiff, aDt, aT, aTB, aTOut, aTIn;
Standard_Real aDist, aDistP, aDistTol;
gp_Pnt aP;
Bnd_Box aCBx;
//
bRet = Standard_False;
aCf = 0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))/2.;
aDt = theRes;
aDistP = 0.;
aDistTol = 1e-9;
aCBx = theCBox;
aCBx.Enlarge(theTol);
//
const Handle(Geom_Curve)& aCurve = theBAC.Curve().Curve();
const GeomAbs_CurveType aCurveType = theBAC.GetType();
//
for (i = 0; i < 2; ++i) {
aTB = !i ? aT1 : aT2;
aT = !i ? aT2 : aTB1;
aC = !i ? 1 : -1;
bRet = Standard_False;
k = 0;
//looking for the point on the edge which is in the box;
while (aC*(aT-aTB) >= 0) {
theBAC.D0(aTB, aP);
aDist = PointBoxDistance(theCBox, aP);
if (aDist > theTol) {
if (fabs(aDist - aDistP) < aDistTol) {
aDt = Resolution(aCurve, aCurveType, theResCoeff, (++k)*aDist);
} else {
k = 0;
aDt = Resolution(aCurve, aCurveType, theResCoeff, aDist);
}
aTB += aC*aDt;
} else {
bRet = Standard_True;
break;
}
aDistP = aDist;
}
//
if (!bRet) {
if (!i) {
//edge is out of the box;
return bRet;
} else {
bRet = !bRet;
aTB = aTB1;
aDt = aT2 - aTB1;
}
}
//
aT = !i ? aT1 : aT2;
if (aTB != aT) {
//one point IN, one point OUT; looking for the bounding point;
aTIn = aTB;
aTOut = aTB - aC*aDt;
aDiff = aTIn - aTOut;
while (fabs(aDiff) > thePTol) {
aTB = aTOut + aDiff*aCf;
theBAC.D0(aTB, aP);
if (aCBx.IsOut(aP)) {
aTOut = aTB;
} else {
aTIn = aTB;
}
aDiff = aTIn - aTOut;
}
}
if (!i) {
aTB1 = aTB;
} else {
aTB2 = aTB;
}
}
return bRet;
}
//=======================================================================
//function : MergeSolutions
//purpose :
//=======================================================================
void IntTools_EdgeEdge::MergeSolutions(const IntTools_SequenceOfRanges& theRanges1,
const IntTools_SequenceOfRanges& theRanges2,
const Standard_Boolean bSplit2)
{
Standard_Integer aNbCP = theRanges1.Length();
if (aNbCP == 0) {
return;
}
//
IntTools_Range aRi1, aRi2, aRj1, aRj2;
Standard_Boolean bCond;
Standard_Integer i, j;
TopAbs_ShapeEnum aType;
Standard_Real aT11, aT12, aT21, aT22;
Standard_Real aTi11, aTi12, aTi21, aTi22;
Standard_Real aTj11, aTj12, aTj21, aTj22;
Standard_Real aRes1, aRes2, dTR1, dTR2;
BOPCol_MapOfInteger aMI;
//
aRes1 = Resolution(myCurve1.Curve().Curve(),
myCurve1.GetType(), myResCoeff1, myTol);
aRes2 = Resolution(myCurve2.Curve().Curve(),
myCurve2.GetType(), myResCoeff2, myTol);
//
myRange1.Range(aT11, aT12);
myRange2.Range(aT21, aT22);
dTR1 = 20*aRes1;
dTR2 = 20*aRes2;
aType = TopAbs_VERTEX;
//
for (i = 1; i <= aNbCP;) {
if (aMI.Contains(i)) {
++i;
continue;
}
//
aRi1 = theRanges1(i);
aRi2 = theRanges2(i);
//
aRi1.Range(aTi11, aTi12);
aRi2.Range(aTi21, aTi22);
//
aMI.Add(i);
//
for (j = i+1; j <= aNbCP; ++j) {
if (aMI.Contains(j)) {
continue;
}
//
aRj1 = theRanges1(j);
aRj2 = theRanges2(j);
//
aRj1.Range(aTj11, aTj12);
aRj2.Range(aTj21, aTj22);
//
bCond = (fabs(aTi12 - aTj11) < dTR1) ||
(bSplit2 && (fabs(aTj12 - aTi11) < dTR1));
if (bCond && bSplit2) {
bCond = (fabs((Max(aTi22, aTj22) - Min(aTi21, aTj21)) -
((aTi22 - aTi21) + (aTj22 - aTj21))) < dTR2);
}
//
if (bCond) {
aTi11 = Min(aTi11, aTj11);
aTi12 = Max(aTi12, aTj12);
aTi21 = Min(aTi21, aTj21);
aTi22 = Max(aTi22, aTj22);
aMI.Add(j);
}
else if (!bSplit2) {
i = j;
break;
}
}
//
if (((fabs(aT11 - aTi11) < myRes1) && (fabs(aT12 - aTi12) < myRes1)) ||
((fabs(aT21 - aTi21) < myRes2) && (fabs(aT22 - aTi22) < myRes2))) {
aType = TopAbs_EDGE;
myCommonParts.Clear();
}
//
AddSolution(aTi11, aTi12, aTi21, aTi22, aType);
if (aType == TopAbs_EDGE) {
break;
}
//
if (bSplit2) {
++i;
}
}
}
//=======================================================================
//function : AddSolution
//purpose :
//=======================================================================
void IntTools_EdgeEdge::AddSolution(const Standard_Real aT11,
const Standard_Real aT12,
const Standard_Real aT21,
const Standard_Real aT22,
const TopAbs_ShapeEnum theType)
{
IntTools_CommonPrt aCPart;
//
aCPart.SetType(theType);
if (!mySwap) {
aCPart.SetEdge1(myEdge1);
aCPart.SetEdge2(myEdge2);
aCPart.SetRange1(aT11, aT12);
aCPart.AppendRange2(aT21, aT22);
} else {
aCPart.SetEdge1(myEdge2);
aCPart.SetEdge2(myEdge1);
aCPart.SetRange1(aT21, aT22);
aCPart.AppendRange2(aT11, aT12);
}
//
if (theType == TopAbs_VERTEX) {
Standard_Real aT1, aT2;
//
FindBestSolution(aT11, aT12, aT21, aT22, aT1, aT2);
//
if (!mySwap) {
aCPart.SetVertexParameter1(aT1);
aCPart.SetVertexParameter2(aT2);
} else {
aCPart.SetVertexParameter1(aT2);
aCPart.SetVertexParameter2(aT1);
}
}
myCommonParts.Append(aCPart);
}
//=======================================================================
//function : FindBestSolution
//purpose :
//=======================================================================
void IntTools_EdgeEdge::FindBestSolution(const Standard_Real aT11,
const Standard_Real aT12,
const Standard_Real aT21,
const Standard_Real aT22,
Standard_Real& aT1,
Standard_Real& aT2)
{
Standard_Integer i, aNbS, iErr;
Standard_Real aDMin, aD, aRes1, aSolCriteria, aTouchCriteria;
Standard_Real aT1A, aT1B, aT1Min, aT2Min;
Standard_Real aT1Im, aT2Im, aT1Touch;
GeomAPI_ProjectPointOnCurve aProjPC;
IntTools_SequenceOfRanges aRanges;
Standard_Boolean bTouch;
//
aDMin = Precision::Infinite();
aSolCriteria = 5.e-16;
aTouchCriteria = 5.e-13;
bTouch = Standard_False;
aT1Touch = aT11;
//
aRes1 = Resolution(myCurve1.Curve().Curve(),
myCurve1.GetType(), myResCoeff1, myTol);
aNbS = 10;
aNbS = SplitRangeOnSegments(aT11, aT12, 3*aRes1, aNbS, aRanges);
//
aProjPC.Init(myGeom2, aT21, aT22);
//
aT1 = (aT11 + aT12) * 0.5;
iErr = DistPC(aT1, myGeom1, aSolCriteria, aProjPC, aD, aT2, -1);
if (iErr == 1) {
aT2 = (aT21 + aT22) * 0.5;
}
//
aT1Im = aT1;
aT2Im = aT2;
//
for (i = 1; i <= aNbS; ++i) {
const IntTools_Range& aR1 = aRanges(i);
aR1.Range(aT1A, aT1B);
//
aD = myTol;
iErr = FindDistPC(aT1A, aT1B, myGeom1, aSolCriteria, myPTol1,
aProjPC, aD, aT1Min, aT2Min, Standard_False);
if (iErr != 1) {
if (aD < aDMin) {
aT1 = aT1Min;
aT2 = aT2Min;
aDMin = aD;
}
//
if (aD < aTouchCriteria) {
if (bTouch) {
aT1A = (aT1Touch + aT1Min) * 0.5;
iErr = DistPC(aT1A, myGeom1, aTouchCriteria,
aProjPC, aD, aT2Min, -1);
if (aD > aTouchCriteria) {
aT1 = aT1Im;
aT2 = aT2Im;
break;
}
}
else {
aT1Touch = aT1Min;
bTouch = Standard_True;
}
}
}
}
}
//=======================================================================
//function : ComputeLineLine
//purpose :
//=======================================================================
void IntTools_EdgeEdge::ComputeLineLine()
{
Standard_Boolean IsParallel, IsCoincide;
Standard_Real aSin, aCos, aAng, aTol;
Standard_Real aT1, aT2, aT11, aT12, aT21, aT22;
gp_Pnt aP11, aP12;
gp_Lin aL1, aL2;
gp_Dir aD1, aD2;
IntTools_CommonPrt aCommonPrt;
//
IsParallel = Standard_False;
IsCoincide = Standard_False;
aTol = myTol*myTol;
aL1 = myCurve1.Line();
aL2 = myCurve2.Line();
aD1 = aL1.Position().Direction();
aD2 = aL2.Position().Direction();
myRange1.Range(aT11, aT12);
myRange2.Range(aT21, aT22);
//
aCommonPrt.SetEdge1(myEdge1);
aCommonPrt.SetEdge2(myEdge2);
//
aCos = aD1.Dot(aD2);
aAng = (aCos >= 0.) ? 2.*(1. - aCos) : 2.*(1. + aCos);
//
if(aAng <= Precision::Angular()) {
IsParallel = Standard_True;
if(aL1.SquareDistance(aL2.Location()) <= aTol) {
IsCoincide = Standard_True;
aP11 = ElCLib::Value(aT11, aL1);
aP12 = ElCLib::Value(aT12, aL1);
}
}
else {
aP11 = ElCLib::Value(aT11, aL1);
aP12 = ElCLib::Value(aT12, aL1);
if(aL2.SquareDistance(aP11) <= aTol && aL2.SquareDistance(aP12) <= aTol) {
IsCoincide = Standard_True;
}
}
//
if (IsCoincide) {
Standard_Real t21, t22;
//
t21 = ElCLib::Parameter(aL2, aP11);
t22 = ElCLib::Parameter(aL2, aP12);
if((t21 > aT22 && t22 > aT22) || (t21 < aT21 && t22 < aT21)) {
return;
}
//
Standard_Real temp;
if(t21 > t22) {
temp = t21;
t21 = t22;
t22 = temp;
}
//
if(t21 >= aT21) {
if(t22 <= aT22) {
aCommonPrt.SetRange1(aT11, aT12);
aCommonPrt.SetAllNullFlag(Standard_True);
aCommonPrt.AppendRange2(t21, t22);
}
else {
aCommonPrt.SetRange1(aT11, aT12 - (t22 - aT22));
aCommonPrt.AppendRange2(t21, aT22);
}
}
else {
aCommonPrt.SetRange1(aT11 + (aT21 - t21), aT12);
aCommonPrt.AppendRange2(aT21, t22);
}
aCommonPrt.SetType(TopAbs_EDGE);
myCommonParts.Append(aCommonPrt);
return;
}
//
if (IsParallel) {
return;
}
//
{
TopoDS_Iterator aIt1, aIt2;
aIt1.Initialize(myEdge1);
for (; aIt1.More(); aIt1.Next()) {
const TopoDS_Shape& aV1 = aIt1.Value();
aIt2.Initialize(myEdge2);
for (; aIt2.More(); aIt2.Next()) {
const TopoDS_Shape& aV2 = aIt2.Value();
if (aV2.IsSame(aV1)) {
return;
}
}
}
}
//
aSin = 1. - aCos*aCos;
gp_Pnt O1 = aL1.Location();
gp_Pnt O2 = aL2.Location();
gp_Vec O1O2 (O1, O2);
//
aT2 = (aD1.XYZ()*(O1O2.Dot(aD1))-(O1O2.XYZ())).Dot(aD2.XYZ());
aT2 /= aSin;
//
if(aT2 < aT21 || aT2 > aT22) {
return;
}
//
gp_Pnt aP2(ElCLib::Value(aT2, aL2));
aT1 = (gp_Vec(O1, aP2)).Dot(aD1);
//
if(aT1 < aT11 || aT1 > aT12) {
return;
}
//
gp_Pnt aP1(ElCLib::Value(aT1, aL1));
Standard_Real aDist = aP1.SquareDistance(aP2);
//
if (aDist > aTol) {
return;
}
//
// compute correct range on the edges
Standard_Real anAngle, aDt1, aDt2;
//
anAngle = aD1.Angle(aD2);
//
aDt1 = IntTools_Tools::ComputeIntRange(myTol1, myTol2, anAngle);
aDt2 = IntTools_Tools::ComputeIntRange(myTol2, myTol1, anAngle);
//
aCommonPrt.SetRange1(aT1 - aDt1, aT1 + aDt1);
aCommonPrt.AppendRange2(aT2 - aDt2, aT2 + aDt2);
aCommonPrt.SetType(TopAbs_VERTEX);
aCommonPrt.SetVertexParameter1(aT1);
aCommonPrt.SetVertexParameter2(aT2);
myCommonParts.Append(aCommonPrt);
}
//=======================================================================
//function : IsIntersection
//purpose :
//=======================================================================
Standard_Boolean IntTools_EdgeEdge::IsIntersection(const Standard_Real aT11,
const Standard_Real aT12,
const Standard_Real aT21,
const Standard_Real aT22)
{
Standard_Boolean bRet;
gp_Pnt aP11, aP12, aP21, aP22;
gp_Vec aV11, aV12, aV21, aV22;
Standard_Real aD11_21, aD11_22, aD12_21, aD12_22, aCriteria, aCoef;
Standard_Boolean bSmall_11_21, bSmall_11_22, bSmall_12_21, bSmall_12_22;
//
bRet = Standard_True;
aCoef = 1.e+5;
if (((aT12 - aT11) > aCoef*myRes1) && ((aT22 - aT21) > aCoef*myRes2)) {
aCoef = 5000;
} else {
Standard_Real aTRMin = Min((aT12 - aT11)/myRes1, (aT22 - aT21)/myRes2);
aCoef = aTRMin / 100.;
if (aCoef < 1.) {
aCoef = 1.;
}
}
aCriteria = aCoef * myTol;
aCriteria *= aCriteria;
//
myGeom1->D1(aT11, aP11, aV11);
myGeom1->D1(aT12, aP12, aV12);
myGeom2->D1(aT21, aP21, aV21);
myGeom2->D1(aT22, aP22, aV22);
//
aD11_21 = aP11.SquareDistance(aP21);
aD11_22 = aP11.SquareDistance(aP22);
aD12_21 = aP12.SquareDistance(aP21);
aD12_22 = aP12.SquareDistance(aP22);
//
bSmall_11_21 = aD11_21 < aCriteria;
bSmall_11_22 = aD11_22 < aCriteria;
bSmall_12_21 = aD12_21 < aCriteria;
bSmall_12_22 = aD12_22 < aCriteria;
//
if ((bSmall_11_21 && bSmall_12_22) ||
(bSmall_11_22 && bSmall_12_21)) {
if (aCoef == 1.) {
return bRet;
}
//
Standard_Real anAngleCriteria;
Standard_Real anAngle1, anAngle2;
//
anAngleCriteria = 5.e-3;
if (bSmall_11_21 && bSmall_12_22) {
anAngle1 = aV11.Angle(aV21);
anAngle2 = aV12.Angle(aV22);
} else {
anAngle1 = aV11.Angle(aV22);
anAngle2 = aV12.Angle(aV21);
}
//
if (((anAngle1 < anAngleCriteria) || ((M_PI - anAngle1) < anAngleCriteria)) ||
((anAngle2 < anAngleCriteria) || ((M_PI - anAngle2) < anAngleCriteria))) {
GeomAPI_ProjectPointOnCurve aProjPC;
Standard_Integer iErr;
Standard_Real aD, aT1Min, aT2Min;
//
aD = Precision::Infinite();
aProjPC.Init(myGeom2, aT21, aT22);
iErr = FindDistPC(aT11, aT12, myGeom1, myTol, myRes1,
aProjPC, aD, aT1Min, aT2Min, Standard_False);
bRet = (iErr == 2);
}
}
return bRet;
}
//=======================================================================
//function : CheckCoincidence
//purpose :
//=======================================================================
Standard_Integer IntTools_EdgeEdge::CheckCoincidence(const Standard_Real aT11,
const Standard_Real aT12,
const Standard_Real aT21,
const Standard_Real aT22,
const Standard_Real theCriteria,
const Standard_Real theCurveRes1)
{
Standard_Integer iErr, aNb, aNb1, i;
Standard_Real aT1A, aT1B, aT1max, aT2max, aDmax;
GeomAPI_ProjectPointOnCurve aProjPC;
IntTools_SequenceOfRanges aRanges;
//
iErr = 0;
aDmax = -1.;
aProjPC.Init(myGeom2, aT21, aT22);
//
// 1. Express evaluation
aNb = 10; // Number of intervals on the curve #1
aNb1 = SplitRangeOnSegments(aT11, aT12, theCurveRes1, aNb, aRanges);
for (i = 1; i < aNb1; ++i) {
const IntTools_Range& aR1 = aRanges(i);
aR1.Range(aT1A, aT1B);
//
iErr = DistPC(aT1B, myGeom1, theCriteria, aProjPC, aDmax, aT2max);
if (iErr) {
return iErr;
}
}
//
// if the ranges in aRanges are less than theCurveRes1,
// there is no need to do step 2 (deep evaluation)
if (aNb1 < aNb) {
return iErr;
}
//
// 2. Deep evaluation
for (i = 2; i < aNb1; ++i) {
const IntTools_Range& aR1 = aRanges(i);
aR1.Range(aT1A, aT1B);
//
iErr = FindDistPC(aT1A, aT1B, myGeom1, theCriteria, theCurveRes1,
aProjPC, aDmax, aT1max, aT2max);
if (iErr) {
return iErr;
}
}
// Possible values:
// iErr == 0 - the patches are coincided
// iErr == 1 - a point from aC1 can not be projected on aC2
// iErr == 2 - the distance is too big
return iErr;
}
//=======================================================================
//function : FindDistPC
//purpose :
//=======================================================================
Standard_Integer FindDistPC(const Standard_Real aT1A,
const Standard_Real aT1B,
const Handle(Geom_Curve)& theC1,
const Standard_Real theCriteria,
const Standard_Real theEps,
GeomAPI_ProjectPointOnCurve& theProjPC,
Standard_Real& aDmax,
Standard_Real& aT1max,
Standard_Real& aT2max,
const Standard_Boolean bMaxDist)
{
Standard_Integer iErr, iC;
Standard_Real aGS, aXP, aA, aB, aXL, aYP, aYL, aT2P, aT2L;
//
iC = bMaxDist ? 1 : -1;
iErr = 0;
aT1max = aT2max = 0.; // silence GCC warning
//
aGS = 0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))-1.;
aA = aT1A;
aB = aT1B;
//
// check bounds
iErr = DistPC(aA, theC1, theCriteria, theProjPC,
aYP, aT2P, aDmax, aT1max, aT2max, iC);
if (iErr == 2) {
return iErr;
}
//
iErr = DistPC(aB, theC1, theCriteria, theProjPC,
aYL, aT2L, aDmax, aT1max, aT2max, iC);
if (iErr == 2) {
return iErr;
}
//
aXP = aA + (aB - aA)*aGS;
aXL = aB - (aB - aA)*aGS;
//
iErr = DistPC(aXP, theC1, theCriteria, theProjPC,
aYP, aT2P, aDmax, aT1max, aT2max, iC);
if (iErr) {
return iErr;
}
//
iErr = DistPC(aXL, theC1, theCriteria, theProjPC,
aYL, aT2L, aDmax, aT1max, aT2max, iC);
if (iErr) {
return iErr;
}
//
for (;;) {
if (iC*(aYP - aYL) > 0) {
aA = aXL;
aXL = aXP;
aYL = aYP;
aXP = aA + (aB - aA)*aGS;
iErr = DistPC(aXP, theC1, theCriteria, theProjPC,
aYP, aT2P, aDmax, aT1max, aT2max, iC);
}
else {
aB = aXP;
aXP = aXL;
aYP = aYL;
aXL = aB - (aB - aA)*aGS;
iErr = DistPC(aXL, theC1, theCriteria, theProjPC,
aYL, aT2L, aDmax, aT1max, aT2max, iC);
}
//
if (iErr) {
if ((iErr == 2) && !bMaxDist) {
aXP = (aA + aB) * 0.5;
DistPC(aXP, theC1, theCriteria, theProjPC,
aYP, aT2P, aDmax, aT1max, aT2max, iC);
}
return iErr;
}
//
if ((aB - aA) < theEps) {
break;
}
}// for (;;) {
//
return iErr;
}
//=======================================================================
//function : DistPC
//purpose :
//=======================================================================
Standard_Integer DistPC(const Standard_Real aT1,
const Handle(Geom_Curve)& theC1,
const Standard_Real theCriteria,
GeomAPI_ProjectPointOnCurve& theProjPC,
Standard_Real& aD,
Standard_Real& aT2,
Standard_Real& aDmax,
Standard_Real& aT1max,
Standard_Real& aT2max,
const Standard_Integer iC)
{
Standard_Integer iErr;
//
iErr = DistPC(aT1, theC1, theCriteria, theProjPC, aD, aT2, iC);
if (iErr == 1) {
return iErr;
}
//
if (iC*(aD - aDmax) > 0) {
aDmax = aD;
aT1max = aT1;
aT2max = aT2;
}
//
return iErr;
}
//=======================================================================
//function : DistPC
//purpose :
//=======================================================================
Standard_Integer DistPC(const Standard_Real aT1,
const Handle(Geom_Curve)& theC1,
const Standard_Real theCriteria,
GeomAPI_ProjectPointOnCurve& theProjPC,
Standard_Real& aD,
Standard_Real& aT2,
const Standard_Integer iC)
{
Standard_Integer iErr, aNbP2;
gp_Pnt aP1;
//
iErr = 0;
theC1->D0(aT1, aP1);
//
theProjPC.Perform(aP1);
aNbP2 = theProjPC.NbPoints();
if (!aNbP2) {
iErr = 1;// the point from aC1 can not be projected on aC2
return iErr;
}
//
aD = theProjPC.LowerDistance();
aT2 = theProjPC.LowerDistanceParameter();
if (iC*(aD - theCriteria) > 0) {
iErr = 2;// the distance is too big or small
}
//
return iErr;
}
//=======================================================================
//function : SplitRangeOnSegments
//purpose :
//=======================================================================
Standard_Integer SplitRangeOnSegments(const Standard_Real aT1,
const Standard_Real aT2,
const Standard_Real theResolution,
const Standard_Integer theNbSeg,
IntTools_SequenceOfRanges& theSegments)
{
Standard_Real aDiff = aT2 - aT1;
if (aDiff < theResolution || theNbSeg == 1) {
theSegments.Append(IntTools_Range(aT1, aT2));
return 1;
}
//
Standard_Real aDt, aT1x, aT2x, aSeg;
Standard_Integer aNbSegments, i;
//
aNbSegments = theNbSeg;
aDt = aDiff / aNbSegments;
if (aDt < theResolution) {
aSeg = aDiff / theResolution;
aNbSegments = Standard_Integer(aSeg) + 1;
aDt = aDiff / aNbSegments;
}
//
aT1x = aT1;
for (i = 1; i < aNbSegments; ++i) {
aT2x = aT1x + aDt;
//
IntTools_Range aR(aT1x, aT2x);
theSegments.Append(aR);
//
aT1x = aT2x;
}
//
IntTools_Range aR(aT1x, aT2);
theSegments.Append(aR);
//
return aNbSegments;
}
//=======================================================================
//function : BndBuildBox
//purpose :
//=======================================================================
void BndBuildBox(const BRepAdaptor_Curve& theBAC,
const Standard_Real aT1,
const Standard_Real aT2,
const Standard_Real theTol,
Bnd_Box& theBox)
{
Bnd_Box aB;
BndLib_Add3dCurve::Add(theBAC, aT1, aT2, theTol, aB);
theBox = aB;
}
//=======================================================================
//function : PointBoxDistance
//purpose :
//=======================================================================
Standard_Real PointBoxDistance(const Bnd_Box& aB,
const gp_Pnt& aP)
{
Standard_Real aPCoord[3];
Standard_Real aBMinCoord[3], aBMaxCoord[3];
Standard_Real aDist, aR1, aR2;
Standard_Integer i;
//
aP.Coord(aPCoord[0], aPCoord[1], aPCoord[2]);
aB.Get(aBMinCoord[0], aBMinCoord[1], aBMinCoord[2],
aBMaxCoord[0], aBMaxCoord[1], aBMaxCoord[2]);
//
aDist = 0.;
for (i = 0; i < 3; ++i) {
aR1 = aBMinCoord[i] - aPCoord[i];
if (aR1 > 0.) {
aDist += aR1*aR1;
continue;
}
//
aR2 = aPCoord[i] - aBMaxCoord[i];
if (aR2 > 0.) {
aDist += aR2*aR2;
}
}
//
aDist = Sqrt(aDist);
return aDist;
}
//=======================================================================
//function : TypeToInteger
//purpose :
//=======================================================================
Standard_Integer TypeToInteger(const GeomAbs_CurveType theCType)
{
Standard_Integer iRet;
//
switch(theCType) {
case GeomAbs_Line:
iRet=0;
break;
case GeomAbs_Hyperbola:
case GeomAbs_Parabola:
iRet=1;
break;
case GeomAbs_Circle:
case GeomAbs_Ellipse:
iRet=2;
break;
case GeomAbs_BezierCurve:
case GeomAbs_BSplineCurve:
iRet=3;
break;
default:
iRet=4;
break;
}
return iRet;
}
//=======================================================================
//function : ResolutionCoeff
//purpose :
//=======================================================================
Standard_Real ResolutionCoeff(const BRepAdaptor_Curve& theBAC,
const IntTools_Range& theRange)
{
Standard_Real aResCoeff = 0.;
//
const Handle(Geom_Curve)& aCurve = theBAC.Curve().Curve();
const GeomAbs_CurveType aCurveType = theBAC.GetType();
//
switch (aCurveType) {
case GeomAbs_Circle :
aResCoeff = 1. / (2 * Handle(Geom_Circle)::DownCast (aCurve)->Circ().Radius());
break;
case GeomAbs_Ellipse :
aResCoeff = 1. / Handle(Geom_Ellipse)::DownCast (aCurve)->MajorRadius();
break;
case GeomAbs_OffsetCurve : {
const Handle(Geom_OffsetCurve)& anOffsetCurve = Handle(Geom_OffsetCurve)::DownCast(aCurve);
const Handle(Geom_Curve)& aBasisCurve = anOffsetCurve->BasisCurve();
const GeomAbs_CurveType aBCType = GeomAdaptor_Curve(aBasisCurve).GetType();
if (aBCType == GeomAbs_Line) {
break;
}
else if (aBCType == GeomAbs_Circle) {
aResCoeff = 1. / (2 * (anOffsetCurve->Offset() +
Handle(Geom_Circle)::DownCast (aBasisCurve)->Circ().Radius()));
break;
}
else if (aBCType == GeomAbs_Ellipse) {
aResCoeff = 1. / (anOffsetCurve->Offset() +
Handle(Geom_Ellipse)::DownCast (aBasisCurve)->MajorRadius());
break;
}
}
case GeomAbs_Hyperbola :
case GeomAbs_Parabola :
case GeomAbs_OtherCurve :{
Standard_Real k, kMin, aDist, aDt, aT1, aT2, aT;
Standard_Integer aNbP, i;
gp_Pnt aP1, aP2;
//
aNbP = 30;
theRange.Range(aT1, aT2);
aDt = (aT2 - aT1) / aNbP;
aT = aT1;
kMin = 10.;
//
theBAC.D0(aT1, aP1);
for (i = 1; i <= aNbP; ++i) {
aT += aDt;
theBAC.D0(aT, aP2);
aDist = aP1.Distance(aP2);
k = aDt / aDist;
if (k < kMin) {
kMin = k;
}
aP1 = aP2;
}
//
aResCoeff = kMin;
break;
}
default:
break;
}
//
return aResCoeff;
}
//=======================================================================
//function : Resolution
//purpose :
//=======================================================================
Standard_Real Resolution(const Handle(Geom_Curve)& theCurve,
const GeomAbs_CurveType theCurveType,
const Standard_Real theResCoeff,
const Standard_Real theR3D)
{
Standard_Real aRes;
//
switch (theCurveType) {
case GeomAbs_Line :
aRes = theR3D;
break;
case GeomAbs_Circle: {
Standard_Real aDt = theResCoeff * theR3D;
aRes = (aDt <= 1.) ? 2*ASin(aDt) : 2*M_PI;
break;
}
case GeomAbs_BezierCurve:
Handle(Geom_BezierCurve)::DownCast (theCurve)->Resolution(theR3D, aRes);
break;
case GeomAbs_BSplineCurve:
Handle(Geom_BSplineCurve)::DownCast (theCurve)->Resolution(theR3D, aRes);
break;
case GeomAbs_OffsetCurve: {
const Handle(Geom_Curve)& aBasisCurve =
Handle(Geom_OffsetCurve)::DownCast(theCurve)->BasisCurve();
const GeomAbs_CurveType aBCType = GeomAdaptor_Curve(aBasisCurve).GetType();
if (aBCType == GeomAbs_Line) {
aRes = theR3D;
break;
}
else if (aBCType == GeomAbs_Circle) {
Standard_Real aDt = theResCoeff * theR3D;
aRes = (aDt <= 1.) ? 2*ASin(aDt) : 2*M_PI;
break;
}
}
default:
aRes = theResCoeff * theR3D;
break;
}
//
return aRes;
}
//=======================================================================
//function : CurveDeflection
//purpose :
//=======================================================================
Standard_Real CurveDeflection(const BRepAdaptor_Curve& theBAC,
const IntTools_Range& theRange)
{
Standard_Real aDt, aT, aT1, aT2, aDefl;
Standard_Integer i, aNbP;
gp_Vec aV1, aV2;
gp_Pnt aP;
//
aDefl = 0;
aNbP = 10;
theRange.Range(aT1, aT2);
aDt = (aT2 - aT1) / aNbP;
aT = aT1;
//
theBAC.D1(aT1, aP, aV1);
for (i = 1; i <= aNbP; ++i) {
aT += aDt;
theBAC.D1(aT, aP, aV2);
if (aV1.Magnitude() > gp::Resolution() &&
aV2.Magnitude() > gp::Resolution()) {
gp_Dir aD1(aV1), aD2(aV2);
aDefl += aD1.Angle(aD2);
}
aV1 = aV2;
}
//
return aDefl;
}
//=======================================================================
//function : IsClosed
//purpose :
//=======================================================================
Standard_Boolean IsClosed(const Handle(Geom_Curve)& theCurve,
const Standard_Real aT1,
const Standard_Real aT2,
const Standard_Real theTol,
const Standard_Real theRes)
{
if (Abs(aT1 - aT2) < theRes)
{
return Standard_False;
}
gp_Pnt aP1, aP2;
theCurve->D0(aT1, aP1);
theCurve->D0(aT2, aP2);
//
Standard_Real aD = aP1.Distance(aP2);
return aD < theTol;
}