1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-05-01 10:26:12 +03:00
occt/src/IntTools/IntTools_BeanBeanIntersector.cxx
abv b9736bcc8e 0023480: New compiler warnings on MS VC 9
Unused local variables eliminated
2012-10-26 17:00:28 +04:00

1398 lines
43 KiB
C++
Executable File

// Copyright (c) 1999-2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#include <IntTools_BeanBeanIntersector.ixx>
#include <IntTools_Root.hxx>
#include <Precision.hxx>
#include <Extrema_POnCurv.hxx>
#include <BRep_Tool.hxx>
#include <Geom_Curve.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <IntTools_CArray1OfReal.hxx>
#include <gp_Lin.hxx>
#include <Intf_Array1OfLin.hxx>
#include <Bnd_Box.hxx>
#include <Extrema_ExtCC.hxx>
#include <Extrema_ExtElC.hxx>
#include <Extrema_LocateExtPC.hxx>
#include <gp_Circ.hxx>
#include <gp_Elips.hxx>
#include <IntTools.hxx>
#include <ElCLib.hxx>
#include <Geom_Line.hxx>
#include <GeomAdaptor_HCurve.hxx>
static
void LocalPrepareArgs(BRepAdaptor_Curve& theCurve,
const Standard_Real theFirstParameter,
const Standard_Real theLastParameter,
Standard_Real& theDeflection,
IntTools_CArray1OfReal& theArgs);
static
Standard_Boolean SetEmptyResultRange(const Standard_Real theParameter,
IntTools_MarkedRangeSet& theMarkedRange);
static
Standard_Integer CheckCoincidence(const Standard_Real aT11,
const Standard_Real aT12,
const Handle(Geom_Curve)& aC1,
const Standard_Real aT21,
const Standard_Real aT22,
const Handle(Geom_Curve)& aC2,
const Standard_Real aCriteria,
const Standard_Real aCurveResolution1,
GeomAPI_ProjectPointOnCurve& aProjector);
// ==================================================================================
// function: IntTools_BeanBeanIntersector
// purpose:
// ==================================================================================
IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector() :
myFirstParameter1(0.),
myLastParameter1(0.),
myFirstParameter2(0.),
myLastParameter2(0.),
myBeanTolerance1(0.),
myBeanTolerance2(0.),
myCurveResolution1(0.),
myCriteria(0.),
myIsDone(Standard_False)
{
}
// ==================================================================================
// function: IntTools_BeanBeanIntersector
// purpose:
// ==================================================================================
IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector(const TopoDS_Edge& theEdge1,
const TopoDS_Edge& theEdge2) :
myFirstParameter1(0.),
myLastParameter1(0.),
myFirstParameter2(0.),
myLastParameter2(0.),
myBeanTolerance1(0.),
myBeanTolerance2(0.),
myCurveResolution1(0.),
myCriteria(0.),
myIsDone(Standard_False)
{
Init(theEdge1, theEdge2);
}
// ==================================================================================
// function: IntTools_BeanBeanIntersector
// purpose:
// ==================================================================================
IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector(const BRepAdaptor_Curve& theCurve1,
const BRepAdaptor_Curve& theCurve2,
const Standard_Real theBeanTolerance1,
const Standard_Real theBeanTolerance2) :
myFirstParameter1(0.),
myLastParameter1(0.),
myFirstParameter2(0.),
myLastParameter2(0.),
myBeanTolerance1(0.),
myBeanTolerance2(0.),
myCurveResolution1(0.),
myCriteria(0.),
myIsDone(Standard_False)
{
Init(theCurve1, theCurve2, theBeanTolerance1, theBeanTolerance2);
}
// ==================================================================================
// function: IntTools_BeanBeanIntersector
// purpose:
// ==================================================================================
IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector(const BRepAdaptor_Curve& theCurve1,
const BRepAdaptor_Curve& theCurve2,
const Standard_Real theFirstParOnCurve1,
const Standard_Real theLastParOnCurve1,
const Standard_Real theFirstParOnCurve2,
const Standard_Real theLastParOnCurve2,
const Standard_Real theBeanTolerance1,
const Standard_Real theBeanTolerance2) :
myFirstParameter1(0.),
myLastParameter1(0.),
myFirstParameter2(0.),
myLastParameter2(0.),
myBeanTolerance1(0.),
myBeanTolerance2(0.),
myCurveResolution1(0.),
myCriteria(0.),
myIsDone(Standard_False)
{
Init(theCurve1, theCurve2, theFirstParOnCurve1, theLastParOnCurve1,
theFirstParOnCurve2, theLastParOnCurve2,
theBeanTolerance1, theBeanTolerance2);
}
// ==================================================================================
// function: Init
// purpose:
// ==================================================================================
void IntTools_BeanBeanIntersector::Init(const TopoDS_Edge& theEdge1,
const TopoDS_Edge& theEdge2)
{
myCurve1.Initialize(theEdge1);
myCurve2.Initialize(theEdge2);
myTrsfCurve1 = Handle(Geom_Curve)::DownCast(myCurve1.Curve().Curve()->Transformed(myCurve1.Trsf()));
myTrsfCurve2 = Handle(Geom_Curve)::DownCast(myCurve2.Curve().Curve()->Transformed(myCurve2.Trsf()));
SetBeanParameters(Standard_True, myCurve1.FirstParameter(), myCurve1.LastParameter());
SetBeanParameters(Standard_False, myCurve2.FirstParameter(), myCurve2.LastParameter());
myBeanTolerance1 = BRep_Tool::Tolerance(theEdge1);
myBeanTolerance2 = BRep_Tool::Tolerance(theEdge2);
myCriteria = myBeanTolerance1 + myBeanTolerance2;
myCurveResolution1 = myCurve1.Resolution(myCriteria);
}
// ==================================================================================
// function: Init
// purpose:
// ==================================================================================
void IntTools_BeanBeanIntersector::Init(const BRepAdaptor_Curve& theCurve1,
const BRepAdaptor_Curve& theCurve2,
const Standard_Real theBeanTolerance1,
const Standard_Real theBeanTolerance2)
{
myCurve1 = theCurve1;
myCurve2 = theCurve2;
SetBeanParameters(Standard_True, myCurve1.FirstParameter(), myCurve1.LastParameter());
SetBeanParameters(Standard_False, myCurve2.FirstParameter(), myCurve2.LastParameter());
myTrsfCurve1 = Handle(Geom_Curve)::DownCast(myCurve1.Curve().Curve()->Transformed(myCurve1.Trsf()));
myTrsfCurve2 = Handle(Geom_Curve)::DownCast(myCurve2.Curve().Curve()->Transformed(myCurve2.Trsf()));
myBeanTolerance1 = theBeanTolerance1;
myBeanTolerance2 = theBeanTolerance2;
myCriteria = myBeanTolerance1 + myBeanTolerance2;
myCurveResolution1 = myCurve1.Resolution(myCriteria);
}
// ==================================================================================
// function: Init
// purpose:
// ==================================================================================
void IntTools_BeanBeanIntersector::Init(const BRepAdaptor_Curve& theCurve1,
const BRepAdaptor_Curve& theCurve2,
const Standard_Real theFirstParOnCurve1,
const Standard_Real theLastParOnCurve1,
const Standard_Real theFirstParOnCurve2,
const Standard_Real theLastParOnCurve2,
const Standard_Real theBeanTolerance1,
const Standard_Real theBeanTolerance2)
{
myCurve1 = theCurve1;
myCurve2 = theCurve2;
myTrsfCurve1 = Handle(Geom_Curve)::DownCast(myCurve1.Curve().Curve()->Transformed(myCurve1.Trsf()));
myTrsfCurve2 = Handle(Geom_Curve)::DownCast(myCurve2.Curve().Curve()->Transformed(myCurve2.Trsf()));
SetBeanParameters(Standard_True, theFirstParOnCurve1, theLastParOnCurve1);
SetBeanParameters(Standard_False, theFirstParOnCurve2, theLastParOnCurve2);
myBeanTolerance1 = theBeanTolerance1;
myBeanTolerance2 = theBeanTolerance2;
myCriteria = myBeanTolerance1 + myBeanTolerance2;
myCurveResolution1 = myCurve1.Resolution(myCriteria);
}
// ==================================================================================
// function: SetBeanParameters
// purpose:
// ==================================================================================
void IntTools_BeanBeanIntersector::SetBeanParameters(const Standard_Boolean IsFirstBean,
const Standard_Real theFirstParOnCurve,
const Standard_Real theLastParOnCurve)
{
if(IsFirstBean) {
myFirstParameter1 = theFirstParOnCurve;
myLastParameter1 = theLastParOnCurve;
}
else {
myFirstParameter2 = theFirstParOnCurve;
myLastParameter2 = theLastParOnCurve;
}
}
// ==================================================================================
// function: Result
// purpose:
// ==================================================================================
const IntTools_SequenceOfRanges& IntTools_BeanBeanIntersector::Result() const
{
return myResults;
}
// ==================================================================================
// function: Result
// purpose:
// ==================================================================================
void IntTools_BeanBeanIntersector::Result(IntTools_SequenceOfRanges& theResults) const
{
theResults = myResults;
}
// ==================================================================================
// function: Perform
// purpose:
// ==================================================================================
void IntTools_BeanBeanIntersector::Perform()
{
Standard_Boolean bFastComputed;
Standard_Integer k, i, iFlag, aNbRanges, aNbResults;
Standard_Real aMidParameter, aCoeff, aParamDist, aPPC;
Standard_Real aCriteria2, aD2;
gp_Pnt aPi, aPh;
IntTools_CArray1OfReal aParams;
IntTools_Range aRange2, aRange;
//
myIsDone = Standard_False;
myResults.Clear();
//
LocalPrepareArgs(myCurve1, myFirstParameter1, myLastParameter1, myDeflection, aParams);
//
myRangeManager.SetRanges(aParams, 0);
//
aNbRanges=myRangeManager.Length();
if(!aNbRanges) {
return;
}
//
bFastComputed=FastComputeIntersection();
if(bFastComputed) {
aRange.SetFirst(myFirstParameter1);
aRange.SetLast (myLastParameter1);
myResults.Append(aRange);
myIsDone = Standard_True;
return;
}
//
ComputeRoughIntersection();
//Standard_Real aMidParameter = (myFirstParameter2 + myLastParameter2) * 0.5;
aCoeff=0.5753;
aMidParameter = myFirstParameter2+(myLastParameter2-myFirstParameter2)*aCoeff;
//
for(k = 0; k < 2; ++k) {
if(!k) {
aRange2.SetFirst(myFirstParameter2);
aRange2.SetLast(aMidParameter);
}
else {
aRange2.SetFirst(aMidParameter);
aRange2.SetLast(myLastParameter2);
}
ComputeUsingExtrema(aRange2);
ComputeNearRangeBoundaries(aRange2);
}
//
// Legend iFlag
//
// 0 - just initialized
// 1 - non-intersected
// 2 - roughly intersected
// 3 - intersection is not done
// 4 - coincided range
//
aPPC=Precision::PConfusion();
aCriteria2=myCriteria*myCriteria;
aNbRanges=myRangeManager.Length();
//
for(i=1; i<=aNbRanges; ++i) {
iFlag=myRangeManager.Flag(i);
//
if(iFlag==4) {
aRange=myRangeManager.Range(i);
aNbResults=myResults.Length();
if(aNbResults>0) {
const IntTools_Range& aLastRange = myResults.Last();
//
aParamDist = Abs(aRange.First() - aLastRange.Last());
if(aParamDist > myCurveResolution1) {
myResults.Append(aRange);
}
else {
aPi=myCurve1.Value(aRange.First());
aPh=myCurve1.Value(aLastRange.Last());
aD2=aPi.SquareDistance(aPh);
if(aParamDist<aPPC || aD2<aCriteria2) {
myResults.ChangeValue(aNbResults).SetLast(aRange.Last());
}
else {
myResults.Append(aRange);
}
}
}// if(aNbR>0) {
else {
myResults.Append(aRange);
}
} //if(iFlag==4) {
} // for(i = 1; i <= myRangeManager.Length(); i++) {
myIsDone = Standard_True;
}
// ==================================================================================
// function: FastComputeIntersection
// purpose:
// ==================================================================================
Standard_Boolean IntTools_BeanBeanIntersector::FastComputeIntersection()
{
Standard_Boolean aresult;
GeomAbs_CurveType aCT1, aCT2;
//
aresult = Standard_False;
//
aCT1=myCurve1.GetType();
aCT2=myCurve2.GetType();
//
if(aCT1 != aCT2) {
return aresult;
}
//
// Line
if(aCT1==GeomAbs_Line) {
Standard_Real par1, par2;
if((Distance(myFirstParameter1, par1) < myCriteria) &&
(Distance(myLastParameter1, par2) < myCriteria)) {
if((par1 >= myFirstParameter2) && (par1 <= myLastParameter2) &&
(par2 >= myFirstParameter2) && (par2 <= myLastParameter2)) {
myRangeManager.InsertRange(myFirstParameter1, myLastParameter1, 4);
aresult = Standard_True;
}
}
return aresult;
}
//
// Circle
if(aCT1==GeomAbs_Circle) {
Standard_Real anAngle, aPA, aDistLoc, aDist, aDiff, aR1, aR2;
gp_Circ aCirc1, aCirc2;
gp_Dir aDir1, aDir2;
//
aCirc1=myCurve1.Circle();
aCirc2=myCurve2.Circle();
aR1=aCirc1.Radius();
aR2=aCirc2.Radius();
//
aPA=Precision::Angular();
aDir1 = aCirc1.Axis().Direction();
aDir2 = aCirc2.Axis().Direction();
//
anAngle = aDir1.Angle(aDir2);
if(anAngle > aPA) {
return aresult; //->
}
//
const gp_Pnt& aPLoc1=aCirc1.Location();
const gp_Pnt& aPLoc2=aCirc2.Location();
aDistLoc = aPLoc1.Distance(aPLoc2);
aDist=aDistLoc;
aDiff=aR1 - aR2;
aDist+=Abs(aDiff);
if(Abs(aDist) > myCriteria) {
return aresult; //->
}
//
Standard_Real aSinPA, atmpvalue, aprojectedradius;
//
aSinPA=sin(aPA);
atmpvalue = aR1*aSinPA;
atmpvalue *= atmpvalue;
aprojectedradius = sqrt(aR1*aR1 - atmpvalue);
aDiff = aprojectedradius - aR2;
aDist = aDistLoc + sqrt((aDiff * aDiff) + atmpvalue);
if(Abs(aDist) > myCriteria) {
return aresult; //->
}
//
Standard_Boolean newparfound;
Standard_Integer i;
Standard_Real afirstpar, alastpar, par1, par2, apar;
//
afirstpar = myFirstParameter1;
alastpar = myLastParameter1;
for(i = 0; i < 2; i++) {
if((Distance(afirstpar, par1) < myCriteria) &&
(Distance(alastpar , par2) < myCriteria)) {
if(i || Distance((myFirstParameter1 + myLastParameter2) * 0.5, apar) < myCriteria) {
myRangeManager.InsertRange(afirstpar, alastpar, 4);
if(!i) {
aresult = Standard_True;
}
}
break;
}
//
if(i) {
break;
}
// i=0 :
newparfound = Standard_False;
if(Distance((myFirstParameter1 + myLastParameter2) * 0.5, apar) < myCriteria) {
afirstpar = myFirstParameter1 + myCriteria;
alastpar = myLastParameter1 - myCriteria;
newparfound = Standard_True;
if(alastpar <= afirstpar) {
newparfound = Standard_False;
}
}
//
if(!newparfound) {
break;
}
}// for(i = 0; i < 2; i++) {
} // if(aCT1==GeomAbs_Circle)
//modified by NIZNHY-PKV Mon Oct 08 14:08:19 2012f
if (aCT1==GeomAbs_BSplineCurve || aCT1==GeomAbs_BezierCurve) {
Standard_Integer iFlag;
//
iFlag=CheckCoincidence(myFirstParameter1,
myLastParameter1,
myTrsfCurve1,
myFirstParameter2,
myLastParameter2,
myTrsfCurve2,
myCriteria,
myCurveResolution1,
myProjector);
if (!iFlag) {
aresult=!aresult;
}
}
//modified by NIZNHY-PKV Mon Oct 08 14:08:23 2012t
return aresult;
}
// ==================================================================================
// function: Distance
// purpose:
// ==================================================================================
Standard_Real IntTools_BeanBeanIntersector::Distance(const Standard_Real theArg,
Standard_Real& theArgOnOtherBean)
{
Standard_Real aDistance;
Standard_Integer aNbPoints;
gp_Pnt aPoint;
//
aDistance=RealLast();
//
aPoint=myCurve1.Value(theArg);
myProjector.Init(myTrsfCurve2, myFirstParameter2, myLastParameter2);
myProjector.Perform(aPoint);
//
aNbPoints=myProjector.NbPoints();
if(aNbPoints > 0) {
theArgOnOtherBean = myProjector.LowerDistanceParameter();
aDistance=myProjector.LowerDistance();
}
//
else {
Standard_Real aDistance1, aDistance2;
//
aDistance1 = aPoint.Distance(myCurve2.Value(myFirstParameter2));
aDistance2 = aPoint.Distance(myCurve2.Value(myLastParameter2));
//
theArgOnOtherBean = myLastParameter2;
aDistance=aDistance2;
if(aDistance1 < aDistance2) {
theArgOnOtherBean = myFirstParameter2;
aDistance=aDistance1;
}
}
return aDistance;
}
// ==================================================================================
// function: ComputeRoughIntersection
// purpose:
// ==================================================================================
void IntTools_BeanBeanIntersector::ComputeRoughIntersection()
{
Standard_Boolean isintersection;
Standard_Integer i, aNbArgs, aNbArgs1, aNbRanges, j, aNbLines, k, pIt, extIt, iFlag;
Standard_Real aDeflection, aGPR, aCurDeflection, aT1, aT2, aD;
Standard_Real aMaxDistance, aDistance, aPPC, aPrm1, aPrm2, aPPA;
GeomAbs_CurveType aCT1, aCT2;
gp_Pnt aPoint1, aPoint2, aMidPOnCurve, aMidPOnLine, aP1, aP2;
IntTools_CArray1OfReal anArgs;
LocalPrepareArgs(myCurve2, myFirstParameter2, myLastParameter2, aDeflection, anArgs);
//
aNbArgs=anArgs.Length();
if(!aNbArgs) {
return;
}
//
aCT1=myCurve1.GetType();
aCT2=myCurve2.GetType();
aGPR=gp::Resolution();
aPPC=Precision::PConfusion();
aPPA=Precision::Angular();
aNbArgs1=aNbArgs-1;
//
Intf_Array1OfLin aLines(1, aNbArgs1);
TColStd_Array1OfInteger aLineFlags(1, aNbArgs1);
TColStd_Array1OfReal aDistances(1, aNbArgs1);
//
aT1=anArgs(0);
aPoint1 = myCurve2.Value(aT1);
for(i=1; i<aNbArgs; ++i) {
aT2=anArgs(i);
aPoint2 = myCurve2.Value(aT2);
gp_Vec aVec(aPoint1, aPoint2);
aD=aVec.Magnitude();
aDistances.SetValue(i, aD);
//
if(aD<=aGPR) {
aLineFlags.SetValue(i, 0);
}
else {
aLineFlags.SetValue(i, 1);
gp_Lin aLine(aPoint1, gp_Dir(aVec));
aLines.SetValue(i, aLine);
//
if((aCT2 == GeomAbs_BezierCurve) ||
(aCT2 == GeomAbs_BSplineCurve)) {
aMidPOnCurve = myCurve2.Value((aT1+aT2) * 0.5);
aMidPOnLine = ElCLib::Value((aDistances(i)*0.5), aLine);
aCurDeflection = aMidPOnCurve.Distance(aMidPOnLine);
if(aCurDeflection > aDeflection) {
aDeflection = aCurDeflection;
}
}
}
aT1=aT2;
aPoint1 = aPoint2;
}
//
aNbLines=aLines.Upper();
aMaxDistance = myCriteria + myDeflection + aDeflection;
aT1=myRangeManager.Range(1).First();
aPoint1 = myCurve1.Value(aT1);
aNbRanges=myRangeManager.Length();
for(i = 1; i <= aNbRanges; ++i) {
const IntTools_Range& aRange = myRangeManager.Range(i);
aT2=aRange.Last();
aPoint2 = myCurve1.Value(aT2);
//
iFlag=myRangeManager.Flag(i);
if(iFlag==4) {// coincided
aT1=aT2;
aPoint1 = aPoint2;
continue;
}
//
myRangeManager.SetFlag(i, 1); // not intersected
Bnd_Box aBox1;
aBox1.Add(aPoint1);
aBox1.Add(aPoint2);
aBox1.Enlarge(myBeanTolerance1 + myDeflection);
gp_Vec aVec(aPoint1, aPoint2);
aDistance=aVec.Magnitude();
if(aDistance <= aGPR) {
myRangeManager.SetFlag(i, 0);
continue;
}
//
gp_Lin aLine(aPoint1, gp_Dir(aVec));
//
if((aCT1 == GeomAbs_BezierCurve) ||
(aCT1 == GeomAbs_BSplineCurve)) {
aMidPOnCurve = myCurve1.Value((aRange.First() + aRange.Last()) * 0.5);
aMidPOnLine = ElCLib::Value((aDistance*0.5), aLine);
aCurDeflection = aMidPOnCurve.Distance(aMidPOnLine);
if(myDeflection < aCurDeflection) {
aMaxDistance += aCurDeflection - myDeflection;
myDeflection = aCurDeflection;
}
}
//
for(j=1; j<=aNbLines; ++j) {
if(!aLineFlags(j)) {
myRangeManager.SetFlag(i, 0);
continue;
}
//
const gp_Lin& aL2=aLines(j);
//Handle(Geom_Line) aC2=new Geom_Line(aL2); // DEB ft
aD=aDistances(j);
aP1=ElCLib::Value(0., aL2);
aP2=ElCLib::Value(aD, aL2);
//
Extrema_ExtElC anExtrema(aLine, aL2, aPPA);
if(anExtrema.IsDone() && (anExtrema.IsParallel() || (anExtrema.NbExt() > 0))) {
isintersection = Standard_False;
if(anExtrema.IsParallel()) {
isintersection = (anExtrema.SquareDistance(1) < aMaxDistance * aMaxDistance);
}
else { //1
for(k = 1; !isintersection && k <= anExtrema.NbExt(); ++k) {
if(anExtrema.SquareDistance(k) < aMaxDistance * aMaxDistance) {
Extrema_POnCurv P1, P2;
anExtrema.Points(k, P1, P2);
aPrm1=P1.Parameter();
aPrm2=P2.Parameter();
if((aPrm1 >= -aMaxDistance) && (aPrm1 <= aDistance+aMaxDistance) &&
(aPrm2 >= -aMaxDistance) && (aPrm2 <= aD+aMaxDistance)) {
isintersection = Standard_True;
}
else { // 2
Extrema_ExtPElC aPointProjector;
for(pIt = 0; !isintersection && (pIt < 4); ++pIt) {
switch (pIt) {
case 0: {
aPointProjector =
//Extrema_ExtPElC(aPoint1, aLines(j), aPPC, 0., aDistances(j));
Extrema_ExtPElC(aPoint1, aL2, aPPC, -aMaxDistance, aD+aMaxDistance);
break;
}
case 1: {
aPointProjector =
//Extrema_ExtPElC(aPoint2, aLines(j), aPPC, 0., aD);
Extrema_ExtPElC(aPoint2, aL2, aPPC, -aMaxDistance, aD+aMaxDistance);
break;
}
case 2: {
aPointProjector =
//Extrema_ExtPElC(ElCLib::Value(0., aLines(j)), aLine, aPPC, 0., aDistance);
Extrema_ExtPElC(aP1, aLine, aPPC, -aMaxDistance, aDistance+aMaxDistance);
break;
}
case 3: {
aPointProjector =
//Extrema_ExtPElC(ElCLib::Value(aDistances(j), aLines(j)), aLine, aPPC, 0., aDistance);
Extrema_ExtPElC(aP2, aLine, aPPC, -aMaxDistance, aDistance+aMaxDistance);
break;
}
default: {
break;
}
}
//
if(aPointProjector.IsDone()) {
Standard_Real aMaxDistance2 = aMaxDistance * aMaxDistance;
for(extIt = 1; extIt <= aPointProjector.NbExt(); extIt++) {
if(aPointProjector.SquareDistance(extIt) < aMaxDistance2) {
isintersection = Standard_True;
}
}
}
} // end for
}// else { // 2
}//if(anExtrema.Value(k) < aMaxDistance) {
}//for(k = 1; !isintersection && k <= anExtrema.NbExt(); k++) {
}//else { //1
if(isintersection) {
myRangeManager.SetFlag(i, 2); // roughly intersected
break;
}
}//if(anExtrema.IsDone() && (anExtrema.IsParallel() || (anExtrema.NbExt() > 0))) {
else {
Bnd_Box aBox2;
aBox2.Add(myCurve2.Value(anArgs(j-1)));
aBox2.Add(myCurve2.Value(anArgs(j)));
aBox2.Enlarge(myBeanTolerance2 + aDeflection);
//
if(!aBox1.IsOut(aBox2)) {
myRangeManager.SetFlag(i, 2); // roughly intersected
break;
}
}
}
aT1=aT2;
aPoint1 = aPoint2;
}
}
// ==================================================================================
// function: ComputeUsingExtrema
// purpose:
// ==================================================================================
void IntTools_BeanBeanIntersector::ComputeUsingExtrema(const IntTools_Range& theRange2)
{
//rln Dec 2008.
//Extrema_ExtCC is reused throughout this method to store caches computed on
//theRange2. However it is actually used only in a few calls of
//ComputeUsingExtrema(), so using a default constructor would add unnecessary overhead
//of initialization its internal fields. Since it is not manipulated by Handle then
//we will use a pointer to it and initialize it only when needed.
Extrema_ExtCC *apExtrema = 0;
Handle(GeomAdaptor_HCurve) aHCurve1, aHCurve2; //will be initialized later, only if needed
//handles are used to guard pointers to GeomAdaptor_Curve inside Extrema
Standard_Real aCriteria2 = myCriteria * myCriteria;
for(Standard_Integer i = 1; i <= myRangeManager.Length(); i++) {
if(myRangeManager.Flag(i) == 2 || myRangeManager.Flag(i) == 0) {
const IntTools_Range& aParamRange = myRangeManager.Range(i);
if(aParamRange.Last() - aParamRange.First() < Precision::PConfusion()) {
if(((i > 1) && (myRangeManager.Flag(i-1) == 4)) ||
((i < myRangeManager.Length()) && (myRangeManager.Flag(i+1) == 4))) {
myRangeManager.SetFlag(i, 4);
continue;
}
}
if (aHCurve2.IsNull()) {
//initialize only once
apExtrema = new Extrema_ExtCC;
Standard_Real ftmp = theRange2.First() - Precision::PConfusion();
Standard_Real ltmp = theRange2.Last() + Precision::PConfusion();
ftmp = (ftmp < myFirstParameter2) ? myFirstParameter2 : ftmp;
ltmp = (ltmp > myLastParameter2) ? myLastParameter2 : ltmp;
aHCurve2 = new GeomAdaptor_HCurve (myTrsfCurve2, ftmp, ltmp);
apExtrema->SetCurve (2, aHCurve2->Curve(), theRange2.First(), theRange2.Last());
}
Extrema_ExtCC& anExtrema = *apExtrema;
Standard_Real ftmp = aParamRange.First() - Precision::PConfusion();
Standard_Real ltmp = aParamRange.Last() + Precision::PConfusion();
ftmp = (ftmp < myFirstParameter1) ? myFirstParameter1 : ftmp;
ltmp = (ltmp > myLastParameter1) ? myLastParameter1 : ltmp;
aHCurve1 = new GeomAdaptor_HCurve (myTrsfCurve1, ftmp, ltmp);
anExtrema.SetCurve (1, aHCurve1->Curve(), aParamRange.First(), aParamRange.Last());
anExtrema.Perform();
if(anExtrema.IsDone() && (anExtrema.IsParallel() || (anExtrema.NbExt() > 0))) {
Standard_Integer anOldNbRanges = myRangeManager.Length();
if (anExtrema.IsParallel()) {
if(anExtrema.SquareDistance(1) < aCriteria2) {
Standard_Real theParameter1, theParameter2;
Standard_Real adistance1 = Distance(aParamRange.First(), theParameter1);
Standard_Real adistance2 = Distance(aParamRange.Last(), theParameter2);
Standard_Boolean validdistance1 = (adistance1 < myCriteria);
Standard_Boolean validdistance2 = (adistance2 < myCriteria);
if (validdistance1 && validdistance2) {
myRangeManager.InsertRange(aParamRange.First(), aParamRange.Last(), 4);
continue;
}
else {
if(validdistance1) {
ComputeRangeFromStartPoint(Standard_True, aParamRange.First(), i, theParameter1, theRange2);
}
else {
if(validdistance2) {
ComputeRangeFromStartPoint(Standard_False, aParamRange.Last(), i, theParameter2, theRange2);
}
else {
Standard_Real a = aParamRange.First();
Standard_Real b = aParamRange.Last();
Standard_Real da = adistance1;
Standard_Real db = adistance2;
Standard_Real asolution = a;
Standard_Boolean found = Standard_False;
while(((b - a) > myCurveResolution1) && !found) {
asolution = (a+b)*0.5;
Standard_Real adist = Distance(asolution, theParameter1);
if(adist < myCriteria) {
found = Standard_True;
}
else {
if(da < db) {
b = asolution;
db = adist;
}
else {
a = asolution;
da = adist;
}
}
} // end while
if(found) {
ComputeRangeFromStartPoint(Standard_False, asolution, i, theParameter1, theRange2);
ComputeRangeFromStartPoint(Standard_True, asolution, i, theParameter1, theRange2);
}
else {
myRangeManager.SetFlag(i, 2);
}
}
}
}
}
}
else {
for(Standard_Integer j = 1 ; j <= anExtrema.NbExt(); j++) {
if(anExtrema.SquareDistance(j) < aCriteria2) {
Extrema_POnCurv p1, p2;
anExtrema.Points(j, p1, p2);
Standard_Integer aNbRanges = myRangeManager.Length();
Standard_Integer anIndex = myRangeManager.GetIndex(p1.Parameter(), Standard_False);
if(anIndex > 0) {
ComputeRangeFromStartPoint(Standard_False, p1.Parameter(), anIndex, p2.Parameter(), theRange2);
}
anIndex = myRangeManager.GetIndex(p1.Parameter(), Standard_True);
if(anIndex > 0) {
ComputeRangeFromStartPoint(Standard_True, p1.Parameter(), anIndex, p2.Parameter(), theRange2);
}
if(aNbRanges == myRangeManager.Length()) {
SetEmptyResultRange(p1.Parameter(), myRangeManager);
}
}
} // end for
}
Standard_Integer adifference = myRangeManager.Length() - anOldNbRanges;
if(adifference > 0) {
i+=adifference;
}
}
else {
myRangeManager.SetFlag(i, 3); // intersection not done.
}
}
}
if (apExtrema) delete apExtrema;
}
// ==================================================================================
// function: ComputeNearRangeBoundaries
// purpose:
// ==================================================================================
void IntTools_BeanBeanIntersector::ComputeNearRangeBoundaries(const IntTools_Range& theRange2)
{
Standard_Real theParameter = theRange2.First();
for(Standard_Integer i = 1; i <= myRangeManager.Length(); i++) {
if(myRangeManager.Flag(i) != 3)
continue;
if((i > 1) && ((myRangeManager.Flag(i-1) == 1) || (myRangeManager.Flag(i-1) == 4))) {
myRangeManager.SetFlag(i, 2);
continue;
}
const IntTools_Range& aParamRange = myRangeManager.Range(i);
if(Distance(aParamRange.First(), theParameter) < myCriteria) {
Standard_Integer aNbRanges = myRangeManager.Length();
if(i > 1) {
ComputeRangeFromStartPoint(Standard_False, aParamRange.First(), i-1, theParameter, theRange2);
}
ComputeRangeFromStartPoint(Standard_True, aParamRange.First(), i + (myRangeManager.Length() - aNbRanges), theParameter, theRange2);
if(aNbRanges == myRangeManager.Length()) {
SetEmptyResultRange(aParamRange.First(), myRangeManager);
}
}
else {
myRangeManager.SetFlag(i, 2);
}
}
if((myRangeManager.Flag(myRangeManager.Length()) == 3) ||
(myRangeManager.Flag(myRangeManager.Length()) == 2)) {
const IntTools_Range& aParamRange = myRangeManager.Range(myRangeManager.Length());
if(Distance(aParamRange.Last(), theParameter) < myCriteria) {
Standard_Integer aNbRanges = myRangeManager.Length();
myRangeManager.SetFlag(myRangeManager.Length(), 2);
ComputeRangeFromStartPoint(Standard_False, aParamRange.Last(), myRangeManager.Length(), theParameter, theRange2);
if(aNbRanges == myRangeManager.Length()) {
SetEmptyResultRange(aParamRange.Last(), myRangeManager);
}
}
else {
myRangeManager.SetFlag(myRangeManager.Length(), 2);
}
}
}
// ==================================================================================
// function: ComputeRangeFromStartPoint
// purpose:
// ==================================================================================
void IntTools_BeanBeanIntersector::ComputeRangeFromStartPoint(const Standard_Boolean ToIncreaseParameter,
const Standard_Real theParameter,
const Standard_Integer theIndex,
const Standard_Real theParameter2,
const IntTools_Range& theRange2)
{
if(myRangeManager.Flag(theIndex) == 4 ||
myRangeManager.Flag(theIndex) == 1)
return;
Standard_Integer aValidIndex = theIndex;
Standard_Real aMinDelta = myCurveResolution1 * 0.5;
Standard_Real aDeltaRestrictor = myLastParameter1 - myFirstParameter1;
if(Abs(aDeltaRestrictor) < Precision::PConfusion()) {
return;
}
if(aMinDelta > aDeltaRestrictor) {
aMinDelta = aDeltaRestrictor;
}
Standard_Real tenOfMinDelta = aMinDelta * 10.;
Standard_Real aDelta = myCurveResolution1;
Standard_Real aCurPar = (ToIncreaseParameter) ? (theParameter + aDelta) : (theParameter - aDelta);
Standard_Real aPrevPar = theParameter;
IntTools_Range aCurrentRange = myRangeManager.Range(aValidIndex);
Standard_Boolean BoundaryCondition = (ToIncreaseParameter) ? (aCurPar > aCurrentRange.Last()) : (aCurPar < aCurrentRange.First());
if(BoundaryCondition) {
aCurPar = (ToIncreaseParameter) ? aCurrentRange.Last() : aCurrentRange.First();
BoundaryCondition = Standard_False;
}
Standard_Integer loopcounter = 0; // neccesary to have no infinite loop
Standard_Real aParameter = theParameter2;
Standard_Boolean anotherSolutionFound = Standard_False;
Standard_Boolean isboundaryindex = Standard_False;
Standard_Boolean isvalidindex = Standard_True;
Standard_Real aCriteria2 = myCriteria * myCriteria;
while((aDelta >= aMinDelta) && (loopcounter <= 10)) {
Standard_Boolean pointfound = Standard_False;
gp_Pnt aPoint = myCurve1.Value(aCurPar);
GeomAdaptor_Curve aCurve2(myTrsfCurve2, theRange2.First(), theRange2.Last());
Extrema_LocateExtPC anExtrema(aPoint, aCurve2, aParameter, theRange2.First(), theRange2.Last(), 1.e-10);
if(anExtrema.IsDone()) {
if(anExtrema.SquareDistance() < aCriteria2) {
Extrema_POnCurv aPOnCurv = anExtrema.Point();
aParameter = aPOnCurv.Parameter();
pointfound = Standard_True;
}
}
else {
// pointfound = (Distance(aCurPar, aParameter) < myCriteria);
Standard_Real afoundparam = aParameter;
if(Distance(aCurPar, afoundparam) < myCriteria) {
aParameter = afoundparam;
pointfound = Standard_True;
}
}
if(pointfound) {
aPrevPar = aCurPar;
anotherSolutionFound = Standard_True;
if(BoundaryCondition && (isboundaryindex || !isvalidindex))
break;
}
else {
aDeltaRestrictor = aDelta;
}
// if pointfound decide to increase aDelta using derivative of distance function
//
aDelta = (pointfound) ? (aDelta * 2.) : (aDelta * 0.5);
aDelta = (aDelta < aDeltaRestrictor) ? aDelta : aDeltaRestrictor;
aCurPar = (ToIncreaseParameter) ? (aPrevPar + aDelta) : (aPrevPar - aDelta);
BoundaryCondition = (ToIncreaseParameter) ? (aCurPar > aCurrentRange.Last()) : (aCurPar < aCurrentRange.First());
isboundaryindex = Standard_False;
isvalidindex = Standard_True;
if(BoundaryCondition) {
isboundaryindex = ((!ToIncreaseParameter && (aValidIndex == 1)) ||
(ToIncreaseParameter && (aValidIndex == myRangeManager.Length())));
if(!isboundaryindex) {
if(pointfound) {
Standard_Integer aFlag = (ToIncreaseParameter) ? myRangeManager.Flag(aValidIndex + 1) : myRangeManager.Flag(aValidIndex - 1);
if(aFlag != 1 && aFlag != 4) {
aValidIndex = (ToIncreaseParameter) ? (aValidIndex + 1) : (aValidIndex - 1);
aCurrentRange = myRangeManager.Range(aValidIndex);
if((ToIncreaseParameter && (aCurPar > aCurrentRange.Last())) ||
(!ToIncreaseParameter && (aCurPar < aCurrentRange.First()))) {
aCurPar = (aCurrentRange.First() + aCurrentRange.Last()) * 0.5;
aDelta*=0.5;
}
}
else {
isvalidindex = Standard_False;
aCurPar = (ToIncreaseParameter) ? aCurrentRange.Last() : aCurrentRange.First();
}
}
}
else {
aCurPar = (ToIncreaseParameter) ? aCurrentRange.Last() : aCurrentRange.First();
}
if(aDelta < tenOfMinDelta) {
loopcounter++;
}
else {
loopcounter = 0;
}
} // end if(BoundaryCondition)
}
if(anotherSolutionFound) {
if(ToIncreaseParameter)
myRangeManager.InsertRange(theParameter, aPrevPar, 4);
else
myRangeManager.InsertRange(aPrevPar, theParameter, 4);
}
}
// ---------------------------------------------------------------------------------
// static function: LocalPrepareArgs
// purpose:
// ---------------------------------------------------------------------------------
static void LocalPrepareArgs(BRepAdaptor_Curve& theCurve,
const Standard_Real theFirstParameter,
const Standard_Real theLastParameter,
Standard_Real& theDeflection,
IntTools_CArray1OfReal& theArgs) {
Standard_Integer aDiscretization = 30;
Standard_Real aRelativeDeflection = 0.01;
theDeflection = aRelativeDeflection;
Standard_Boolean prepareargs = Standard_True;
switch(theCurve.GetType()) {
case GeomAbs_Line: {
prepareargs = Standard_False;
aDiscretization = 3;
theArgs.Append(theFirstParameter);
if((theLastParameter - theFirstParameter) > Precision::PConfusion()) {
theArgs.Append((theFirstParameter + theLastParameter)*0.5);
}
theArgs.Append(theLastParameter);
theDeflection = Precision::Confusion();
break;
}
case GeomAbs_Circle: {
aDiscretization = 23;
theDeflection = aRelativeDeflection * theCurve.Circle().Radius();
break;
}
case GeomAbs_Ellipse: {
aDiscretization = 40;
theDeflection = 2 * aRelativeDeflection * theCurve.Ellipse().MajorRadius();
break;
}
case GeomAbs_Hyperbola:
case GeomAbs_Parabola: {
aDiscretization = 40;
theDeflection = aRelativeDeflection;
break;
}
case GeomAbs_BezierCurve: {
aDiscretization = 30;
theDeflection = aRelativeDeflection;
break;
}
case GeomAbs_BSplineCurve: {
aDiscretization = 30;
theDeflection = aRelativeDeflection;
break;
}
default: {
aDiscretization = 30;
theDeflection = aRelativeDeflection;
}
}
if(prepareargs) {
IntTools::PrepareArgs(theCurve, theLastParameter, theFirstParameter, aDiscretization, aRelativeDeflection, theArgs);
}
}
// ---------------------------------------------------------------------------------
// static function: SetEmptyResultRange
// purpose:
// ---------------------------------------------------------------------------------
static Standard_Boolean SetEmptyResultRange(const Standard_Real theParameter,
IntTools_MarkedRangeSet& theMarkedRange) {
const TColStd_SequenceOfInteger& anIndices = theMarkedRange.GetIndices(theParameter);
Standard_Boolean add = (anIndices.Length() > 0);
for(Standard_Integer k = 1; k <= anIndices.Length(); k++) {
if(theMarkedRange.Flag(anIndices(k)) == 4) {
add = Standard_False;
break;
}
}
if(add) {
theMarkedRange.InsertRange(theParameter, theParameter, 4);
}
return add;
}
//modified by NIZNHY-PKV Fri Oct 12 09:34:10 2012f
static
Standard_Integer DistPC(const Standard_Real aT1,
const Handle(Geom_Curve)& aC1,
const Standard_Real aCriteria,
GeomAPI_ProjectPointOnCurve& aProjector,
Standard_Real& aD,
Standard_Real& aT2);
static
Standard_Integer DistPC(const Standard_Real aT1,
const Handle(Geom_Curve)& aC1,
const Standard_Real aCriteria,
GeomAPI_ProjectPointOnCurve& aProjector,
Standard_Real& aD,
Standard_Real& aT2,
Standard_Real& aDmax,
Standard_Real& aTmax);
static
Standard_Integer FindMaxDistPC(const Standard_Real aT1A,
const Standard_Real aT1B,
const Handle(Geom_Curve)& aC1,
const Standard_Real aCriteria,
const Standard_Real aEps1,
GeomAPI_ProjectPointOnCurve& aProjector,
Standard_Real& aDmax,
Standard_Real& aT1max);
//=======================================================================
//function : CheckCoincidence
//purpose :
//=======================================================================
Standard_Integer CheckCoincidence(const Standard_Real aT11,
const Standard_Real aT12,
const Handle(Geom_Curve)& aC1,
const Standard_Real aT21,
const Standard_Real aT22,
const Handle(Geom_Curve)& aC2,
const Standard_Real aCriteria,
const Standard_Real aEps1,
GeomAPI_ProjectPointOnCurve& aProjector)
{
Standard_Integer iErr, aNb1, i, aNbX;
Standard_Real dT1, aT1, aT2, aD, aDmax, aTmax;
Standard_Real aT1A, aT1B, aD1max,aT1max;
//
iErr=0; // the patches are coincided
//
//
aProjector.Init(aC2, aT21, aT22);
//
aDmax=-1.;
//
// 1. Express evaluation
//
aNb1=10; // Number of intervals on the curve #1
dT1=(aT12-aT11)/aNb1;
for (i=1; i<aNb1; ++i) {
aT1=aT11+i*dT1;
//
iErr=DistPC(aT1, aC1, aCriteria, aProjector, aD, aT2, aDmax, aTmax);
if (iErr) {
iErr=1;// a point from aC1 can not be projected on aC2
return iErr;
}
//
if (aDmax>aCriteria) {
iErr=2; // the distance is too big
return iErr;
}
}
//
// 2. Deep evaluation
aD1max=aDmax;
//
aNbX=aNb1-1;
for (i=1; i<aNbX; ++i) {
aT1A=aT11+i*dT1;
aT1B=aT1A+dT1;
//
iErr=FindMaxDistPC(aT1A, aT1B, aC1, aCriteria, aEps1, aProjector, aD1max, aT1max);
if (iErr) {
iErr=1;
return iErr;
}
}
//
return iErr;
}
//
//=======================================================================
//function : FindMaxDistPC
//purpose :
//=======================================================================
Standard_Integer FindMaxDistPC(const Standard_Real aT1A,
const Standard_Real aT1B,
const Handle(Geom_Curve)& aC1,
const Standard_Real aCriteria,
const Standard_Real aEps1,
GeomAPI_ProjectPointOnCurve& aProjector,
Standard_Real& aDmax,
Standard_Real& aT1max)
{
Standard_Integer iErr, iCnt;
Standard_Real aGS, aXP, aA, aB, aXL, aYP, aYL, aT2P, aT2L, aX0;
//
iCnt=0;
iErr=0;
aDmax=0.;
//
aGS=0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))-1.;
aA=aT1A;
aB=aT1B;
//
aXP=aA+(aB-aA)*aGS;
aXL=aB-(aB-aA)*aGS;
//
iErr=DistPC(aXP, aC1, aCriteria, aProjector, aYP, aT2P, aDmax, aT1max);
if(iErr){
return iErr;
}
//
iErr=DistPC(aXL, aC1, aCriteria, aProjector, aYL, aT2L, aDmax, aT1max);
if(iErr){
return iErr;
}
//
while(1) {
if (aYP>aYL) {
aA=aXL;
aXL=aXP;
aYL=aYP;
aXP=aA+(aB-aA)*aGS;
iErr=DistPC(aXP, aC1, aCriteria, aProjector, aYP, aT2P, aDmax, aT1max);
if(iErr){
return iErr;
}
}
else {
aB=aXP;
aXP=aXL;
aYP=aYL;
aXL=aB-(aB-aA)*aGS;
iErr=DistPC(aXL, aC1, aCriteria, aProjector, aYL, aT2L, aDmax, aT1max);
if(iErr){
return iErr;
}
}
//
if ((aB-aA)<aEps1) {
aX0=0.5*(aA+aB);
break;
}
}// while(1) {
//
return iErr;
}
//=======================================================================
//function : DistPC
//purpose :
//=======================================================================
Standard_Integer DistPC(const Standard_Real aT1,
const Handle(Geom_Curve)& aC1,
const Standard_Real aCriteria,
GeomAPI_ProjectPointOnCurve& aProjector,
Standard_Real& aD,
Standard_Real& aT2,
Standard_Real& aDmax,
Standard_Real& aTmax)
{
Standard_Integer iErr;
//
iErr=DistPC(aT1, aC1, aCriteria, aProjector, aD, aT2);
if (iErr) {
return iErr;
}
//
if (aD>aDmax) {
aDmax=aD;
aTmax=aT2;
}
//
return iErr;
}
//=======================================================================
//function : DistPC
//purpose :
//=======================================================================
Standard_Integer DistPC(const Standard_Real aT1,
const Handle(Geom_Curve)& aC1,
const Standard_Real aCriteria,
GeomAPI_ProjectPointOnCurve& aProjector,
Standard_Real& aD,
Standard_Real& aT2)
{
Standard_Integer iErr, aNbP2;
gp_Pnt aP1;
//
iErr=0;
aC1->D0(aT1, aP1);
//
aProjector.Perform(aP1);
aNbP2=aProjector.NbPoints();
if (!aNbP2) {
iErr=1;// the point from aC1 can not be projected on aC2
return iErr;
}
//
aD=aProjector.LowerDistance();
aT2=aProjector.LowerDistanceParameter();
if (aD>aCriteria) {
iErr=2;// the distance is too big
}
//
return iErr;
}
//modified by NIZNHY-PKV Fri Oct 12 09:34:12 2012t