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 | |
24def445 |
41 | static |
42 | void LocalPrepareArgs(BRepAdaptor_Curve& theCurve, |
43 | const Standard_Real theFirstParameter, |
44 | const Standard_Real theLastParameter, |
45 | Standard_Real& theDeflection, |
46 | IntTools_CArray1OfReal& theArgs); |
47 | |
48 | static |
49 | Standard_Boolean SetEmptyResultRange(const Standard_Real theParameter, |
50 | IntTools_MarkedRangeSet& theMarkedRange); |
51 | static |
52 | Standard_Integer CheckCoincidence(const Standard_Real aT11, |
53 | const Standard_Real aT12, |
54 | const Handle(Geom_Curve)& aC1, |
55 | const Standard_Real aT21, |
56 | const Standard_Real aT22, |
57 | const Handle(Geom_Curve)& aC2, |
58 | const Standard_Real aCriteria, |
59 | const Standard_Real aCurveResolution1, |
60 | GeomAPI_ProjectPointOnCurve& aProjector); |
7fd59977 |
61 | |
7fd59977 |
62 | |
63 | // ================================================================================== |
64 | // function: IntTools_BeanBeanIntersector |
65 | // purpose: |
66 | // ================================================================================== |
67 | IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector() : |
68 | |
69 | myFirstParameter1(0.), |
70 | myLastParameter1(0.), |
71 | myFirstParameter2(0.), |
72 | myLastParameter2(0.), |
73 | myBeanTolerance1(0.), |
74 | myBeanTolerance2(0.), |
75 | myCurveResolution1(0.), |
76 | myCriteria(0.), |
77 | myIsDone(Standard_False) |
78 | { |
79 | } |
80 | |
81 | // ================================================================================== |
82 | // function: IntTools_BeanBeanIntersector |
83 | // purpose: |
84 | // ================================================================================== |
85 | IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector(const TopoDS_Edge& theEdge1, |
86 | const TopoDS_Edge& theEdge2) : |
87 | |
88 | myFirstParameter1(0.), |
89 | myLastParameter1(0.), |
90 | myFirstParameter2(0.), |
91 | myLastParameter2(0.), |
92 | myBeanTolerance1(0.), |
93 | myBeanTolerance2(0.), |
94 | myCurveResolution1(0.), |
95 | myCriteria(0.), |
96 | myIsDone(Standard_False) |
97 | { |
98 | Init(theEdge1, theEdge2); |
99 | } |
100 | |
101 | // ================================================================================== |
102 | // function: IntTools_BeanBeanIntersector |
103 | // purpose: |
104 | // ================================================================================== |
105 | IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector(const BRepAdaptor_Curve& theCurve1, |
106 | const BRepAdaptor_Curve& theCurve2, |
107 | const Standard_Real theBeanTolerance1, |
108 | const Standard_Real theBeanTolerance2) : |
109 | |
110 | myFirstParameter1(0.), |
111 | myLastParameter1(0.), |
112 | myFirstParameter2(0.), |
113 | myLastParameter2(0.), |
114 | myBeanTolerance1(0.), |
115 | myBeanTolerance2(0.), |
116 | myCurveResolution1(0.), |
117 | myCriteria(0.), |
118 | myIsDone(Standard_False) |
119 | { |
120 | Init(theCurve1, theCurve2, theBeanTolerance1, theBeanTolerance2); |
121 | } |
122 | |
123 | // ================================================================================== |
124 | // function: IntTools_BeanBeanIntersector |
125 | // purpose: |
126 | // ================================================================================== |
127 | IntTools_BeanBeanIntersector::IntTools_BeanBeanIntersector(const BRepAdaptor_Curve& theCurve1, |
128 | const BRepAdaptor_Curve& theCurve2, |
129 | const Standard_Real theFirstParOnCurve1, |
130 | const Standard_Real theLastParOnCurve1, |
131 | const Standard_Real theFirstParOnCurve2, |
132 | const Standard_Real theLastParOnCurve2, |
133 | const Standard_Real theBeanTolerance1, |
134 | const Standard_Real theBeanTolerance2) : |
135 | |
136 | myFirstParameter1(0.), |
137 | myLastParameter1(0.), |
138 | myFirstParameter2(0.), |
139 | myLastParameter2(0.), |
140 | myBeanTolerance1(0.), |
141 | myBeanTolerance2(0.), |
142 | myCurveResolution1(0.), |
143 | myCriteria(0.), |
144 | myIsDone(Standard_False) |
145 | { |
146 | Init(theCurve1, theCurve2, theFirstParOnCurve1, theLastParOnCurve1, |
147 | theFirstParOnCurve2, theLastParOnCurve2, |
148 | theBeanTolerance1, theBeanTolerance2); |
149 | } |
150 | |
151 | // ================================================================================== |
152 | // function: Init |
153 | // purpose: |
154 | // ================================================================================== |
155 | void IntTools_BeanBeanIntersector::Init(const TopoDS_Edge& theEdge1, |
156 | const TopoDS_Edge& theEdge2) |
157 | { |
158 | myCurve1.Initialize(theEdge1); |
159 | myCurve2.Initialize(theEdge2); |
160 | |
161 | myTrsfCurve1 = Handle(Geom_Curve)::DownCast(myCurve1.Curve().Curve()->Transformed(myCurve1.Trsf())); |
162 | myTrsfCurve2 = Handle(Geom_Curve)::DownCast(myCurve2.Curve().Curve()->Transformed(myCurve2.Trsf())); |
163 | |
164 | SetBeanParameters(Standard_True, myCurve1.FirstParameter(), myCurve1.LastParameter()); |
165 | SetBeanParameters(Standard_False, myCurve2.FirstParameter(), myCurve2.LastParameter()); |
166 | |
167 | myBeanTolerance1 = BRep_Tool::Tolerance(theEdge1); |
168 | myBeanTolerance2 = BRep_Tool::Tolerance(theEdge2); |
169 | myCriteria = myBeanTolerance1 + myBeanTolerance2; |
170 | myCurveResolution1 = myCurve1.Resolution(myCriteria); |
171 | } |
172 | |
173 | // ================================================================================== |
174 | // function: Init |
175 | // purpose: |
176 | // ================================================================================== |
177 | void IntTools_BeanBeanIntersector::Init(const BRepAdaptor_Curve& theCurve1, |
178 | const BRepAdaptor_Curve& theCurve2, |
179 | const Standard_Real theBeanTolerance1, |
180 | const Standard_Real theBeanTolerance2) |
181 | { |
182 | myCurve1 = theCurve1; |
183 | myCurve2 = theCurve2; |
184 | |
185 | SetBeanParameters(Standard_True, myCurve1.FirstParameter(), myCurve1.LastParameter()); |
186 | SetBeanParameters(Standard_False, myCurve2.FirstParameter(), myCurve2.LastParameter()); |
187 | |
188 | myTrsfCurve1 = Handle(Geom_Curve)::DownCast(myCurve1.Curve().Curve()->Transformed(myCurve1.Trsf())); |
189 | myTrsfCurve2 = Handle(Geom_Curve)::DownCast(myCurve2.Curve().Curve()->Transformed(myCurve2.Trsf())); |
190 | |
191 | myBeanTolerance1 = theBeanTolerance1; |
192 | myBeanTolerance2 = theBeanTolerance2; |
193 | myCriteria = myBeanTolerance1 + myBeanTolerance2; |
194 | myCurveResolution1 = myCurve1.Resolution(myCriteria); |
195 | } |
196 | |
197 | // ================================================================================== |
198 | // function: Init |
199 | // purpose: |
200 | // ================================================================================== |
201 | void IntTools_BeanBeanIntersector::Init(const BRepAdaptor_Curve& theCurve1, |
202 | const BRepAdaptor_Curve& theCurve2, |
203 | const Standard_Real theFirstParOnCurve1, |
204 | const Standard_Real theLastParOnCurve1, |
205 | const Standard_Real theFirstParOnCurve2, |
206 | const Standard_Real theLastParOnCurve2, |
207 | const Standard_Real theBeanTolerance1, |
208 | const Standard_Real theBeanTolerance2) |
209 | { |
210 | myCurve1 = theCurve1; |
211 | myCurve2 = theCurve2; |
212 | |
213 | myTrsfCurve1 = Handle(Geom_Curve)::DownCast(myCurve1.Curve().Curve()->Transformed(myCurve1.Trsf())); |
214 | myTrsfCurve2 = Handle(Geom_Curve)::DownCast(myCurve2.Curve().Curve()->Transformed(myCurve2.Trsf())); |
215 | |
216 | SetBeanParameters(Standard_True, theFirstParOnCurve1, theLastParOnCurve1); |
217 | SetBeanParameters(Standard_False, theFirstParOnCurve2, theLastParOnCurve2); |
218 | |
219 | myBeanTolerance1 = theBeanTolerance1; |
220 | myBeanTolerance2 = theBeanTolerance2; |
221 | myCriteria = myBeanTolerance1 + myBeanTolerance2; |
222 | myCurveResolution1 = myCurve1.Resolution(myCriteria); |
223 | } |
224 | |
225 | // ================================================================================== |
226 | // function: SetBeanParameters |
227 | // purpose: |
228 | // ================================================================================== |
229 | void IntTools_BeanBeanIntersector::SetBeanParameters(const Standard_Boolean IsFirstBean, |
230 | const Standard_Real theFirstParOnCurve, |
231 | const Standard_Real theLastParOnCurve) |
232 | { |
233 | if(IsFirstBean) { |
234 | myFirstParameter1 = theFirstParOnCurve; |
235 | myLastParameter1 = theLastParOnCurve; |
236 | } |
237 | else { |
238 | myFirstParameter2 = theFirstParOnCurve; |
239 | myLastParameter2 = theLastParOnCurve; |
240 | } |
241 | } |
242 | // ================================================================================== |
243 | // function: Result |
244 | // purpose: |
245 | // ================================================================================== |
246 | const IntTools_SequenceOfRanges& IntTools_BeanBeanIntersector::Result() const |
247 | { |
248 | return myResults; |
249 | } |
250 | |
251 | // ================================================================================== |
252 | // function: Result |
253 | // purpose: |
254 | // ================================================================================== |
255 | void IntTools_BeanBeanIntersector::Result(IntTools_SequenceOfRanges& theResults) const |
256 | { |
257 | theResults = myResults; |
258 | } |
259 | // ================================================================================== |
260 | // function: Perform |
261 | // purpose: |
262 | // ================================================================================== |
263 | void IntTools_BeanBeanIntersector::Perform() |
264 | { |
265 | Standard_Boolean bFastComputed; |
266 | Standard_Integer k, i, iFlag, aNbRanges, aNbResults; |
267 | Standard_Real aMidParameter, aCoeff, aParamDist, aPPC; |
268 | Standard_Real aCriteria2, aD2; |
269 | gp_Pnt aPi, aPh; |
270 | IntTools_CArray1OfReal aParams; |
271 | IntTools_Range aRange2, aRange; |
272 | // |
273 | myIsDone = Standard_False; |
274 | myResults.Clear(); |
275 | // |
276 | LocalPrepareArgs(myCurve1, myFirstParameter1, myLastParameter1, myDeflection, aParams); |
277 | // |
278 | myRangeManager.SetRanges(aParams, 0); |
279 | // |
280 | aNbRanges=myRangeManager.Length(); |
281 | if(!aNbRanges) { |
282 | return; |
283 | } |
284 | // |
285 | bFastComputed=FastComputeIntersection(); |
286 | if(bFastComputed) { |
287 | aRange.SetFirst(myFirstParameter1); |
288 | aRange.SetLast (myLastParameter1); |
289 | myResults.Append(aRange); |
290 | myIsDone = Standard_True; |
291 | return; |
292 | } |
293 | // |
294 | ComputeRoughIntersection(); |
295 | |
296 | //Standard_Real aMidParameter = (myFirstParameter2 + myLastParameter2) * 0.5; |
297 | aCoeff=0.5753; |
298 | aMidParameter = myFirstParameter2+(myLastParameter2-myFirstParameter2)*aCoeff; |
299 | // |
300 | for(k = 0; k < 2; ++k) { |
301 | if(!k) { |
302 | aRange2.SetFirst(myFirstParameter2); |
303 | aRange2.SetLast(aMidParameter); |
304 | } |
305 | else { |
306 | aRange2.SetFirst(aMidParameter); |
307 | aRange2.SetLast(myLastParameter2); |
308 | } |
309 | |
310 | ComputeUsingExtrema(aRange2); |
311 | |
312 | ComputeNearRangeBoundaries(aRange2); |
313 | } |
314 | // |
315 | // Legend iFlag |
316 | // |
317 | // 0 - just initialized |
318 | // 1 - non-intersected |
319 | // 2 - roughly intersected |
320 | // 3 - intersection is not done |
321 | // 4 - coincided range |
322 | // |
323 | aPPC=Precision::PConfusion(); |
324 | aCriteria2=myCriteria*myCriteria; |
325 | aNbRanges=myRangeManager.Length(); |
326 | // |
327 | for(i=1; i<=aNbRanges; ++i) { |
328 | iFlag=myRangeManager.Flag(i); |
329 | // |
330 | if(iFlag==4) { |
331 | aRange=myRangeManager.Range(i); |
332 | aNbResults=myResults.Length(); |
333 | if(aNbResults>0) { |
334 | const IntTools_Range& aLastRange = myResults.Last(); |
335 | // |
336 | aParamDist = Abs(aRange.First() - aLastRange.Last()); |
337 | if(aParamDist > myCurveResolution1) { |
338 | myResults.Append(aRange); |
339 | } |
340 | else { |
341 | aPi=myCurve1.Value(aRange.First()); |
342 | aPh=myCurve1.Value(aLastRange.Last()); |
343 | aD2=aPi.SquareDistance(aPh); |
344 | if(aParamDist<aPPC || aD2<aCriteria2) { |
345 | myResults.ChangeValue(aNbResults).SetLast(aRange.Last()); |
346 | } |
347 | else { |
348 | myResults.Append(aRange); |
349 | } |
350 | } |
351 | }// if(aNbR>0) { |
352 | else { |
353 | myResults.Append(aRange); |
354 | } |
355 | } //if(iFlag==4) { |
356 | } // for(i = 1; i <= myRangeManager.Length(); i++) { |
357 | myIsDone = Standard_True; |
358 | } |
359 | // ================================================================================== |
360 | // function: FastComputeIntersection |
361 | // purpose: |
362 | // ================================================================================== |
363 | Standard_Boolean IntTools_BeanBeanIntersector::FastComputeIntersection() |
364 | { |
365 | Standard_Boolean aresult; |
366 | GeomAbs_CurveType aCT1, aCT2; |
367 | // |
368 | aresult = Standard_False; |
369 | // |
370 | aCT1=myCurve1.GetType(); |
371 | aCT2=myCurve2.GetType(); |
372 | // |
373 | if(aCT1 != aCT2) { |
374 | return aresult; |
375 | } |
376 | // |
377 | // Line |
378 | if(aCT1==GeomAbs_Line) { |
379 | Standard_Real par1, par2; |
380 | |
381 | if((Distance(myFirstParameter1, par1) < myCriteria) && |
382 | (Distance(myLastParameter1, par2) < myCriteria)) { |
383 | |
384 | if((par1 >= myFirstParameter2) && (par1 <= myLastParameter2) && |
385 | (par2 >= myFirstParameter2) && (par2 <= myLastParameter2)) { |
386 | myRangeManager.InsertRange(myFirstParameter1, myLastParameter1, 4); |
387 | aresult = Standard_True; |
388 | } |
389 | } |
390 | return aresult; |
391 | } |
392 | // |
393 | // Circle |
394 | if(aCT1==GeomAbs_Circle) { |
395 | Standard_Real anAngle, aPA, aDistLoc, aDist, aDiff, aR1, aR2; |
396 | gp_Circ aCirc1, aCirc2; |
397 | gp_Dir aDir1, aDir2; |
398 | // |
399 | aCirc1=myCurve1.Circle(); |
400 | aCirc2=myCurve2.Circle(); |
401 | aR1=aCirc1.Radius(); |
402 | aR2=aCirc2.Radius(); |
403 | // |
404 | aPA=Precision::Angular(); |
405 | aDir1 = aCirc1.Axis().Direction(); |
406 | aDir2 = aCirc2.Axis().Direction(); |
407 | // |
408 | anAngle = aDir1.Angle(aDir2); |
409 | if(anAngle > aPA) { |
410 | return aresult; //-> |
411 | } |
412 | // |
413 | const gp_Pnt& aPLoc1=aCirc1.Location(); |
414 | const gp_Pnt& aPLoc2=aCirc2.Location(); |
415 | aDistLoc = aPLoc1.Distance(aPLoc2); |
416 | aDist=aDistLoc; |
417 | aDiff=aR1 - aR2; |
418 | aDist+=Abs(aDiff); |
419 | if(Abs(aDist) > myCriteria) { |
420 | return aresult; //-> |
421 | } |
422 | // |
423 | Standard_Real aSinPA, atmpvalue, aprojectedradius; |
424 | // |
425 | aSinPA=sin(aPA); |
426 | atmpvalue = aR1*aSinPA; |
427 | atmpvalue *= atmpvalue; |
428 | aprojectedradius = sqrt(aR1*aR1 - atmpvalue); |
429 | |
430 | aDiff = aprojectedradius - aR2; |
431 | aDist = aDistLoc + sqrt((aDiff * aDiff) + atmpvalue); |
432 | if(Abs(aDist) > myCriteria) { |
433 | return aresult; //-> |
434 | } |
435 | // |
436 | Standard_Boolean newparfound; |
437 | Standard_Integer i; |
438 | Standard_Real afirstpar, alastpar, par1, par2, apar; |
439 | // |
440 | afirstpar = myFirstParameter1; |
441 | alastpar = myLastParameter1; |
442 | |
443 | for(i = 0; i < 2; i++) { |
444 | if((Distance(afirstpar, par1) < myCriteria) && |
445 | (Distance(alastpar , par2) < myCriteria)) { |
446 | |
447 | if(i || Distance((myFirstParameter1 + myLastParameter2) * 0.5, apar) < myCriteria) { |
448 | myRangeManager.InsertRange(afirstpar, alastpar, 4); |
449 | |
450 | if(!i) { |
451 | aresult = Standard_True; |
452 | } |
453 | } |
454 | break; |
455 | } |
456 | // |
457 | if(i) { |
458 | break; |
459 | } |
460 | // i=0 : |
461 | newparfound = Standard_False; |
462 | |
463 | if(Distance((myFirstParameter1 + myLastParameter2) * 0.5, apar) < myCriteria) { |
464 | afirstpar = myFirstParameter1 + myCriteria; |
465 | alastpar = myLastParameter1 - myCriteria; |
466 | newparfound = Standard_True; |
467 | |
468 | if(alastpar <= afirstpar) { |
469 | newparfound = Standard_False; |
470 | } |
471 | } |
24def445 |
472 | // |
7fd59977 |
473 | if(!newparfound) { |
474 | break; |
475 | } |
476 | }// for(i = 0; i < 2; i++) { |
477 | } // if(aCT1==GeomAbs_Circle) |
24def445 |
478 | //modified by NIZNHY-PKV Mon Oct 08 14:08:19 2012f |
479 | if (aCT1==GeomAbs_BSplineCurve || aCT1==GeomAbs_BezierCurve) { |
480 | Standard_Integer iFlag; |
481 | // |
482 | iFlag=CheckCoincidence(myFirstParameter1, |
483 | myLastParameter1, |
484 | myTrsfCurve1, |
485 | myFirstParameter2, |
486 | myLastParameter2, |
487 | myTrsfCurve2, |
488 | myCriteria, |
489 | myCurveResolution1, |
490 | myProjector); |
491 | if (!iFlag) { |
492 | aresult=!aresult; |
493 | } |
494 | } |
495 | //modified by NIZNHY-PKV Mon Oct 08 14:08:23 2012t |
7fd59977 |
496 | return aresult; |
497 | } |
498 | // ================================================================================== |
499 | // function: Distance |
500 | // purpose: |
501 | // ================================================================================== |
502 | Standard_Real IntTools_BeanBeanIntersector::Distance(const Standard_Real theArg, |
24def445 |
503 | Standard_Real& theArgOnOtherBean) |
7fd59977 |
504 | { |
505 | Standard_Real aDistance; |
506 | Standard_Integer aNbPoints; |
507 | gp_Pnt aPoint; |
508 | // |
509 | aDistance=RealLast(); |
510 | // |
511 | aPoint=myCurve1.Value(theArg); |
7fd59977 |
512 | myProjector.Init(myTrsfCurve2, myFirstParameter2, myLastParameter2); |
513 | myProjector.Perform(aPoint); |
7fd59977 |
514 | // |
515 | aNbPoints=myProjector.NbPoints(); |
516 | if(aNbPoints > 0) { |
517 | theArgOnOtherBean = myProjector.LowerDistanceParameter(); |
518 | aDistance=myProjector.LowerDistance(); |
519 | } |
520 | // |
521 | else { |
522 | Standard_Real aDistance1, aDistance2; |
523 | // |
524 | aDistance1 = aPoint.Distance(myCurve2.Value(myFirstParameter2)); |
525 | aDistance2 = aPoint.Distance(myCurve2.Value(myLastParameter2)); |
526 | // |
527 | theArgOnOtherBean = myLastParameter2; |
528 | aDistance=aDistance2; |
529 | if(aDistance1 < aDistance2) { |
530 | theArgOnOtherBean = myFirstParameter2; |
531 | aDistance=aDistance1; |
532 | } |
533 | } |
534 | return aDistance; |
535 | } |
536 | // ================================================================================== |
537 | // function: ComputeRoughIntersection |
538 | // purpose: |
539 | // ================================================================================== |
540 | void IntTools_BeanBeanIntersector::ComputeRoughIntersection() |
541 | { |
542 | Standard_Boolean isintersection; |
543 | Standard_Integer i, aNbArgs, aNbArgs1, aNbRanges, j, aNbLines, k, pIt, extIt, iFlag; |
544 | Standard_Real aDeflection, aGPR, aCurDeflection, aT1, aT2, aD; |
545 | Standard_Real aMaxDistance, aDistance, aPPC, aPrm1, aPrm2, aPPA; |
546 | GeomAbs_CurveType aCT1, aCT2; |
547 | gp_Pnt aPoint1, aPoint2, aMidPOnCurve, aMidPOnLine, aP1, aP2; |
548 | IntTools_CArray1OfReal anArgs; |
549 | LocalPrepareArgs(myCurve2, myFirstParameter2, myLastParameter2, aDeflection, anArgs); |
550 | // |
551 | aNbArgs=anArgs.Length(); |
552 | if(!aNbArgs) { |
553 | return; |
554 | } |
555 | // |
556 | aCT1=myCurve1.GetType(); |
557 | aCT2=myCurve2.GetType(); |
558 | aGPR=gp::Resolution(); |
559 | aPPC=Precision::PConfusion(); |
560 | aPPA=Precision::Angular(); |
561 | aNbArgs1=aNbArgs-1; |
562 | // |
563 | Intf_Array1OfLin aLines(1, aNbArgs1); |
564 | TColStd_Array1OfInteger aLineFlags(1, aNbArgs1); |
565 | TColStd_Array1OfReal aDistances(1, aNbArgs1); |
566 | // |
567 | aT1=anArgs(0); |
568 | aPoint1 = myCurve2.Value(aT1); |
569 | for(i=1; i<aNbArgs; ++i) { |
570 | aT2=anArgs(i); |
571 | aPoint2 = myCurve2.Value(aT2); |
572 | gp_Vec aVec(aPoint1, aPoint2); |
573 | aD=aVec.Magnitude(); |
574 | aDistances.SetValue(i, aD); |
575 | // |
576 | if(aD<=aGPR) { |
577 | aLineFlags.SetValue(i, 0); |
578 | } |
579 | else { |
580 | aLineFlags.SetValue(i, 1); |
581 | gp_Lin aLine(aPoint1, gp_Dir(aVec)); |
582 | aLines.SetValue(i, aLine); |
583 | // |
584 | if((aCT2 == GeomAbs_BezierCurve) || |
585 | (aCT2 == GeomAbs_BSplineCurve)) { |
586 | aMidPOnCurve = myCurve2.Value((aT1+aT2) * 0.5); |
587 | aMidPOnLine = ElCLib::Value((aDistances(i)*0.5), aLine); |
588 | aCurDeflection = aMidPOnCurve.Distance(aMidPOnLine); |
589 | if(aCurDeflection > aDeflection) { |
590 | aDeflection = aCurDeflection; |
591 | } |
592 | } |
593 | } |
594 | aT1=aT2; |
595 | aPoint1 = aPoint2; |
596 | } |
597 | // |
598 | aNbLines=aLines.Upper(); |
599 | aMaxDistance = myCriteria + myDeflection + aDeflection; |
600 | |
601 | aT1=myRangeManager.Range(1).First(); |
602 | aPoint1 = myCurve1.Value(aT1); |
603 | aNbRanges=myRangeManager.Length(); |
604 | for(i = 1; i <= aNbRanges; ++i) { |
605 | const IntTools_Range& aRange = myRangeManager.Range(i); |
606 | aT2=aRange.Last(); |
607 | aPoint2 = myCurve1.Value(aT2); |
608 | // |
609 | iFlag=myRangeManager.Flag(i); |
610 | if(iFlag==4) {// coincided |
611 | aT1=aT2; |
612 | aPoint1 = aPoint2; |
613 | continue; |
614 | } |
615 | // |
616 | myRangeManager.SetFlag(i, 1); // not intersected |
617 | |
618 | Bnd_Box aBox1; |
619 | aBox1.Add(aPoint1); |
620 | aBox1.Add(aPoint2); |
621 | aBox1.Enlarge(myBeanTolerance1 + myDeflection); |
622 | |
623 | gp_Vec aVec(aPoint1, aPoint2); |
624 | |
625 | aDistance=aVec.Magnitude(); |
626 | if(aDistance <= aGPR) { |
627 | myRangeManager.SetFlag(i, 0); |
628 | continue; |
629 | } |
630 | // |
631 | gp_Lin aLine(aPoint1, gp_Dir(aVec)); |
632 | // |
633 | if((aCT1 == GeomAbs_BezierCurve) || |
634 | (aCT1 == GeomAbs_BSplineCurve)) { |
635 | aMidPOnCurve = myCurve1.Value((aRange.First() + aRange.Last()) * 0.5); |
636 | aMidPOnLine = ElCLib::Value((aDistance*0.5), aLine); |
637 | aCurDeflection = aMidPOnCurve.Distance(aMidPOnLine); |
638 | if(myDeflection < aCurDeflection) { |
639 | aMaxDistance += aCurDeflection - myDeflection; |
640 | myDeflection = aCurDeflection; |
641 | } |
642 | } |
643 | // |
644 | for(j=1; j<=aNbLines; ++j) { |
645 | if(!aLineFlags(j)) { |
646 | myRangeManager.SetFlag(i, 0); |
647 | continue; |
648 | } |
649 | // |
650 | const gp_Lin& aL2=aLines(j); |
651 | //Handle(Geom_Line) aC2=new Geom_Line(aL2); // DEB ft |
652 | aD=aDistances(j); |
653 | aP1=ElCLib::Value(0., aL2); |
654 | aP2=ElCLib::Value(aD, aL2); |
655 | // |
656 | Extrema_ExtElC anExtrema(aLine, aL2, aPPA); |
657 | if(anExtrema.IsDone() && (anExtrema.IsParallel() || (anExtrema.NbExt() > 0))) { |
658 | isintersection = Standard_False; |
659 | |
660 | if(anExtrema.IsParallel()) { |
661 | isintersection = (anExtrema.SquareDistance(1) < aMaxDistance * aMaxDistance); |
662 | } |
663 | else { //1 |
664 | for(k = 1; !isintersection && k <= anExtrema.NbExt(); ++k) { |
665 | if(anExtrema.SquareDistance(k) < aMaxDistance * aMaxDistance) { |
666 | Extrema_POnCurv P1, P2; |
667 | anExtrema.Points(k, P1, P2); |
668 | aPrm1=P1.Parameter(); |
669 | aPrm2=P2.Parameter(); |
670 | if((aPrm1 >= -aMaxDistance) && (aPrm1 <= aDistance+aMaxDistance) && |
671 | (aPrm2 >= -aMaxDistance) && (aPrm2 <= aD+aMaxDistance)) { |
672 | isintersection = Standard_True; |
673 | } |
674 | else { // 2 |
675 | Extrema_ExtPElC aPointProjector; |
676 | |
677 | for(pIt = 0; !isintersection && (pIt < 4); ++pIt) { |
678 | switch (pIt) { |
679 | case 0: { |
680 | aPointProjector = |
681 | //Extrema_ExtPElC(aPoint1, aLines(j), aPPC, 0., aDistances(j)); |
682 | Extrema_ExtPElC(aPoint1, aL2, aPPC, -aMaxDistance, aD+aMaxDistance); |
683 | break; |
684 | } |
685 | case 1: { |
686 | aPointProjector = |
687 | //Extrema_ExtPElC(aPoint2, aLines(j), aPPC, 0., aD); |
688 | Extrema_ExtPElC(aPoint2, aL2, aPPC, -aMaxDistance, aD+aMaxDistance); |
689 | break; |
690 | } |
691 | case 2: { |
692 | aPointProjector = |
693 | //Extrema_ExtPElC(ElCLib::Value(0., aLines(j)), aLine, aPPC, 0., aDistance); |
694 | Extrema_ExtPElC(aP1, aLine, aPPC, -aMaxDistance, aDistance+aMaxDistance); |
695 | break; |
696 | } |
697 | case 3: { |
698 | aPointProjector = |
699 | //Extrema_ExtPElC(ElCLib::Value(aDistances(j), aLines(j)), aLine, aPPC, 0., aDistance); |
700 | Extrema_ExtPElC(aP2, aLine, aPPC, -aMaxDistance, aDistance+aMaxDistance); |
701 | break; |
702 | } |
703 | default: { |
704 | break; |
705 | } |
706 | } |
707 | // |
708 | if(aPointProjector.IsDone()) { |
709 | Standard_Real aMaxDistance2 = aMaxDistance * aMaxDistance; |
710 | for(extIt = 1; extIt <= aPointProjector.NbExt(); extIt++) { |
711 | if(aPointProjector.SquareDistance(extIt) < aMaxDistance2) { |
712 | isintersection = Standard_True; |
713 | } |
714 | } |
715 | } |
716 | } // end for |
717 | }// else { // 2 |
718 | }//if(anExtrema.Value(k) < aMaxDistance) { |
719 | }//for(k = 1; !isintersection && k <= anExtrema.NbExt(); k++) { |
720 | }//else { //1 |
721 | |
722 | if(isintersection) { |
723 | myRangeManager.SetFlag(i, 2); // roughly intersected |
724 | break; |
725 | } |
726 | }//if(anExtrema.IsDone() && (anExtrema.IsParallel() || (anExtrema.NbExt() > 0))) { |
727 | else { |
728 | Bnd_Box aBox2; |
729 | aBox2.Add(myCurve2.Value(anArgs(j-1))); |
730 | aBox2.Add(myCurve2.Value(anArgs(j))); |
731 | aBox2.Enlarge(myBeanTolerance2 + aDeflection); |
732 | // |
733 | if(!aBox1.IsOut(aBox2)) { |
734 | myRangeManager.SetFlag(i, 2); // roughly intersected |
735 | break; |
736 | } |
737 | } |
738 | } |
739 | aT1=aT2; |
740 | aPoint1 = aPoint2; |
741 | } |
742 | } |
743 | |
744 | // ================================================================================== |
745 | // function: ComputeUsingExtrema |
746 | // purpose: |
747 | // ================================================================================== |
748 | void IntTools_BeanBeanIntersector::ComputeUsingExtrema(const IntTools_Range& theRange2) |
749 | { |
750 | //rln Dec 2008. |
751 | //Extrema_ExtCC is reused throughout this method to store caches computed on |
752 | //theRange2. However it is actually used only in a few calls of |
753 | //ComputeUsingExtrema(), so using a default constructor would add unnecessary overhead |
754 | //of initialization its internal fields. Since it is not manipulated by Handle then |
755 | //we will use a pointer to it and initialize it only when needed. |
756 | Extrema_ExtCC *apExtrema = 0; |
757 | Handle(GeomAdaptor_HCurve) aHCurve1, aHCurve2; //will be initialized later, only if needed |
758 | //handles are used to guard pointers to GeomAdaptor_Curve inside Extrema |
759 | Standard_Real aCriteria2 = myCriteria * myCriteria; |
760 | for(Standard_Integer i = 1; i <= myRangeManager.Length(); i++) { |
761 | |
762 | if(myRangeManager.Flag(i) == 2 || myRangeManager.Flag(i) == 0) { |
763 | const IntTools_Range& aParamRange = myRangeManager.Range(i); |
764 | |
765 | if(aParamRange.Last() - aParamRange.First() < Precision::PConfusion()) { |
766 | |
767 | if(((i > 1) && (myRangeManager.Flag(i-1) == 4)) || |
768 | ((i < myRangeManager.Length()) && (myRangeManager.Flag(i+1) == 4))) { |
769 | myRangeManager.SetFlag(i, 4); |
770 | continue; |
771 | } |
772 | } |
773 | if (aHCurve2.IsNull()) { |
774 | //initialize only once |
775 | apExtrema = new Extrema_ExtCC; |
776 | Standard_Real ftmp = theRange2.First() - Precision::PConfusion(); |
777 | Standard_Real ltmp = theRange2.Last() + Precision::PConfusion(); |
778 | ftmp = (ftmp < myFirstParameter2) ? myFirstParameter2 : ftmp; |
779 | ltmp = (ltmp > myLastParameter2) ? myLastParameter2 : ltmp; |
780 | aHCurve2 = new GeomAdaptor_HCurve (myTrsfCurve2, ftmp, ltmp); |
781 | apExtrema->SetCurve (2, aHCurve2->Curve(), theRange2.First(), theRange2.Last()); |
782 | } |
783 | Extrema_ExtCC& anExtrema = *apExtrema; |
784 | |
785 | Standard_Real ftmp = aParamRange.First() - Precision::PConfusion(); |
786 | Standard_Real ltmp = aParamRange.Last() + Precision::PConfusion(); |
787 | ftmp = (ftmp < myFirstParameter1) ? myFirstParameter1 : ftmp; |
788 | ltmp = (ltmp > myLastParameter1) ? myLastParameter1 : ltmp; |
789 | aHCurve1 = new GeomAdaptor_HCurve (myTrsfCurve1, ftmp, ltmp); |
790 | anExtrema.SetCurve (1, aHCurve1->Curve(), aParamRange.First(), aParamRange.Last()); |
791 | |
792 | anExtrema.Perform(); |
793 | |
794 | if(anExtrema.IsDone() && (anExtrema.IsParallel() || (anExtrema.NbExt() > 0))) { |
795 | Standard_Integer anOldNbRanges = myRangeManager.Length(); |
796 | |
797 | if (anExtrema.IsParallel()) { |
798 | if(anExtrema.SquareDistance(1) < aCriteria2) { |
799 | Standard_Real theParameter1, theParameter2; |
800 | Standard_Real adistance1 = Distance(aParamRange.First(), theParameter1); |
801 | Standard_Real adistance2 = Distance(aParamRange.Last(), theParameter2); |
802 | Standard_Boolean validdistance1 = (adistance1 < myCriteria); |
803 | Standard_Boolean validdistance2 = (adistance2 < myCriteria); |
804 | |
805 | if (validdistance1 && validdistance2) { |
806 | myRangeManager.InsertRange(aParamRange.First(), aParamRange.Last(), 4); |
807 | continue; |
808 | } |
809 | else { |
810 | if(validdistance1) { |
811 | ComputeRangeFromStartPoint(Standard_True, aParamRange.First(), i, theParameter1, theRange2); |
812 | } |
813 | else { |
814 | if(validdistance2) { |
815 | ComputeRangeFromStartPoint(Standard_False, aParamRange.Last(), i, theParameter2, theRange2); |
816 | } |
817 | else { |
818 | Standard_Real a = aParamRange.First(); |
819 | Standard_Real b = aParamRange.Last(); |
820 | Standard_Real da = adistance1; |
821 | Standard_Real db = adistance2; |
822 | Standard_Real asolution = a; |
823 | Standard_Boolean found = Standard_False; |
824 | |
825 | while(((b - a) > myCurveResolution1) && !found) { |
826 | asolution = (a+b)*0.5; |
827 | Standard_Real adist = Distance(asolution, theParameter1); |
828 | |
829 | if(adist < myCriteria) { |
830 | found = Standard_True; |
831 | } |
832 | else { |
833 | if(da < db) { |
834 | b = asolution; |
835 | db = adist; |
836 | } |
837 | else { |
838 | a = asolution; |
839 | da = adist; |
840 | } |
841 | } |
842 | } // end while |
843 | |
844 | if(found) { |
845 | ComputeRangeFromStartPoint(Standard_False, asolution, i, theParameter1, theRange2); |
846 | ComputeRangeFromStartPoint(Standard_True, asolution, i, theParameter1, theRange2); |
847 | } |
848 | else { |
849 | myRangeManager.SetFlag(i, 2); |
850 | } |
851 | } |
852 | } |
853 | } |
854 | } |
855 | } |
856 | else { |
857 | |
858 | for(Standard_Integer j = 1 ; j <= anExtrema.NbExt(); j++) { |
859 | if(anExtrema.SquareDistance(j) < aCriteria2) { |
860 | Extrema_POnCurv p1, p2; |
861 | anExtrema.Points(j, p1, p2); |
862 | |
863 | Standard_Integer aNbRanges = myRangeManager.Length(); |
864 | |
865 | Standard_Integer anIndex = myRangeManager.GetIndex(p1.Parameter(), Standard_False); |
866 | if(anIndex > 0) { |
867 | ComputeRangeFromStartPoint(Standard_False, p1.Parameter(), anIndex, p2.Parameter(), theRange2); |
868 | } |
869 | |
870 | anIndex = myRangeManager.GetIndex(p1.Parameter(), Standard_True); |
871 | |
872 | if(anIndex > 0) { |
873 | ComputeRangeFromStartPoint(Standard_True, p1.Parameter(), anIndex, p2.Parameter(), theRange2); |
874 | } |
875 | |
876 | if(aNbRanges == myRangeManager.Length()) { |
877 | SetEmptyResultRange(p1.Parameter(), myRangeManager); |
878 | } |
879 | } |
880 | } // end for |
881 | } |
882 | Standard_Integer adifference = myRangeManager.Length() - anOldNbRanges; |
883 | |
884 | if(adifference > 0) { |
885 | i+=adifference; |
886 | } |
887 | } |
888 | else { |
889 | myRangeManager.SetFlag(i, 3); // intersection not done. |
890 | } |
891 | } |
892 | } |
893 | if (apExtrema) delete apExtrema; |
894 | } |
895 | |
896 | // ================================================================================== |
897 | // function: ComputeNearRangeBoundaries |
898 | // purpose: |
899 | // ================================================================================== |
900 | void IntTools_BeanBeanIntersector::ComputeNearRangeBoundaries(const IntTools_Range& theRange2) |
901 | { |
902 | Standard_Real theParameter = theRange2.First(); |
903 | |
904 | for(Standard_Integer i = 1; i <= myRangeManager.Length(); i++) { |
905 | if(myRangeManager.Flag(i) != 3) |
906 | continue; |
907 | |
908 | if((i > 1) && ((myRangeManager.Flag(i-1) == 1) || (myRangeManager.Flag(i-1) == 4))) { |
909 | myRangeManager.SetFlag(i, 2); |
910 | continue; |
911 | } |
912 | |
913 | const IntTools_Range& aParamRange = myRangeManager.Range(i); |
914 | |
915 | if(Distance(aParamRange.First(), theParameter) < myCriteria) { |
916 | Standard_Integer aNbRanges = myRangeManager.Length(); |
917 | |
918 | if(i > 1) { |
919 | ComputeRangeFromStartPoint(Standard_False, aParamRange.First(), i-1, theParameter, theRange2); |
920 | } |
921 | ComputeRangeFromStartPoint(Standard_True, aParamRange.First(), i + (myRangeManager.Length() - aNbRanges), theParameter, theRange2); |
922 | |
923 | if(aNbRanges == myRangeManager.Length()) { |
924 | SetEmptyResultRange(aParamRange.First(), myRangeManager); |
925 | } |
926 | } |
927 | else { |
928 | myRangeManager.SetFlag(i, 2); |
929 | } |
930 | } |
931 | |
932 | if((myRangeManager.Flag(myRangeManager.Length()) == 3) || |
933 | (myRangeManager.Flag(myRangeManager.Length()) == 2)) { |
934 | const IntTools_Range& aParamRange = myRangeManager.Range(myRangeManager.Length()); |
935 | |
936 | if(Distance(aParamRange.Last(), theParameter) < myCriteria) { |
937 | Standard_Integer aNbRanges = myRangeManager.Length(); |
938 | myRangeManager.SetFlag(myRangeManager.Length(), 2); |
939 | |
940 | ComputeRangeFromStartPoint(Standard_False, aParamRange.Last(), myRangeManager.Length(), theParameter, theRange2); |
941 | |
942 | if(aNbRanges == myRangeManager.Length()) { |
943 | SetEmptyResultRange(aParamRange.Last(), myRangeManager); |
944 | } |
945 | } |
946 | else { |
947 | myRangeManager.SetFlag(myRangeManager.Length(), 2); |
948 | } |
949 | } |
950 | } |
951 | |
952 | // ================================================================================== |
953 | // function: ComputeRangeFromStartPoint |
954 | // purpose: |
955 | // ================================================================================== |
956 | void IntTools_BeanBeanIntersector::ComputeRangeFromStartPoint(const Standard_Boolean ToIncreaseParameter, |
957 | const Standard_Real theParameter, |
958 | const Standard_Integer theIndex, |
959 | const Standard_Real theParameter2, |
960 | const IntTools_Range& theRange2) |
961 | { |
962 | |
963 | if(myRangeManager.Flag(theIndex) == 4 || |
964 | myRangeManager.Flag(theIndex) == 1) |
965 | return; |
966 | |
967 | Standard_Integer aValidIndex = theIndex; |
968 | Standard_Real aMinDelta = myCurveResolution1 * 0.5; |
969 | Standard_Real aDeltaRestrictor = myLastParameter1 - myFirstParameter1; |
970 | |
971 | if(Abs(aDeltaRestrictor) < Precision::PConfusion()) { |
972 | return; |
973 | } |
974 | |
975 | if(aMinDelta > aDeltaRestrictor) { |
976 | aMinDelta = aDeltaRestrictor; |
977 | } |
978 | Standard_Real tenOfMinDelta = aMinDelta * 10.; |
979 | Standard_Real aDelta = myCurveResolution1; |
980 | Standard_Real aCurPar = (ToIncreaseParameter) ? (theParameter + aDelta) : (theParameter - aDelta); |
981 | Standard_Real aPrevPar = theParameter; |
982 | IntTools_Range aCurrentRange = myRangeManager.Range(aValidIndex); |
983 | |
984 | Standard_Boolean BoundaryCondition = (ToIncreaseParameter) ? (aCurPar > aCurrentRange.Last()) : (aCurPar < aCurrentRange.First()); |
985 | |
986 | if(BoundaryCondition) { |
987 | aCurPar = (ToIncreaseParameter) ? aCurrentRange.Last() : aCurrentRange.First(); |
988 | BoundaryCondition = Standard_False; |
989 | } |
990 | |
991 | Standard_Integer loopcounter = 0; // neccesary to have no infinite loop |
992 | Standard_Real aParameter = theParameter2; |
993 | Standard_Boolean anotherSolutionFound = Standard_False; |
994 | |
995 | Standard_Boolean isboundaryindex = Standard_False; |
996 | Standard_Boolean isvalidindex = Standard_True; |
997 | |
998 | Standard_Real aCriteria2 = myCriteria * myCriteria; |
999 | |
1000 | while((aDelta >= aMinDelta) && (loopcounter <= 10)) { |
1001 | Standard_Boolean pointfound = Standard_False; |
1002 | |
1003 | gp_Pnt aPoint = myCurve1.Value(aCurPar); |
1004 | GeomAdaptor_Curve aCurve2(myTrsfCurve2, theRange2.First(), theRange2.Last()); |
1005 | |
1006 | Extrema_LocateExtPC anExtrema(aPoint, aCurve2, aParameter, theRange2.First(), theRange2.Last(), 1.e-10); |
1007 | |
1008 | if(anExtrema.IsDone()) { |
1009 | if(anExtrema.SquareDistance() < aCriteria2) { |
1010 | Extrema_POnCurv aPOnCurv = anExtrema.Point(); |
1011 | aParameter = aPOnCurv.Parameter(); |
1012 | pointfound = Standard_True; |
1013 | } |
1014 | } |
1015 | else { |
1016 | // pointfound = (Distance(aCurPar, aParameter) < myCriteria); |
1017 | Standard_Real afoundparam = aParameter; |
1018 | |
1019 | if(Distance(aCurPar, afoundparam) < myCriteria) { |
1020 | aParameter = afoundparam; |
1021 | pointfound = Standard_True; |
1022 | } |
1023 | } |
1024 | |
1025 | if(pointfound) { |
1026 | aPrevPar = aCurPar; |
1027 | anotherSolutionFound = Standard_True; |
1028 | |
1029 | if(BoundaryCondition && (isboundaryindex || !isvalidindex)) |
1030 | break; |
1031 | } |
1032 | else { |
1033 | aDeltaRestrictor = aDelta; |
1034 | } |
1035 | |
1036 | // if pointfound decide to increase aDelta using derivative of distance function |
1037 | // |
1038 | |
1039 | aDelta = (pointfound) ? (aDelta * 2.) : (aDelta * 0.5); |
1040 | aDelta = (aDelta < aDeltaRestrictor) ? aDelta : aDeltaRestrictor; |
1041 | aCurPar = (ToIncreaseParameter) ? (aPrevPar + aDelta) : (aPrevPar - aDelta); |
1042 | |
1043 | BoundaryCondition = (ToIncreaseParameter) ? (aCurPar > aCurrentRange.Last()) : (aCurPar < aCurrentRange.First()); |
1044 | |
1045 | isboundaryindex = Standard_False; |
1046 | isvalidindex = Standard_True; |
1047 | |
1048 | if(BoundaryCondition) { |
1049 | isboundaryindex = ((!ToIncreaseParameter && (aValidIndex == 1)) || |
1050 | (ToIncreaseParameter && (aValidIndex == myRangeManager.Length()))); |
1051 | |
1052 | if(!isboundaryindex) { |
1053 | if(pointfound) { |
1054 | Standard_Integer aFlag = (ToIncreaseParameter) ? myRangeManager.Flag(aValidIndex + 1) : myRangeManager.Flag(aValidIndex - 1); |
1055 | |
1056 | if(aFlag != 1 && aFlag != 4) { |
1057 | aValidIndex = (ToIncreaseParameter) ? (aValidIndex + 1) : (aValidIndex - 1); |
1058 | aCurrentRange = myRangeManager.Range(aValidIndex); |
1059 | |
1060 | if((ToIncreaseParameter && (aCurPar > aCurrentRange.Last())) || |
1061 | (!ToIncreaseParameter && (aCurPar < aCurrentRange.First()))) { |
1062 | aCurPar = (aCurrentRange.First() + aCurrentRange.Last()) * 0.5; |
1063 | aDelta*=0.5; |
1064 | } |
1065 | } |
1066 | else { |
1067 | isvalidindex = Standard_False; |
1068 | aCurPar = (ToIncreaseParameter) ? aCurrentRange.Last() : aCurrentRange.First(); |
1069 | } |
1070 | } |
1071 | } |
1072 | else { |
1073 | aCurPar = (ToIncreaseParameter) ? aCurrentRange.Last() : aCurrentRange.First(); |
1074 | } |
1075 | |
1076 | if(aDelta < tenOfMinDelta) { |
1077 | loopcounter++; |
1078 | } |
1079 | else { |
1080 | loopcounter = 0; |
1081 | } |
1082 | } // end if(BoundaryCondition) |
1083 | } |
1084 | |
1085 | if(anotherSolutionFound) { |
1086 | if(ToIncreaseParameter) |
1087 | myRangeManager.InsertRange(theParameter, aPrevPar, 4); |
1088 | else |
1089 | myRangeManager.InsertRange(aPrevPar, theParameter, 4); |
1090 | } |
1091 | } |
1092 | |
1093 | // --------------------------------------------------------------------------------- |
1094 | // static function: LocalPrepareArgs |
1095 | // purpose: |
1096 | // --------------------------------------------------------------------------------- |
1097 | static void LocalPrepareArgs(BRepAdaptor_Curve& theCurve, |
1098 | const Standard_Real theFirstParameter, |
1099 | const Standard_Real theLastParameter, |
1100 | Standard_Real& theDeflection, |
1101 | IntTools_CArray1OfReal& theArgs) { |
1102 | Standard_Integer aDiscretization = 30; |
1103 | Standard_Real aRelativeDeflection = 0.01; |
1104 | theDeflection = aRelativeDeflection; |
1105 | Standard_Boolean prepareargs = Standard_True; |
1106 | |
1107 | switch(theCurve.GetType()) { |
1108 | case GeomAbs_Line: { |
1109 | prepareargs = Standard_False; |
1110 | aDiscretization = 3; |
1111 | theArgs.Append(theFirstParameter); |
1112 | |
1113 | if((theLastParameter - theFirstParameter) > Precision::PConfusion()) { |
1114 | theArgs.Append((theFirstParameter + theLastParameter)*0.5); |
1115 | } |
1116 | theArgs.Append(theLastParameter); |
1117 | theDeflection = Precision::Confusion(); |
1118 | break; |
1119 | } |
1120 | case GeomAbs_Circle: { |
1121 | aDiscretization = 23; |
1122 | theDeflection = aRelativeDeflection * theCurve.Circle().Radius(); |
1123 | break; |
1124 | } |
1125 | case GeomAbs_Ellipse: { |
1126 | aDiscretization = 40; |
1127 | theDeflection = 2 * aRelativeDeflection * theCurve.Ellipse().MajorRadius(); |
1128 | break; |
1129 | } |
1130 | case GeomAbs_Hyperbola: |
1131 | case GeomAbs_Parabola: { |
1132 | aDiscretization = 40; |
1133 | theDeflection = aRelativeDeflection; |
1134 | break; |
1135 | } |
1136 | case GeomAbs_BezierCurve: { |
1137 | aDiscretization = 30; |
1138 | theDeflection = aRelativeDeflection; |
1139 | break; |
1140 | } |
1141 | case GeomAbs_BSplineCurve: { |
1142 | aDiscretization = 30; |
1143 | theDeflection = aRelativeDeflection; |
1144 | break; |
1145 | } |
1146 | default: { |
1147 | aDiscretization = 30; |
1148 | theDeflection = aRelativeDeflection; |
1149 | } |
1150 | } |
1151 | |
1152 | if(prepareargs) { |
1153 | IntTools::PrepareArgs(theCurve, theLastParameter, theFirstParameter, aDiscretization, aRelativeDeflection, theArgs); |
1154 | } |
1155 | } |
7fd59977 |
1156 | // --------------------------------------------------------------------------------- |
1157 | // static function: SetEmptyResultRange |
1158 | // purpose: |
1159 | // --------------------------------------------------------------------------------- |
1160 | static Standard_Boolean SetEmptyResultRange(const Standard_Real theParameter, |
1161 | IntTools_MarkedRangeSet& theMarkedRange) { |
1162 | |
1163 | const TColStd_SequenceOfInteger& anIndices = theMarkedRange.GetIndices(theParameter); |
1164 | Standard_Boolean add = (anIndices.Length() > 0); |
1165 | |
1166 | for(Standard_Integer k = 1; k <= anIndices.Length(); k++) { |
1167 | if(theMarkedRange.Flag(anIndices(k)) == 4) { |
1168 | add = Standard_False; |
1169 | break; |
1170 | } |
1171 | } |
1172 | |
1173 | if(add) { |
1174 | theMarkedRange.InsertRange(theParameter, theParameter, 4); |
1175 | } |
1176 | |
1177 | return add; |
1178 | } |
24def445 |
1179 | //modified by NIZNHY-PKV Fri Oct 12 09:34:10 2012f |
1180 | static |
1181 | Standard_Integer DistPC(const Standard_Real aT1, |
1182 | const Handle(Geom_Curve)& aC1, |
1183 | const Standard_Real aCriteria, |
1184 | GeomAPI_ProjectPointOnCurve& aProjector, |
1185 | Standard_Real& aD, |
1186 | Standard_Real& aT2); |
1187 | |
1188 | |
1189 | static |
1190 | Standard_Integer DistPC(const Standard_Real aT1, |
1191 | const Handle(Geom_Curve)& aC1, |
1192 | const Standard_Real aCriteria, |
1193 | GeomAPI_ProjectPointOnCurve& aProjector, |
1194 | Standard_Real& aD, |
1195 | Standard_Real& aT2, |
1196 | Standard_Real& aDmax, |
1197 | Standard_Real& aTmax); |
1198 | |
1199 | static |
1200 | Standard_Integer FindMaxDistPC(const Standard_Real aT1A, |
1201 | const Standard_Real aT1B, |
1202 | const Handle(Geom_Curve)& aC1, |
1203 | const Standard_Real aCriteria, |
1204 | const Standard_Real aEps1, |
1205 | GeomAPI_ProjectPointOnCurve& aProjector, |
1206 | Standard_Real& aDmax, |
1207 | Standard_Real& aT1max); |
1208 | |
1209 | //======================================================================= |
1210 | //function : CheckCoincidence |
1211 | //purpose : |
1212 | //======================================================================= |
1213 | Standard_Integer CheckCoincidence(const Standard_Real aT11, |
1214 | const Standard_Real aT12, |
1215 | const Handle(Geom_Curve)& aC1, |
1216 | const Standard_Real aT21, |
1217 | const Standard_Real aT22, |
1218 | const Handle(Geom_Curve)& aC2, |
1219 | const Standard_Real aCriteria, |
1220 | const Standard_Real aEps1, |
1221 | GeomAPI_ProjectPointOnCurve& aProjector) |
1222 | { |
1223 | Standard_Integer iErr, aNb1, i, aNbX; |
b9736bcc |
1224 | Standard_Real dT1, aT1, aT2, aD, aDmax, aTmax; |
24def445 |
1225 | Standard_Real aT1A, aT1B, aD1max,aT1max; |
1226 | // |
1227 | iErr=0; // the patches are coincided |
1228 | // |
1229 | // |
1230 | aProjector.Init(aC2, aT21, aT22); |
1231 | // |
1232 | aDmax=-1.; |
1233 | // |
1234 | // 1. Express evaluation |
1235 | // |
1236 | aNb1=10; // Number of intervals on the curve #1 |
1237 | dT1=(aT12-aT11)/aNb1; |
1238 | for (i=1; i<aNb1; ++i) { |
1239 | aT1=aT11+i*dT1; |
1240 | // |
1241 | iErr=DistPC(aT1, aC1, aCriteria, aProjector, aD, aT2, aDmax, aTmax); |
1242 | if (iErr) { |
1243 | iErr=1;// a point from aC1 can not be projected on aC2 |
1244 | return iErr; |
1245 | } |
1246 | // |
1247 | if (aDmax>aCriteria) { |
1248 | iErr=2; // the distance is too big |
1249 | return iErr; |
1250 | } |
1251 | } |
1252 | // |
1253 | // 2. Deep evaluation |
1254 | aD1max=aDmax; |
1255 | // |
1256 | aNbX=aNb1-1; |
1257 | for (i=1; i<aNbX; ++i) { |
1258 | aT1A=aT11+i*dT1; |
1259 | aT1B=aT1A+dT1; |
1260 | // |
1261 | iErr=FindMaxDistPC(aT1A, aT1B, aC1, aCriteria, aEps1, aProjector, aD1max, aT1max); |
1262 | if (iErr) { |
1263 | iErr=1; |
1264 | return iErr; |
1265 | } |
1266 | } |
1267 | // |
1268 | return iErr; |
1269 | } |
1270 | // |
1271 | //======================================================================= |
1272 | //function : FindMaxDistPC |
1273 | //purpose : |
1274 | //======================================================================= |
1275 | Standard_Integer FindMaxDistPC(const Standard_Real aT1A, |
1276 | const Standard_Real aT1B, |
1277 | const Handle(Geom_Curve)& aC1, |
1278 | const Standard_Real aCriteria, |
1279 | const Standard_Real aEps1, |
1280 | GeomAPI_ProjectPointOnCurve& aProjector, |
1281 | Standard_Real& aDmax, |
1282 | Standard_Real& aT1max) |
1283 | { |
1284 | Standard_Integer iErr, iCnt; |
1285 | Standard_Real aGS, aXP, aA, aB, aXL, aYP, aYL, aT2P, aT2L, aX0; |
1286 | // |
1287 | iCnt=0; |
1288 | iErr=0; |
1289 | aDmax=0.; |
1290 | // |
1291 | aGS=0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))-1.; |
1292 | aA=aT1A; |
1293 | aB=aT1B; |
1294 | // |
1295 | aXP=aA+(aB-aA)*aGS; |
1296 | aXL=aB-(aB-aA)*aGS; |
1297 | // |
1298 | iErr=DistPC(aXP, aC1, aCriteria, aProjector, aYP, aT2P, aDmax, aT1max); |
1299 | if(iErr){ |
1300 | return iErr; |
1301 | } |
1302 | // |
1303 | iErr=DistPC(aXL, aC1, aCriteria, aProjector, aYL, aT2L, aDmax, aT1max); |
1304 | if(iErr){ |
1305 | return iErr; |
1306 | } |
1307 | // |
1308 | while(1) { |
1309 | if (aYP>aYL) { |
1310 | aA=aXL; |
1311 | aXL=aXP; |
1312 | aYL=aYP; |
1313 | aXP=aA+(aB-aA)*aGS; |
1314 | iErr=DistPC(aXP, aC1, aCriteria, aProjector, aYP, aT2P, aDmax, aT1max); |
1315 | if(iErr){ |
1316 | return iErr; |
1317 | } |
1318 | } |
1319 | else { |
1320 | aB=aXP; |
1321 | aXP=aXL; |
1322 | aYP=aYL; |
1323 | aXL=aB-(aB-aA)*aGS; |
1324 | iErr=DistPC(aXL, aC1, aCriteria, aProjector, aYL, aT2L, aDmax, aT1max); |
1325 | if(iErr){ |
1326 | return iErr; |
1327 | } |
1328 | } |
1329 | // |
1330 | if ((aB-aA)<aEps1) { |
1331 | aX0=0.5*(aA+aB); |
1332 | break; |
1333 | } |
1334 | }// while(1) { |
1335 | // |
1336 | return iErr; |
1337 | } |
1338 | //======================================================================= |
1339 | //function : DistPC |
1340 | //purpose : |
1341 | //======================================================================= |
1342 | Standard_Integer DistPC(const Standard_Real aT1, |
1343 | const Handle(Geom_Curve)& aC1, |
1344 | const Standard_Real aCriteria, |
1345 | GeomAPI_ProjectPointOnCurve& aProjector, |
1346 | Standard_Real& aD, |
1347 | Standard_Real& aT2, |
1348 | Standard_Real& aDmax, |
1349 | Standard_Real& aTmax) |
1350 | { |
1351 | Standard_Integer iErr; |
1352 | // |
1353 | iErr=DistPC(aT1, aC1, aCriteria, aProjector, aD, aT2); |
1354 | if (iErr) { |
1355 | return iErr; |
1356 | } |
1357 | // |
1358 | if (aD>aDmax) { |
1359 | aDmax=aD; |
1360 | aTmax=aT2; |
1361 | } |
1362 | // |
1363 | return iErr; |
1364 | } |
1365 | //======================================================================= |
1366 | //function : DistPC |
1367 | //purpose : |
1368 | //======================================================================= |
1369 | Standard_Integer DistPC(const Standard_Real aT1, |
1370 | const Handle(Geom_Curve)& aC1, |
1371 | const Standard_Real aCriteria, |
1372 | GeomAPI_ProjectPointOnCurve& aProjector, |
1373 | Standard_Real& aD, |
1374 | Standard_Real& aT2) |
1375 | { |
1376 | Standard_Integer iErr, aNbP2; |
1377 | gp_Pnt aP1; |
1378 | // |
1379 | iErr=0; |
1380 | aC1->D0(aT1, aP1); |
1381 | // |
1382 | aProjector.Perform(aP1); |
1383 | aNbP2=aProjector.NbPoints(); |
1384 | if (!aNbP2) { |
1385 | iErr=1;// the point from aC1 can not be projected on aC2 |
1386 | return iErr; |
1387 | } |
1388 | // |
1389 | aD=aProjector.LowerDistance(); |
1390 | aT2=aProjector.LowerDistanceParameter(); |
1391 | if (aD>aCriteria) { |
1392 | iErr=2;// the distance is too big |
1393 | } |
1394 | // |
1395 | return iErr; |
1396 | } |
1397 | //modified by NIZNHY-PKV Fri Oct 12 09:34:12 2012t |