0023354: The use of 'if (A) {...} else if (A) {...}' pattern was detected.
[occt.git] / src / IntTools / IntTools_BeanBeanIntersector.cxx
CommitLineData
b311480e 1// Copyright (c) 1999-2012 OPEN CASCADE SAS
7fd59977 2//
b311480e 3// The content of this file is subject to the Open CASCADE Technology Public
4// License Version 6.5 (the "License"). You may not use the content of this file
5// except in compliance with the License. Please obtain a copy of the License
6// at http://www.opencascade.org and read it completely before using this file.
7fd59977 7//
b311480e 8// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
7fd59977 10//
b311480e 11// The Original Code and all software distributed under the License is
12// distributed on an "AS IS" basis, without warranty of any kind, and the
13// Initial Developer hereby disclaims all such warranties, including without
14// limitation, any warranties of merchantability, fitness for a particular
15// purpose or non-infringement. Please see the License for the specific terms
16// and conditions governing the rights and limitations under the License.
17
7fd59977 18#include <IntTools_BeanBeanIntersector.ixx>
19
20#include <IntTools_Root.hxx>
21#include <Precision.hxx>
22#include <Extrema_POnCurv.hxx>
23#include <BRep_Tool.hxx>
24#include <Geom_Curve.hxx>
25#include <TColStd_Array1OfReal.hxx>
26#include <TColStd_Array1OfInteger.hxx>
27#include <IntTools_CArray1OfReal.hxx>
28#include <gp_Lin.hxx>
29#include <Intf_Array1OfLin.hxx>
30#include <Bnd_Box.hxx>
31#include <Extrema_ExtCC.hxx>
32#include <Extrema_ExtElC.hxx>
33#include <Extrema_LocateExtPC.hxx>
34#include <gp_Circ.hxx>
35#include <gp_Elips.hxx>
36#include <IntTools.hxx>
37#include <ElCLib.hxx>
38#include <Geom_Line.hxx>
39#include <GeomAdaptor_HCurve.hxx>
40
41static void LocalPrepareArgs(BRepAdaptor_Curve& theCurve,
42 const Standard_Real theFirstParameter,
43 const Standard_Real theLastParameter,
44 Standard_Real& theDeflection,
45 IntTools_CArray1OfReal& theArgs);
46
47static Standard_Boolean SetEmptyResultRange(const Standard_Real theParameter,
48 IntTools_MarkedRangeSet& theMarkedRange);
49
50// ==================================================================================
51// function: IntTools_BeanBeanIntersector
52// purpose:
53// ==================================================================================
54IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector() :
55
56myFirstParameter1(0.),
57myLastParameter1(0.),
58myFirstParameter2(0.),
59myLastParameter2(0.),
60myBeanTolerance1(0.),
61myBeanTolerance2(0.),
62myCurveResolution1(0.),
63myCriteria(0.),
64myIsDone(Standard_False)
65{
66}
67
68// ==================================================================================
69// function: IntTools_BeanBeanIntersector
70// purpose:
71// ==================================================================================
72IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector(const TopoDS_Edge& theEdge1,
73 const TopoDS_Edge& theEdge2) :
74
75myFirstParameter1(0.),
76myLastParameter1(0.),
77myFirstParameter2(0.),
78myLastParameter2(0.),
79myBeanTolerance1(0.),
80myBeanTolerance2(0.),
81myCurveResolution1(0.),
82myCriteria(0.),
83myIsDone(Standard_False)
84{
85 Init(theEdge1, theEdge2);
86}
87
88// ==================================================================================
89// function: IntTools_BeanBeanIntersector
90// purpose:
91// ==================================================================================
92IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector(const BRepAdaptor_Curve& theCurve1,
93 const BRepAdaptor_Curve& theCurve2,
94 const Standard_Real theBeanTolerance1,
95 const Standard_Real theBeanTolerance2) :
96
97myFirstParameter1(0.),
98myLastParameter1(0.),
99myFirstParameter2(0.),
100myLastParameter2(0.),
101myBeanTolerance1(0.),
102myBeanTolerance2(0.),
103myCurveResolution1(0.),
104myCriteria(0.),
105myIsDone(Standard_False)
106{
107 Init(theCurve1, theCurve2, theBeanTolerance1, theBeanTolerance2);
108}
109
110// ==================================================================================
111// function: IntTools_BeanBeanIntersector
112// purpose:
113// ==================================================================================
114IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector(const BRepAdaptor_Curve& theCurve1,
115 const BRepAdaptor_Curve& theCurve2,
116 const Standard_Real theFirstParOnCurve1,
117 const Standard_Real theLastParOnCurve1,
118 const Standard_Real theFirstParOnCurve2,
119 const Standard_Real theLastParOnCurve2,
120 const Standard_Real theBeanTolerance1,
121 const Standard_Real theBeanTolerance2) :
122
123myFirstParameter1(0.),
124myLastParameter1(0.),
125myFirstParameter2(0.),
126myLastParameter2(0.),
127myBeanTolerance1(0.),
128myBeanTolerance2(0.),
129myCurveResolution1(0.),
130myCriteria(0.),
131myIsDone(Standard_False)
132{
133 Init(theCurve1, theCurve2, theFirstParOnCurve1, theLastParOnCurve1,
134 theFirstParOnCurve2, theLastParOnCurve2,
135 theBeanTolerance1, theBeanTolerance2);
136}
137
138// ==================================================================================
139// function: Init
140// purpose:
141// ==================================================================================
142void IntTools_BeanBeanIntersector::Init(const TopoDS_Edge& theEdge1,
143 const TopoDS_Edge& theEdge2)
144{
145 myCurve1.Initialize(theEdge1);
146 myCurve2.Initialize(theEdge2);
147
148 myTrsfCurve1 = Handle(Geom_Curve)::DownCast(myCurve1.Curve().Curve()->Transformed(myCurve1.Trsf()));
149 myTrsfCurve2 = Handle(Geom_Curve)::DownCast(myCurve2.Curve().Curve()->Transformed(myCurve2.Trsf()));
150
151 SetBeanParameters(Standard_True, myCurve1.FirstParameter(), myCurve1.LastParameter());
152 SetBeanParameters(Standard_False, myCurve2.FirstParameter(), myCurve2.LastParameter());
153
154 myBeanTolerance1 = BRep_Tool::Tolerance(theEdge1);
155 myBeanTolerance2 = BRep_Tool::Tolerance(theEdge2);
156 myCriteria = myBeanTolerance1 + myBeanTolerance2;
157 myCurveResolution1 = myCurve1.Resolution(myCriteria);
158}
159
160// ==================================================================================
161// function: Init
162// purpose:
163// ==================================================================================
164void IntTools_BeanBeanIntersector::Init(const BRepAdaptor_Curve& theCurve1,
165 const BRepAdaptor_Curve& theCurve2,
166 const Standard_Real theBeanTolerance1,
167 const Standard_Real theBeanTolerance2)
168{
169 myCurve1 = theCurve1;
170 myCurve2 = theCurve2;
171
172 SetBeanParameters(Standard_True, myCurve1.FirstParameter(), myCurve1.LastParameter());
173 SetBeanParameters(Standard_False, myCurve2.FirstParameter(), myCurve2.LastParameter());
174
175 myTrsfCurve1 = Handle(Geom_Curve)::DownCast(myCurve1.Curve().Curve()->Transformed(myCurve1.Trsf()));
176 myTrsfCurve2 = Handle(Geom_Curve)::DownCast(myCurve2.Curve().Curve()->Transformed(myCurve2.Trsf()));
177
178 myBeanTolerance1 = theBeanTolerance1;
179 myBeanTolerance2 = theBeanTolerance2;
180 myCriteria = myBeanTolerance1 + myBeanTolerance2;
181 myCurveResolution1 = myCurve1.Resolution(myCriteria);
182}
183
184// ==================================================================================
185// function: Init
186// purpose:
187// ==================================================================================
188void IntTools_BeanBeanIntersector::Init(const BRepAdaptor_Curve& theCurve1,
189 const BRepAdaptor_Curve& theCurve2,
190 const Standard_Real theFirstParOnCurve1,
191 const Standard_Real theLastParOnCurve1,
192 const Standard_Real theFirstParOnCurve2,
193 const Standard_Real theLastParOnCurve2,
194 const Standard_Real theBeanTolerance1,
195 const Standard_Real theBeanTolerance2)
196{
197 myCurve1 = theCurve1;
198 myCurve2 = theCurve2;
199
200 myTrsfCurve1 = Handle(Geom_Curve)::DownCast(myCurve1.Curve().Curve()->Transformed(myCurve1.Trsf()));
201 myTrsfCurve2 = Handle(Geom_Curve)::DownCast(myCurve2.Curve().Curve()->Transformed(myCurve2.Trsf()));
202
203 SetBeanParameters(Standard_True, theFirstParOnCurve1, theLastParOnCurve1);
204 SetBeanParameters(Standard_False, theFirstParOnCurve2, theLastParOnCurve2);
205
206 myBeanTolerance1 = theBeanTolerance1;
207 myBeanTolerance2 = theBeanTolerance2;
208 myCriteria = myBeanTolerance1 + myBeanTolerance2;
209 myCurveResolution1 = myCurve1.Resolution(myCriteria);
210}
211
212// ==================================================================================
213// function: SetBeanParameters
214// purpose:
215// ==================================================================================
216void IntTools_BeanBeanIntersector::SetBeanParameters(const Standard_Boolean IsFirstBean,
217 const Standard_Real theFirstParOnCurve,
218 const Standard_Real theLastParOnCurve)
219{
220 if(IsFirstBean) {
221 myFirstParameter1 = theFirstParOnCurve;
222 myLastParameter1 = theLastParOnCurve;
223 }
224 else {
225 myFirstParameter2 = theFirstParOnCurve;
226 myLastParameter2 = theLastParOnCurve;
227 }
228}
229// ==================================================================================
230// function: Result
231// purpose:
232// ==================================================================================
233const IntTools_SequenceOfRanges& IntTools_BeanBeanIntersector::Result() const
234{
235 return myResults;
236}
237
238// ==================================================================================
239// function: Result
240// purpose:
241// ==================================================================================
242 void IntTools_BeanBeanIntersector::Result(IntTools_SequenceOfRanges& theResults) const
243{
244 theResults = myResults;
245}
246// ==================================================================================
247// function: Perform
248// purpose:
249// ==================================================================================
250void IntTools_BeanBeanIntersector::Perform()
251{
252 Standard_Boolean bFastComputed;
253 Standard_Integer k, i, iFlag, aNbRanges, aNbResults;
254 Standard_Real aMidParameter, aCoeff, aParamDist, aPPC;
255 Standard_Real aCriteria2, aD2;
256 gp_Pnt aPi, aPh;
257 IntTools_CArray1OfReal aParams;
258 IntTools_Range aRange2, aRange;
259 //
260 myIsDone = Standard_False;
261 myResults.Clear();
262 //
263 LocalPrepareArgs(myCurve1, myFirstParameter1, myLastParameter1, myDeflection, aParams);
264 //
265 myRangeManager.SetRanges(aParams, 0);
266 //
267 aNbRanges=myRangeManager.Length();
268 if(!aNbRanges) {
269 return;
270 }
271 //
272 bFastComputed=FastComputeIntersection();
273 if(bFastComputed) {
274 aRange.SetFirst(myFirstParameter1);
275 aRange.SetLast (myLastParameter1);
276 myResults.Append(aRange);
277 myIsDone = Standard_True;
278 return;
279 }
280 //
281 ComputeRoughIntersection();
282
283 //Standard_Real aMidParameter = (myFirstParameter2 + myLastParameter2) * 0.5;
284 aCoeff=0.5753;
285 aMidParameter = myFirstParameter2+(myLastParameter2-myFirstParameter2)*aCoeff;
286 //
287 for(k = 0; k < 2; ++k) {
288 if(!k) {
289 aRange2.SetFirst(myFirstParameter2);
290 aRange2.SetLast(aMidParameter);
291 }
292 else {
293 aRange2.SetFirst(aMidParameter);
294 aRange2.SetLast(myLastParameter2);
295 }
296
297 ComputeUsingExtrema(aRange2);
298
299 ComputeNearRangeBoundaries(aRange2);
300 }
301 //
302 // Legend iFlag
303 //
304 // 0 - just initialized
305 // 1 - non-intersected
306 // 2 - roughly intersected
307 // 3 - intersection is not done
308 // 4 - coincided range
309 //
310 aPPC=Precision::PConfusion();
311 aCriteria2=myCriteria*myCriteria;
312 aNbRanges=myRangeManager.Length();
313 //
314 for(i=1; i<=aNbRanges; ++i) {
315 iFlag=myRangeManager.Flag(i);
316 //
317 if(iFlag==4) {
318 aRange=myRangeManager.Range(i);
319 aNbResults=myResults.Length();
320 if(aNbResults>0) {
321 const IntTools_Range& aLastRange = myResults.Last();
322 //
323 aParamDist = Abs(aRange.First() - aLastRange.Last());
324 if(aParamDist > myCurveResolution1) {
325 myResults.Append(aRange);
326 }
327 else {
328 aPi=myCurve1.Value(aRange.First());
329 aPh=myCurve1.Value(aLastRange.Last());
330 aD2=aPi.SquareDistance(aPh);
331 if(aParamDist<aPPC || aD2<aCriteria2) {
332 myResults.ChangeValue(aNbResults).SetLast(aRange.Last());
333 }
334 else {
335 myResults.Append(aRange);
336 }
337 }
338 }// if(aNbR>0) {
339 else {
340 myResults.Append(aRange);
341 }
342 } //if(iFlag==4) {
343 } // for(i = 1; i <= myRangeManager.Length(); i++) {
344 myIsDone = Standard_True;
345}
346// ==================================================================================
347// function: FastComputeIntersection
348// purpose:
349// ==================================================================================
350Standard_Boolean IntTools_BeanBeanIntersector::FastComputeIntersection()
351{
352 Standard_Boolean aresult;
353 GeomAbs_CurveType aCT1, aCT2;
354 //
355 aresult = Standard_False;
356 //
357 aCT1=myCurve1.GetType();
358 aCT2=myCurve2.GetType();
359 //
360 if(aCT1 != aCT2) {
361 return aresult;
362 }
363 //
364 // Line
365 if(aCT1==GeomAbs_Line) {
366 Standard_Real par1, par2;
367
368 if((Distance(myFirstParameter1, par1) < myCriteria) &&
369 (Distance(myLastParameter1, par2) < myCriteria)) {
370
371 if((par1 >= myFirstParameter2) && (par1 <= myLastParameter2) &&
372 (par2 >= myFirstParameter2) && (par2 <= myLastParameter2)) {
373 myRangeManager.InsertRange(myFirstParameter1, myLastParameter1, 4);
374 aresult = Standard_True;
375 }
376 }
377 return aresult;
378 }
379 //
380 // Circle
381 if(aCT1==GeomAbs_Circle) {
382 Standard_Real anAngle, aPA, aDistLoc, aDist, aDiff, aR1, aR2;
383 gp_Circ aCirc1, aCirc2;
384 gp_Dir aDir1, aDir2;
385 //
386 aCirc1=myCurve1.Circle();
387 aCirc2=myCurve2.Circle();
388 aR1=aCirc1.Radius();
389 aR2=aCirc2.Radius();
390 //
391 aPA=Precision::Angular();
392 aDir1 = aCirc1.Axis().Direction();
393 aDir2 = aCirc2.Axis().Direction();
394 //
395 anAngle = aDir1.Angle(aDir2);
396 if(anAngle > aPA) {
397 return aresult; //->
398 }
399 //
400 const gp_Pnt& aPLoc1=aCirc1.Location();
401 const gp_Pnt& aPLoc2=aCirc2.Location();
402 aDistLoc = aPLoc1.Distance(aPLoc2);
403 aDist=aDistLoc;
404 aDiff=aR1 - aR2;
405 aDist+=Abs(aDiff);
406 if(Abs(aDist) > myCriteria) {
407 return aresult; //->
408 }
409 //
410 Standard_Real aSinPA, atmpvalue, aprojectedradius;
411 //
412 aSinPA=sin(aPA);
413 atmpvalue = aR1*aSinPA;
414 atmpvalue *= atmpvalue;
415 aprojectedradius = sqrt(aR1*aR1 - atmpvalue);
416
417 aDiff = aprojectedradius - aR2;
418 aDist = aDistLoc + sqrt((aDiff * aDiff) + atmpvalue);
419 if(Abs(aDist) > myCriteria) {
420 return aresult; //->
421 }
422 //
423 Standard_Boolean newparfound;
424 Standard_Integer i;
425 Standard_Real afirstpar, alastpar, par1, par2, apar;
426 //
427 afirstpar = myFirstParameter1;
428 alastpar = myLastParameter1;
429
430 for(i = 0; i < 2; i++) {
431 if((Distance(afirstpar, par1) < myCriteria) &&
432 (Distance(alastpar , par2) < myCriteria)) {
433
434 if(i || Distance((myFirstParameter1 + myLastParameter2) * 0.5, apar) < myCriteria) {
435 myRangeManager.InsertRange(afirstpar, alastpar, 4);
436
437 if(!i) {
438 aresult = Standard_True;
439 }
440 }
441 break;
442 }
443 //
444 if(i) {
445 break;
446 }
447 // i=0 :
448 newparfound = Standard_False;
449
450 if(Distance((myFirstParameter1 + myLastParameter2) * 0.5, apar) < myCriteria) {
451 afirstpar = myFirstParameter1 + myCriteria;
452 alastpar = myLastParameter1 - myCriteria;
453 newparfound = Standard_True;
454
455 if(alastpar <= afirstpar) {
456 newparfound = Standard_False;
457 }
458 }
459
460 if(!newparfound) {
461 break;
462 }
463 }// for(i = 0; i < 2; i++) {
464 } // if(aCT1==GeomAbs_Circle)
465 return aresult;
466}
467// ==================================================================================
468// function: Distance
469// purpose:
470// ==================================================================================
471Standard_Real IntTools_BeanBeanIntersector::Distance(const Standard_Real theArg,
472 Standard_Real& theArgOnOtherBean)
473{
474 Standard_Real aDistance;
475 Standard_Integer aNbPoints;
476 gp_Pnt aPoint;
477 //
478 aDistance=RealLast();
479 //
480 aPoint=myCurve1.Value(theArg);
481 //modified by NIZNHY-PKV Thu Jul 01 12:20:52 2010f
482 myProjector.Init(myTrsfCurve2, myFirstParameter2, myLastParameter2);
483 myProjector.Perform(aPoint);
484 //myProjector.Init(aPoint, myTrsfCurve2, myFirstParameter2, myLastParameter2);
485 //modified by NIZNHY-PKV Thu Jul 01 12:21:05 2010t
486 //
487 aNbPoints=myProjector.NbPoints();
488 if(aNbPoints > 0) {
489 theArgOnOtherBean = myProjector.LowerDistanceParameter();
490 aDistance=myProjector.LowerDistance();
491 }
492 //
493 else {
494 Standard_Real aDistance1, aDistance2;
495 //
496 aDistance1 = aPoint.Distance(myCurve2.Value(myFirstParameter2));
497 aDistance2 = aPoint.Distance(myCurve2.Value(myLastParameter2));
498 //
499 theArgOnOtherBean = myLastParameter2;
500 aDistance=aDistance2;
501 if(aDistance1 < aDistance2) {
502 theArgOnOtherBean = myFirstParameter2;
503 aDistance=aDistance1;
504 }
505 }
506 return aDistance;
507}
508// ==================================================================================
509// function: ComputeRoughIntersection
510// purpose:
511// ==================================================================================
512void IntTools_BeanBeanIntersector::ComputeRoughIntersection()
513{
514 Standard_Boolean isintersection;
515 Standard_Integer i, aNbArgs, aNbArgs1, aNbRanges, j, aNbLines, k, pIt, extIt, iFlag;
516 Standard_Real aDeflection, aGPR, aCurDeflection, aT1, aT2, aD;
517 Standard_Real aMaxDistance, aDistance, aPPC, aPrm1, aPrm2, aPPA;
518 GeomAbs_CurveType aCT1, aCT2;
519 gp_Pnt aPoint1, aPoint2, aMidPOnCurve, aMidPOnLine, aP1, aP2;
520 IntTools_CArray1OfReal anArgs;
521 LocalPrepareArgs(myCurve2, myFirstParameter2, myLastParameter2, aDeflection, anArgs);
522 //
523 aNbArgs=anArgs.Length();
524 if(!aNbArgs) {
525 return;
526 }
527 //
528 aCT1=myCurve1.GetType();
529 aCT2=myCurve2.GetType();
530 aGPR=gp::Resolution();
531 aPPC=Precision::PConfusion();
532 aPPA=Precision::Angular();
533 aNbArgs1=aNbArgs-1;
534 //
535 Intf_Array1OfLin aLines(1, aNbArgs1);
536 TColStd_Array1OfInteger aLineFlags(1, aNbArgs1);
537 TColStd_Array1OfReal aDistances(1, aNbArgs1);
538 //
539 aT1=anArgs(0);
540 aPoint1 = myCurve2.Value(aT1);
541 for(i=1; i<aNbArgs; ++i) {
542 aT2=anArgs(i);
543 aPoint2 = myCurve2.Value(aT2);
544 gp_Vec aVec(aPoint1, aPoint2);
545 aD=aVec.Magnitude();
546 aDistances.SetValue(i, aD);
547 //
548 if(aD<=aGPR) {
549 aLineFlags.SetValue(i, 0);
550 }
551 else {
552 aLineFlags.SetValue(i, 1);
553 gp_Lin aLine(aPoint1, gp_Dir(aVec));
554 aLines.SetValue(i, aLine);
555 //
556 if((aCT2 == GeomAbs_BezierCurve) ||
557 (aCT2 == GeomAbs_BSplineCurve)) {
558 aMidPOnCurve = myCurve2.Value((aT1+aT2) * 0.5);
559 aMidPOnLine = ElCLib::Value((aDistances(i)*0.5), aLine);
560 aCurDeflection = aMidPOnCurve.Distance(aMidPOnLine);
561 if(aCurDeflection > aDeflection) {
562 aDeflection = aCurDeflection;
563 }
564 }
565 }
566 aT1=aT2;
567 aPoint1 = aPoint2;
568 }
569 //
570 aNbLines=aLines.Upper();
571 aMaxDistance = myCriteria + myDeflection + aDeflection;
572
573 aT1=myRangeManager.Range(1).First();
574 aPoint1 = myCurve1.Value(aT1);
575 aNbRanges=myRangeManager.Length();
576 for(i = 1; i <= aNbRanges; ++i) {
577 const IntTools_Range& aRange = myRangeManager.Range(i);
578 aT2=aRange.Last();
579 aPoint2 = myCurve1.Value(aT2);
580 //
581 iFlag=myRangeManager.Flag(i);
582 if(iFlag==4) {// coincided
583 aT1=aT2;
584 aPoint1 = aPoint2;
585 continue;
586 }
587 //
588 myRangeManager.SetFlag(i, 1); // not intersected
589
590 Bnd_Box aBox1;
591 aBox1.Add(aPoint1);
592 aBox1.Add(aPoint2);
593 aBox1.Enlarge(myBeanTolerance1 + myDeflection);
594
595 gp_Vec aVec(aPoint1, aPoint2);
596
597 aDistance=aVec.Magnitude();
598 if(aDistance <= aGPR) {
599 myRangeManager.SetFlag(i, 0);
600 continue;
601 }
602 //
603 gp_Lin aLine(aPoint1, gp_Dir(aVec));
604 //
605 if((aCT1 == GeomAbs_BezierCurve) ||
606 (aCT1 == GeomAbs_BSplineCurve)) {
607 aMidPOnCurve = myCurve1.Value((aRange.First() + aRange.Last()) * 0.5);
608 aMidPOnLine = ElCLib::Value((aDistance*0.5), aLine);
609 aCurDeflection = aMidPOnCurve.Distance(aMidPOnLine);
610 if(myDeflection < aCurDeflection) {
611 aMaxDistance += aCurDeflection - myDeflection;
612 myDeflection = aCurDeflection;
613 }
614 }
615 //
616 for(j=1; j<=aNbLines; ++j) {
617 if(!aLineFlags(j)) {
618 myRangeManager.SetFlag(i, 0);
619 continue;
620 }
621 //
622 const gp_Lin& aL2=aLines(j);
623 //Handle(Geom_Line) aC2=new Geom_Line(aL2); // DEB ft
624 aD=aDistances(j);
625 aP1=ElCLib::Value(0., aL2);
626 aP2=ElCLib::Value(aD, aL2);
627 //
628 Extrema_ExtElC anExtrema(aLine, aL2, aPPA);
629 if(anExtrema.IsDone() && (anExtrema.IsParallel() || (anExtrema.NbExt() > 0))) {
630 isintersection = Standard_False;
631
632 if(anExtrema.IsParallel()) {
633 isintersection = (anExtrema.SquareDistance(1) < aMaxDistance * aMaxDistance);
634 }
635 else { //1
636 for(k = 1; !isintersection && k <= anExtrema.NbExt(); ++k) {
637 if(anExtrema.SquareDistance(k) < aMaxDistance * aMaxDistance) {
638 Extrema_POnCurv P1, P2;
639 anExtrema.Points(k, P1, P2);
640 aPrm1=P1.Parameter();
641 aPrm2=P2.Parameter();
642 if((aPrm1 >= -aMaxDistance) && (aPrm1 <= aDistance+aMaxDistance) &&
643 (aPrm2 >= -aMaxDistance) && (aPrm2 <= aD+aMaxDistance)) {
644 isintersection = Standard_True;
645 }
646 else { // 2
647 Extrema_ExtPElC aPointProjector;
648
649 for(pIt = 0; !isintersection && (pIt < 4); ++pIt) {
650 switch (pIt) {
651 case 0: {
652 aPointProjector =
653 //Extrema_ExtPElC(aPoint1, aLines(j), aPPC, 0., aDistances(j));
654 Extrema_ExtPElC(aPoint1, aL2, aPPC, -aMaxDistance, aD+aMaxDistance);
655 break;
656 }
657 case 1: {
658 aPointProjector =
659 //Extrema_ExtPElC(aPoint2, aLines(j), aPPC, 0., aD);
660 Extrema_ExtPElC(aPoint2, aL2, aPPC, -aMaxDistance, aD+aMaxDistance);
661 break;
662 }
663 case 2: {
664 aPointProjector =
665 //Extrema_ExtPElC(ElCLib::Value(0., aLines(j)), aLine, aPPC, 0., aDistance);
666 Extrema_ExtPElC(aP1, aLine, aPPC, -aMaxDistance, aDistance+aMaxDistance);
667 break;
668 }
669 case 3: {
670 aPointProjector =
671 //Extrema_ExtPElC(ElCLib::Value(aDistances(j), aLines(j)), aLine, aPPC, 0., aDistance);
672 Extrema_ExtPElC(aP2, aLine, aPPC, -aMaxDistance, aDistance+aMaxDistance);
673 break;
674 }
675 default: {
676 break;
677 }
678 }
679 //
680 if(aPointProjector.IsDone()) {
681 Standard_Real aMaxDistance2 = aMaxDistance * aMaxDistance;
682 for(extIt = 1; extIt <= aPointProjector.NbExt(); extIt++) {
683 if(aPointProjector.SquareDistance(extIt) < aMaxDistance2) {
684 isintersection = Standard_True;
685 }
686 }
687 }
688 } // end for
689 }// else { // 2
690 }//if(anExtrema.Value(k) < aMaxDistance) {
691 }//for(k = 1; !isintersection && k <= anExtrema.NbExt(); k++) {
692 }//else { //1
693
694 if(isintersection) {
695 myRangeManager.SetFlag(i, 2); // roughly intersected
696 break;
697 }
698 }//if(anExtrema.IsDone() && (anExtrema.IsParallel() || (anExtrema.NbExt() > 0))) {
699 else {
700 Bnd_Box aBox2;
701 aBox2.Add(myCurve2.Value(anArgs(j-1)));
702 aBox2.Add(myCurve2.Value(anArgs(j)));
703 aBox2.Enlarge(myBeanTolerance2 + aDeflection);
704 //
705 if(!aBox1.IsOut(aBox2)) {
706 myRangeManager.SetFlag(i, 2); // roughly intersected
707 break;
708 }
709 }
710 }
711 aT1=aT2;
712 aPoint1 = aPoint2;
713 }
714}
715
716// ==================================================================================
717// function: ComputeUsingExtrema
718// purpose:
719// ==================================================================================
720void IntTools_BeanBeanIntersector::ComputeUsingExtrema(const IntTools_Range& theRange2)
721{
722 //rln Dec 2008.
723 //Extrema_ExtCC is reused throughout this method to store caches computed on
724 //theRange2. However it is actually used only in a few calls of
725 //ComputeUsingExtrema(), so using a default constructor would add unnecessary overhead
726 //of initialization its internal fields. Since it is not manipulated by Handle then
727 //we will use a pointer to it and initialize it only when needed.
728 Extrema_ExtCC *apExtrema = 0;
729 Handle(GeomAdaptor_HCurve) aHCurve1, aHCurve2; //will be initialized later, only if needed
730 //handles are used to guard pointers to GeomAdaptor_Curve inside Extrema
731 Standard_Real aCriteria2 = myCriteria * myCriteria;
732 for(Standard_Integer i = 1; i <= myRangeManager.Length(); i++) {
733
734 if(myRangeManager.Flag(i) == 2 || myRangeManager.Flag(i) == 0) {
735 const IntTools_Range& aParamRange = myRangeManager.Range(i);
736
737 if(aParamRange.Last() - aParamRange.First() < Precision::PConfusion()) {
738
739 if(((i > 1) && (myRangeManager.Flag(i-1) == 4)) ||
740 ((i < myRangeManager.Length()) && (myRangeManager.Flag(i+1) == 4))) {
741 myRangeManager.SetFlag(i, 4);
742 continue;
743 }
744 }
745 if (aHCurve2.IsNull()) {
746 //initialize only once
747 apExtrema = new Extrema_ExtCC;
748 Standard_Real ftmp = theRange2.First() - Precision::PConfusion();
749 Standard_Real ltmp = theRange2.Last() + Precision::PConfusion();
750 ftmp = (ftmp < myFirstParameter2) ? myFirstParameter2 : ftmp;
751 ltmp = (ltmp > myLastParameter2) ? myLastParameter2 : ltmp;
752 aHCurve2 = new GeomAdaptor_HCurve (myTrsfCurve2, ftmp, ltmp);
753 apExtrema->SetCurve (2, aHCurve2->Curve(), theRange2.First(), theRange2.Last());
754 }
755 Extrema_ExtCC& anExtrema = *apExtrema;
756
757 Standard_Real ftmp = aParamRange.First() - Precision::PConfusion();
758 Standard_Real ltmp = aParamRange.Last() + Precision::PConfusion();
759 ftmp = (ftmp < myFirstParameter1) ? myFirstParameter1 : ftmp;
760 ltmp = (ltmp > myLastParameter1) ? myLastParameter1 : ltmp;
761 aHCurve1 = new GeomAdaptor_HCurve (myTrsfCurve1, ftmp, ltmp);
762 anExtrema.SetCurve (1, aHCurve1->Curve(), aParamRange.First(), aParamRange.Last());
763
764 anExtrema.Perform();
765
766 if(anExtrema.IsDone() && (anExtrema.IsParallel() || (anExtrema.NbExt() > 0))) {
767 Standard_Integer anOldNbRanges = myRangeManager.Length();
768
769 if (anExtrema.IsParallel()) {
770 if(anExtrema.SquareDistance(1) < aCriteria2) {
771 Standard_Real theParameter1, theParameter2;
772 Standard_Real adistance1 = Distance(aParamRange.First(), theParameter1);
773 Standard_Real adistance2 = Distance(aParamRange.Last(), theParameter2);
774 Standard_Boolean validdistance1 = (adistance1 < myCriteria);
775 Standard_Boolean validdistance2 = (adistance2 < myCriteria);
776
777 if (validdistance1 && validdistance2) {
778 myRangeManager.InsertRange(aParamRange.First(), aParamRange.Last(), 4);
779 continue;
780 }
781 else {
782 if(validdistance1) {
783 ComputeRangeFromStartPoint(Standard_True, aParamRange.First(), i, theParameter1, theRange2);
784 }
785 else {
786 if(validdistance2) {
787 ComputeRangeFromStartPoint(Standard_False, aParamRange.Last(), i, theParameter2, theRange2);
788 }
789 else {
790 Standard_Real a = aParamRange.First();
791 Standard_Real b = aParamRange.Last();
792 Standard_Real da = adistance1;
793 Standard_Real db = adistance2;
794 Standard_Real asolution = a;
795 Standard_Boolean found = Standard_False;
796
797 while(((b - a) > myCurveResolution1) && !found) {
798 asolution = (a+b)*0.5;
799 Standard_Real adist = Distance(asolution, theParameter1);
800
801 if(adist < myCriteria) {
802 found = Standard_True;
803 }
804 else {
805 if(da < db) {
806 b = asolution;
807 db = adist;
808 }
809 else {
810 a = asolution;
811 da = adist;
812 }
813 }
814 } // end while
815
816 if(found) {
817 ComputeRangeFromStartPoint(Standard_False, asolution, i, theParameter1, theRange2);
818 ComputeRangeFromStartPoint(Standard_True, asolution, i, theParameter1, theRange2);
819 }
820 else {
821 myRangeManager.SetFlag(i, 2);
822 }
823 }
824 }
825 }
826 }
827 }
828 else {
829
830 for(Standard_Integer j = 1 ; j <= anExtrema.NbExt(); j++) {
831 if(anExtrema.SquareDistance(j) < aCriteria2) {
832 Extrema_POnCurv p1, p2;
833 anExtrema.Points(j, p1, p2);
834
835 Standard_Integer aNbRanges = myRangeManager.Length();
836
837 Standard_Integer anIndex = myRangeManager.GetIndex(p1.Parameter(), Standard_False);
838 if(anIndex > 0) {
839 ComputeRangeFromStartPoint(Standard_False, p1.Parameter(), anIndex, p2.Parameter(), theRange2);
840 }
841
842 anIndex = myRangeManager.GetIndex(p1.Parameter(), Standard_True);
843
844 if(anIndex > 0) {
845 ComputeRangeFromStartPoint(Standard_True, p1.Parameter(), anIndex, p2.Parameter(), theRange2);
846 }
847
848 if(aNbRanges == myRangeManager.Length()) {
849 SetEmptyResultRange(p1.Parameter(), myRangeManager);
850 }
851 }
852 } // end for
853 }
854 Standard_Integer adifference = myRangeManager.Length() - anOldNbRanges;
855
856 if(adifference > 0) {
857 i+=adifference;
858 }
859 }
860 else {
861 myRangeManager.SetFlag(i, 3); // intersection not done.
862 }
863 }
864 }
865 if (apExtrema) delete apExtrema;
866}
867
868// ==================================================================================
869// function: ComputeNearRangeBoundaries
870// purpose:
871// ==================================================================================
872void IntTools_BeanBeanIntersector::ComputeNearRangeBoundaries(const IntTools_Range& theRange2)
873{
874 Standard_Real theParameter = theRange2.First();
875
876 for(Standard_Integer i = 1; i <= myRangeManager.Length(); i++) {
877 if(myRangeManager.Flag(i) != 3)
878 continue;
879
880 if((i > 1) && ((myRangeManager.Flag(i-1) == 1) || (myRangeManager.Flag(i-1) == 4))) {
881 myRangeManager.SetFlag(i, 2);
882 continue;
883 }
884
885 const IntTools_Range& aParamRange = myRangeManager.Range(i);
886
887 if(Distance(aParamRange.First(), theParameter) < myCriteria) {
888 Standard_Integer aNbRanges = myRangeManager.Length();
889
890 if(i > 1) {
891 ComputeRangeFromStartPoint(Standard_False, aParamRange.First(), i-1, theParameter, theRange2);
892 }
893 ComputeRangeFromStartPoint(Standard_True, aParamRange.First(), i + (myRangeManager.Length() - aNbRanges), theParameter, theRange2);
894
895 if(aNbRanges == myRangeManager.Length()) {
896 SetEmptyResultRange(aParamRange.First(), myRangeManager);
897 }
898 }
899 else {
900 myRangeManager.SetFlag(i, 2);
901 }
902 }
903
904 if((myRangeManager.Flag(myRangeManager.Length()) == 3) ||
905 (myRangeManager.Flag(myRangeManager.Length()) == 2)) {
906 const IntTools_Range& aParamRange = myRangeManager.Range(myRangeManager.Length());
907
908 if(Distance(aParamRange.Last(), theParameter) < myCriteria) {
909 Standard_Integer aNbRanges = myRangeManager.Length();
910 myRangeManager.SetFlag(myRangeManager.Length(), 2);
911
912 ComputeRangeFromStartPoint(Standard_False, aParamRange.Last(), myRangeManager.Length(), theParameter, theRange2);
913
914 if(aNbRanges == myRangeManager.Length()) {
915 SetEmptyResultRange(aParamRange.Last(), myRangeManager);
916 }
917 }
918 else {
919 myRangeManager.SetFlag(myRangeManager.Length(), 2);
920 }
921 }
922}
923
924// ==================================================================================
925// function: ComputeRangeFromStartPoint
926// purpose:
927// ==================================================================================
928void IntTools_BeanBeanIntersector::ComputeRangeFromStartPoint(const Standard_Boolean ToIncreaseParameter,
929 const Standard_Real theParameter,
930 const Standard_Integer theIndex,
931 const Standard_Real theParameter2,
932 const IntTools_Range& theRange2)
933{
934
935 if(myRangeManager.Flag(theIndex) == 4 ||
936 myRangeManager.Flag(theIndex) == 1)
937 return;
938
939 Standard_Integer aValidIndex = theIndex;
940 Standard_Real aMinDelta = myCurveResolution1 * 0.5;
941 Standard_Real aDeltaRestrictor = myLastParameter1 - myFirstParameter1;
942
943 if(Abs(aDeltaRestrictor) < Precision::PConfusion()) {
944 return;
945 }
946
947 if(aMinDelta > aDeltaRestrictor) {
948 aMinDelta = aDeltaRestrictor;
949 }
950 Standard_Real tenOfMinDelta = aMinDelta * 10.;
951 Standard_Real aDelta = myCurveResolution1;
952 Standard_Real aCurPar = (ToIncreaseParameter) ? (theParameter + aDelta) : (theParameter - aDelta);
953 Standard_Real aPrevPar = theParameter;
954 IntTools_Range aCurrentRange = myRangeManager.Range(aValidIndex);
955
956 Standard_Boolean BoundaryCondition = (ToIncreaseParameter) ? (aCurPar > aCurrentRange.Last()) : (aCurPar < aCurrentRange.First());
957
958 if(BoundaryCondition) {
959 aCurPar = (ToIncreaseParameter) ? aCurrentRange.Last() : aCurrentRange.First();
960 BoundaryCondition = Standard_False;
961 }
962
963 Standard_Integer loopcounter = 0; // neccesary to have no infinite loop
964 Standard_Real aParameter = theParameter2;
965 Standard_Boolean anotherSolutionFound = Standard_False;
966
967 Standard_Boolean isboundaryindex = Standard_False;
968 Standard_Boolean isvalidindex = Standard_True;
969
970 Standard_Real aCriteria2 = myCriteria * myCriteria;
971
972 while((aDelta >= aMinDelta) && (loopcounter <= 10)) {
973 Standard_Boolean pointfound = Standard_False;
974
975 gp_Pnt aPoint = myCurve1.Value(aCurPar);
976 GeomAdaptor_Curve aCurve2(myTrsfCurve2, theRange2.First(), theRange2.Last());
977
978 Extrema_LocateExtPC anExtrema(aPoint, aCurve2, aParameter, theRange2.First(), theRange2.Last(), 1.e-10);
979
980 if(anExtrema.IsDone()) {
981 if(anExtrema.SquareDistance() < aCriteria2) {
982 Extrema_POnCurv aPOnCurv = anExtrema.Point();
983 aParameter = aPOnCurv.Parameter();
984 pointfound = Standard_True;
985 }
986 }
987 else {
988 // pointfound = (Distance(aCurPar, aParameter) < myCriteria);
989 Standard_Real afoundparam = aParameter;
990
991 if(Distance(aCurPar, afoundparam) < myCriteria) {
992 aParameter = afoundparam;
993 pointfound = Standard_True;
994 }
995 }
996
997 if(pointfound) {
998 aPrevPar = aCurPar;
999 anotherSolutionFound = Standard_True;
1000
1001 if(BoundaryCondition && (isboundaryindex || !isvalidindex))
1002 break;
1003 }
1004 else {
1005 aDeltaRestrictor = aDelta;
1006 }
1007
1008 // if pointfound decide to increase aDelta using derivative of distance function
1009 //
1010
1011 aDelta = (pointfound) ? (aDelta * 2.) : (aDelta * 0.5);
1012 aDelta = (aDelta < aDeltaRestrictor) ? aDelta : aDeltaRestrictor;
1013 aCurPar = (ToIncreaseParameter) ? (aPrevPar + aDelta) : (aPrevPar - aDelta);
1014
1015 BoundaryCondition = (ToIncreaseParameter) ? (aCurPar > aCurrentRange.Last()) : (aCurPar < aCurrentRange.First());
1016
1017 isboundaryindex = Standard_False;
1018 isvalidindex = Standard_True;
1019
1020 if(BoundaryCondition) {
1021 isboundaryindex = ((!ToIncreaseParameter && (aValidIndex == 1)) ||
1022 (ToIncreaseParameter && (aValidIndex == myRangeManager.Length())));
1023
1024 if(!isboundaryindex) {
1025 if(pointfound) {
1026 Standard_Integer aFlag = (ToIncreaseParameter) ? myRangeManager.Flag(aValidIndex + 1) : myRangeManager.Flag(aValidIndex - 1);
1027
1028 if(aFlag != 1 && aFlag != 4) {
1029 aValidIndex = (ToIncreaseParameter) ? (aValidIndex + 1) : (aValidIndex - 1);
1030 aCurrentRange = myRangeManager.Range(aValidIndex);
1031
1032 if((ToIncreaseParameter && (aCurPar > aCurrentRange.Last())) ||
1033 (!ToIncreaseParameter && (aCurPar < aCurrentRange.First()))) {
1034 aCurPar = (aCurrentRange.First() + aCurrentRange.Last()) * 0.5;
1035 aDelta*=0.5;
1036 }
1037 }
1038 else {
1039 isvalidindex = Standard_False;
1040 aCurPar = (ToIncreaseParameter) ? aCurrentRange.Last() : aCurrentRange.First();
1041 }
1042 }
1043 }
1044 else {
1045 aCurPar = (ToIncreaseParameter) ? aCurrentRange.Last() : aCurrentRange.First();
1046 }
1047
1048 if(aDelta < tenOfMinDelta) {
1049 loopcounter++;
1050 }
1051 else {
1052 loopcounter = 0;
1053 }
1054 } // end if(BoundaryCondition)
1055 }
1056
1057 if(anotherSolutionFound) {
1058 if(ToIncreaseParameter)
1059 myRangeManager.InsertRange(theParameter, aPrevPar, 4);
1060 else
1061 myRangeManager.InsertRange(aPrevPar, theParameter, 4);
1062 }
1063}
1064
1065// ---------------------------------------------------------------------------------
1066// static function: LocalPrepareArgs
1067// purpose:
1068// ---------------------------------------------------------------------------------
1069static void LocalPrepareArgs(BRepAdaptor_Curve& theCurve,
1070 const Standard_Real theFirstParameter,
1071 const Standard_Real theLastParameter,
1072 Standard_Real& theDeflection,
1073 IntTools_CArray1OfReal& theArgs) {
1074 Standard_Integer aDiscretization = 30;
1075 Standard_Real aRelativeDeflection = 0.01;
1076 theDeflection = aRelativeDeflection;
1077 Standard_Boolean prepareargs = Standard_True;
1078
1079 switch(theCurve.GetType()) {
1080 case GeomAbs_Line: {
1081 prepareargs = Standard_False;
1082 aDiscretization = 3;
1083 theArgs.Append(theFirstParameter);
1084
1085 if((theLastParameter - theFirstParameter) > Precision::PConfusion()) {
1086 theArgs.Append((theFirstParameter + theLastParameter)*0.5);
1087 }
1088 theArgs.Append(theLastParameter);
1089 theDeflection = Precision::Confusion();
1090 break;
1091 }
1092 case GeomAbs_Circle: {
1093 aDiscretization = 23;
1094 theDeflection = aRelativeDeflection * theCurve.Circle().Radius();
1095 break;
1096 }
1097 case GeomAbs_Ellipse: {
1098 aDiscretization = 40;
1099 theDeflection = 2 * aRelativeDeflection * theCurve.Ellipse().MajorRadius();
1100 break;
1101 }
1102 case GeomAbs_Hyperbola:
1103 case GeomAbs_Parabola: {
1104 aDiscretization = 40;
1105 theDeflection = aRelativeDeflection;
1106 break;
1107 }
1108 case GeomAbs_BezierCurve: {
1109 aDiscretization = 30;
1110 theDeflection = aRelativeDeflection;
1111 break;
1112 }
1113 case GeomAbs_BSplineCurve: {
1114 aDiscretization = 30;
1115 theDeflection = aRelativeDeflection;
1116 break;
1117 }
1118 default: {
1119 aDiscretization = 30;
1120 theDeflection = aRelativeDeflection;
1121 }
1122 }
1123
1124 if(prepareargs) {
1125 IntTools::PrepareArgs(theCurve, theLastParameter, theFirstParameter, aDiscretization, aRelativeDeflection, theArgs);
1126 }
1127}
1128
1129// ---------------------------------------------------------------------------------
1130// static function: SetEmptyResultRange
1131// purpose:
1132// ---------------------------------------------------------------------------------
1133static Standard_Boolean SetEmptyResultRange(const Standard_Real theParameter,
1134 IntTools_MarkedRangeSet& theMarkedRange) {
1135
1136 const TColStd_SequenceOfInteger& anIndices = theMarkedRange.GetIndices(theParameter);
1137 Standard_Boolean add = (anIndices.Length() > 0);
1138
1139 for(Standard_Integer k = 1; k <= anIndices.Length(); k++) {
1140 if(theMarkedRange.Flag(anIndices(k)) == 4) {
1141 add = Standard_False;
1142 break;
1143 }
1144 }
1145
1146 if(add) {
1147 theMarkedRange.InsertRange(theParameter, theParameter, 4);
1148 }
1149
1150 return add;
1151}
1152