ec0cdc0e |
1 | // Created by: Eugeny MALTCHIKOV |
d5f74e42 |
2 | // Copyright (c) 2013-2014 OPEN CASCADE SAS |
7fd59977 |
3 | // |
973c2be1 |
4 | // This file is part of Open CASCADE Technology software library. |
b311480e |
5 | // |
d5f74e42 |
6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
10 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
11 | // |
973c2be1 |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
b311480e |
14 | |
7fd59977 |
15 | |
ec0cdc0e |
16 | #include <Bnd_Box.hxx> |
17 | #include <BndLib_Add3dCurve.hxx> |
42cf5bc1 |
18 | #include <BOPCol_MapOfInteger.hxx> |
19 | #include <BRep_Tool.hxx> |
20 | #include <BRepAdaptor_Curve.hxx> |
21 | #include <ElCLib.hxx> |
a4e383e1 |
22 | #include <Geom_BezierCurve.hxx> |
23 | #include <Geom_BSplineCurve.hxx> |
e91a710c |
24 | #include <Geom_Line.hxx> |
42cf5bc1 |
25 | #include <Geom_Circle.hxx> |
26 | #include <Geom_Curve.hxx> |
27 | #include <Geom_Ellipse.hxx> |
e91a710c |
28 | #include <Geom_OffsetCurve.hxx> |
fa9681ca |
29 | #include <GeomAPI_ProjectPointOnCurve.hxx> |
42cf5bc1 |
30 | #include <gp_Dir.hxx> |
31 | #include <gp_Lin.hxx> |
ec0cdc0e |
32 | #include <IntTools_CommonPrt.hxx> |
42cf5bc1 |
33 | #include <IntTools_EdgeEdge.hxx> |
34 | #include <IntTools_Range.hxx> |
3510db62 |
35 | #include <IntTools_Tools.hxx> |
42cf5bc1 |
36 | #include <TopoDS_Edge.hxx> |
37 | #include <TopoDS_Iterator.hxx> |
6b1fe48c |
38 | |
ec0cdc0e |
39 | static |
40 | void BndBuildBox(const BRepAdaptor_Curve& theBAC, |
41 | const Standard_Real aT1, |
42 | const Standard_Real aT2, |
43 | const Standard_Real theTol, |
44 | Bnd_Box& theBox); |
6b1fe48c |
45 | static |
46 | Standard_Real PointBoxDistance(const Bnd_Box& aB, |
47 | const gp_Pnt& aP); |
ec0cdc0e |
48 | static |
bd28b2af |
49 | Standard_Integer SplitRangeOnSegments(const Standard_Real aT1, |
50 | const Standard_Real aT2, |
51 | const Standard_Real theResolution, |
52 | const Standard_Integer theNbSeg, |
53 | IntTools_SequenceOfRanges& theSegments); |
ec0cdc0e |
54 | static |
55 | Standard_Integer DistPC(const Standard_Real aT1, |
56 | const Handle(Geom_Curve)& theC1, |
57 | const Standard_Real theCriteria, |
58 | GeomAPI_ProjectPointOnCurve& theProjector, |
59 | Standard_Real& aD, |
60 | Standard_Real& aT2, |
61 | const Standard_Integer iC = 1); |
62 | static |
63 | Standard_Integer DistPC(const Standard_Real aT1, |
64 | const Handle(Geom_Curve)& theC1, |
65 | const Standard_Real theCriteria, |
66 | GeomAPI_ProjectPointOnCurve& theProjector, |
67 | Standard_Real& aD, |
68 | Standard_Real& aT2, |
69 | Standard_Real& aDmax, |
70 | Standard_Real& aT1max, |
71 | Standard_Real& aT2max, |
72 | const Standard_Integer iC = 1); |
73 | static |
74 | Standard_Integer FindDistPC(const Standard_Real aT1A, |
75 | const Standard_Real aT1B, |
76 | const Handle(Geom_Curve)& theC1, |
77 | const Standard_Real theCriteria, |
78 | const Standard_Real theEps, |
79 | GeomAPI_ProjectPointOnCurve& theProjector, |
80 | Standard_Real& aDmax, |
81 | Standard_Real& aT1max, |
82 | Standard_Real& aT2max, |
83 | const Standard_Boolean bMaxDist = Standard_True); |
a4e383e1 |
84 | static |
85 | Standard_Real ResolutionCoeff(const BRepAdaptor_Curve& theBAC, |
86 | const IntTools_Range& theRange); |
87 | static |
88 | Standard_Real Resolution(const Handle(Geom_Curve)& theCurve, |
89 | const GeomAbs_CurveType theCurveType, |
90 | const Standard_Real theResCoeff, |
91 | const Standard_Real theR3D); |
92 | static |
93 | Standard_Real CurveDeflection(const BRepAdaptor_Curve& theBAC, |
94 | const IntTools_Range& theRange); |
3e594885 |
95 | static |
dde68833 |
96 | Standard_Boolean IsClosed(const Handle(Geom_Curve)& theCurve, |
3e594885 |
97 | const Standard_Real aT1, |
98 | const Standard_Real aT2, |
99 | const Standard_Real theTol, |
100 | const Standard_Real theRes); |
ec0cdc0e |
101 | static |
102 | Standard_Integer TypeToInteger(const GeomAbs_CurveType theCType); |
7fd59977 |
103 | |
104 | //======================================================================= |
ec0cdc0e |
105 | //function : Prepare |
7fd59977 |
106 | //purpose : |
107 | //======================================================================= |
ec0cdc0e |
108 | void IntTools_EdgeEdge::Prepare() |
7fd59977 |
109 | { |
ec0cdc0e |
110 | GeomAbs_CurveType aCT1, aCT2; |
111 | Standard_Integer iCT1, iCT2; |
112 | // |
113 | myCurve1.Initialize(myEdge1); |
114 | myCurve2.Initialize(myEdge2); |
115 | // |
116 | if (myRange1.First() == 0. && myRange1.Last() == 0.) { |
117 | myRange1.SetFirst(myCurve1.FirstParameter()); |
118 | myRange1.SetLast (myCurve1.LastParameter()); |
119 | } |
120 | // |
121 | if (myRange2.First() == 0. && myRange2.Last() == 0.) { |
122 | myRange2.SetFirst(myCurve2.FirstParameter()); |
123 | myRange2.SetLast (myCurve2.LastParameter()); |
124 | } |
125 | // |
126 | aCT1 = myCurve1.GetType(); |
127 | aCT2 = myCurve2.GetType(); |
128 | // |
129 | iCT1 = TypeToInteger(aCT1); |
130 | iCT2 = TypeToInteger(aCT2); |
131 | // |
132 | if (iCT1 == iCT2) { |
133 | if (iCT1 != 0) { |
134 | //compute deflection |
a4e383e1 |
135 | Standard_Real aC1, aC2; |
ec0cdc0e |
136 | // |
a4e383e1 |
137 | aC2 = CurveDeflection(myCurve2, myRange2); |
138 | aC1 = (aC2 > Precision::Confusion()) ? |
139 | CurveDeflection(myCurve1, myRange1) : 1.; |
ec0cdc0e |
140 | // |
141 | if (aC1 < aC2) { |
142 | --iCT1; |
143 | } |
144 | } |
145 | } |
146 | // |
147 | if (iCT1 < iCT2) { |
148 | TopoDS_Edge tmpE = myEdge1; |
149 | myEdge1 = myEdge2; |
150 | myEdge2 = tmpE; |
151 | // |
152 | BRepAdaptor_Curve tmpC = myCurve1; |
153 | myCurve1 = myCurve2; |
154 | myCurve2 = tmpC; |
155 | // |
156 | IntTools_Range tmpR = myRange1; |
157 | myRange1 = myRange2; |
158 | myRange2 = tmpR; |
159 | // |
160 | mySwap = Standard_True; |
161 | } |
162 | // |
0d0481c7 |
163 | Standard_Real aTolAdd = myFuzzyValue / 2.; |
3510db62 |
164 | myTol1 = myCurve1.Tolerance() + aTolAdd; |
165 | myTol2 = myCurve2.Tolerance() + aTolAdd; |
ec0cdc0e |
166 | myTol = myTol1 + myTol2; |
167 | // |
ec0cdc0e |
168 | if (iCT1 != 0 || iCT2 != 0) { |
a743e2e5 |
169 | Standard_Real f, l, aTM; |
170 | // |
ec0cdc0e |
171 | myGeom1 = BRep_Tool::Curve(myEdge1, f, l); |
172 | myGeom2 = BRep_Tool::Curve(myEdge2, f, l); |
a743e2e5 |
173 | // |
a4e383e1 |
174 | myResCoeff1 = ResolutionCoeff(myCurve1, myRange1); |
175 | myResCoeff2 = ResolutionCoeff(myCurve2, myRange2); |
176 | // |
524a5f7a |
177 | myRes1 = Resolution(myCurve1.Curve().Curve(), myCurve1.GetType(), myResCoeff1, myTol1); |
178 | myRes2 = Resolution(myCurve2.Curve().Curve(), myCurve2.GetType(), myResCoeff2, myTol2); |
a4e383e1 |
179 | // |
a743e2e5 |
180 | myPTol1 = 5.e-13; |
181 | aTM = Max(fabs(myRange1.First()), fabs(myRange1.Last())); |
182 | if (aTM > 999.) { |
183 | myPTol1 = 5.e-16 * aTM; |
184 | } |
185 | // |
186 | myPTol2 = 5.e-13; |
187 | aTM = Max(fabs(myRange2.First()), fabs(myRange2.Last())); |
188 | if (aTM > 999.) { |
189 | myPTol2 = 5.e-16 * aTM; |
190 | } |
ec0cdc0e |
191 | } |
7fd59977 |
192 | } |
7fd59977 |
193 | |
7fd59977 |
194 | //======================================================================= |
195 | //function : Perform |
196 | //purpose : |
197 | //======================================================================= |
ec0cdc0e |
198 | void IntTools_EdgeEdge::Perform() |
7fd59977 |
199 | { |
ec0cdc0e |
200 | //1. Check data |
7fd59977 |
201 | CheckData(); |
7fd59977 |
202 | if (myErrorStatus) { |
203 | return; |
204 | } |
205 | // |
ec0cdc0e |
206 | //2. Prepare Data |
207 | Prepare(); |
f793011e |
208 | // |
ec0cdc0e |
209 | //3.1. Check Line/Line case |
210 | if (myCurve1.GetType() == GeomAbs_Line && |
211 | myCurve2.GetType() == GeomAbs_Line) { |
7fd59977 |
212 | ComputeLineLine(); |
7fd59977 |
213 | return; |
214 | } |
f793011e |
215 | // |
6dc83e21 |
216 | if (myQuickCoincidenceCheck) { |
217 | if (IsCoincident()) { |
218 | Standard_Real aT11, aT12, aT21, aT22; |
219 | // |
220 | myRange1.Range(aT11, aT12); |
221 | myRange2.Range(aT21, aT22); |
222 | AddSolution(aT11, aT12, aT21, aT22, TopAbs_EDGE); |
223 | return; |
224 | } |
225 | } |
226 | // |
6b1fe48c |
227 | IntTools_SequenceOfRanges aRanges1, aRanges2; |
228 | // |
a743e2e5 |
229 | //3.2. Find ranges containig solutions |
3e594885 |
230 | Standard_Boolean bSplit2; |
231 | FindSolutions(aRanges1, aRanges2, bSplit2); |
6b1fe48c |
232 | // |
a743e2e5 |
233 | //4. Merge solutions and save common parts |
3e594885 |
234 | MergeSolutions(aRanges1, aRanges2, bSplit2); |
235 | } |
236 | |
6dc83e21 |
237 | //======================================================================= |
238 | //function : IsCoincident |
239 | //purpose : |
240 | //======================================================================= |
241 | Standard_Boolean IntTools_EdgeEdge::IsCoincident() |
242 | { |
243 | Standard_Integer i, iCnt, aNbSeg, aNbP2; |
244 | Standard_Real dT, aT1, aCoeff, aTresh, aD; |
245 | Standard_Real aT11, aT12, aT21, aT22; |
246 | GeomAPI_ProjectPointOnCurve aProjPC; |
247 | gp_Pnt aP1; |
248 | // |
249 | aTresh=0.5; |
250 | aNbSeg=23; |
251 | myRange1.Range(aT11, aT12); |
252 | myRange2.Range(aT21, aT22); |
253 | // |
254 | aProjPC.Init(myGeom2, aT21, aT22); |
255 | // |
256 | dT=(aT12-aT11)/aNbSeg; |
257 | // |
258 | iCnt=0; |
259 | for(i=0; i <= aNbSeg; ++i) { |
260 | aT1 = aT11+i*dT; |
261 | myGeom1->D0(aT1, aP1); |
262 | // |
263 | aProjPC.Perform(aP1); |
264 | aNbP2=aProjPC.NbPoints(); |
265 | if (!aNbP2) { |
266 | continue; |
267 | } |
268 | // |
269 | aD=aProjPC.LowerDistance(); |
270 | if(aD < myTol) { |
271 | ++iCnt; |
272 | } |
273 | } |
274 | // |
275 | aCoeff=(Standard_Real)iCnt/((Standard_Real)aNbSeg+1); |
276 | return aCoeff > aTresh; |
277 | } |
3e594885 |
278 | //======================================================================= |
279 | //function : FindSolutions |
280 | //purpose : |
281 | //======================================================================= |
282 | void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1, |
283 | IntTools_SequenceOfRanges& theRanges2, |
284 | Standard_Boolean& bSplit2) |
285 | { |
286 | Standard_Boolean bIsClosed2; |
287 | Standard_Real aT11, aT12, aT21, aT22; |
288 | Bnd_Box aB2; |
289 | // |
290 | bSplit2 = Standard_False; |
291 | myRange1.Range(aT11, aT12); |
292 | myRange2.Range(aT21, aT22); |
293 | // |
294 | bIsClosed2 = IsClosed(myGeom2, aT21, aT22, myTol2, myRes2); |
295 | // |
296 | if (bIsClosed2) { |
297 | Bnd_Box aB1; |
298 | BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1); |
299 | // |
300 | gp_Pnt aP = myGeom2->Value(aT21); |
301 | bIsClosed2 = !aB1.IsOut(aP); |
302 | } |
303 | // |
304 | if (!bIsClosed2) { |
305 | BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2); |
306 | FindSolutions(myRange1, myRange2, aB2, theRanges1, theRanges2); |
307 | return; |
308 | } |
309 | // |
524a5f7a |
310 | if (!CheckCoincidence(aT11, aT12, aT21, aT22, myTol, myRes1)) { |
311 | theRanges1.Append(myRange1); |
312 | theRanges2.Append(myRange2); |
313 | return; |
314 | } |
315 | // |
3e594885 |
316 | Standard_Integer i, j, aNb1, aNb2; |
317 | IntTools_SequenceOfRanges aSegments1, aSegments2; |
318 | // |
319 | aNb1 = IsClosed(myGeom1, aT11, aT12, myTol1, myRes1) ? 2 : 1; |
320 | aNb2 = 2; |
321 | // |
bd28b2af |
322 | aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, aNb1, aSegments1); |
323 | aNb2 = SplitRangeOnSegments(aT21, aT22, myRes2, aNb2, aSegments2); |
3e594885 |
324 | // |
3e594885 |
325 | for (i = 1; i <= aNb1; ++i) { |
326 | const IntTools_Range& aR1 = aSegments1(i); |
327 | for (j = 1; j <= aNb2; ++j) { |
328 | const IntTools_Range& aR2 = aSegments2(j); |
329 | BndBuildBox(myCurve2, aR2.First(), aR2.Last(), myTol2, aB2); |
330 | FindSolutions(aR1, aR2, aB2, theRanges1, theRanges2); |
331 | } |
332 | } |
333 | // |
334 | bSplit2 = aNb2 > 1; |
0d19eb34 |
335 | } |
336 | |
337 | //======================================================================= |
338 | //function : FindSolutions |
339 | //purpose : |
340 | //======================================================================= |
341 | void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1, |
342 | const IntTools_Range& theR2, |
3e594885 |
343 | const Bnd_Box& theBox2, |
344 | IntTools_SequenceOfRanges& theRanges1, |
0d19eb34 |
345 | IntTools_SequenceOfRanges& theRanges2) |
346 | { |
ec0cdc0e |
347 | Standard_Boolean bOut, bStop, bThin; |
0d19eb34 |
348 | Standard_Real aT11, aT12, aT21, aT22; |
349 | Standard_Real aTB11, aTB12, aTB21, aTB22; |
524a5f7a |
350 | Standard_Real aSmallStep1, aSmallStep2; |
ec0cdc0e |
351 | Standard_Integer iCom; |
0d19eb34 |
352 | Bnd_Box aB1, aB2; |
353 | // |
354 | theR1.Range(aT11, aT12); |
355 | theR2.Range(aT21, aT22); |
a743e2e5 |
356 | // |
3e594885 |
357 | aB2 = theBox2; |
f793011e |
358 | // |
ec0cdc0e |
359 | bThin = Standard_False; |
360 | bStop = Standard_False; |
ec0cdc0e |
361 | iCom = 1; |
362 | // |
363 | do { |
a4e383e1 |
364 | aTB11 = aT11; |
365 | aTB12 = aT12; |
366 | aTB21 = aT21; |
367 | aTB22 = aT22; |
368 | // |
369 | //1. Build box for first edge and find parameters |
370 | // of the second one in that box |
371 | BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1); |
372 | bOut = aB1.IsOut(aB2); |
ec0cdc0e |
373 | if (bOut) { |
374 | break; |
375 | } |
f793011e |
376 | // |
a4e383e1 |
377 | bThin = ((aT12 - aT11) < myRes1) || |
524a5f7a |
378 | (aB1.IsXThin(myTol) && aB1.IsYThin(myTol) && aB1.IsZThin(myTol)); |
a4e383e1 |
379 | // |
3510db62 |
380 | bOut = !FindParameters(myCurve2, aTB21, aTB22, myTol2, myRes2, myPTol2, |
a4e383e1 |
381 | myResCoeff2, aB1, aT21, aT22); |
382 | if (bOut || bThin) { |
0d19eb34 |
383 | break; |
384 | } |
385 | // |
a4e383e1 |
386 | //2. Build box for second edge and find parameters |
387 | // of the first one in that box |
388 | BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2); |
389 | bOut = aB1.IsOut(aB2); |
0d19eb34 |
390 | if (bOut) { |
391 | break; |
392 | } |
393 | // |
524a5f7a |
394 | bThin = ((aT22 - aT21) < myRes2) || |
395 | (aB2.IsXThin(myTol) && aB2.IsYThin(myTol) && aB2.IsZThin(myTol)); |
0d19eb34 |
396 | // |
3510db62 |
397 | bOut = !FindParameters(myCurve1, aTB11, aTB12, myTol1, myRes1, myPTol1, |
a4e383e1 |
398 | myResCoeff1, aB2, aT11, aT12); |
399 | // |
400 | if (bOut || bThin) { |
401 | break; |
7fd59977 |
402 | } |
ec0cdc0e |
403 | // |
a4e383e1 |
404 | //3. Check if it makes sense to continue |
405 | aSmallStep1 = (aTB12 - aTB11) / 250.; |
406 | aSmallStep2 = (aTB22 - aTB21) / 250.; |
407 | // |
408 | if (aSmallStep1 < myRes1) { |
409 | aSmallStep1 = myRes1; |
410 | } |
411 | if (aSmallStep2 < myRes2) { |
412 | aSmallStep2 = myRes2; |
413 | } |
414 | // |
415 | if (((aT11 - aTB11) < aSmallStep1) && ((aTB12 - aT12) < aSmallStep1) && |
416 | ((aT21 - aTB21) < aSmallStep2) && ((aTB22 - aT22) < aSmallStep2)) { |
417 | bStop = Standard_True; |
418 | } |
419 | // |
420 | } while (!bStop); |
ec0cdc0e |
421 | // |
422 | if (bOut) { |
423 | //no intersection; |
424 | return; |
7fd59977 |
425 | } |
f793011e |
426 | // |
ec0cdc0e |
427 | if (!bThin) { |
428 | //check curves for coincidence on the ranges |
429 | iCom = CheckCoincidence(aT11, aT12, aT21, aT22, myTol, myRes1); |
430 | if (!iCom) { |
431 | bThin = Standard_True; |
a4e383e1 |
432 | } |
7fd59977 |
433 | } |
434 | // |
ec0cdc0e |
435 | if (bThin) { |
436 | if (iCom != 0) { |
437 | //check intermediate points |
524a5f7a |
438 | Standard_Boolean bSol; |
439 | Standard_Real aT1; |
440 | gp_Pnt aP1; |
441 | GeomAPI_ProjectPointOnCurve aProjPC; |
f793011e |
442 | // |
3e594885 |
443 | aT1 = (aT11 + aT12) * .5; |
6b1fe48c |
444 | myGeom1->D0(aT1, aP1); |
f793011e |
445 | // |
524a5f7a |
446 | aProjPC.Init(myGeom2, aT21, aT22); |
447 | aProjPC.Perform(aP1); |
448 | // |
449 | if (aProjPC.NbPoints()) { |
450 | bSol = aProjPC.LowerDistance() <= myTol; |
451 | } |
452 | else { |
453 | Standard_Real aT2; |
454 | gp_Pnt aP2; |
455 | // |
456 | aT2 = (aT21 + aT22) * .5; |
457 | myGeom2->D0(aT2, aP2); |
458 | // |
459 | bSol = aP1.IsEqual(aP2, myTol); |
460 | } |
461 | // |
462 | if (!bSol) { |
ec0cdc0e |
463 | return; |
7fd59977 |
464 | } |
465 | } |
ec0cdc0e |
466 | //add common part |
467 | IntTools_Range aR1(aT11, aT12), aR2(aT21, aT22); |
468 | // |
469 | theRanges1.Append(aR1); |
470 | theRanges2.Append(aR2); |
471 | return; |
7fd59977 |
472 | } |
f793011e |
473 | // |
ec0cdc0e |
474 | if (!IsIntersection(aT11, aT12, aT21, aT22)) { |
475 | return; |
7fd59977 |
476 | } |
f793011e |
477 | // |
ec0cdc0e |
478 | //split ranges on segments and repeat |
479 | Standard_Integer i, aNb1; |
480 | IntTools_SequenceOfRanges aSegments1; |
481 | // |
482 | IntTools_Range aR2(aT21, aT22); |
3e594885 |
483 | BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2); |
0d19eb34 |
484 | // |
bd28b2af |
485 | aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, 3, aSegments1); |
ec0cdc0e |
486 | for (i = 1; i <= aNb1; ++i) { |
487 | const IntTools_Range& aR1 = aSegments1(i); |
3e594885 |
488 | FindSolutions(aR1, aR2, aB2, theRanges1, theRanges2); |
7fd59977 |
489 | } |
7fd59977 |
490 | } |
ec0cdc0e |
491 | |
7fd59977 |
492 | //======================================================================= |
ec0cdc0e |
493 | //function : FindParameters |
7fd59977 |
494 | //purpose : |
495 | //======================================================================= |
ec0cdc0e |
496 | Standard_Boolean IntTools_EdgeEdge::FindParameters(const BRepAdaptor_Curve& theBAC, |
497 | const Standard_Real aT1, |
3510db62 |
498 | const Standard_Real aT2, |
499 | const Standard_Real theTol, |
ec0cdc0e |
500 | const Standard_Real theRes, |
a743e2e5 |
501 | const Standard_Real thePTol, |
a4e383e1 |
502 | const Standard_Real theResCoeff, |
ec0cdc0e |
503 | const Bnd_Box& theCBox, |
504 | Standard_Real& aTB1, |
505 | Standard_Real& aTB2) |
7fd59977 |
506 | { |
ec0cdc0e |
507 | Standard_Boolean bRet; |
508 | Standard_Integer aC, i, k; |
6b1fe48c |
509 | Standard_Real aCf, aDiff, aDt, aT, aTB, aTOut, aTIn; |
3510db62 |
510 | Standard_Real aDist, aDistP, aDistTol; |
ec0cdc0e |
511 | gp_Pnt aP; |
512 | Bnd_Box aCBx; |
7fd59977 |
513 | // |
ec0cdc0e |
514 | bRet = Standard_False; |
515 | aCf = 0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))/2.; |
516 | aDt = theRes; |
ec0cdc0e |
517 | aDistP = 0.; |
3510db62 |
518 | aDistTol = 1e-9; |
ec0cdc0e |
519 | aCBx = theCBox; |
3510db62 |
520 | aCBx.Enlarge(theTol); |
7fd59977 |
521 | // |
a4e383e1 |
522 | const Handle(Geom_Curve)& aCurve = theBAC.Curve().Curve(); |
523 | const GeomAbs_CurveType aCurveType = theBAC.GetType(); |
524 | // |
ec0cdc0e |
525 | for (i = 0; i < 2; ++i) { |
526 | aTB = !i ? aT1 : aT2; |
527 | aT = !i ? aT2 : aTB1; |
528 | aC = !i ? 1 : -1; |
529 | bRet = Standard_False; |
530 | k = 0; |
531 | //looking for the point on the edge which is in the box; |
532 | while (aC*(aT-aTB) >= 0) { |
6b1fe48c |
533 | theBAC.D0(aTB, aP); |
534 | aDist = PointBoxDistance(theCBox, aP); |
3510db62 |
535 | if (aDist > theTol) { |
6b1fe48c |
536 | if (fabs(aDist - aDistP) < aDistTol) { |
a4e383e1 |
537 | aDt = Resolution(aCurve, aCurveType, theResCoeff, (++k)*aDist); |
6b1fe48c |
538 | } else { |
539 | k = 0; |
a4e383e1 |
540 | aDt = Resolution(aCurve, aCurveType, theResCoeff, aDist); |
6b1fe48c |
541 | } |
ec0cdc0e |
542 | aTB += aC*aDt; |
543 | } else { |
544 | bRet = Standard_True; |
545 | break; |
546 | } |
547 | aDistP = aDist; |
548 | } |
549 | // |
550 | if (!bRet) { |
551 | if (!i) { |
552 | //edge is out of the box; |
553 | return bRet; |
554 | } else { |
555 | bRet = !bRet; |
556 | aTB = aTB1; |
557 | aDt = aT2 - aTB1; |
558 | } |
559 | } |
560 | // |
561 | aT = !i ? aT1 : aT2; |
562 | if (aTB != aT) { |
563 | //one point IN, one point OUT; looking for the bounding point; |
564 | aTIn = aTB; |
565 | aTOut = aTB - aC*aDt; |
566 | aDiff = aTIn - aTOut; |
a743e2e5 |
567 | while (fabs(aDiff) > thePTol) { |
ec0cdc0e |
568 | aTB = aTOut + aDiff*aCf; |
6b1fe48c |
569 | theBAC.D0(aTB, aP); |
ec0cdc0e |
570 | if (aCBx.IsOut(aP)) { |
571 | aTOut = aTB; |
572 | } else { |
573 | aTIn = aTB; |
574 | } |
575 | aDiff = aTIn - aTOut; |
576 | } |
577 | } |
578 | if (!i) { |
579 | aTB1 = aTB; |
580 | } else { |
581 | aTB2 = aTB; |
7fd59977 |
582 | } |
583 | } |
ec0cdc0e |
584 | return bRet; |
7fd59977 |
585 | } |
586 | |
587 | //======================================================================= |
ec0cdc0e |
588 | //function : MergeSolutions |
7fd59977 |
589 | //purpose : |
590 | //======================================================================= |
ec0cdc0e |
591 | void IntTools_EdgeEdge::MergeSolutions(const IntTools_SequenceOfRanges& theRanges1, |
3e594885 |
592 | const IntTools_SequenceOfRanges& theRanges2, |
593 | const Standard_Boolean bSplit2) |
7fd59977 |
594 | { |
3e594885 |
595 | Standard_Integer aNbCP = theRanges1.Length(); |
596 | if (aNbCP == 0) { |
597 | return; |
598 | } |
599 | // |
ec0cdc0e |
600 | IntTools_Range aRi1, aRi2, aRj1, aRj2; |
524a5f7a |
601 | Standard_Boolean bCond; |
3e594885 |
602 | Standard_Integer i, j; |
ec0cdc0e |
603 | TopAbs_ShapeEnum aType; |
524a5f7a |
604 | Standard_Real aT11, aT12, aT21, aT22; |
605 | Standard_Real aTi11, aTi12, aTi21, aTi22; |
606 | Standard_Real aTj11, aTj12, aTj21, aTj22; |
607 | Standard_Real aRes1, aRes2, dTR1, dTR2; |
3e594885 |
608 | BOPCol_MapOfInteger aMI; |
ec0cdc0e |
609 | // |
524a5f7a |
610 | aRes1 = Resolution(myCurve1.Curve().Curve(), |
611 | myCurve1.GetType(), myResCoeff1, myTol); |
612 | aRes2 = Resolution(myCurve2.Curve().Curve(), |
613 | myCurve2.GetType(), myResCoeff2, myTol); |
614 | // |
615 | myRange1.Range(aT11, aT12); |
616 | myRange2.Range(aT21, aT22); |
617 | dTR1 = 20*aRes1; |
618 | dTR2 = 20*aRes2; |
ec0cdc0e |
619 | aType = TopAbs_VERTEX; |
620 | // |
3e594885 |
621 | for (i = 1; i <= aNbCP;) { |
622 | if (aMI.Contains(i)) { |
623 | ++i; |
624 | continue; |
625 | } |
626 | // |
ec0cdc0e |
627 | aRi1 = theRanges1(i); |
628 | aRi2 = theRanges2(i); |
629 | // |
630 | aRi1.Range(aTi11, aTi12); |
631 | aRi2.Range(aTi21, aTi22); |
632 | // |
3e594885 |
633 | aMI.Add(i); |
634 | // |
ec0cdc0e |
635 | for (j = i+1; j <= aNbCP; ++j) { |
3e594885 |
636 | if (aMI.Contains(j)) { |
637 | continue; |
638 | } |
639 | // |
ec0cdc0e |
640 | aRj1 = theRanges1(j); |
641 | aRj2 = theRanges2(j); |
642 | // |
643 | aRj1.Range(aTj11, aTj12); |
644 | aRj2.Range(aTj21, aTj22); |
524a5f7a |
645 | // |
646 | bCond = (fabs(aTi12 - aTj11) < dTR1) || |
647 | (bSplit2 && (fabs(aTj12 - aTi11) < dTR1)); |
648 | if (bCond && bSplit2) { |
649 | bCond = (fabs((Max(aTi22, aTj22) - Min(aTi21, aTj21)) - |
650 | ((aTi22 - aTi21) + (aTj22 - aTj21))) < dTR2); |
651 | } |
652 | // |
653 | if (bCond) { |
ec0cdc0e |
654 | aTi11 = Min(aTi11, aTj11); |
655 | aTi12 = Max(aTi12, aTj12); |
656 | aTi21 = Min(aTi21, aTj21); |
657 | aTi22 = Max(aTi22, aTj22); |
3e594885 |
658 | aMI.Add(j); |
659 | } |
660 | else if (!bSplit2) { |
661 | i = j; |
ec0cdc0e |
662 | break; |
7fd59977 |
663 | } |
664 | } |
ec0cdc0e |
665 | // |
524a5f7a |
666 | if (((fabs(aT11 - aTi11) < myRes1) && (fabs(aT12 - aTi12) < myRes1)) || |
667 | ((fabs(aT21 - aTi21) < myRes2) && (fabs(aT22 - aTi22) < myRes2))) { |
ec0cdc0e |
668 | aType = TopAbs_EDGE; |
3e594885 |
669 | myCommonParts.Clear(); |
ec0cdc0e |
670 | } |
671 | // |
672 | AddSolution(aTi11, aTi12, aTi21, aTi22, aType); |
3e594885 |
673 | if (aType == TopAbs_EDGE) { |
674 | break; |
675 | } |
676 | // |
677 | if (bSplit2) { |
678 | ++i; |
679 | } |
7fd59977 |
680 | } |
7fd59977 |
681 | } |
682 | |
683 | //======================================================================= |
ec0cdc0e |
684 | //function : AddSolution |
7fd59977 |
685 | //purpose : |
686 | //======================================================================= |
ec0cdc0e |
687 | void IntTools_EdgeEdge::AddSolution(const Standard_Real aT11, |
688 | const Standard_Real aT12, |
689 | const Standard_Real aT21, |
690 | const Standard_Real aT22, |
691 | const TopAbs_ShapeEnum theType) |
7fd59977 |
692 | { |
ec0cdc0e |
693 | IntTools_CommonPrt aCPart; |
694 | // |
695 | aCPart.SetType(theType); |
696 | if (!mySwap) { |
697 | aCPart.SetEdge1(myEdge1); |
698 | aCPart.SetEdge2(myEdge2); |
699 | aCPart.SetRange1(aT11, aT12); |
700 | aCPart.AppendRange2(aT21, aT22); |
701 | } else { |
702 | aCPart.SetEdge1(myEdge2); |
703 | aCPart.SetEdge2(myEdge1); |
704 | aCPart.SetRange1(aT21, aT22); |
705 | aCPart.AppendRange2(aT11, aT12); |
0d19eb34 |
706 | } |
ec0cdc0e |
707 | // |
708 | if (theType == TopAbs_VERTEX) { |
709 | Standard_Real aT1, aT2; |
710 | // |
711 | FindBestSolution(aT11, aT12, aT21, aT22, aT1, aT2); |
712 | // |
713 | if (!mySwap) { |
714 | aCPart.SetVertexParameter1(aT1); |
715 | aCPart.SetVertexParameter2(aT2); |
716 | } else { |
717 | aCPart.SetVertexParameter1(aT2); |
718 | aCPart.SetVertexParameter2(aT1); |
719 | } |
720 | } |
721 | myCommonParts.Append(aCPart); |
7fd59977 |
722 | } |
723 | |
7fd59977 |
724 | //======================================================================= |
ec0cdc0e |
725 | //function : FindBestSolution |
726 | //purpose : |
7fd59977 |
727 | //======================================================================= |
ec0cdc0e |
728 | void IntTools_EdgeEdge::FindBestSolution(const Standard_Real aT11, |
729 | const Standard_Real aT12, |
730 | const Standard_Real aT21, |
731 | const Standard_Real aT22, |
732 | Standard_Real& aT1, |
733 | Standard_Real& aT2) |
7fd59977 |
734 | { |
0d19eb34 |
735 | Standard_Integer i, aNbS, iErr; |
bd28b2af |
736 | Standard_Real aDMin, aD, aRes1, aSolCriteria, aTouchCriteria; |
737 | Standard_Real aT1A, aT1B, aT1Min, aT2Min; |
738 | Standard_Real aT1Im, aT2Im, aT1Touch; |
739 | GeomAPI_ProjectPointOnCurve aProjPC; |
740 | IntTools_SequenceOfRanges aRanges; |
741 | Standard_Boolean bTouch; |
0d19eb34 |
742 | // |
bd28b2af |
743 | aDMin = Precision::Infinite(); |
744 | aSolCriteria = 5.e-16; |
745 | aTouchCriteria = 5.e-13; |
746 | bTouch = Standard_False; |
747 | aT1Touch = aT11; |
ec0cdc0e |
748 | // |
524a5f7a |
749 | aRes1 = Resolution(myCurve1.Curve().Curve(), |
750 | myCurve1.GetType(), myResCoeff1, myTol); |
0d19eb34 |
751 | aNbS = 10; |
bd28b2af |
752 | aNbS = SplitRangeOnSegments(aT11, aT12, 3*aRes1, aNbS, aRanges); |
753 | // |
754 | aProjPC.Init(myGeom2, aT21, aT22); |
755 | // |
756 | aT1 = (aT11 + aT12) * 0.5; |
757 | iErr = DistPC(aT1, myGeom1, aSolCriteria, aProjPC, aD, aT2, -1); |
758 | if (iErr == 1) { |
759 | aT2 = (aT21 + aT22) * 0.5; |
760 | } |
761 | // |
762 | aT1Im = aT1; |
763 | aT2Im = aT2; |
0d19eb34 |
764 | // |
0d19eb34 |
765 | for (i = 1; i <= aNbS; ++i) { |
bd28b2af |
766 | const IntTools_Range& aR1 = aRanges(i); |
767 | aR1.Range(aT1A, aT1B); |
0d19eb34 |
768 | // |
bd28b2af |
769 | aD = myTol; |
770 | iErr = FindDistPC(aT1A, aT1B, myGeom1, aSolCriteria, myPTol1, |
771 | aProjPC, aD, aT1Min, aT2Min, Standard_False); |
772 | if (iErr != 1) { |
773 | if (aD < aDMin) { |
774 | aT1 = aT1Min; |
775 | aT2 = aT2Min; |
776 | aDMin = aD; |
777 | } |
778 | // |
779 | if (aD < aTouchCriteria) { |
780 | if (bTouch) { |
781 | aT1A = (aT1Touch + aT1Min) * 0.5; |
782 | iErr = DistPC(aT1A, myGeom1, aTouchCriteria, |
783 | aProjPC, aD, aT2Min, -1); |
784 | if (aD > aTouchCriteria) { |
785 | aT1 = aT1Im; |
786 | aT2 = aT2Im; |
787 | break; |
788 | } |
789 | } |
790 | else { |
791 | aT1Touch = aT1Min; |
792 | bTouch = Standard_True; |
793 | } |
7fd59977 |
794 | } |
795 | } |
7fd59977 |
796 | } |
797 | } |
798 | |
799 | //======================================================================= |
ec0cdc0e |
800 | //function : ComputeLineLine |
7fd59977 |
801 | //purpose : |
802 | //======================================================================= |
ec0cdc0e |
803 | void IntTools_EdgeEdge::ComputeLineLine() |
7fd59977 |
804 | { |
ec0cdc0e |
805 | Standard_Boolean IsParallel, IsCoincide; |
806 | Standard_Real aSin, aCos, aAng, aTol; |
807 | Standard_Real aT1, aT2, aT11, aT12, aT21, aT22; |
808 | gp_Pnt aP11, aP12; |
809 | gp_Lin aL1, aL2; |
810 | gp_Dir aD1, aD2; |
811 | IntTools_CommonPrt aCommonPrt; |
7fd59977 |
812 | // |
ec0cdc0e |
813 | IsParallel = Standard_False; |
814 | IsCoincide = Standard_False; |
815 | aTol = myTol*myTol; |
816 | aL1 = myCurve1.Line(); |
817 | aL2 = myCurve2.Line(); |
818 | aD1 = aL1.Position().Direction(); |
819 | aD2 = aL2.Position().Direction(); |
820 | myRange1.Range(aT11, aT12); |
821 | myRange2.Range(aT21, aT22); |
7fd59977 |
822 | // |
ec0cdc0e |
823 | aCommonPrt.SetEdge1(myEdge1); |
824 | aCommonPrt.SetEdge2(myEdge2); |
7fd59977 |
825 | // |
ec0cdc0e |
826 | aCos = aD1.Dot(aD2); |
827 | aAng = (aCos >= 0.) ? 2.*(1. - aCos) : 2.*(1. + aCos); |
7fd59977 |
828 | // |
ec0cdc0e |
829 | if(aAng <= Precision::Angular()) { |
830 | IsParallel = Standard_True; |
831 | if(aL1.SquareDistance(aL2.Location()) <= aTol) { |
832 | IsCoincide = Standard_True; |
833 | aP11 = ElCLib::Value(aT11, aL1); |
834 | aP12 = ElCLib::Value(aT12, aL1); |
7fd59977 |
835 | } |
7fd59977 |
836 | } |
ec0cdc0e |
837 | else { |
838 | aP11 = ElCLib::Value(aT11, aL1); |
839 | aP12 = ElCLib::Value(aT12, aL1); |
840 | if(aL2.SquareDistance(aP11) <= aTol && aL2.SquareDistance(aP12) <= aTol) { |
841 | IsCoincide = Standard_True; |
7fd59977 |
842 | } |
843 | } |
844 | // |
ec0cdc0e |
845 | if (IsCoincide) { |
846 | Standard_Real t21, t22; |
847 | // |
848 | t21 = ElCLib::Parameter(aL2, aP11); |
849 | t22 = ElCLib::Parameter(aL2, aP12); |
850 | if((t21 > aT22 && t22 > aT22) || (t21 < aT21 && t22 < aT21)) { |
851 | return; |
7fd59977 |
852 | } |
ec0cdc0e |
853 | // |
854 | Standard_Real temp; |
855 | if(t21 > t22) { |
856 | temp = t21; |
857 | t21 = t22; |
858 | t22 = temp; |
7fd59977 |
859 | } |
ec0cdc0e |
860 | // |
861 | if(t21 >= aT21) { |
862 | if(t22 <= aT22) { |
863 | aCommonPrt.SetRange1(aT11, aT12); |
864 | aCommonPrt.SetAllNullFlag(Standard_True); |
865 | aCommonPrt.AppendRange2(t21, t22); |
866 | } |
867 | else { |
868 | aCommonPrt.SetRange1(aT11, aT12 - (t22 - aT22)); |
869 | aCommonPrt.AppendRange2(t21, aT22); |
870 | } |
7fd59977 |
871 | } |
ec0cdc0e |
872 | else { |
873 | aCommonPrt.SetRange1(aT11 + (aT21 - t21), aT12); |
874 | aCommonPrt.AppendRange2(aT21, t22); |
7fd59977 |
875 | } |
ec0cdc0e |
876 | aCommonPrt.SetType(TopAbs_EDGE); |
877 | myCommonParts.Append(aCommonPrt); |
878 | return; |
879 | } |
880 | // |
881 | if (IsParallel) { |
882 | return; |
883 | } |
884 | // |
885 | { |
886 | TopoDS_Iterator aIt1, aIt2; |
887 | aIt1.Initialize(myEdge1); |
888 | for (; aIt1.More(); aIt1.Next()) { |
889 | const TopoDS_Shape& aV1 = aIt1.Value(); |
890 | aIt2.Initialize(myEdge2); |
891 | for (; aIt2.More(); aIt2.Next()) { |
892 | const TopoDS_Shape& aV2 = aIt2.Value(); |
893 | if (aV2.IsSame(aV1)) { |
894 | return; |
895 | } |
896 | } |
7fd59977 |
897 | } |
7fd59977 |
898 | } |
ec0cdc0e |
899 | // |
900 | aSin = 1. - aCos*aCos; |
901 | gp_Pnt O1 = aL1.Location(); |
902 | gp_Pnt O2 = aL2.Location(); |
903 | gp_Vec O1O2 (O1, O2); |
904 | // |
905 | aT2 = (aD1.XYZ()*(O1O2.Dot(aD1))-(O1O2.XYZ())).Dot(aD2.XYZ()); |
906 | aT2 /= aSin; |
907 | // |
908 | if(aT2 < aT21 || aT2 > aT22) { |
909 | return; |
910 | } |
911 | // |
912 | gp_Pnt aP2(ElCLib::Value(aT2, aL2)); |
913 | aT1 = (gp_Vec(O1, aP2)).Dot(aD1); |
914 | // |
915 | if(aT1 < aT11 || aT1 > aT12) { |
916 | return; |
917 | } |
918 | // |
919 | gp_Pnt aP1(ElCLib::Value(aT1, aL1)); |
920 | Standard_Real aDist = aP1.SquareDistance(aP2); |
921 | // |
922 | if (aDist > aTol) { |
923 | return; |
924 | } |
925 | // |
3510db62 |
926 | // compute correct range on the edges |
927 | Standard_Real anAngle, aDt1, aDt2; |
928 | // |
929 | anAngle = aD1.Angle(aD2); |
930 | // |
931 | aDt1 = IntTools_Tools::ComputeIntRange(myTol1, myTol2, anAngle); |
932 | aDt2 = IntTools_Tools::ComputeIntRange(myTol2, myTol1, anAngle); |
933 | // |
934 | aCommonPrt.SetRange1(aT1 - aDt1, aT1 + aDt1); |
935 | aCommonPrt.AppendRange2(aT2 - aDt2, aT2 + aDt2); |
ec0cdc0e |
936 | aCommonPrt.SetType(TopAbs_VERTEX); |
937 | aCommonPrt.SetVertexParameter1(aT1); |
938 | aCommonPrt.SetVertexParameter2(aT2); |
939 | myCommonParts.Append(aCommonPrt); |
7fd59977 |
940 | } |
ec0cdc0e |
941 | |
7fd59977 |
942 | //======================================================================= |
ec0cdc0e |
943 | //function : IsIntersection |
7fd59977 |
944 | //purpose : |
945 | //======================================================================= |
ec0cdc0e |
946 | Standard_Boolean IntTools_EdgeEdge::IsIntersection(const Standard_Real aT11, |
947 | const Standard_Real aT12, |
948 | const Standard_Real aT21, |
949 | const Standard_Real aT22) |
7fd59977 |
950 | { |
ec0cdc0e |
951 | Standard_Boolean bRet; |
952 | gp_Pnt aP11, aP12, aP21, aP22; |
953 | gp_Vec aV11, aV12, aV21, aV22; |
954 | Standard_Real aD11_21, aD11_22, aD12_21, aD12_22, aCriteria, aCoef; |
955 | Standard_Boolean bSmall_11_21, bSmall_11_22, bSmall_12_21, bSmall_12_22; |
956 | // |
957 | bRet = Standard_True; |
958 | aCoef = 1.e+5; |
959 | if (((aT12 - aT11) > aCoef*myRes1) && ((aT22 - aT21) > aCoef*myRes2)) { |
960 | aCoef = 5000; |
961 | } else { |
962 | Standard_Real aTRMin = Min((aT12 - aT11)/myRes1, (aT22 - aT21)/myRes2); |
963 | aCoef = aTRMin / 100.; |
964 | if (aCoef < 1.) { |
965 | aCoef = 1.; |
7fd59977 |
966 | } |
967 | } |
ec0cdc0e |
968 | aCriteria = aCoef * myTol; |
969 | aCriteria *= aCriteria; |
7fd59977 |
970 | // |
ec0cdc0e |
971 | myGeom1->D1(aT11, aP11, aV11); |
972 | myGeom1->D1(aT12, aP12, aV12); |
973 | myGeom2->D1(aT21, aP21, aV21); |
974 | myGeom2->D1(aT22, aP22, aV22); |
975 | // |
976 | aD11_21 = aP11.SquareDistance(aP21); |
977 | aD11_22 = aP11.SquareDistance(aP22); |
978 | aD12_21 = aP12.SquareDistance(aP21); |
979 | aD12_22 = aP12.SquareDistance(aP22); |
980 | // |
981 | bSmall_11_21 = aD11_21 < aCriteria; |
982 | bSmall_11_22 = aD11_22 < aCriteria; |
983 | bSmall_12_21 = aD12_21 < aCriteria; |
984 | bSmall_12_22 = aD12_22 < aCriteria; |
985 | // |
986 | if ((bSmall_11_21 && bSmall_12_22) || |
987 | (bSmall_11_22 && bSmall_12_21)) { |
988 | if (aCoef == 1.) { |
989 | return bRet; |
7fd59977 |
990 | } |
ec0cdc0e |
991 | // |
992 | Standard_Real anAngleCriteria; |
993 | Standard_Real anAngle1, anAngle2; |
994 | // |
995 | anAngleCriteria = 5.e-3; |
996 | if (bSmall_11_21 && bSmall_12_22) { |
997 | anAngle1 = aV11.Angle(aV21); |
998 | anAngle2 = aV12.Angle(aV22); |
999 | } else { |
1000 | anAngle1 = aV11.Angle(aV22); |
1001 | anAngle2 = aV12.Angle(aV21); |
7fd59977 |
1002 | } |
ec0cdc0e |
1003 | // |
1004 | if (((anAngle1 < anAngleCriteria) || ((M_PI - anAngle1) < anAngleCriteria)) || |
1005 | ((anAngle2 < anAngleCriteria) || ((M_PI - anAngle2) < anAngleCriteria))) { |
bd28b2af |
1006 | GeomAPI_ProjectPointOnCurve aProjPC; |
ec0cdc0e |
1007 | Standard_Integer iErr; |
bd28b2af |
1008 | Standard_Real aD, aT1Min, aT2Min; |
ec0cdc0e |
1009 | // |
bd28b2af |
1010 | aD = Precision::Infinite(); |
1011 | aProjPC.Init(myGeom2, aT21, aT22); |
1012 | iErr = FindDistPC(aT11, aT12, myGeom1, myTol, myRes1, |
1013 | aProjPC, aD, aT1Min, aT2Min, Standard_False); |
ec0cdc0e |
1014 | bRet = (iErr == 2); |
7fd59977 |
1015 | } |
7fd59977 |
1016 | } |
ec0cdc0e |
1017 | return bRet; |
7fd59977 |
1018 | } |
1019 | |
1020 | //======================================================================= |
ec0cdc0e |
1021 | //function : CheckCoincidence |
7fd59977 |
1022 | //purpose : |
1023 | //======================================================================= |
ec0cdc0e |
1024 | Standard_Integer IntTools_EdgeEdge::CheckCoincidence(const Standard_Real aT11, |
1025 | const Standard_Real aT12, |
1026 | const Standard_Real aT21, |
1027 | const Standard_Real aT22, |
1028 | const Standard_Real theCriteria, |
0d19eb34 |
1029 | const Standard_Real theCurveRes1) |
7fd59977 |
1030 | { |
6b1fe48c |
1031 | Standard_Integer iErr, aNb, aNb1, i; |
0d19eb34 |
1032 | Standard_Real aT1A, aT1B, aT1max, aT2max, aDmax; |
ec0cdc0e |
1033 | GeomAPI_ProjectPointOnCurve aProjPC; |
bd28b2af |
1034 | IntTools_SequenceOfRanges aRanges; |
ec0cdc0e |
1035 | // |
1036 | iErr = 0; |
1037 | aDmax = -1.; |
1038 | aProjPC.Init(myGeom2, aT21, aT22); |
1039 | // |
1040 | // 1. Express evaluation |
1041 | aNb = 10; // Number of intervals on the curve #1 |
bd28b2af |
1042 | aNb1 = SplitRangeOnSegments(aT11, aT12, theCurveRes1, aNb, aRanges); |
6b1fe48c |
1043 | for (i = 1; i < aNb1; ++i) { |
bd28b2af |
1044 | const IntTools_Range& aR1 = aRanges(i); |
0d19eb34 |
1045 | aR1.Range(aT1A, aT1B); |
ec0cdc0e |
1046 | // |
0d19eb34 |
1047 | iErr = DistPC(aT1B, myGeom1, theCriteria, aProjPC, aDmax, aT2max); |
ec0cdc0e |
1048 | if (iErr) { |
1049 | return iErr; |
7fd59977 |
1050 | } |
1051 | } |
ec0cdc0e |
1052 | // |
bd28b2af |
1053 | // if the ranges in aRanges are less than theCurveRes1, |
0d19eb34 |
1054 | // there is no need to do step 2 (deep evaluation) |
6b1fe48c |
1055 | if (aNb1 < aNb) { |
0d19eb34 |
1056 | return iErr; |
1057 | } |
1058 | // |
ec0cdc0e |
1059 | // 2. Deep evaluation |
6b1fe48c |
1060 | for (i = 2; i < aNb1; ++i) { |
bd28b2af |
1061 | const IntTools_Range& aR1 = aRanges(i); |
0d19eb34 |
1062 | aR1.Range(aT1A, aT1B); |
ec0cdc0e |
1063 | // |
0d19eb34 |
1064 | iErr = FindDistPC(aT1A, aT1B, myGeom1, theCriteria, theCurveRes1, |
ec0cdc0e |
1065 | aProjPC, aDmax, aT1max, aT2max); |
1066 | if (iErr) { |
1067 | return iErr; |
7fd59977 |
1068 | } |
7fd59977 |
1069 | } |
ec0cdc0e |
1070 | // Possible values: |
1071 | // iErr == 0 - the patches are coincided |
1072 | // iErr == 1 - a point from aC1 can not be projected on aC2 |
1073 | // iErr == 2 - the distance is too big |
1074 | return iErr; |
7fd59977 |
1075 | } |
ec0cdc0e |
1076 | |
7fd59977 |
1077 | //======================================================================= |
ec0cdc0e |
1078 | //function : FindDistPC |
7fd59977 |
1079 | //purpose : |
1080 | //======================================================================= |
ec0cdc0e |
1081 | Standard_Integer FindDistPC(const Standard_Real aT1A, |
1082 | const Standard_Real aT1B, |
1083 | const Handle(Geom_Curve)& theC1, |
1084 | const Standard_Real theCriteria, |
1085 | const Standard_Real theEps, |
1086 | GeomAPI_ProjectPointOnCurve& theProjPC, |
1087 | Standard_Real& aDmax, |
1088 | Standard_Real& aT1max, |
1089 | Standard_Real& aT2max, |
1090 | const Standard_Boolean bMaxDist) |
7fd59977 |
1091 | { |
ec0cdc0e |
1092 | Standard_Integer iErr, iC; |
1093 | Standard_Real aGS, aXP, aA, aB, aXL, aYP, aYL, aT2P, aT2L; |
1094 | // |
1095 | iC = bMaxDist ? 1 : -1; |
1096 | iErr = 0; |
04e93070 |
1097 | aT1max = aT2max = 0.; // silence GCC warning |
ec0cdc0e |
1098 | // |
1099 | aGS = 0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))-1.; |
1100 | aA = aT1A; |
1101 | aB = aT1B; |
1102 | // |
1103 | // check bounds |
bd28b2af |
1104 | iErr = DistPC(aA, theC1, theCriteria, theProjPC, |
1105 | aYP, aT2P, aDmax, aT1max, aT2max, iC); |
ec0cdc0e |
1106 | if (iErr == 2) { |
1107 | return iErr; |
7fd59977 |
1108 | } |
ec0cdc0e |
1109 | // |
bd28b2af |
1110 | iErr = DistPC(aB, theC1, theCriteria, theProjPC, |
1111 | aYL, aT2L, aDmax, aT1max, aT2max, iC); |
ec0cdc0e |
1112 | if (iErr == 2) { |
1113 | return iErr; |
7fd59977 |
1114 | } |
ec0cdc0e |
1115 | // |
1116 | aXP = aA + (aB - aA)*aGS; |
1117 | aXL = aB - (aB - aA)*aGS; |
1118 | // |
bd28b2af |
1119 | iErr = DistPC(aXP, theC1, theCriteria, theProjPC, |
1120 | aYP, aT2P, aDmax, aT1max, aT2max, iC); |
ec0cdc0e |
1121 | if (iErr) { |
1122 | return iErr; |
7fd59977 |
1123 | } |
ec0cdc0e |
1124 | // |
bd28b2af |
1125 | iErr = DistPC(aXL, theC1, theCriteria, theProjPC, |
1126 | aYL, aT2L, aDmax, aT1max, aT2max, iC); |
ec0cdc0e |
1127 | if (iErr) { |
1128 | return iErr; |
7fd59977 |
1129 | } |
7fd59977 |
1130 | // |
ec0cdc0e |
1131 | for (;;) { |
1132 | if (iC*(aYP - aYL) > 0) { |
1133 | aA = aXL; |
1134 | aXL = aXP; |
1135 | aYL = aYP; |
1136 | aXP = aA + (aB - aA)*aGS; |
bd28b2af |
1137 | iErr = DistPC(aXP, theC1, theCriteria, theProjPC, |
1138 | aYP, aT2P, aDmax, aT1max, aT2max, iC); |
ec0cdc0e |
1139 | } |
1140 | else { |
1141 | aB = aXP; |
1142 | aXP = aXL; |
1143 | aYP = aYL; |
1144 | aXL = aB - (aB - aA)*aGS; |
bd28b2af |
1145 | iErr = DistPC(aXL, theC1, theCriteria, theProjPC, |
1146 | aYL, aT2L, aDmax, aT1max, aT2max, iC); |
1147 | } |
1148 | // |
1149 | if (iErr) { |
1150 | if ((iErr == 2) && !bMaxDist) { |
1151 | aXP = (aA + aB) * 0.5; |
1152 | DistPC(aXP, theC1, theCriteria, theProjPC, |
1153 | aYP, aT2P, aDmax, aT1max, aT2max, iC); |
ec0cdc0e |
1154 | } |
bd28b2af |
1155 | return iErr; |
7fd59977 |
1156 | } |
ec0cdc0e |
1157 | // |
1158 | if ((aB - aA) < theEps) { |
1159 | break; |
7fd59977 |
1160 | } |
ec0cdc0e |
1161 | }// for (;;) { |
7fd59977 |
1162 | // |
ec0cdc0e |
1163 | return iErr; |
7fd59977 |
1164 | } |
7fd59977 |
1165 | //======================================================================= |
ec0cdc0e |
1166 | //function : DistPC |
1167 | //purpose : |
7fd59977 |
1168 | //======================================================================= |
ec0cdc0e |
1169 | Standard_Integer DistPC(const Standard_Real aT1, |
1170 | const Handle(Geom_Curve)& theC1, |
1171 | const Standard_Real theCriteria, |
1172 | GeomAPI_ProjectPointOnCurve& theProjPC, |
1173 | Standard_Real& aD, |
1174 | Standard_Real& aT2, |
1175 | Standard_Real& aDmax, |
1176 | Standard_Real& aT1max, |
1177 | Standard_Real& aT2max, |
1178 | const Standard_Integer iC) |
7fd59977 |
1179 | { |
ec0cdc0e |
1180 | Standard_Integer iErr; |
7fd59977 |
1181 | // |
ec0cdc0e |
1182 | iErr = DistPC(aT1, theC1, theCriteria, theProjPC, aD, aT2, iC); |
bd28b2af |
1183 | if (iErr == 1) { |
ec0cdc0e |
1184 | return iErr; |
7fd59977 |
1185 | } |
1186 | // |
ec0cdc0e |
1187 | if (iC*(aD - aDmax) > 0) { |
1188 | aDmax = aD; |
1189 | aT1max = aT1; |
1190 | aT2max = aT2; |
7fd59977 |
1191 | } |
1192 | // |
ec0cdc0e |
1193 | return iErr; |
1194 | } |
1195 | //======================================================================= |
1196 | //function : DistPC |
1197 | //purpose : |
1198 | //======================================================================= |
1199 | Standard_Integer DistPC(const Standard_Real aT1, |
1200 | const Handle(Geom_Curve)& theC1, |
1201 | const Standard_Real theCriteria, |
1202 | GeomAPI_ProjectPointOnCurve& theProjPC, |
1203 | Standard_Real& aD, |
1204 | Standard_Real& aT2, |
1205 | const Standard_Integer iC) |
1206 | { |
1207 | Standard_Integer iErr, aNbP2; |
1208 | gp_Pnt aP1; |
1209 | // |
1210 | iErr = 0; |
1211 | theC1->D0(aT1, aP1); |
1212 | // |
1213 | theProjPC.Perform(aP1); |
1214 | aNbP2 = theProjPC.NbPoints(); |
1215 | if (!aNbP2) { |
1216 | iErr = 1;// the point from aC1 can not be projected on aC2 |
1217 | return iErr; |
7fd59977 |
1218 | } |
1219 | // |
ec0cdc0e |
1220 | aD = theProjPC.LowerDistance(); |
1221 | aT2 = theProjPC.LowerDistanceParameter(); |
1222 | if (iC*(aD - theCriteria) > 0) { |
1223 | iErr = 2;// the distance is too big or small |
7fd59977 |
1224 | } |
1225 | // |
ec0cdc0e |
1226 | return iErr; |
7fd59977 |
1227 | } |
ec0cdc0e |
1228 | |
7fd59977 |
1229 | //======================================================================= |
ec0cdc0e |
1230 | //function : SplitRangeOnSegments |
7fd59977 |
1231 | //purpose : |
1232 | //======================================================================= |
bd28b2af |
1233 | Standard_Integer SplitRangeOnSegments(const Standard_Real aT1, |
1234 | const Standard_Real aT2, |
1235 | const Standard_Real theResolution, |
1236 | const Standard_Integer theNbSeg, |
1237 | IntTools_SequenceOfRanges& theSegments) |
7fd59977 |
1238 | { |
6b1fe48c |
1239 | Standard_Real aDiff = aT2 - aT1; |
a4e383e1 |
1240 | if (aDiff < theResolution || theNbSeg == 1) { |
0d19eb34 |
1241 | theSegments.Append(IntTools_Range(aT1, aT2)); |
bd28b2af |
1242 | return 1; |
0d19eb34 |
1243 | } |
1244 | // |
ec0cdc0e |
1245 | Standard_Real aDt, aT1x, aT2x, aSeg; |
1246 | Standard_Integer aNbSegments, i; |
1247 | // |
1248 | aNbSegments = theNbSeg; |
6b1fe48c |
1249 | aDt = aDiff / aNbSegments; |
ec0cdc0e |
1250 | if (aDt < theResolution) { |
6b1fe48c |
1251 | aSeg = aDiff / theResolution; |
0d19eb34 |
1252 | aNbSegments = Standard_Integer(aSeg) + 1; |
6b1fe48c |
1253 | aDt = aDiff / aNbSegments; |
7fd59977 |
1254 | } |
ec0cdc0e |
1255 | // |
ec0cdc0e |
1256 | aT1x = aT1; |
6b1fe48c |
1257 | for (i = 1; i < aNbSegments; ++i) { |
ec0cdc0e |
1258 | aT2x = aT1x + aDt; |
ec0cdc0e |
1259 | // |
1260 | IntTools_Range aR(aT1x, aT2x); |
1261 | theSegments.Append(aR); |
1262 | // |
1263 | aT1x = aT2x; |
7fd59977 |
1264 | } |
0d19eb34 |
1265 | // |
6b1fe48c |
1266 | IntTools_Range aR(aT1x, aT2); |
1267 | theSegments.Append(aR); |
bd28b2af |
1268 | // |
1269 | return aNbSegments; |
ec0cdc0e |
1270 | } |
7fd59977 |
1271 | |
ec0cdc0e |
1272 | //======================================================================= |
1273 | //function : BndBuildBox |
1274 | //purpose : |
1275 | //======================================================================= |
1276 | void BndBuildBox(const BRepAdaptor_Curve& theBAC, |
1277 | const Standard_Real aT1, |
1278 | const Standard_Real aT2, |
1279 | const Standard_Real theTol, |
1280 | Bnd_Box& theBox) |
1281 | { |
1282 | Bnd_Box aB; |
1283 | BndLib_Add3dCurve::Add(theBAC, aT1, aT2, theTol, aB); |
1284 | theBox = aB; |
1285 | } |
7fd59977 |
1286 | |
6b1fe48c |
1287 | //======================================================================= |
1288 | //function : PointBoxDistance |
1289 | //purpose : |
1290 | //======================================================================= |
1291 | Standard_Real PointBoxDistance(const Bnd_Box& aB, |
1292 | const gp_Pnt& aP) |
1293 | { |
1294 | Standard_Real aPCoord[3]; |
1295 | Standard_Real aBMinCoord[3], aBMaxCoord[3]; |
1296 | Standard_Real aDist, aR1, aR2; |
1297 | Standard_Integer i; |
1298 | // |
1299 | aP.Coord(aPCoord[0], aPCoord[1], aPCoord[2]); |
1300 | aB.Get(aBMinCoord[0], aBMinCoord[1], aBMinCoord[2], |
1301 | aBMaxCoord[0], aBMaxCoord[1], aBMaxCoord[2]); |
1302 | // |
1303 | aDist = 0.; |
1304 | for (i = 0; i < 3; ++i) { |
1305 | aR1 = aBMinCoord[i] - aPCoord[i]; |
1306 | if (aR1 > 0.) { |
1307 | aDist += aR1*aR1; |
1308 | continue; |
1309 | } |
1310 | // |
1311 | aR2 = aPCoord[i] - aBMaxCoord[i]; |
1312 | if (aR2 > 0.) { |
1313 | aDist += aR2*aR2; |
1314 | } |
1315 | } |
1316 | // |
1317 | aDist = Sqrt(aDist); |
1318 | return aDist; |
1319 | } |
1320 | |
ec0cdc0e |
1321 | //======================================================================= |
1322 | //function : TypeToInteger |
1323 | //purpose : |
1324 | //======================================================================= |
1325 | Standard_Integer TypeToInteger(const GeomAbs_CurveType theCType) |
1326 | { |
1327 | Standard_Integer iRet; |
bd05fabf |
1328 | // |
ec0cdc0e |
1329 | switch(theCType) { |
1330 | case GeomAbs_Line: |
1331 | iRet=0; |
1332 | break; |
ec0cdc0e |
1333 | case GeomAbs_Hyperbola: |
1334 | case GeomAbs_Parabola: |
3e594885 |
1335 | iRet=1; |
1336 | break; |
1337 | case GeomAbs_Circle: |
1338 | case GeomAbs_Ellipse: |
ec0cdc0e |
1339 | iRet=2; |
1340 | break; |
1341 | case GeomAbs_BezierCurve: |
1342 | case GeomAbs_BSplineCurve: |
1343 | iRet=3; |
1344 | break; |
1345 | default: |
1346 | iRet=4; |
1347 | break; |
1348 | } |
1349 | return iRet; |
7fd59977 |
1350 | } |
ec0cdc0e |
1351 | |
a4e383e1 |
1352 | //======================================================================= |
1353 | //function : ResolutionCoeff |
1354 | //purpose : |
1355 | //======================================================================= |
1356 | Standard_Real ResolutionCoeff(const BRepAdaptor_Curve& theBAC, |
1357 | const IntTools_Range& theRange) |
1358 | { |
e91a710c |
1359 | Standard_Real aResCoeff = 0.; |
a4e383e1 |
1360 | // |
1361 | const Handle(Geom_Curve)& aCurve = theBAC.Curve().Curve(); |
1362 | const GeomAbs_CurveType aCurveType = theBAC.GetType(); |
1363 | // |
1364 | switch (aCurveType) { |
1365 | case GeomAbs_Circle : |
c5f3a425 |
1366 | aResCoeff = 1. / (2 * Handle(Geom_Circle)::DownCast (aCurve)->Circ().Radius()); |
a4e383e1 |
1367 | break; |
1368 | case GeomAbs_Ellipse : |
c5f3a425 |
1369 | aResCoeff = 1. / Handle(Geom_Ellipse)::DownCast (aCurve)->MajorRadius(); |
a4e383e1 |
1370 | break; |
e91a710c |
1371 | case GeomAbs_OffsetCurve : { |
1372 | const Handle(Geom_OffsetCurve)& anOffsetCurve = Handle(Geom_OffsetCurve)::DownCast(aCurve); |
1373 | const Handle(Geom_Curve)& aBasisCurve = anOffsetCurve->BasisCurve(); |
a318d719 |
1374 | GeomAdaptor_Curve aGBasisCurve(aBasisCurve); |
1375 | const GeomAbs_CurveType aBCType = aGBasisCurve.GetType(); |
e91a710c |
1376 | if (aBCType == GeomAbs_Line) { |
1377 | break; |
1378 | } |
1379 | else if (aBCType == GeomAbs_Circle) { |
a318d719 |
1380 | aResCoeff = 1. / (2 * (anOffsetCurve->Offset() + aGBasisCurve.Circle().Radius())); |
e91a710c |
1381 | break; |
1382 | } |
1383 | else if (aBCType == GeomAbs_Ellipse) { |
a318d719 |
1384 | aResCoeff = 1. / (anOffsetCurve->Offset() + aGBasisCurve.Ellipse().MajorRadius()); |
e91a710c |
1385 | break; |
1386 | } |
1387 | } |
a4e383e1 |
1388 | case GeomAbs_Hyperbola : |
1389 | case GeomAbs_Parabola : |
1390 | case GeomAbs_OtherCurve :{ |
1391 | Standard_Real k, kMin, aDist, aDt, aT1, aT2, aT; |
1392 | Standard_Integer aNbP, i; |
1393 | gp_Pnt aP1, aP2; |
1394 | // |
1395 | aNbP = 30; |
1396 | theRange.Range(aT1, aT2); |
1397 | aDt = (aT2 - aT1) / aNbP; |
1398 | aT = aT1; |
1399 | kMin = 10.; |
1400 | // |
1401 | theBAC.D0(aT1, aP1); |
1402 | for (i = 1; i <= aNbP; ++i) { |
1403 | aT += aDt; |
1404 | theBAC.D0(aT, aP2); |
1405 | aDist = aP1.Distance(aP2); |
1406 | k = aDt / aDist; |
1407 | if (k < kMin) { |
1408 | kMin = k; |
1409 | } |
1410 | aP1 = aP2; |
1411 | } |
1412 | // |
1413 | aResCoeff = kMin; |
1414 | break; |
1415 | } |
1416 | default: |
a4e383e1 |
1417 | break; |
1418 | } |
1419 | // |
1420 | return aResCoeff; |
1421 | } |
1422 | |
1423 | //======================================================================= |
1424 | //function : Resolution |
1425 | //purpose : |
1426 | //======================================================================= |
1427 | Standard_Real Resolution(const Handle(Geom_Curve)& theCurve, |
1428 | const GeomAbs_CurveType theCurveType, |
1429 | const Standard_Real theResCoeff, |
1430 | const Standard_Real theR3D) |
1431 | { |
1432 | Standard_Real aRes; |
1433 | // |
1434 | switch (theCurveType) { |
1435 | case GeomAbs_Line : |
1436 | aRes = theR3D; |
1437 | break; |
1438 | case GeomAbs_Circle: { |
1439 | Standard_Real aDt = theResCoeff * theR3D; |
1440 | aRes = (aDt <= 1.) ? 2*ASin(aDt) : 2*M_PI; |
1441 | break; |
1442 | } |
1443 | case GeomAbs_BezierCurve: |
c5f3a425 |
1444 | Handle(Geom_BezierCurve)::DownCast (theCurve)->Resolution(theR3D, aRes); |
a4e383e1 |
1445 | break; |
1446 | case GeomAbs_BSplineCurve: |
c5f3a425 |
1447 | Handle(Geom_BSplineCurve)::DownCast (theCurve)->Resolution(theR3D, aRes); |
a4e383e1 |
1448 | break; |
e91a710c |
1449 | case GeomAbs_OffsetCurve: { |
1450 | const Handle(Geom_Curve)& aBasisCurve = |
1451 | Handle(Geom_OffsetCurve)::DownCast(theCurve)->BasisCurve(); |
1452 | const GeomAbs_CurveType aBCType = GeomAdaptor_Curve(aBasisCurve).GetType(); |
1453 | if (aBCType == GeomAbs_Line) { |
1454 | aRes = theR3D; |
1455 | break; |
1456 | } |
1457 | else if (aBCType == GeomAbs_Circle) { |
1458 | Standard_Real aDt = theResCoeff * theR3D; |
1459 | aRes = (aDt <= 1.) ? 2*ASin(aDt) : 2*M_PI; |
1460 | break; |
1461 | } |
1462 | } |
a4e383e1 |
1463 | default: |
1464 | aRes = theResCoeff * theR3D; |
1465 | break; |
1466 | } |
1467 | // |
1468 | return aRes; |
1469 | } |
1470 | |
1471 | //======================================================================= |
1472 | //function : CurveDeflection |
1473 | //purpose : |
1474 | //======================================================================= |
1475 | Standard_Real CurveDeflection(const BRepAdaptor_Curve& theBAC, |
1476 | const IntTools_Range& theRange) |
1477 | { |
1478 | Standard_Real aDt, aT, aT1, aT2, aDefl; |
1479 | Standard_Integer i, aNbP; |
1480 | gp_Vec aV1, aV2; |
1481 | gp_Pnt aP; |
1482 | // |
1483 | aDefl = 0; |
1484 | aNbP = 10; |
1485 | theRange.Range(aT1, aT2); |
1486 | aDt = (aT2 - aT1) / aNbP; |
1487 | aT = aT1; |
1488 | // |
1489 | theBAC.D1(aT1, aP, aV1); |
1490 | for (i = 1; i <= aNbP; ++i) { |
1491 | aT += aDt; |
1492 | theBAC.D1(aT, aP, aV2); |
1493 | if (aV1.Magnitude() > gp::Resolution() && |
1494 | aV2.Magnitude() > gp::Resolution()) { |
1495 | gp_Dir aD1(aV1), aD2(aV2); |
1496 | aDefl += aD1.Angle(aD2); |
1497 | } |
1498 | aV1 = aV2; |
1499 | } |
1500 | // |
1501 | return aDefl; |
1502 | } |
1503 | |
3e594885 |
1504 | //======================================================================= |
1505 | //function : IsClosed |
1506 | //purpose : |
1507 | //======================================================================= |
dde68833 |
1508 | Standard_Boolean IsClosed(const Handle(Geom_Curve)& theCurve, |
3e594885 |
1509 | const Standard_Real aT1, |
1510 | const Standard_Real aT2, |
1511 | const Standard_Real theTol, |
1512 | const Standard_Real theRes) |
1513 | { |
dde68833 |
1514 | if (Abs(aT1 - aT2) < theRes) |
1515 | { |
1516 | return Standard_False; |
3e594885 |
1517 | } |
dde68833 |
1518 | |
1519 | gp_Pnt aP1, aP2; |
3e594885 |
1520 | theCurve->D0(aT1, aP1); |
1521 | theCurve->D0(aT2, aP2); |
1522 | // |
dde68833 |
1523 | Standard_Real aD = aP1.Distance(aP2); |
1524 | return aD < theTol; |
3e594885 |
1525 | } |