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