1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and / or modify it
6 // under the terms of the GNU Lesser General Public version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include <IntTools_BeanBeanIntersector.ixx>
16 #include <IntTools_Root.hxx>
17 #include <Precision.hxx>
18 #include <Extrema_POnCurv.hxx>
19 #include <BRep_Tool.hxx>
20 #include <Geom_Curve.hxx>
21 #include <TColStd_Array1OfReal.hxx>
22 #include <TColStd_Array1OfInteger.hxx>
23 #include <IntTools_CArray1OfReal.hxx>
25 #include <Intf_Array1OfLin.hxx>
26 #include <Bnd_Box.hxx>
27 #include <Extrema_ExtCC.hxx>
28 #include <Extrema_ExtElC.hxx>
29 #include <Extrema_LocateExtPC.hxx>
30 #include <gp_Circ.hxx>
31 #include <gp_Elips.hxx>
32 #include <IntTools.hxx>
34 #include <Geom_Line.hxx>
35 #include <GeomAdaptor_HCurve.hxx>
38 void LocalPrepareArgs(BRepAdaptor_Curve& theCurve,
39 const Standard_Real theFirstParameter,
40 const Standard_Real theLastParameter,
41 Standard_Real& theDeflection,
42 IntTools_CArray1OfReal& theArgs);
45 Standard_Boolean SetEmptyResultRange(const Standard_Real theParameter,
46 IntTools_MarkedRangeSet& theMarkedRange);
48 Standard_Integer CheckCoincidence(const Standard_Real aT11,
49 const Standard_Real aT12,
50 const Handle(Geom_Curve)& aC1,
51 const Standard_Real aT21,
52 const Standard_Real aT22,
53 const Handle(Geom_Curve)& aC2,
54 const Standard_Real aCriteria,
55 const Standard_Real aCurveResolution1,
56 GeomAPI_ProjectPointOnCurve& aProjector);
59 // ==================================================================================
60 // function: IntTools_BeanBeanIntersector
62 // ==================================================================================
63 IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector() :
65 myFirstParameter1(0.),
67 myFirstParameter2(0.),
71 myCurveResolution1(0.),
73 myIsDone(Standard_False)
77 // ==================================================================================
78 // function: IntTools_BeanBeanIntersector
80 // ==================================================================================
81 IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector(const TopoDS_Edge& theEdge1,
82 const TopoDS_Edge& theEdge2) :
84 myFirstParameter1(0.),
86 myFirstParameter2(0.),
90 myCurveResolution1(0.),
92 myIsDone(Standard_False)
94 Init(theEdge1, theEdge2);
97 // ==================================================================================
98 // function: IntTools_BeanBeanIntersector
100 // ==================================================================================
101 IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector(const BRepAdaptor_Curve& theCurve1,
102 const BRepAdaptor_Curve& theCurve2,
103 const Standard_Real theBeanTolerance1,
104 const Standard_Real theBeanTolerance2) :
106 myFirstParameter1(0.),
107 myLastParameter1(0.),
108 myFirstParameter2(0.),
109 myLastParameter2(0.),
110 myBeanTolerance1(0.),
111 myBeanTolerance2(0.),
112 myCurveResolution1(0.),
114 myIsDone(Standard_False)
116 Init(theCurve1, theCurve2, theBeanTolerance1, theBeanTolerance2);
119 // ==================================================================================
120 // function: IntTools_BeanBeanIntersector
122 // ==================================================================================
123 IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector(const BRepAdaptor_Curve& theCurve1,
124 const BRepAdaptor_Curve& theCurve2,
125 const Standard_Real theFirstParOnCurve1,
126 const Standard_Real theLastParOnCurve1,
127 const Standard_Real theFirstParOnCurve2,
128 const Standard_Real theLastParOnCurve2,
129 const Standard_Real theBeanTolerance1,
130 const Standard_Real theBeanTolerance2) :
132 myFirstParameter1(0.),
133 myLastParameter1(0.),
134 myFirstParameter2(0.),
135 myLastParameter2(0.),
136 myBeanTolerance1(0.),
137 myBeanTolerance2(0.),
138 myCurveResolution1(0.),
140 myIsDone(Standard_False)
142 Init(theCurve1, theCurve2, theFirstParOnCurve1, theLastParOnCurve1,
143 theFirstParOnCurve2, theLastParOnCurve2,
144 theBeanTolerance1, theBeanTolerance2);
147 // ==================================================================================
150 // ==================================================================================
151 void IntTools_BeanBeanIntersector::Init(const TopoDS_Edge& theEdge1,
152 const TopoDS_Edge& theEdge2)
154 myCurve1.Initialize(theEdge1);
155 myCurve2.Initialize(theEdge2);
157 myTrsfCurve1 = Handle(Geom_Curve)::DownCast(myCurve1.Curve().Curve()->Transformed(myCurve1.Trsf()));
158 myTrsfCurve2 = Handle(Geom_Curve)::DownCast(myCurve2.Curve().Curve()->Transformed(myCurve2.Trsf()));
160 SetBeanParameters(Standard_True, myCurve1.FirstParameter(), myCurve1.LastParameter());
161 SetBeanParameters(Standard_False, myCurve2.FirstParameter(), myCurve2.LastParameter());
163 myBeanTolerance1 = BRep_Tool::Tolerance(theEdge1);
164 myBeanTolerance2 = BRep_Tool::Tolerance(theEdge2);
165 myCriteria = myBeanTolerance1 + myBeanTolerance2;
166 myCurveResolution1 = myCurve1.Resolution(myCriteria);
169 // ==================================================================================
172 // ==================================================================================
173 void IntTools_BeanBeanIntersector::Init(const BRepAdaptor_Curve& theCurve1,
174 const BRepAdaptor_Curve& theCurve2,
175 const Standard_Real theBeanTolerance1,
176 const Standard_Real theBeanTolerance2)
178 myCurve1 = theCurve1;
179 myCurve2 = theCurve2;
181 SetBeanParameters(Standard_True, myCurve1.FirstParameter(), myCurve1.LastParameter());
182 SetBeanParameters(Standard_False, myCurve2.FirstParameter(), myCurve2.LastParameter());
184 myTrsfCurve1 = Handle(Geom_Curve)::DownCast(myCurve1.Curve().Curve()->Transformed(myCurve1.Trsf()));
185 myTrsfCurve2 = Handle(Geom_Curve)::DownCast(myCurve2.Curve().Curve()->Transformed(myCurve2.Trsf()));
187 myBeanTolerance1 = theBeanTolerance1;
188 myBeanTolerance2 = theBeanTolerance2;
189 myCriteria = myBeanTolerance1 + myBeanTolerance2;
190 myCurveResolution1 = myCurve1.Resolution(myCriteria);
193 // ==================================================================================
196 // ==================================================================================
197 void IntTools_BeanBeanIntersector::Init(const BRepAdaptor_Curve& theCurve1,
198 const BRepAdaptor_Curve& theCurve2,
199 const Standard_Real theFirstParOnCurve1,
200 const Standard_Real theLastParOnCurve1,
201 const Standard_Real theFirstParOnCurve2,
202 const Standard_Real theLastParOnCurve2,
203 const Standard_Real theBeanTolerance1,
204 const Standard_Real theBeanTolerance2)
206 myCurve1 = theCurve1;
207 myCurve2 = theCurve2;
209 myTrsfCurve1 = Handle(Geom_Curve)::DownCast(myCurve1.Curve().Curve()->Transformed(myCurve1.Trsf()));
210 myTrsfCurve2 = Handle(Geom_Curve)::DownCast(myCurve2.Curve().Curve()->Transformed(myCurve2.Trsf()));
212 SetBeanParameters(Standard_True, theFirstParOnCurve1, theLastParOnCurve1);
213 SetBeanParameters(Standard_False, theFirstParOnCurve2, theLastParOnCurve2);
215 myBeanTolerance1 = theBeanTolerance1;
216 myBeanTolerance2 = theBeanTolerance2;
217 myCriteria = myBeanTolerance1 + myBeanTolerance2;
218 myCurveResolution1 = myCurve1.Resolution(myCriteria);
221 // ==================================================================================
222 // function: SetBeanParameters
224 // ==================================================================================
225 void IntTools_BeanBeanIntersector::SetBeanParameters(const Standard_Boolean IsFirstBean,
226 const Standard_Real theFirstParOnCurve,
227 const Standard_Real theLastParOnCurve)
230 myFirstParameter1 = theFirstParOnCurve;
231 myLastParameter1 = theLastParOnCurve;
234 myFirstParameter2 = theFirstParOnCurve;
235 myLastParameter2 = theLastParOnCurve;
238 // ==================================================================================
241 // ==================================================================================
242 const IntTools_SequenceOfRanges& IntTools_BeanBeanIntersector::Result() const
247 // ==================================================================================
250 // ==================================================================================
251 void IntTools_BeanBeanIntersector::Result(IntTools_SequenceOfRanges& theResults) const
253 theResults = myResults;
255 // ==================================================================================
258 // ==================================================================================
259 void IntTools_BeanBeanIntersector::Perform()
261 Standard_Boolean bFastComputed;
262 Standard_Integer k, i, iFlag, aNbRanges, aNbResults;
263 Standard_Real aMidParameter, aCoeff, aParamDist, aPPC;
264 Standard_Real aCriteria2, aD2;
266 IntTools_CArray1OfReal aParams;
267 IntTools_Range aRange2, aRange;
269 myIsDone = Standard_False;
272 LocalPrepareArgs(myCurve1, myFirstParameter1, myLastParameter1, myDeflection, aParams);
274 myRangeManager.SetRanges(aParams, 0);
276 aNbRanges=myRangeManager.Length();
281 bFastComputed=FastComputeIntersection();
283 aRange.SetFirst(myFirstParameter1);
284 aRange.SetLast (myLastParameter1);
285 myResults.Append(aRange);
286 myIsDone = Standard_True;
290 ComputeRoughIntersection();
292 //Standard_Real aMidParameter = (myFirstParameter2 + myLastParameter2) * 0.5;
294 aMidParameter = myFirstParameter2+(myLastParameter2-myFirstParameter2)*aCoeff;
296 for(k = 0; k < 2; ++k) {
298 aRange2.SetFirst(myFirstParameter2);
299 aRange2.SetLast(aMidParameter);
302 aRange2.SetFirst(aMidParameter);
303 aRange2.SetLast(myLastParameter2);
306 ComputeUsingExtrema(aRange2);
308 ComputeNearRangeBoundaries(aRange2);
313 // 0 - just initialized
314 // 1 - non-intersected
315 // 2 - roughly intersected
316 // 3 - intersection is not done
317 // 4 - coincided range
319 aPPC=Precision::PConfusion();
320 aCriteria2=myCriteria*myCriteria;
321 aNbRanges=myRangeManager.Length();
323 for(i=1; i<=aNbRanges; ++i) {
324 iFlag=myRangeManager.Flag(i);
327 aRange=myRangeManager.Range(i);
328 aNbResults=myResults.Length();
330 const IntTools_Range& aLastRange = myResults.Last();
332 aParamDist = Abs(aRange.First() - aLastRange.Last());
333 if(aParamDist > myCurveResolution1) {
334 myResults.Append(aRange);
337 aPi=myCurve1.Value(aRange.First());
338 aPh=myCurve1.Value(aLastRange.Last());
339 aD2=aPi.SquareDistance(aPh);
340 if(aParamDist<aPPC || aD2<aCriteria2) {
341 myResults.ChangeValue(aNbResults).SetLast(aRange.Last());
344 myResults.Append(aRange);
349 myResults.Append(aRange);
352 } // for(i = 1; i <= myRangeManager.Length(); i++) {
353 myIsDone = Standard_True;
355 // ==================================================================================
356 // function: FastComputeIntersection
358 // ==================================================================================
359 Standard_Boolean IntTools_BeanBeanIntersector::FastComputeIntersection()
361 Standard_Boolean aresult;
362 GeomAbs_CurveType aCT1, aCT2;
364 aresult = Standard_False;
366 aCT1=myCurve1.GetType();
367 aCT2=myCurve2.GetType();
374 if(aCT1==GeomAbs_Line) {
375 Standard_Real par1, par2;
377 if((Distance(myFirstParameter1, par1) < myCriteria) &&
378 (Distance(myLastParameter1, par2) < myCriteria)) {
380 if((par1 >= myFirstParameter2) && (par1 <= myLastParameter2) &&
381 (par2 >= myFirstParameter2) && (par2 <= myLastParameter2)) {
382 myRangeManager.InsertRange(myFirstParameter1, myLastParameter1, 4);
383 aresult = Standard_True;
390 if(aCT1==GeomAbs_Circle) {
391 Standard_Real anAngle, aPA, aDistLoc, aDist, aDiff, aR1, aR2;
392 gp_Circ aCirc1, aCirc2;
395 aCirc1=myCurve1.Circle();
396 aCirc2=myCurve2.Circle();
400 aPA=Precision::Angular();
401 aDir1 = aCirc1.Axis().Direction();
402 aDir2 = aCirc2.Axis().Direction();
404 anAngle = aDir1.Angle(aDir2);
409 const gp_Pnt& aPLoc1=aCirc1.Location();
410 const gp_Pnt& aPLoc2=aCirc2.Location();
411 aDistLoc = aPLoc1.Distance(aPLoc2);
415 if(Abs(aDist) > myCriteria) {
419 Standard_Real aSinPA, atmpvalue, aprojectedradius;
422 atmpvalue = aR1*aSinPA;
423 atmpvalue *= atmpvalue;
424 aprojectedradius = sqrt(aR1*aR1 - atmpvalue);
426 aDiff = aprojectedradius - aR2;
427 aDist = aDistLoc + sqrt((aDiff * aDiff) + atmpvalue);
428 if(Abs(aDist) > myCriteria) {
432 Standard_Boolean newparfound;
434 Standard_Real afirstpar, alastpar, par1, par2, apar;
436 afirstpar = myFirstParameter1;
437 alastpar = myLastParameter1;
439 for(i = 0; i < 2; i++) {
440 if((Distance(afirstpar, par1) < myCriteria) &&
441 (Distance(alastpar , par2) < myCriteria)) {
443 if(i || Distance((myFirstParameter1 + myLastParameter2) * 0.5, apar) < myCriteria) {
444 myRangeManager.InsertRange(afirstpar, alastpar, 4);
447 aresult = Standard_True;
457 newparfound = Standard_False;
459 if(Distance((myFirstParameter1 + myLastParameter2) * 0.5, apar) < myCriteria) {
460 afirstpar = myFirstParameter1 + myCriteria;
461 alastpar = myLastParameter1 - myCriteria;
462 newparfound = Standard_True;
464 if(alastpar <= afirstpar) {
465 newparfound = Standard_False;
472 }// for(i = 0; i < 2; i++) {
473 } // if(aCT1==GeomAbs_Circle)
474 //modified by NIZNHY-PKV Mon Oct 08 14:08:19 2012f
475 if (aCT1==GeomAbs_BSplineCurve || aCT1==GeomAbs_BezierCurve) {
476 Standard_Integer iFlag;
478 iFlag=CheckCoincidence(myFirstParameter1,
491 //modified by NIZNHY-PKV Mon Oct 08 14:08:23 2012t
494 // ==================================================================================
495 // function: Distance
497 // ==================================================================================
498 Standard_Real IntTools_BeanBeanIntersector::Distance(const Standard_Real theArg,
499 Standard_Real& theArgOnOtherBean)
501 Standard_Real aDistance;
502 Standard_Integer aNbPoints;
505 aDistance=RealLast();
507 aPoint=myCurve1.Value(theArg);
508 myProjector.Init(myTrsfCurve2, myFirstParameter2, myLastParameter2);
509 myProjector.Perform(aPoint);
511 aNbPoints=myProjector.NbPoints();
513 theArgOnOtherBean = myProjector.LowerDistanceParameter();
514 aDistance=myProjector.LowerDistance();
518 Standard_Real aDistance1, aDistance2;
520 aDistance1 = aPoint.Distance(myCurve2.Value(myFirstParameter2));
521 aDistance2 = aPoint.Distance(myCurve2.Value(myLastParameter2));
523 theArgOnOtherBean = myLastParameter2;
524 aDistance=aDistance2;
525 if(aDistance1 < aDistance2) {
526 theArgOnOtherBean = myFirstParameter2;
527 aDistance=aDistance1;
532 // ==================================================================================
533 // function: ComputeRoughIntersection
535 // ==================================================================================
536 void IntTools_BeanBeanIntersector::ComputeRoughIntersection()
538 Standard_Boolean isintersection;
539 Standard_Integer i, aNbArgs, aNbArgs1, aNbRanges, j, aNbLines, k, pIt, extIt, iFlag;
540 Standard_Real aDeflection, aGPR, aCurDeflection, aT1, aT2, aD;
541 Standard_Real aMaxDistance, aDistance, aPPC, aPrm1, aPrm2, aPPA;
542 GeomAbs_CurveType aCT1, aCT2;
543 gp_Pnt aPoint1, aPoint2, aMidPOnCurve, aMidPOnLine, aP1, aP2;
544 IntTools_CArray1OfReal anArgs;
545 LocalPrepareArgs(myCurve2, myFirstParameter2, myLastParameter2, aDeflection, anArgs);
547 aNbArgs=anArgs.Length();
552 aCT1=myCurve1.GetType();
553 aCT2=myCurve2.GetType();
554 aGPR=gp::Resolution();
555 aPPC=Precision::PConfusion();
556 aPPA=Precision::Angular();
559 Intf_Array1OfLin aLines(1, aNbArgs1);
560 TColStd_Array1OfInteger aLineFlags(1, aNbArgs1);
561 TColStd_Array1OfReal aDistances(1, aNbArgs1);
564 aPoint1 = myCurve2.Value(aT1);
565 for(i=1; i<aNbArgs; ++i) {
567 aPoint2 = myCurve2.Value(aT2);
568 gp_Vec aVec(aPoint1, aPoint2);
570 aDistances.SetValue(i, aD);
573 aLineFlags.SetValue(i, 0);
576 aLineFlags.SetValue(i, 1);
577 gp_Lin aLine(aPoint1, gp_Dir(aVec));
578 aLines.SetValue(i, aLine);
580 if((aCT2 == GeomAbs_BezierCurve) ||
581 (aCT2 == GeomAbs_BSplineCurve)) {
582 aMidPOnCurve = myCurve2.Value((aT1+aT2) * 0.5);
583 aMidPOnLine = ElCLib::Value((aDistances(i)*0.5), aLine);
584 aCurDeflection = aMidPOnCurve.Distance(aMidPOnLine);
585 if(aCurDeflection > aDeflection) {
586 aDeflection = aCurDeflection;
594 aNbLines=aLines.Upper();
595 aMaxDistance = myCriteria + myDeflection + aDeflection;
597 aT1=myRangeManager.Range(1).First();
598 aPoint1 = myCurve1.Value(aT1);
599 aNbRanges=myRangeManager.Length();
600 for(i = 1; i <= aNbRanges; ++i) {
601 const IntTools_Range& aRange = myRangeManager.Range(i);
603 aPoint2 = myCurve1.Value(aT2);
605 iFlag=myRangeManager.Flag(i);
606 if(iFlag==4) {// coincided
612 myRangeManager.SetFlag(i, 1); // not intersected
617 aBox1.Enlarge(myBeanTolerance1 + myDeflection);
619 gp_Vec aVec(aPoint1, aPoint2);
621 aDistance=aVec.Magnitude();
622 if(aDistance <= aGPR) {
623 myRangeManager.SetFlag(i, 0);
627 gp_Lin aLine(aPoint1, gp_Dir(aVec));
629 if((aCT1 == GeomAbs_BezierCurve) ||
630 (aCT1 == GeomAbs_BSplineCurve)) {
631 aMidPOnCurve = myCurve1.Value((aRange.First() + aRange.Last()) * 0.5);
632 aMidPOnLine = ElCLib::Value((aDistance*0.5), aLine);
633 aCurDeflection = aMidPOnCurve.Distance(aMidPOnLine);
634 if(myDeflection < aCurDeflection) {
635 aMaxDistance += aCurDeflection - myDeflection;
636 myDeflection = aCurDeflection;
640 for(j=1; j<=aNbLines; ++j) {
642 myRangeManager.SetFlag(i, 0);
646 const gp_Lin& aL2=aLines(j);
647 //Handle(Geom_Line) aC2=new Geom_Line(aL2); // DEB ft
649 aP1=ElCLib::Value(0., aL2);
650 aP2=ElCLib::Value(aD, aL2);
652 Extrema_ExtElC anExtrema(aLine, aL2, aPPA);
653 if(anExtrema.IsDone() && (anExtrema.IsParallel() || (anExtrema.NbExt() > 0))) {
654 isintersection = Standard_False;
656 if(anExtrema.IsParallel()) {
657 isintersection = (anExtrema.SquareDistance(1) < aMaxDistance * aMaxDistance);
660 for(k = 1; !isintersection && k <= anExtrema.NbExt(); ++k) {
661 if(anExtrema.SquareDistance(k) < aMaxDistance * aMaxDistance) {
662 Extrema_POnCurv P1, P2;
663 anExtrema.Points(k, P1, P2);
664 aPrm1=P1.Parameter();
665 aPrm2=P2.Parameter();
666 if((aPrm1 >= -aMaxDistance) && (aPrm1 <= aDistance+aMaxDistance) &&
667 (aPrm2 >= -aMaxDistance) && (aPrm2 <= aD+aMaxDistance)) {
668 isintersection = Standard_True;
671 Extrema_ExtPElC aPointProjector;
673 for(pIt = 0; !isintersection && (pIt < 4); ++pIt) {
677 //Extrema_ExtPElC(aPoint1, aLines(j), aPPC, 0., aDistances(j));
678 Extrema_ExtPElC(aPoint1, aL2, aPPC, -aMaxDistance, aD+aMaxDistance);
683 //Extrema_ExtPElC(aPoint2, aLines(j), aPPC, 0., aD);
684 Extrema_ExtPElC(aPoint2, aL2, aPPC, -aMaxDistance, aD+aMaxDistance);
689 //Extrema_ExtPElC(ElCLib::Value(0., aLines(j)), aLine, aPPC, 0., aDistance);
690 Extrema_ExtPElC(aP1, aLine, aPPC, -aMaxDistance, aDistance+aMaxDistance);
695 //Extrema_ExtPElC(ElCLib::Value(aDistances(j), aLines(j)), aLine, aPPC, 0., aDistance);
696 Extrema_ExtPElC(aP2, aLine, aPPC, -aMaxDistance, aDistance+aMaxDistance);
704 if(aPointProjector.IsDone()) {
705 Standard_Real aMaxDistance2 = aMaxDistance * aMaxDistance;
706 for(extIt = 1; extIt <= aPointProjector.NbExt(); extIt++) {
707 if(aPointProjector.SquareDistance(extIt) < aMaxDistance2) {
708 isintersection = Standard_True;
714 }//if(anExtrema.Value(k) < aMaxDistance) {
715 }//for(k = 1; !isintersection && k <= anExtrema.NbExt(); k++) {
719 myRangeManager.SetFlag(i, 2); // roughly intersected
722 }//if(anExtrema.IsDone() && (anExtrema.IsParallel() || (anExtrema.NbExt() > 0))) {
725 aBox2.Add(myCurve2.Value(anArgs(j-1)));
726 aBox2.Add(myCurve2.Value(anArgs(j)));
727 aBox2.Enlarge(myBeanTolerance2 + aDeflection);
729 if(!aBox1.IsOut(aBox2)) {
730 myRangeManager.SetFlag(i, 2); // roughly intersected
740 // ==================================================================================
741 // function: ComputeUsingExtrema
743 // ==================================================================================
744 void IntTools_BeanBeanIntersector::ComputeUsingExtrema(const IntTools_Range& theRange2)
747 //Extrema_ExtCC is reused throughout this method to store caches computed on
748 //theRange2. However it is actually used only in a few calls of
749 //ComputeUsingExtrema(), so using a default constructor would add unnecessary overhead
750 //of initialization its internal fields. Since it is not manipulated by Handle then
751 //we will use a pointer to it and initialize it only when needed.
752 Extrema_ExtCC *apExtrema = 0;
753 Handle(GeomAdaptor_HCurve) aHCurve1, aHCurve2; //will be initialized later, only if needed
754 //handles are used to guard pointers to GeomAdaptor_Curve inside Extrema
755 Standard_Real aCriteria2 = myCriteria * myCriteria;
756 for(Standard_Integer i = 1; i <= myRangeManager.Length(); i++) {
758 if(myRangeManager.Flag(i) == 2 || myRangeManager.Flag(i) == 0) {
759 const IntTools_Range& aParamRange = myRangeManager.Range(i);
761 if(aParamRange.Last() - aParamRange.First() < Precision::PConfusion()) {
763 if(((i > 1) && (myRangeManager.Flag(i-1) == 4)) ||
764 ((i < myRangeManager.Length()) && (myRangeManager.Flag(i+1) == 4))) {
765 myRangeManager.SetFlag(i, 4);
769 if (aHCurve2.IsNull()) {
770 //initialize only once
771 apExtrema = new Extrema_ExtCC;
772 Standard_Real ftmp = theRange2.First() - Precision::PConfusion();
773 Standard_Real ltmp = theRange2.Last() + Precision::PConfusion();
774 ftmp = (ftmp < myFirstParameter2) ? myFirstParameter2 : ftmp;
775 ltmp = (ltmp > myLastParameter2) ? myLastParameter2 : ltmp;
776 aHCurve2 = new GeomAdaptor_HCurve (myTrsfCurve2, ftmp, ltmp);
777 apExtrema->SetCurve (2, aHCurve2->Curve(), theRange2.First(), theRange2.Last());
779 Extrema_ExtCC& anExtrema = *apExtrema;
781 Standard_Real ftmp = aParamRange.First() - Precision::PConfusion();
782 Standard_Real ltmp = aParamRange.Last() + Precision::PConfusion();
783 ftmp = (ftmp < myFirstParameter1) ? myFirstParameter1 : ftmp;
784 ltmp = (ltmp > myLastParameter1) ? myLastParameter1 : ltmp;
785 aHCurve1 = new GeomAdaptor_HCurve (myTrsfCurve1, ftmp, ltmp);
786 anExtrema.SetCurve (1, aHCurve1->Curve(), aParamRange.First(), aParamRange.Last());
790 if(anExtrema.IsDone() && (anExtrema.IsParallel() || (anExtrema.NbExt() > 0))) {
791 Standard_Integer anOldNbRanges = myRangeManager.Length();
793 if (anExtrema.IsParallel()) {
794 if(anExtrema.SquareDistance(1) < aCriteria2) {
795 Standard_Real theParameter1, theParameter2;
796 Standard_Real adistance1 = Distance(aParamRange.First(), theParameter1);
797 Standard_Real adistance2 = Distance(aParamRange.Last(), theParameter2);
798 Standard_Boolean validdistance1 = (adistance1 < myCriteria);
799 Standard_Boolean validdistance2 = (adistance2 < myCriteria);
801 if (validdistance1 && validdistance2) {
802 myRangeManager.InsertRange(aParamRange.First(), aParamRange.Last(), 4);
807 ComputeRangeFromStartPoint(Standard_True, aParamRange.First(), i, theParameter1, theRange2);
811 ComputeRangeFromStartPoint(Standard_False, aParamRange.Last(), i, theParameter2, theRange2);
814 Standard_Real a = aParamRange.First();
815 Standard_Real b = aParamRange.Last();
816 Standard_Real da = adistance1;
817 Standard_Real db = adistance2;
818 Standard_Real asolution = a;
819 Standard_Boolean found = Standard_False;
821 while(((b - a) > myCurveResolution1) && !found) {
822 asolution = (a+b)*0.5;
823 Standard_Real adist = Distance(asolution, theParameter1);
825 if(adist < myCriteria) {
826 found = Standard_True;
841 ComputeRangeFromStartPoint(Standard_False, asolution, i, theParameter1, theRange2);
842 ComputeRangeFromStartPoint(Standard_True, asolution, i, theParameter1, theRange2);
845 myRangeManager.SetFlag(i, 2);
854 for(Standard_Integer j = 1 ; j <= anExtrema.NbExt(); j++) {
855 if(anExtrema.SquareDistance(j) < aCriteria2) {
856 Extrema_POnCurv p1, p2;
857 anExtrema.Points(j, p1, p2);
859 Standard_Integer aNbRanges = myRangeManager.Length();
861 Standard_Integer anIndex = myRangeManager.GetIndex(p1.Parameter(), Standard_False);
863 ComputeRangeFromStartPoint(Standard_False, p1.Parameter(), anIndex, p2.Parameter(), theRange2);
866 anIndex = myRangeManager.GetIndex(p1.Parameter(), Standard_True);
869 ComputeRangeFromStartPoint(Standard_True, p1.Parameter(), anIndex, p2.Parameter(), theRange2);
872 if(aNbRanges == myRangeManager.Length()) {
873 SetEmptyResultRange(p1.Parameter(), myRangeManager);
878 Standard_Integer adifference = myRangeManager.Length() - anOldNbRanges;
880 if(adifference > 0) {
885 myRangeManager.SetFlag(i, 3); // intersection not done.
889 if (apExtrema) delete apExtrema;
892 // ==================================================================================
893 // function: ComputeNearRangeBoundaries
895 // ==================================================================================
896 void IntTools_BeanBeanIntersector::ComputeNearRangeBoundaries(const IntTools_Range& theRange2)
898 Standard_Real theParameter = theRange2.First();
900 for(Standard_Integer i = 1; i <= myRangeManager.Length(); i++) {
901 if(myRangeManager.Flag(i) != 3)
904 if((i > 1) && ((myRangeManager.Flag(i-1) == 1) || (myRangeManager.Flag(i-1) == 4))) {
905 myRangeManager.SetFlag(i, 2);
909 const IntTools_Range& aParamRange = myRangeManager.Range(i);
911 if(Distance(aParamRange.First(), theParameter) < myCriteria) {
912 Standard_Integer aNbRanges = myRangeManager.Length();
915 ComputeRangeFromStartPoint(Standard_False, aParamRange.First(), i-1, theParameter, theRange2);
917 ComputeRangeFromStartPoint(Standard_True, aParamRange.First(), i + (myRangeManager.Length() - aNbRanges), theParameter, theRange2);
919 if(aNbRanges == myRangeManager.Length()) {
920 SetEmptyResultRange(aParamRange.First(), myRangeManager);
924 myRangeManager.SetFlag(i, 2);
928 if((myRangeManager.Flag(myRangeManager.Length()) == 3) ||
929 (myRangeManager.Flag(myRangeManager.Length()) == 2)) {
930 const IntTools_Range& aParamRange = myRangeManager.Range(myRangeManager.Length());
932 if(Distance(aParamRange.Last(), theParameter) < myCriteria) {
933 Standard_Integer aNbRanges = myRangeManager.Length();
934 myRangeManager.SetFlag(myRangeManager.Length(), 2);
936 ComputeRangeFromStartPoint(Standard_False, aParamRange.Last(), myRangeManager.Length(), theParameter, theRange2);
938 if(aNbRanges == myRangeManager.Length()) {
939 SetEmptyResultRange(aParamRange.Last(), myRangeManager);
943 myRangeManager.SetFlag(myRangeManager.Length(), 2);
948 // ==================================================================================
949 // function: ComputeRangeFromStartPoint
951 // ==================================================================================
952 void IntTools_BeanBeanIntersector::ComputeRangeFromStartPoint(const Standard_Boolean ToIncreaseParameter,
953 const Standard_Real theParameter,
954 const Standard_Integer theIndex,
955 const Standard_Real theParameter2,
956 const IntTools_Range& theRange2)
959 if(myRangeManager.Flag(theIndex) == 4 ||
960 myRangeManager.Flag(theIndex) == 1)
963 Standard_Integer aValidIndex = theIndex;
964 Standard_Real aMinDelta = myCurveResolution1 * 0.5;
965 Standard_Real aDeltaRestrictor = myLastParameter1 - myFirstParameter1;
967 if(Abs(aDeltaRestrictor) < Precision::PConfusion()) {
971 if(aMinDelta > aDeltaRestrictor) {
972 aMinDelta = aDeltaRestrictor;
974 Standard_Real tenOfMinDelta = aMinDelta * 10.;
975 Standard_Real aDelta = myCurveResolution1;
976 Standard_Real aCurPar = (ToIncreaseParameter) ? (theParameter + aDelta) : (theParameter - aDelta);
977 Standard_Real aPrevPar = theParameter;
978 IntTools_Range aCurrentRange = myRangeManager.Range(aValidIndex);
980 Standard_Boolean BoundaryCondition = (ToIncreaseParameter) ? (aCurPar > aCurrentRange.Last()) : (aCurPar < aCurrentRange.First());
982 if(BoundaryCondition) {
983 aCurPar = (ToIncreaseParameter) ? aCurrentRange.Last() : aCurrentRange.First();
984 BoundaryCondition = Standard_False;
987 Standard_Integer loopcounter = 0; // neccesary to have no infinite loop
988 Standard_Real aParameter = theParameter2;
989 Standard_Boolean anotherSolutionFound = Standard_False;
991 Standard_Boolean isboundaryindex = Standard_False;
992 Standard_Boolean isvalidindex = Standard_True;
994 Standard_Real aCriteria2 = myCriteria * myCriteria;
996 while((aDelta >= aMinDelta) && (loopcounter <= 10)) {
997 Standard_Boolean pointfound = Standard_False;
999 gp_Pnt aPoint = myCurve1.Value(aCurPar);
1000 GeomAdaptor_Curve aCurve2(myTrsfCurve2, theRange2.First(), theRange2.Last());
1002 Extrema_LocateExtPC anExtrema(aPoint, aCurve2, aParameter, theRange2.First(), theRange2.Last(), 1.e-10);
1004 if(anExtrema.IsDone()) {
1005 if(anExtrema.SquareDistance() < aCriteria2) {
1006 Extrema_POnCurv aPOnCurv = anExtrema.Point();
1007 aParameter = aPOnCurv.Parameter();
1008 pointfound = Standard_True;
1012 // pointfound = (Distance(aCurPar, aParameter) < myCriteria);
1013 Standard_Real afoundparam = aParameter;
1015 if(Distance(aCurPar, afoundparam) < myCriteria) {
1016 aParameter = afoundparam;
1017 pointfound = Standard_True;
1023 anotherSolutionFound = Standard_True;
1025 if(BoundaryCondition && (isboundaryindex || !isvalidindex))
1029 aDeltaRestrictor = aDelta;
1032 // if pointfound decide to increase aDelta using derivative of distance function
1035 aDelta = (pointfound) ? (aDelta * 2.) : (aDelta * 0.5);
1036 aDelta = (aDelta < aDeltaRestrictor) ? aDelta : aDeltaRestrictor;
1037 aCurPar = (ToIncreaseParameter) ? (aPrevPar + aDelta) : (aPrevPar - aDelta);
1039 BoundaryCondition = (ToIncreaseParameter) ? (aCurPar > aCurrentRange.Last()) : (aCurPar < aCurrentRange.First());
1041 isboundaryindex = Standard_False;
1042 isvalidindex = Standard_True;
1044 if(BoundaryCondition) {
1045 isboundaryindex = ((!ToIncreaseParameter && (aValidIndex == 1)) ||
1046 (ToIncreaseParameter && (aValidIndex == myRangeManager.Length())));
1048 if(!isboundaryindex) {
1050 Standard_Integer aFlag = (ToIncreaseParameter) ? myRangeManager.Flag(aValidIndex + 1) : myRangeManager.Flag(aValidIndex - 1);
1052 if(aFlag != 1 && aFlag != 4) {
1053 aValidIndex = (ToIncreaseParameter) ? (aValidIndex + 1) : (aValidIndex - 1);
1054 aCurrentRange = myRangeManager.Range(aValidIndex);
1056 if((ToIncreaseParameter && (aCurPar > aCurrentRange.Last())) ||
1057 (!ToIncreaseParameter && (aCurPar < aCurrentRange.First()))) {
1058 aCurPar = (aCurrentRange.First() + aCurrentRange.Last()) * 0.5;
1063 isvalidindex = Standard_False;
1064 aCurPar = (ToIncreaseParameter) ? aCurrentRange.Last() : aCurrentRange.First();
1069 aCurPar = (ToIncreaseParameter) ? aCurrentRange.Last() : aCurrentRange.First();
1072 if(aDelta < tenOfMinDelta) {
1078 } // end if(BoundaryCondition)
1081 if(anotherSolutionFound) {
1082 if(ToIncreaseParameter)
1083 myRangeManager.InsertRange(theParameter, aPrevPar, 4);
1085 myRangeManager.InsertRange(aPrevPar, theParameter, 4);
1089 // ---------------------------------------------------------------------------------
1090 // static function: LocalPrepareArgs
1092 // ---------------------------------------------------------------------------------
1093 static void LocalPrepareArgs(BRepAdaptor_Curve& theCurve,
1094 const Standard_Real theFirstParameter,
1095 const Standard_Real theLastParameter,
1096 Standard_Real& theDeflection,
1097 IntTools_CArray1OfReal& theArgs) {
1098 Standard_Integer aDiscretization = 30;
1099 Standard_Real aRelativeDeflection = 0.01;
1100 theDeflection = aRelativeDeflection;
1101 Standard_Boolean prepareargs = Standard_True;
1103 switch(theCurve.GetType()) {
1104 case GeomAbs_Line: {
1105 prepareargs = Standard_False;
1106 aDiscretization = 3;
1107 theArgs.Append(theFirstParameter);
1109 if((theLastParameter - theFirstParameter) > Precision::PConfusion()) {
1110 theArgs.Append((theFirstParameter + theLastParameter)*0.5);
1112 theArgs.Append(theLastParameter);
1113 theDeflection = Precision::Confusion();
1116 case GeomAbs_Circle: {
1117 aDiscretization = 23;
1118 theDeflection = aRelativeDeflection * theCurve.Circle().Radius();
1121 case GeomAbs_Ellipse: {
1122 aDiscretization = 40;
1123 theDeflection = 2 * aRelativeDeflection * theCurve.Ellipse().MajorRadius();
1126 case GeomAbs_Hyperbola:
1127 case GeomAbs_Parabola: {
1128 aDiscretization = 40;
1129 theDeflection = aRelativeDeflection;
1132 case GeomAbs_BezierCurve: {
1133 aDiscretization = 30;
1134 theDeflection = aRelativeDeflection;
1137 case GeomAbs_BSplineCurve: {
1138 aDiscretization = 30;
1139 theDeflection = aRelativeDeflection;
1143 aDiscretization = 30;
1144 theDeflection = aRelativeDeflection;
1149 IntTools::PrepareArgs(theCurve, theLastParameter, theFirstParameter, aDiscretization, aRelativeDeflection, theArgs);
1152 // ---------------------------------------------------------------------------------
1153 // static function: SetEmptyResultRange
1155 // ---------------------------------------------------------------------------------
1156 static Standard_Boolean SetEmptyResultRange(const Standard_Real theParameter,
1157 IntTools_MarkedRangeSet& theMarkedRange) {
1159 const TColStd_SequenceOfInteger& anIndices = theMarkedRange.GetIndices(theParameter);
1160 Standard_Boolean add = (anIndices.Length() > 0);
1162 for(Standard_Integer k = 1; k <= anIndices.Length(); k++) {
1163 if(theMarkedRange.Flag(anIndices(k)) == 4) {
1164 add = Standard_False;
1170 theMarkedRange.InsertRange(theParameter, theParameter, 4);
1175 //modified by NIZNHY-PKV Fri Oct 12 09:34:10 2012f
1177 Standard_Integer DistPC(const Standard_Real aT1,
1178 const Handle(Geom_Curve)& aC1,
1179 const Standard_Real aCriteria,
1180 GeomAPI_ProjectPointOnCurve& aProjector,
1182 Standard_Real& aT2);
1186 Standard_Integer DistPC(const Standard_Real aT1,
1187 const Handle(Geom_Curve)& aC1,
1188 const Standard_Real aCriteria,
1189 GeomAPI_ProjectPointOnCurve& aProjector,
1192 Standard_Real& aDmax,
1193 Standard_Real& aTmax);
1196 Standard_Integer FindMaxDistPC(const Standard_Real aT1A,
1197 const Standard_Real aT1B,
1198 const Handle(Geom_Curve)& aC1,
1199 const Standard_Real aCriteria,
1200 const Standard_Real aEps1,
1201 GeomAPI_ProjectPointOnCurve& aProjector,
1202 Standard_Real& aDmax,
1203 Standard_Real& aT1max);
1205 //=======================================================================
1206 //function : CheckCoincidence
1208 //=======================================================================
1209 Standard_Integer CheckCoincidence(const Standard_Real aT11,
1210 const Standard_Real aT12,
1211 const Handle(Geom_Curve)& aC1,
1212 const Standard_Real aT21,
1213 const Standard_Real aT22,
1214 const Handle(Geom_Curve)& aC2,
1215 const Standard_Real aCriteria,
1216 const Standard_Real aEps1,
1217 GeomAPI_ProjectPointOnCurve& aProjector)
1219 Standard_Integer iErr, aNb1, i, aNbX;
1220 Standard_Real dT1, aT1, aT2, aD, aDmax, aTmax;
1221 Standard_Real aT1A, aT1B, aD1max,aT1max;
1223 iErr=0; // the patches are coincided
1226 aProjector.Init(aC2, aT21, aT22);
1230 // 1. Express evaluation
1232 aNb1=10; // Number of intervals on the curve #1
1233 dT1=(aT12-aT11)/aNb1;
1234 for (i=1; i<aNb1; ++i) {
1237 iErr=DistPC(aT1, aC1, aCriteria, aProjector, aD, aT2, aDmax, aTmax);
1239 iErr=1;// a point from aC1 can not be projected on aC2
1243 if (aDmax>aCriteria) {
1244 iErr=2; // the distance is too big
1249 // 2. Deep evaluation
1253 for (i=1; i<aNbX; ++i) {
1257 iErr=FindMaxDistPC(aT1A, aT1B, aC1, aCriteria, aEps1, aProjector, aD1max, aT1max);
1267 //=======================================================================
1268 //function : FindMaxDistPC
1270 //=======================================================================
1271 Standard_Integer FindMaxDistPC(const Standard_Real aT1A,
1272 const Standard_Real aT1B,
1273 const Handle(Geom_Curve)& aC1,
1274 const Standard_Real aCriteria,
1275 const Standard_Real aEps1,
1276 GeomAPI_ProjectPointOnCurve& aProjector,
1277 Standard_Real& aDmax,
1278 Standard_Real& aT1max)
1280 Standard_Integer iErr;
1281 Standard_Real aGS, aXP, aA, aB, aXL, aYP, aYL, aT2P, aT2L;
1286 aGS=0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))-1.;
1293 iErr=DistPC(aXP, aC1, aCriteria, aProjector, aYP, aT2P, aDmax, aT1max);
1298 iErr=DistPC(aXL, aC1, aCriteria, aProjector, aYL, aT2L, aDmax, aT1max);
1309 iErr=DistPC(aXP, aC1, aCriteria, aProjector, aYP, aT2P, aDmax, aT1max);
1319 iErr=DistPC(aXL, aC1, aCriteria, aProjector, aYL, aT2L, aDmax, aT1max);
1325 if ((aB-aA)<aEps1) {
1332 //=======================================================================
1335 //=======================================================================
1336 Standard_Integer DistPC(const Standard_Real aT1,
1337 const Handle(Geom_Curve)& aC1,
1338 const Standard_Real aCriteria,
1339 GeomAPI_ProjectPointOnCurve& aProjector,
1342 Standard_Real& aDmax,
1343 Standard_Real& aTmax)
1345 Standard_Integer iErr;
1347 iErr=DistPC(aT1, aC1, aCriteria, aProjector, aD, aT2);
1359 //=======================================================================
1362 //=======================================================================
1363 Standard_Integer DistPC(const Standard_Real aT1,
1364 const Handle(Geom_Curve)& aC1,
1365 const Standard_Real aCriteria,
1366 GeomAPI_ProjectPointOnCurve& aProjector,
1370 Standard_Integer iErr, aNbP2;
1376 aProjector.Perform(aP1);
1377 aNbP2=aProjector.NbPoints();
1379 iErr=1;// the point from aC1 can not be projected on aC2
1383 aD=aProjector.LowerDistance();
1384 aT2=aProjector.LowerDistanceParameter();
1386 iErr=2;// the distance is too big
1391 //modified by NIZNHY-PKV Fri Oct 12 09:34:12 2012t