0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / IntTools / IntTools_FaceFace.cxx
1 // Created on: 2000-11-23
2 // Created by: Michael KLOKOV
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <IntTools_FaceFace.ixx>
17
18 #include <Precision.hxx>
19
20 #include <TColStd_HArray1OfReal.hxx>
21 #include <TColStd_Array1OfReal.hxx>
22 #include <TColStd_Array1OfInteger.hxx>
23 #include <TColStd_SequenceOfReal.hxx>
24 #include <TColStd_ListOfInteger.hxx>
25 #include <TColStd_ListIteratorOfListOfInteger.hxx>
26 #include <TColStd_Array1OfListOfInteger.hxx>
27
28 #include <gp_Lin2d.hxx>
29 #include <gp_Ax22d.hxx>
30 #include <gp_Circ2d.hxx>
31 #include <gp_Torus.hxx>
32 #include <gp_Cylinder.hxx>
33
34 #include <Bnd_Box.hxx>
35
36 #include <TColgp_HArray1OfPnt2d.hxx>
37 #include <TColgp_SequenceOfPnt2d.hxx>
38 #include <TColgp_Array1OfPnt.hxx>
39 #include <TColgp_Array1OfPnt2d.hxx>
40
41 #include <IntAna_QuadQuadGeo.hxx>
42
43 #include <IntSurf_PntOn2S.hxx>
44 #include <IntSurf_LineOn2S.hxx>
45 #include <IntSurf_PntOn2S.hxx>
46 #include <IntSurf_ListOfPntOn2S.hxx>
47 #include <IntRes2d_Domain.hxx>
48 #include <ProjLib_Plane.hxx>
49
50 #include <IntPatch_GLine.hxx>
51 #include <IntPatch_RLine.hxx>
52 #include <IntPatch_WLine.hxx>
53 #include <IntPatch_ALine.hxx>
54 #include <IntPatch_ALineToWLine.hxx>
55
56 #include <ElSLib.hxx>
57 #include <ElCLib.hxx>
58
59 #include <Extrema_ExtCC.hxx>
60 #include <Extrema_POnCurv.hxx>
61 #include <BndLib_AddSurface.hxx>
62
63 #include <Adaptor3d_SurfacePtr.hxx>
64 #include <Adaptor2d_HLine2d.hxx>
65
66 #include <GeomAbs_SurfaceType.hxx>
67 #include <GeomAbs_CurveType.hxx>
68
69 #include <Geom_Surface.hxx>
70 #include <Geom_Line.hxx>
71 #include <Geom_Circle.hxx>
72 #include <Geom_Ellipse.hxx>
73 #include <Geom_Parabola.hxx>
74 #include <Geom_Hyperbola.hxx>
75 #include <Geom_TrimmedCurve.hxx>
76 #include <Geom_BSplineCurve.hxx>
77 #include <Geom_RectangularTrimmedSurface.hxx>
78 #include <Geom_OffsetSurface.hxx>
79 #include <Geom_Curve.hxx>
80 #include <Geom_Conic.hxx>
81
82 #include <Geom2d_TrimmedCurve.hxx>
83 #include <Geom2d_BSplineCurve.hxx>
84 #include <Geom2d_Line.hxx>
85 #include <Geom2d_Curve.hxx>
86 #include <Geom2d_Circle.hxx>
87
88 #include <Geom2dAPI_InterCurveCurve.hxx>
89 #include <Geom2dInt_GInter.hxx>
90 #include <Geom2dAdaptor.hxx>
91 #include <GeomAdaptor_Curve.hxx>
92 #include <GeomAdaptor_HSurface.hxx>
93 #include <GeomAdaptor_Surface.hxx>
94 #include <GeomLib_CheckBSplineCurve.hxx>
95 #include <GeomLib_Check2dBSplineCurve.hxx>
96
97 #include <GeomInt_WLApprox.hxx>
98 #include <GeomProjLib.hxx>
99 #include <GeomAPI_ProjectPointOnSurf.hxx>
100 #include <Geom2dAdaptor_Curve.hxx>
101 #include <TopoDS.hxx>
102 #include <TopoDS_Edge.hxx>
103 #include <TopExp_Explorer.hxx>
104
105 #include <BRep_Tool.hxx>
106 #include <BRepTools.hxx>
107 #include <BRepAdaptor_Surface.hxx>
108
109 #include <IntTools_Curve.hxx>
110 #include <IntTools_Tools.hxx>
111 #include <IntTools_Tools.hxx>
112 #include <IntTools_TopolTool.hxx>
113 #include <IntTools_PntOnFace.hxx>
114 #include <IntTools_PntOn2Faces.hxx>
115 #include <IntTools_Context.hxx>
116 #include <IntSurf_ListIteratorOfListOfPntOn2S.hxx>
117 #include <GeomInt.hxx>
118
119 #include <Approx_CurveOnSurface.hxx>
120 #include <GeomAdaptor.hxx>
121 #include <GeomInt_IntSS.hxx>
122
123 static
124   void RefineVector(gp_Vec2d& aV2D);
125 #ifdef OCCT_DEBUG_DUMPWLINE
126 static
127   void DumpWLine(const Handle(IntPatch_WLine)& aWLine);
128 #endif
129 //
130 static
131   void TolR3d(const TopoDS_Face& ,
132               const TopoDS_Face& ,
133               Standard_Real& );
134 static 
135   Handle(Geom_Curve) MakeBSpline (const Handle(IntPatch_WLine)&,
136                                   const Standard_Integer,
137                                   const Standard_Integer);
138
139 static 
140   void Parameters(const Handle(GeomAdaptor_HSurface)&,
141                   const Handle(GeomAdaptor_HSurface)&,
142                   const gp_Pnt&,
143                   Standard_Real&,
144                   Standard_Real&,
145                   Standard_Real&,
146                   Standard_Real&);
147
148 static 
149   void CorrectSurfaceBoundaries(const TopoDS_Face&  theFace,
150                                 const Standard_Real theTolerance,
151                                 Standard_Real&      theumin,
152                                 Standard_Real&      theumax, 
153                                 Standard_Real&      thevmin, 
154                                 Standard_Real&      thevmax);
155
156 static
157   Standard_Boolean NotUseSurfacesForApprox
158           (const TopoDS_Face& aF1,
159            const TopoDS_Face& aF2,
160            const Handle(IntPatch_WLine)& WL,
161            const Standard_Integer ifprm,
162            const Standard_Integer ilprm);
163
164 static 
165   Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine)& theWLine);
166
167 static 
168   Handle(Geom2d_BSplineCurve) MakeBSpline2d(const Handle(IntPatch_WLine)& theWLine,
169                                             const Standard_Integer                         ideb,
170                                             const Standard_Integer                         ifin,
171                                             const Standard_Boolean                         onFirst);
172
173 static 
174   Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
175                                         const Handle(GeomAdaptor_HSurface)&            theSurface1, 
176                                         const Handle(GeomAdaptor_HSurface)&            theSurface2,
177                                         const TopoDS_Face&                             theFace1,
178                                         const TopoDS_Face&                             theFace2,
179                                         const GeomInt_LineConstructor&                 theLConstructor,
180                                         const Standard_Boolean                         theAvoidLConstructor,
181                                         IntPatch_SequenceOfLine&                       theNewLines,
182                                         Standard_Real&                                 theReachedTol3d,
183                                         const Handle(IntTools_Context)& );
184
185 static 
186   Standard_Boolean ParameterOutOfBoundary(const Standard_Real       theParameter, 
187                                           const Handle(Geom_Curve)& theCurve, 
188                                           const TopoDS_Face&        theFace1, 
189                                           const TopoDS_Face&        theFace2,
190                                           const Standard_Real       theOtherParameter,
191                                           const Standard_Boolean    bIncreasePar,
192                                           Standard_Real&            theNewParameter,
193                                           const Handle(IntTools_Context)& );
194
195 static 
196   Standard_Boolean IsCurveValid(Handle(Geom2d_Curve)& thePCurve);
197
198 static 
199   Standard_Boolean IsPointOnBoundary(const Standard_Real theParameter,
200                                      const Standard_Real theFirstBoundary,
201                                      const Standard_Real theSecondBoundary,
202                                      const Standard_Real theResolution,
203                                      Standard_Boolean&   IsOnFirstBoundary);
204 static
205   Standard_Boolean FindPoint(const gp_Pnt2d&     theFirstPoint,
206                              const gp_Pnt2d&     theLastPoint,
207                              const Standard_Real theUmin, 
208                              const Standard_Real theUmax,
209                              const Standard_Real theVmin,
210                              const Standard_Real theVmax,
211                              gp_Pnt2d&           theNewPoint);
212
213
214 static 
215   Standard_Integer ComputeTangentZones( const Handle(GeomAdaptor_HSurface)& theSurface1,
216                                        const Handle(GeomAdaptor_HSurface)&  theSurface2,
217                                        const TopoDS_Face&                   theFace1,
218                                        const TopoDS_Face&                   theFace2,
219                                        Handle(TColgp_HArray1OfPnt2d)&       theResultOnS1,
220                                        Handle(TColgp_HArray1OfPnt2d)&       theResultOnS2,
221                                        Handle(TColStd_HArray1OfReal)&       theResultRadius,
222                                        const Handle(IntTools_Context)& );
223
224 static
225   Standard_Boolean FindPoint(const gp_Pnt2d&     theFirstPoint,
226                              const gp_Pnt2d&     theLastPoint,
227                              const Standard_Real theUmin, 
228                              const Standard_Real theUmax,
229                              const Standard_Real theVmin,
230                              const Standard_Real theVmax,
231                              const gp_Pnt2d&     theTanZoneCenter,
232                              const Standard_Real theZoneRadius,
233                              Handle(GeomAdaptor_HSurface) theGASurface,
234                              gp_Pnt2d&           theNewPoint);
235
236 static
237   Standard_Boolean IsInsideTanZone(const gp_Pnt2d&     thePoint,
238                                    const gp_Pnt2d&     theTanZoneCenter,
239                                    const Standard_Real theZoneRadius,
240                                    Handle(GeomAdaptor_HSurface) theGASurface);
241
242 static
243   gp_Pnt2d AdjustByNeighbour(const gp_Pnt2d&     theaNeighbourPoint,
244                              const gp_Pnt2d&     theOriginalPoint,
245                              Handle(GeomAdaptor_HSurface) theGASurface);
246 static
247   Standard_Boolean  ApproxWithPCurves(const gp_Cylinder& theCyl, 
248                                       const gp_Sphere& theSph);
249
250 static void  PerformPlanes(const Handle(GeomAdaptor_HSurface)& theS1, 
251                            const Handle(GeomAdaptor_HSurface)& theS2, 
252                            const Standard_Real TolAng, 
253                            const Standard_Real TolTang, 
254                            const Standard_Boolean theApprox1,
255                            const Standard_Boolean theApprox2,
256                            IntTools_SequenceOfCurves& theSeqOfCurve, 
257                            Standard_Boolean& theTangentFaces);
258
259 static Standard_Boolean ClassifyLin2d(const Handle(GeomAdaptor_HSurface)& theS, 
260                                       const gp_Lin2d& theLin2d, 
261                                       const Standard_Real theTol,
262                                       Standard_Real& theP1, 
263                                       Standard_Real& theP2);
264 //
265 static
266   void ApproxParameters(const Handle(GeomAdaptor_HSurface)& aHS1,
267                         const Handle(GeomAdaptor_HSurface)& aHS2,
268                         Standard_Integer& iDegMin,
269                         Standard_Integer& iNbIter,
270                         Standard_Integer& iDegMax);
271
272 static
273   void Tolerances(const Handle(GeomAdaptor_HSurface)& aHS1,
274                   const Handle(GeomAdaptor_HSurface)& aHS2,
275                   Standard_Real& aTolTang);
276
277 static
278   Standard_Boolean SortTypes(const GeomAbs_SurfaceType aType1,
279                              const GeomAbs_SurfaceType aType2);
280 static
281   Standard_Integer IndexType(const GeomAbs_SurfaceType aType);
282
283 //
284 static
285   Standard_Boolean CheckPCurve(const Handle(Geom2d_Curve)& aPC, 
286                                const TopoDS_Face& aFace);
287
288 static
289   void CorrectPlaneBoundaries(Standard_Real& aUmin,
290                               Standard_Real& aUmax, 
291                               Standard_Real& aVmin, 
292                               Standard_Real& aVmax);
293
294 //=======================================================================
295 //function : 
296 //purpose  : 
297 //=======================================================================
298 IntTools_FaceFace::IntTools_FaceFace()
299 {
300   myIsDone=Standard_False;
301   myTangentFaces=Standard_False;
302   //
303   myHS1 = new GeomAdaptor_HSurface ();
304   myHS2 = new GeomAdaptor_HSurface ();
305   myTolReached2d=0.; 
306   myTolReached3d=0.;
307   SetParameters(Standard_True, Standard_True, Standard_True, 1.e-07);
308   
309 }
310 //=======================================================================
311 //function : SetContext
312 //purpose  : 
313 //======================================================================= 
314 void IntTools_FaceFace::SetContext(const Handle(IntTools_Context)& aContext)
315 {
316   myContext=aContext;
317 }
318 //=======================================================================
319 //function : Context
320 //purpose  : 
321 //======================================================================= 
322 const Handle(IntTools_Context)& IntTools_FaceFace::Context()const
323 {
324   return myContext;
325 }
326 //=======================================================================
327 //function : Face1
328 //purpose  : 
329 //======================================================================= 
330 const TopoDS_Face& IntTools_FaceFace::Face1() const
331 {
332   return myFace1;
333 }
334 //=======================================================================
335 //function : Face2
336 //purpose  : 
337 //======================================================================= 
338 const TopoDS_Face& IntTools_FaceFace::Face2() const
339 {
340   return myFace2;
341 }
342 //=======================================================================
343 //function : TangentFaces
344 //purpose  : 
345 //======================================================================= 
346 Standard_Boolean IntTools_FaceFace::TangentFaces() const
347 {
348   return myTangentFaces;
349 }
350 //=======================================================================
351 //function : Points
352 //purpose  : 
353 //======================================================================= 
354 const IntTools_SequenceOfPntOn2Faces& IntTools_FaceFace::Points() const
355 {
356   return myPnts;
357 }
358 //=======================================================================
359 //function : IsDone
360 //purpose  : 
361 //======================================================================= 
362 Standard_Boolean IntTools_FaceFace::IsDone() const
363 {
364   return myIsDone;
365 }
366 //=======================================================================
367 //function : TolReached3d
368 //purpose  : 
369 //=======================================================================
370 Standard_Real IntTools_FaceFace::TolReached3d() const
371 {
372   return myTolReached3d;
373 }
374 //=======================================================================
375 //function : Lines
376 //purpose  : return lines of intersection
377 //=======================================================================
378 const IntTools_SequenceOfCurves& IntTools_FaceFace::Lines() const
379 {
380   StdFail_NotDone_Raise_if
381     (!myIsDone,
382      "IntTools_FaceFace::Lines() => myIntersector NOT DONE");
383   return mySeqOfCurve;
384 }
385 //=======================================================================
386 //function : TolReached2d
387 //purpose  : 
388 //=======================================================================
389 Standard_Real IntTools_FaceFace::TolReached2d() const
390 {
391   return myTolReached2d;
392 }
393 // =======================================================================
394 // function: SetParameters
395 //
396 // =======================================================================
397 void IntTools_FaceFace::SetParameters(const Standard_Boolean ToApproxC3d,
398                                       const Standard_Boolean ToApproxC2dOnS1,
399                                       const Standard_Boolean ToApproxC2dOnS2,
400                                       const Standard_Real ApproximationTolerance) 
401 {
402   myApprox = ToApproxC3d;
403   myApprox1 = ToApproxC2dOnS1;
404   myApprox2 = ToApproxC2dOnS2;
405   myTolApprox = ApproximationTolerance;
406 }
407 //=======================================================================
408 //function : SetList
409 //purpose  : 
410 //=======================================================================
411 void IntTools_FaceFace::SetList(IntSurf_ListOfPntOn2S& aListOfPnts)
412 {
413   myListOfPnts = aListOfPnts;  
414 }
415
416
417 static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
418                                         const TopoDS_Face& theF2)
419 {
420   const Standard_Real Tolang = 1.e-8;
421   const Standard_Real aTolF1=BRep_Tool::Tolerance(theF1);
422   const Standard_Real aTolF2=BRep_Tool::Tolerance(theF2);
423   const Standard_Real aTolSum = aTolF1 + aTolF2;
424   Standard_Real aHigh = 0.0;
425
426   const BRepAdaptor_Surface aBAS1(theF1), aBAS2(theF2);
427   const GeomAbs_SurfaceType aType1=aBAS1.GetType();
428   const GeomAbs_SurfaceType aType2=aBAS2.GetType();
429   
430   gp_Pln aS1;
431   gp_Cylinder aS2;
432   if(aType1 == GeomAbs_Plane)
433   {
434     aS1=aBAS1.Plane();
435   }
436   else if(aType2 == GeomAbs_Plane)
437   {
438     aS1=aBAS2.Plane();
439   }
440   else
441   {
442     return Standard_True;
443   }
444
445   if(aType1 == GeomAbs_Cylinder)
446   {
447     aS2=aBAS1.Cylinder();
448     const Standard_Real VMin = aBAS1.FirstVParameter();
449     const Standard_Real VMax = aBAS1.LastVParameter();
450
451     if( Precision::IsNegativeInfinite(VMin) ||
452         Precision::IsPositiveInfinite(VMax))
453           return Standard_True;
454     else
455       aHigh = VMax - VMin;
456   }
457   else if(aType2 == GeomAbs_Cylinder)
458   {
459     aS2=aBAS2.Cylinder();
460
461     const Standard_Real VMin = aBAS2.FirstVParameter();
462     const Standard_Real VMax = aBAS2.LastVParameter();
463
464     if( Precision::IsNegativeInfinite(VMin) ||
465         Precision::IsPositiveInfinite(VMax))
466           return Standard_True;
467     else
468       aHigh = VMax - VMin;
469   }
470   else
471   {
472     return Standard_True;
473   }
474
475   IntAna_QuadQuadGeo inter;
476   inter.Perform(aS1,aS2,Tolang,aTolSum, aHigh);
477   if(inter.TypeInter() == IntAna_Ellipse)
478   {
479     const gp_Elips anEl = inter.Ellipse(1);
480     const Standard_Real aMajorR = anEl.MajorRadius();
481     const Standard_Real aMinorR = anEl.MinorRadius();
482     
483     return (aMajorR < 100000.0 * aMinorR);
484   }
485   else
486   {
487     return inter.IsDone();
488   }
489 }
490 //=======================================================================
491 //function : Perform
492 //purpose  : intersect surfaces of the faces
493 //=======================================================================
494 void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
495                                 const TopoDS_Face& aF2)
496 {
497   Standard_Boolean RestrictLine = Standard_False, hasCone = Standard_False;
498   
499   if (myContext.IsNull()) {
500     myContext=new IntTools_Context;
501   }
502
503   mySeqOfCurve.Clear();
504   myTolReached2d=0.;
505   myTolReached3d=0.;
506   myIsDone = Standard_False;
507   myNbrestr=0;//?
508
509   myFace1=aF1;
510   myFace2=aF2;
511
512   const BRepAdaptor_Surface aBAS1(myFace1, Standard_False);
513   const BRepAdaptor_Surface aBAS2(myFace2, Standard_False);
514   GeomAbs_SurfaceType aType1=aBAS1.GetType();
515   GeomAbs_SurfaceType aType2=aBAS2.GetType();
516
517   const Standard_Boolean bReverse=SortTypes(aType1, aType2);
518   if (bReverse)
519   {
520     myFace1=aF2;
521     myFace2=aF1;
522     aType1=aBAS2.GetType();
523     aType2=aBAS1.GetType();
524
525     if (myListOfPnts.Extent())
526     {
527       Standard_Real aU1,aV1,aU2,aV2;
528       IntSurf_ListIteratorOfListOfPntOn2S aItP2S;
529       //
530       aItP2S.Initialize(myListOfPnts);
531       for (; aItP2S.More(); aItP2S.Next())
532       {
533         IntSurf_PntOn2S& aP2S=aItP2S.Value();
534         aP2S.Parameters(aU1,aV1,aU2,aV2);
535         aP2S.SetValue(aU2,aV2,aU1,aV1);
536       }
537     }
538     //
539     Standard_Boolean anAproxTmp = myApprox1;
540     myApprox1 = myApprox2;
541     myApprox2 = anAproxTmp;
542   }
543
544
545   const Handle(Geom_Surface) S1=BRep_Tool::Surface(myFace1);
546   const Handle(Geom_Surface) S2=BRep_Tool::Surface(myFace2);
547
548   const Standard_Real aTolF1=BRep_Tool::Tolerance(myFace1);
549   const Standard_Real aTolF2=BRep_Tool::Tolerance(myFace2);
550
551   Standard_Real TolArc = aTolF1 + aTolF2;
552   Standard_Real TolTang = TolArc;
553
554   const Standard_Boolean isFace1Quad = (aType1 == GeomAbs_Cylinder ||
555                                         aType1 == GeomAbs_Cone ||
556                                         aType1 == GeomAbs_Torus);
557
558   const Standard_Boolean isFace2Quad = (aType2 == GeomAbs_Cylinder ||
559                                         aType2 == GeomAbs_Cone ||
560                                         aType2 == GeomAbs_Torus);
561
562   if(aType1==GeomAbs_Plane && aType2==GeomAbs_Plane)  {
563     Standard_Real umin, umax, vmin, vmax;
564     //
565     BRepTools::UVBounds(myFace1, umin, umax, vmin, vmax);
566     CorrectPlaneBoundaries(umin, umax, vmin, vmax);
567     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
568     //
569     BRepTools::UVBounds(myFace2, umin, umax, vmin, vmax);
570     CorrectPlaneBoundaries(umin, umax, vmin, vmax);
571     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
572     //
573     Standard_Real TolAng = 1.e-8;
574     //
575     PerformPlanes(myHS1, myHS2, TolAng, TolTang, myApprox1, myApprox2, 
576                   mySeqOfCurve, myTangentFaces);
577     //
578     myIsDone = Standard_True;
579     
580     if(!myTangentFaces) {
581       const Standard_Integer NbLinPP = mySeqOfCurve.Length();
582       if(NbLinPP) {
583         Standard_Real aTolFMax;
584         myTolReached3d = 1.e-7;
585         aTolFMax=Max(aTolF1, aTolF2);
586         if (aTolFMax>myTolReached3d) {
587           myTolReached3d=aTolFMax;
588         }
589         //
590         myTolReached2d = myTolReached3d;
591
592         if (bReverse) {
593           Handle(Geom2d_Curve) aC2D1, aC2D2;
594           const Standard_Integer aNbLin = mySeqOfCurve.Length();
595           for (Standard_Integer i = 1; i <= aNbLin; ++i) {
596             IntTools_Curve& aIC=mySeqOfCurve(i);
597             aC2D1=aIC.FirstCurve2d();
598             aC2D2=aIC.SecondCurve2d();
599             aIC.SetFirstCurve2d(aC2D2);
600             aIC.SetSecondCurve2d(aC2D1);
601           }
602         }
603       }
604     }
605     return;
606   }//if(aType1==GeomAbs_Plane && aType2==GeomAbs_Plane){
607
608   if ((aType1==GeomAbs_Plane) && isFace2Quad)
609   {
610     Standard_Real umin, umax, vmin, vmax;
611     // F1
612     BRepTools::UVBounds(myFace1, umin, umax, vmin, vmax); 
613     CorrectPlaneBoundaries(umin, umax, vmin, vmax);
614     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
615     // F2
616     BRepTools::UVBounds(myFace2, umin, umax, vmin, vmax);
617     CorrectSurfaceBoundaries(myFace2, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
618     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
619     //
620     if( aType2==GeomAbs_Cone ) { 
621       TolArc = 0.0001; 
622       hasCone = Standard_True; 
623     }
624   }
625   else if ((aType2==GeomAbs_Plane) && isFace1Quad)
626   {
627     Standard_Real umin, umax, vmin, vmax;
628     //F1
629     BRepTools::UVBounds(myFace1, umin, umax, vmin, vmax);
630     CorrectSurfaceBoundaries(myFace1, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
631     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
632     // F2
633     BRepTools::UVBounds(myFace2, umin, umax, vmin, vmax);
634     CorrectPlaneBoundaries(umin, umax, vmin, vmax);
635     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
636     //
637     if( aType1==GeomAbs_Cone ) {
638       TolArc = 0.0001; 
639       hasCone = Standard_True; 
640     }
641   }
642   else
643   {
644     Standard_Real umin, umax, vmin, vmax;
645     BRepTools::UVBounds(myFace1, umin, umax, vmin, vmax);
646     CorrectSurfaceBoundaries(myFace1, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
647     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
648     BRepTools::UVBounds(myFace2, umin, umax, vmin, vmax);
649     CorrectSurfaceBoundaries(myFace2, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
650     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
651   }
652
653   const Handle(IntTools_TopolTool) dom1 = new IntTools_TopolTool(myHS1);
654   const Handle(IntTools_TopolTool) dom2 = new IntTools_TopolTool(myHS2);
655
656   myLConstruct.Load(dom1, dom2, myHS1, myHS2);
657   
658
659   Tolerances(myHS1, myHS2, TolTang);
660
661   {
662     const Standard_Real UVMaxStep = 0.001;
663     const Standard_Real Deflection = (hasCone) ? 0.085 : 0.1;
664   myIntersector.SetTolerances(TolArc, TolTang, UVMaxStep, Deflection); 
665   }
666   
667   if((myHS1->IsUClosed() && !myHS1->IsUPeriodic()) || 
668      (myHS1->IsVClosed() && !myHS1->IsVPeriodic()) ||
669      (myHS2->IsUClosed() && !myHS2->IsUPeriodic()) || 
670      (myHS2->IsVClosed() && !myHS2->IsVPeriodic()))
671   {
672     RestrictLine = Standard_True;
673   }
674   //
675   if((aType1 != GeomAbs_BSplineSurface) &&
676       (aType1 != GeomAbs_BezierSurface)  &&
677      (aType1 != GeomAbs_OtherSurface)  &&
678      (aType2 != GeomAbs_BSplineSurface) &&
679       (aType2 != GeomAbs_BezierSurface)  &&
680      (aType2 != GeomAbs_OtherSurface))
681   {
682     RestrictLine = Standard_True;
683
684     if ((aType1 == GeomAbs_Torus) ||
685         (aType2 == GeomAbs_Torus))
686     {
687       myListOfPnts.Clear();
688     }
689   }
690
691   //
692   if(!RestrictLine)
693   {
694     TopExp_Explorer aExp;
695     for(Standard_Integer i = 0; (!RestrictLine) && (i < 2); i++)
696     {
697       const TopoDS_Face& aF=(!i) ? myFace1 : myFace2;
698       aExp.Init(aF, TopAbs_EDGE);
699       for(; aExp.More(); aExp.Next())
700       {
701         const TopoDS_Edge& aE=TopoDS::Edge(aExp.Current());
702
703         if(BRep_Tool::Degenerated(aE))
704         {
705           RestrictLine = Standard_True;
706           break;
707         }
708       }
709     }
710   }
711
712   const Standard_Boolean isGeomInt = isTreatAnalityc(aF1, aF2);
713   myIntersector.Perform(myHS1, dom1, myHS2, dom2, TolArc, TolTang, 
714                                   myListOfPnts, RestrictLine, isGeomInt);
715
716   myIsDone = myIntersector.IsDone();
717
718   if (myIsDone)
719   {
720     myTangentFaces=myIntersector.TangentFaces();
721     if (myTangentFaces) {
722       return;
723     }
724     //
725     if(RestrictLine) {
726       myListOfPnts.Clear(); // to use LineConstructor
727     }
728     //
729     const Standard_Integer aNbLin = myIntersector.NbLines();
730     for (Standard_Integer i=1; i <= aNbLin; ++i) {
731       MakeCurve(i, dom1, dom2);
732     }
733     //
734     ComputeTolReached3d();
735     //
736     if (bReverse) {
737       Handle(Geom2d_Curve) aC2D1, aC2D2;
738       //
739       const Standard_Integer aNbLin=mySeqOfCurve.Length();
740       for (Standard_Integer i=1; i<=aNbLin; ++i)
741       {
742         IntTools_Curve& aIC=mySeqOfCurve(i);
743         aC2D1=aIC.FirstCurve2d();
744         aC2D2=aIC.SecondCurve2d();
745         aIC.SetFirstCurve2d(aC2D2);
746         aIC.SetSecondCurve2d(aC2D1);
747       }
748     }
749
750     // Points
751     Standard_Boolean bValid2D1, bValid2D2;
752     Standard_Real U1,V1,U2,V2;
753     IntTools_PntOnFace aPntOnF1, aPntOnF2;
754     IntTools_PntOn2Faces aPntOn2Faces;
755     //
756     const Standard_Integer aNbPnts = myIntersector.NbPnts();
757     for (Standard_Integer i=1; i <= aNbPnts; ++i)
758     {
759       const IntSurf_PntOn2S& aISPnt=myIntersector.Point(i).PntOn2S();
760       const gp_Pnt& aPnt=aISPnt.Value();
761       aISPnt.Parameters(U1,V1,U2,V2);
762       //
763       // check the validity of the intersection point for the faces
764       bValid2D1 = myContext->IsPointInOnFace(myFace1, gp_Pnt2d(U1, V1));
765       if (!bValid2D1) {
766         continue;
767       }
768       //
769       bValid2D2 = myContext->IsPointInOnFace(myFace2, gp_Pnt2d(U2, V2));
770       if (!bValid2D2) {
771         continue;
772       }
773       //
774       // add the intersection point
775       aPntOnF1.Init(myFace1, aPnt, U1, V1);
776       aPntOnF2.Init(myFace2, aPnt, U2, V2);
777       //
778       if (!bReverse)
779       {
780         aPntOn2Faces.SetP1(aPntOnF1);
781         aPntOn2Faces.SetP2(aPntOnF2);
782       }
783       else
784       {
785         aPntOn2Faces.SetP2(aPntOnF1);
786         aPntOn2Faces.SetP1(aPntOnF2);
787       }
788
789       myPnts.Append(aPntOn2Faces);
790     }
791   }
792 }
793
794 //=======================================================================
795 //function : ComputeTolerance
796 //purpose  : 
797 //=======================================================================
798 Standard_Real IntTools_FaceFace::ComputeTolerance()
799 {
800   Standard_Integer i, j, aNbLin;
801   Standard_Real aFirst, aLast, aD, aDMax, aT;
802   Handle(Geom_Surface) aS1, aS2;
803   //
804   aDMax = 0;
805   aNbLin = mySeqOfCurve.Length();
806   //
807   aS1 = myHS1->ChangeSurface().Surface();
808   aS2 = myHS2->ChangeSurface().Surface();
809   //
810   for (i = 1; i <= aNbLin; ++i)
811   {
812     const IntTools_Curve& aIC = mySeqOfCurve(i);
813     const Handle(Geom_Curve)& aC3D = aIC.Curve();
814     if (aC3D.IsNull())
815     {
816       continue;
817     }
818     //
819     aFirst = aC3D->FirstParameter();
820     aLast  = aC3D->LastParameter();
821     //
822     const Handle(Geom2d_Curve)& aC2D1 = aIC.FirstCurve2d();
823     const Handle(Geom2d_Curve)& aC2D2 = aIC.SecondCurve2d();
824     //
825     for (j = 0; j < 2; ++j)
826     {
827       const Handle(Geom2d_Curve)& aC2D = !j ? aC2D1 : aC2D2;
828       const Handle(Geom_Surface)& aS = !j ? aS1 : aS2;
829       //
830       if (!aC2D.IsNull())
831       {
832         if (IntTools_Tools::ComputeTolerance
833             (aC3D, aC2D, aS, aFirst, aLast, aD, aT))
834         {
835           if (aD > aDMax)
836           {
837             aDMax = aD;
838           }
839         }
840       }
841     }
842   }
843   //
844   return aDMax;
845 }
846
847 //=======================================================================
848 //function :ComputeTolReached3d 
849 //purpose  : 
850 //=======================================================================
851   void IntTools_FaceFace::ComputeTolReached3d()
852 {
853   Standard_Integer aNbLin, i;
854   GeomAbs_SurfaceType aType1, aType2;
855   //
856   aNbLin=myIntersector.NbLines();
857   if (!aNbLin) {
858     return;
859   }
860   //
861   aType1=myHS1->Surface().GetType();
862   aType2=myHS2->Surface().GetType();
863   //
864   if (aType1==GeomAbs_Cylinder && aType2==GeomAbs_Cylinder) {
865     if (aNbLin==2){ 
866       Handle(IntPatch_Line) aIL1, aIL2;
867       IntPatch_IType aTL1, aTL2;
868       //
869       aIL1=myIntersector.Line(1);
870       aIL2=myIntersector.Line(2);
871       aTL1=aIL1->ArcType();
872       aTL2=aIL2->ArcType();
873       if (aTL1==IntPatch_Lin && aTL2==IntPatch_Lin) {
874         Standard_Real aD, aDTresh, dTol;
875         gp_Lin aL1, aL2;
876         //
877         dTol=1.e-8;
878         aDTresh=1.5e-6;
879         //
880         aL1=Handle(IntPatch_GLine)::DownCast(aIL1)->Line();
881         aL2=Handle(IntPatch_GLine)::DownCast(aIL2)->Line();
882         aD=aL1.Distance(aL2);
883         aD=0.5*aD;
884         if (aD<aDTresh) {
885           myTolReached3d=aD+dTol;
886         }
887         return;
888       }
889     }
890     //ZZ
891     if (aNbLin) {// Check the distances
892       Standard_Real aDMax;
893       //
894       aDMax = ComputeTolerance();
895       if (aDMax > 0.) {
896         myTolReached3d = aDMax;
897       }
898     }// if (aNbLin) 
899   }// if (aType1==GeomAbs_Cylinder && aType2==GeomAbs_Cylinder) {
900   //
901   //904/G3 f
902   else if (aType1==GeomAbs_Plane && aType2==GeomAbs_Plane) {
903     Standard_Real aTolF1, aTolF2, aTolFMax, aTolTresh;
904     //
905     aTolTresh=1.e-7;
906     //
907     aTolF1 = BRep_Tool::Tolerance(myFace1);
908     aTolF2 = BRep_Tool::Tolerance(myFace2);
909     aTolFMax=Max(aTolF1, aTolF2);
910     //
911     if (aTolFMax>aTolTresh) {
912       myTolReached3d=aTolFMax;
913     }
914   }//if (aType1==GeomAbs_Plane && aType2==GeomAbs_Plane) {
915   //t
916   //IFV Bug OCC20297 
917   else if((aType1 == GeomAbs_Cylinder && aType2 == GeomAbs_Plane) ||
918           (aType2 == GeomAbs_Cylinder && aType1 == GeomAbs_Plane)) {
919     if(aNbLin == 1) {
920       const Handle(IntPatch_Line)& aIL1 = myIntersector.Line(1);
921       if(aIL1->ArcType() == IntPatch_Circle) {
922         gp_Circ aCir = Handle(IntPatch_GLine)::DownCast(aIL1)->Circle();
923         gp_XYZ aCirDir = aCir.Axis().Direction().XYZ();
924         gp_XYZ aPlDir;
925         gp_Pln aPln;
926         if(aType1 == GeomAbs_Plane) {
927           aPln = myHS1->Surface().Plane();
928         }
929         else {
930           aPln = myHS2->Surface().Plane();
931         }
932         aPlDir = aPln.Axis().Direction().XYZ();
933         Standard_Real cs = aCirDir*aPlDir;
934         if(cs < 0.) aPlDir.Reverse();
935         Standard_Real eps = 1.e-14;
936         if(!aPlDir.IsEqual(aCirDir, eps)) {
937           Standard_Integer aNbP = 11;
938           Standard_Real dt = 2.*M_PI / (aNbP - 1), t;
939           for(t = 0.; t < 2.*M_PI; t += dt) {
940             Standard_Real d = aPln.Distance(ElCLib::Value(t, aCir)); 
941             if(myTolReached3d < d) myTolReached3d = d;
942           }
943           myTolReached3d *= 1.1;
944         }
945       } //aIL1->ArcType() == IntPatch_Circle
946     } //aNbLin == 1
947   } // aType1 == GeomAbs_Cylinder && aType2 == GeomAbs_Plane) 
948   //End IFV Bug OCC20297
949   //
950   else if ((aType1==GeomAbs_Plane && aType2==GeomAbs_Torus) ||
951            (aType2==GeomAbs_Plane && aType1==GeomAbs_Torus)) {
952     aNbLin=mySeqOfCurve.Length();
953     if (aNbLin!=1) {
954       return;
955     }
956     //
957     Standard_Integer aNbP;
958     Standard_Real aT, aT1, aT2, dT, aUT, aVT, aUP, aVP;
959     Standard_Real aDP, aDT, aDmax;
960     gp_Pln aPln;
961     gp_Torus aTorus;
962     gp_Pnt aP, aPP, aPT;
963     //
964     const IntTools_Curve& aIC=mySeqOfCurve(1);
965     const Handle(Geom_Curve)& aC3D=aIC.Curve();
966     Handle(Geom_BSplineCurve) aBS (Handle(Geom_BSplineCurve)::DownCast(aC3D));
967     if (aBS.IsNull()) {
968       return;
969     }
970     //
971     aT1=aBS->FirstParameter();
972     aT2=aBS->LastParameter();
973     //
974     aPln  =(aType1==GeomAbs_Plane) ? myHS1->Plane() : myHS2->Plane();
975     aTorus=(aType1==GeomAbs_Plane) ? myHS2->Torus() : myHS1->Torus();
976     //
977     aDmax=-1.;
978     aNbP=11;
979     dT=(aT2-aT1)/(aNbP-1);
980     for (i=0; i<aNbP; ++i) {
981       aT=aT1+i*dT;
982       if (i==aNbP-1) {
983         aT=aT2;
984       }
985       //
986       aC3D->D0(aT, aP);
987       //
988       ElSLib::Parameters(aPln, aP, aUP, aVP);
989       aPP=ElSLib::Value(aUP, aVP, aPln);
990       aDP=aP.SquareDistance(aPP);
991       if (aDP>aDmax) {
992         aDmax=aDP;
993       }
994       //
995       ElSLib::Parameters(aTorus, aP, aUT, aVT);
996       aPT=ElSLib::Value(aUT, aVT, aTorus);
997       aDT=aP.SquareDistance(aPT);
998       if (aDT>aDmax) {
999         aDmax=aDT;
1000       }
1001     }
1002     //
1003     if (aDmax > myTolReached3d*myTolReached3d) {
1004       myTolReached3d=sqrt(aDmax);
1005       myTolReached3d=1.1*myTolReached3d;
1006     }
1007   }// if ((aType1==GeomAbs_Plane && aType2==GeomAbs_Torus) ||
1008   //
1009   else if ((aType1==GeomAbs_SurfaceOfRevolution && aType2==GeomAbs_Cylinder) ||
1010            (aType2==GeomAbs_SurfaceOfRevolution && aType1==GeomAbs_Cylinder) ||
1011            (aType1==GeomAbs_Plane && aType2==GeomAbs_Sphere) ||
1012            (aType2==GeomAbs_Plane && aType1==GeomAbs_Sphere) ||
1013            (aType1==GeomAbs_Plane && aType2==GeomAbs_SurfaceOfExtrusion) ||
1014            (aType2==GeomAbs_Plane && aType1==GeomAbs_SurfaceOfExtrusion) ||
1015            (aType1==GeomAbs_Plane && aType2==GeomAbs_BSplineSurface) ||
1016            (aType2==GeomAbs_Plane && aType1==GeomAbs_BSplineSurface) ||
1017            !myApprox) {
1018     //
1019     Standard_Real aDMax;
1020     //
1021     aDMax = ComputeTolerance();
1022     if (aDMax > myTolReached3d) {
1023       myTolReached3d = aDMax;
1024     }
1025   }
1026 }
1027
1028 //=======================================================================
1029 //function : MakeCurve
1030 //purpose  : 
1031 //=======================================================================
1032   void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
1033                                     const Handle(Adaptor3d_TopolTool)& dom1,
1034                                     const Handle(Adaptor3d_TopolTool)& dom2) 
1035 {
1036   Standard_Boolean bDone, rejectSurface, reApprox, bAvoidLineConstructor;
1037   Standard_Boolean ok, bPCurvesOk;
1038   Standard_Integer i, j, aNbParts;
1039   Standard_Real fprm, lprm;
1040   Standard_Real Tolpc;
1041   Handle(IntPatch_Line) L;
1042   IntPatch_IType typl;
1043   Handle(Geom_Curve) newc;
1044   //
1045   const Standard_Real TOLCHECK   =0.0000001;
1046   const Standard_Real TOLANGCHECK=0.1;
1047   //
1048   rejectSurface = Standard_False;
1049   reApprox = Standard_False;
1050   //
1051   bPCurvesOk = Standard_True;
1052  
1053  reapprox:;
1054   
1055   Tolpc = myTolApprox;
1056   bAvoidLineConstructor = Standard_False;
1057   L = myIntersector.Line(Index);
1058   typl = L->ArcType();
1059   //
1060   if(typl==IntPatch_Walking) {
1061     Handle(IntPatch_Line) anewL;
1062     //
1063     Handle(IntPatch_WLine) aWLine (Handle(IntPatch_WLine)::DownCast(L));
1064     //DumpWLine(aWLine);
1065
1066     anewL = ComputePurgedWLine(aWLine);
1067     if(anewL.IsNull()) {
1068       return;
1069     }
1070     L = anewL;
1071     
1072     //Handle(IntPatch_WLine) aWLineX (Handle(IntPatch_WLine)::DownCast(L));
1073     //DumpWLine(aWLineX);
1074
1075     //
1076     if(!myListOfPnts.IsEmpty()) {
1077       bAvoidLineConstructor = Standard_True;
1078     }
1079
1080     Standard_Integer nbp = aWLine->NbPnts();
1081     const IntSurf_PntOn2S& p1 = aWLine->Point(1);
1082     const IntSurf_PntOn2S& p2 = aWLine->Point(nbp);
1083
1084     const gp_Pnt& P1 = p1.Value();
1085     const gp_Pnt& P2 = p2.Value();
1086
1087     if(P1.SquareDistance(P2) < 1.e-14) {
1088       bAvoidLineConstructor = Standard_False;
1089     }
1090   }
1091
1092   typl=L->ArcType();
1093
1094   //
1095   // Line Constructor
1096   if(!bAvoidLineConstructor) {
1097     myLConstruct.Perform(L);
1098     //
1099     bDone=myLConstruct.IsDone();
1100     if(!bDone)
1101     {
1102       return;
1103     }
1104
1105     if(typl != IntPatch_Restriction)
1106     {
1107       aNbParts=myLConstruct.NbParts();
1108       if (aNbParts <= 0)
1109       {
1110         return;
1111       }
1112     }
1113   }
1114   // Do the Curve
1115   
1116   
1117   switch (typl) {
1118   //########################################  
1119   // Line, Parabola, Hyperbola
1120   //########################################  
1121   case IntPatch_Lin:
1122   case IntPatch_Parabola: 
1123   case IntPatch_Hyperbola: {
1124     if (typl == IntPatch_Lin) {
1125       newc = 
1126         new Geom_Line (Handle(IntPatch_GLine)::DownCast(L)->Line());
1127     }
1128
1129     else if (typl == IntPatch_Parabola) {
1130       newc = 
1131         new Geom_Parabola(Handle(IntPatch_GLine)::DownCast(L)->Parabola());
1132     }
1133     
1134     else if (typl == IntPatch_Hyperbola) {
1135       newc = 
1136         new Geom_Hyperbola (Handle(IntPatch_GLine)::DownCast(L)->Hyperbola());
1137     }
1138     //
1139     // myTolReached3d
1140     if (typl == IntPatch_Lin) {
1141       TolR3d (myFace1, myFace2, myTolReached3d);
1142     }
1143     //
1144     aNbParts=myLConstruct.NbParts();
1145     for (i=1; i<=aNbParts; i++) {
1146       Standard_Boolean bFNIt, bLPIt;
1147       //
1148       myLConstruct.Part(i, fprm, lprm);
1149         //
1150       bFNIt=Precision::IsNegativeInfinite(fprm);
1151       bLPIt=Precision::IsPositiveInfinite(lprm);
1152       //
1153       if (!bFNIt && !bLPIt) {
1154         //
1155         IntTools_Curve aCurve;
1156         //
1157         Handle(Geom_TrimmedCurve) aCT3D=new Geom_TrimmedCurve(newc, fprm, lprm);
1158         aCurve.SetCurve(aCT3D);
1159         if (typl == IntPatch_Parabola) {
1160           Standard_Real aTolF1, aTolF2, aTolBase;
1161           
1162           aTolF1 = BRep_Tool::Tolerance(myFace1);
1163           aTolF2 = BRep_Tool::Tolerance(myFace2);
1164           aTolBase=aTolF1+aTolF2;
1165           myTolReached3d=IntTools_Tools::CurveTolerance(aCT3D, aTolBase);
1166         }
1167         //
1168         aCurve.SetCurve(new Geom_TrimmedCurve(newc, fprm, lprm));
1169         if(myApprox1) { 
1170           Handle (Geom2d_Curve) C2d;
1171           GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc,
1172                 myHS1->ChangeSurface().Surface(), newc, C2d);
1173           if(Tolpc>myTolReached2d || myTolReached2d==0.) { 
1174             myTolReached2d=Tolpc;
1175           }
1176             //            
1177             aCurve.SetFirstCurve2d(new Geom2d_TrimmedCurve(C2d,fprm,lprm));
1178           }
1179           else { 
1180             Handle(Geom2d_BSplineCurve) H1;
1181             //
1182             aCurve.SetFirstCurve2d(H1);
1183           }
1184         //
1185         if(myApprox2) { 
1186           Handle (Geom2d_Curve) C2d;
1187           GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc,
1188                     myHS2->ChangeSurface().Surface(), newc, C2d);
1189           if(Tolpc>myTolReached2d || myTolReached2d==0.) { 
1190             myTolReached2d=Tolpc;
1191           }
1192           //
1193           aCurve.SetSecondCurve2d(new Geom2d_TrimmedCurve(C2d,fprm,lprm));
1194           }
1195         else { 
1196           Handle(Geom2d_BSplineCurve) H1;
1197           //
1198           aCurve.SetSecondCurve2d(H1);
1199         }
1200         mySeqOfCurve.Append(aCurve);
1201       } //if (!bFNIt && !bLPIt) {
1202       else {
1203         //  on regarde si on garde
1204         //
1205         Standard_Real aTestPrm, dT=100.;
1206         //
1207         aTestPrm=0.;
1208         if (bFNIt && !bLPIt) {
1209           aTestPrm=lprm-dT;
1210         }
1211         else if (!bFNIt && bLPIt) {
1212           aTestPrm=fprm+dT;
1213         }
1214         else {
1215           // i.e, if (bFNIt && bLPIt)
1216           aTestPrm=IntTools_Tools::IntermediatePoint(-dT, dT);
1217         }
1218         //
1219         gp_Pnt ptref(newc->Value(aTestPrm));
1220         //
1221         GeomAbs_SurfaceType typS1 = myHS1->GetType();
1222         GeomAbs_SurfaceType typS2 = myHS2->GetType();
1223         if( typS1 == GeomAbs_SurfaceOfExtrusion ||
1224             typS1 == GeomAbs_OffsetSurface ||
1225             typS1 == GeomAbs_SurfaceOfRevolution ||
1226             typS2 == GeomAbs_SurfaceOfExtrusion ||
1227             typS2 == GeomAbs_OffsetSurface ||
1228             typS2 == GeomAbs_SurfaceOfRevolution) {
1229           Handle(Geom2d_BSplineCurve) H1;
1230           mySeqOfCurve.Append(IntTools_Curve(newc, H1, H1));
1231           continue;
1232         }
1233
1234         Standard_Real u1, v1, u2, v2, Tol;
1235         
1236         Tol = Precision::Confusion();
1237         Parameters(myHS1, myHS2, ptref,  u1, v1, u2, v2);
1238         ok = (dom1->Classify(gp_Pnt2d(u1, v1), Tol) != TopAbs_OUT);
1239         if(ok) { 
1240           ok = (dom2->Classify(gp_Pnt2d(u2,v2),Tol) != TopAbs_OUT); 
1241         }
1242         if (ok) {
1243           Handle(Geom2d_BSplineCurve) H1;
1244           mySeqOfCurve.Append(IntTools_Curve(newc, H1, H1));
1245         }
1246       }
1247     }// for (i=1; i<=aNbParts; i++) {
1248   }// case IntPatch_Lin:  case IntPatch_Parabola:  case IntPatch_Hyperbola:
1249     break;
1250
1251   //########################################  
1252   // Circle and Ellipse
1253   //########################################  
1254   case IntPatch_Circle: 
1255   case IntPatch_Ellipse: {
1256
1257     if (typl == IntPatch_Circle) {
1258       newc = new Geom_Circle
1259         (Handle(IntPatch_GLine)::DownCast(L)->Circle());
1260     }
1261     else { //IntPatch_Ellipse
1262       newc = new Geom_Ellipse
1263         (Handle(IntPatch_GLine)::DownCast(L)->Ellipse());
1264     }
1265     //
1266     // myTolReached3d
1267     TolR3d (myFace1, myFace2, myTolReached3d);
1268     //
1269     aNbParts=myLConstruct.NbParts();
1270     //
1271     Standard_Real aPeriod, aNul;
1272     TColStd_SequenceOfReal aSeqFprm,  aSeqLprm;
1273     
1274     aNul=0.;
1275     aPeriod=M_PI+M_PI;
1276
1277     for (i=1; i<=aNbParts; i++) {
1278       myLConstruct.Part(i, fprm, lprm);
1279
1280       if (fprm < aNul && lprm > aNul) {
1281         // interval that goes through 0. is divided on two intervals;
1282         while (fprm<aNul || fprm>aPeriod) fprm=fprm+aPeriod;
1283         while (lprm<aNul || lprm>aPeriod) lprm=lprm+aPeriod;
1284         //
1285         if((aPeriod - fprm) > Tolpc) {
1286           aSeqFprm.Append(fprm);
1287           aSeqLprm.Append(aPeriod);
1288         }
1289         else {
1290           gp_Pnt P1 = newc->Value(fprm);
1291           gp_Pnt P2 = newc->Value(aPeriod);
1292           Standard_Real aTolDist = BRep_Tool::Tolerance(myFace1) + BRep_Tool::Tolerance(myFace2);
1293           aTolDist = (myTolReached3d > aTolDist) ? myTolReached3d : aTolDist;
1294
1295           if(P1.Distance(P2) > aTolDist) {
1296             Standard_Real anewpar = fprm;
1297
1298             if(ParameterOutOfBoundary(fprm, newc, myFace1, myFace2, 
1299                                       lprm, Standard_False, anewpar, myContext)) {
1300               fprm = anewpar;
1301             }
1302             aSeqFprm.Append(fprm);
1303             aSeqLprm.Append(aPeriod);
1304           }
1305         }
1306
1307         //
1308         if((lprm - aNul) > Tolpc) {
1309           aSeqFprm.Append(aNul);
1310           aSeqLprm.Append(lprm);
1311         }
1312         else {
1313           gp_Pnt P1 = newc->Value(aNul);
1314           gp_Pnt P2 = newc->Value(lprm);
1315           Standard_Real aTolDist = BRep_Tool::Tolerance(myFace1) + BRep_Tool::Tolerance(myFace2);
1316           aTolDist = (myTolReached3d > aTolDist) ? myTolReached3d : aTolDist;
1317
1318           if(P1.Distance(P2) > aTolDist) {
1319             Standard_Real anewpar = lprm;
1320
1321             if(ParameterOutOfBoundary(lprm, newc, myFace1, myFace2, 
1322                                       fprm, Standard_True, anewpar, myContext)) {
1323               lprm = anewpar;
1324             }
1325             aSeqFprm.Append(aNul);
1326             aSeqLprm.Append(lprm);
1327           }
1328         }
1329       }
1330       else {
1331         // usual interval 
1332         aSeqFprm.Append(fprm);
1333         aSeqLprm.Append(lprm);
1334       }
1335     }
1336     
1337     //
1338     aNbParts=aSeqFprm.Length();
1339     for (i=1; i<=aNbParts; i++) {
1340       fprm=aSeqFprm(i);
1341       lprm=aSeqLprm(i);
1342       //
1343       Standard_Real aRealEpsilon=RealEpsilon();
1344       if (Abs(fprm) > aRealEpsilon || Abs(lprm-2.*M_PI) > aRealEpsilon) {
1345         //==============================================
1346         ////
1347         IntTools_Curve aCurve;
1348         Handle(Geom_TrimmedCurve) aTC3D=new Geom_TrimmedCurve(newc,fprm,lprm);
1349         aCurve.SetCurve(aTC3D);
1350         fprm=aTC3D->FirstParameter();
1351         lprm=aTC3D->LastParameter ();
1352         ////         
1353         if (typl == IntPatch_Circle || typl == IntPatch_Ellipse) {//// 
1354           if(myApprox1) { 
1355             Handle (Geom2d_Curve) C2d;
1356             GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc, 
1357                         myHS1->ChangeSurface().Surface(), newc, C2d);
1358             if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1359               myTolReached2d=Tolpc;
1360             }
1361             //
1362             aCurve.SetFirstCurve2d(C2d);
1363           }
1364           else { //// 
1365             Handle(Geom2d_BSplineCurve) H1;
1366             aCurve.SetFirstCurve2d(H1);
1367           }
1368
1369
1370           if(myApprox2) { 
1371             Handle (Geom2d_Curve) C2d;
1372             GeomInt_IntSS::BuildPCurves(fprm,lprm,Tolpc,
1373                     myHS2->ChangeSurface().Surface(),newc,C2d);
1374             if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1375               myTolReached2d=Tolpc;
1376             }
1377             //
1378             aCurve.SetSecondCurve2d(C2d);
1379           }
1380           else { 
1381             Handle(Geom2d_BSplineCurve) H1;
1382             aCurve.SetSecondCurve2d(H1);
1383           }
1384         }
1385         
1386         else { 
1387           Handle(Geom2d_BSplineCurve) H1;
1388           aCurve.SetFirstCurve2d(H1);
1389           aCurve.SetSecondCurve2d(H1);
1390         }
1391         mySeqOfCurve.Append(aCurve);
1392           //==============================================        
1393       } //if (Abs(fprm) > RealEpsilon() || Abs(lprm-2.*M_PI) > RealEpsilon())
1394
1395       else {
1396         //  on regarde si on garde
1397         //
1398         if (aNbParts==1) {
1399 //           if (Abs(fprm) < RealEpsilon() &&  Abs(lprm-2.*M_PI) < RealEpsilon()) {
1400           if (Abs(fprm) <= aRealEpsilon && Abs(lprm-2.*M_PI) <= aRealEpsilon) {
1401             IntTools_Curve aCurve;
1402             Handle(Geom_TrimmedCurve) aTC3D=new Geom_TrimmedCurve(newc,fprm,lprm);
1403             aCurve.SetCurve(aTC3D);
1404             fprm=aTC3D->FirstParameter();
1405             lprm=aTC3D->LastParameter ();
1406             
1407             if(myApprox1) { 
1408               Handle (Geom2d_Curve) C2d;
1409               GeomInt_IntSS::BuildPCurves(fprm,lprm,Tolpc,
1410                     myHS1->ChangeSurface().Surface(),newc,C2d);
1411               if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1412                 myTolReached2d=Tolpc;
1413               }
1414               //
1415               aCurve.SetFirstCurve2d(C2d);
1416             }
1417             else { //// 
1418               Handle(Geom2d_BSplineCurve) H1;
1419               aCurve.SetFirstCurve2d(H1);
1420             }
1421
1422             if(myApprox2) { 
1423               Handle (Geom2d_Curve) C2d;
1424               GeomInt_IntSS::BuildPCurves(fprm,lprm,Tolpc,
1425                     myHS2->ChangeSurface().Surface(),newc,C2d);
1426               if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1427                 myTolReached2d=Tolpc;
1428               }
1429               //
1430               aCurve.SetSecondCurve2d(C2d);
1431             }
1432             else { 
1433               Handle(Geom2d_BSplineCurve) H1;
1434               aCurve.SetSecondCurve2d(H1);
1435             }
1436             mySeqOfCurve.Append(aCurve);
1437             break;
1438           }
1439         }
1440         //
1441         Standard_Real aTwoPIdiv17, u1, v1, u2, v2, Tol;
1442
1443         aTwoPIdiv17=2.*M_PI/17.;
1444
1445         for (j=0; j<=17; j++) {
1446           gp_Pnt ptref (newc->Value (j*aTwoPIdiv17));
1447           Tol = Precision::Confusion();
1448
1449           Parameters(myHS1, myHS2, ptref, u1, v1, u2, v2);
1450           ok = (dom1->Classify(gp_Pnt2d(u1,v1),Tol) != TopAbs_OUT);
1451           if(ok) { 
1452             ok = (dom2->Classify(gp_Pnt2d(u2,v2),Tol) != TopAbs_OUT);
1453           }
1454           if (ok) {
1455             IntTools_Curve aCurve;
1456             aCurve.SetCurve(newc);
1457             //==============================================
1458             if (typl == IntPatch_Circle || typl == IntPatch_Ellipse) {
1459               
1460               if(myApprox1) { 
1461                 Handle (Geom2d_Curve) C2d;
1462                 GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc, 
1463                         myHS1->ChangeSurface().Surface(), newc, C2d);
1464                 if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1465                   myTolReached2d=Tolpc;
1466                 }
1467                 // 
1468                 aCurve.SetFirstCurve2d(C2d);
1469               }
1470               else { 
1471                 Handle(Geom2d_BSplineCurve) H1;
1472                 aCurve.SetFirstCurve2d(H1);
1473               }
1474                 
1475               if(myApprox2) { 
1476                 Handle (Geom2d_Curve) C2d;
1477                 GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc,
1478                         myHS2->ChangeSurface().Surface(), newc, C2d);
1479                 if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1480                   myTolReached2d=Tolpc;
1481                 }
1482                 //                 
1483                 aCurve.SetSecondCurve2d(C2d);
1484               }
1485                 
1486               else { 
1487                 Handle(Geom2d_BSplineCurve) H1;
1488                 aCurve.SetSecondCurve2d(H1);
1489               }
1490             }//  end of if (typl == IntPatch_Circle || typl == IntPatch_Ellipse)
1491              
1492             else { 
1493               Handle(Geom2d_BSplineCurve) H1;
1494               //         
1495               aCurve.SetFirstCurve2d(H1);
1496               aCurve.SetSecondCurve2d(H1);
1497             }
1498             //==============================================        
1499             //
1500             mySeqOfCurve.Append(aCurve);
1501             break;
1502
1503             }//  end of if (ok) {
1504           }//  end of for (Standard_Integer j=0; j<=17; j++)
1505         }//  end of else { on regarde si on garde
1506       }// for (i=1; i<=myLConstruct.NbParts(); i++)
1507     }// IntPatch_Circle: IntPatch_Ellipse:
1508     break;
1509     
1510   case IntPatch_Analytic: {
1511     IntSurf_Quadric quad1,quad2;
1512     GeomAbs_SurfaceType typs = myHS1->Surface().GetType();
1513     
1514     switch (typs) {
1515       case GeomAbs_Plane:
1516         quad1.SetValue(myHS1->Surface().Plane());
1517         break;
1518       case GeomAbs_Cylinder:
1519         quad1.SetValue(myHS1->Surface().Cylinder());
1520         break;
1521       case GeomAbs_Cone:
1522         quad1.SetValue(myHS1->Surface().Cone());
1523         break;
1524       case GeomAbs_Sphere:
1525         quad1.SetValue(myHS1->Surface().Sphere());
1526         break;
1527     case GeomAbs_Torus:
1528       quad1.SetValue(myHS1->Surface().Torus());
1529       break;
1530       default:
1531         Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve 1");
1532       }
1533       
1534     typs = myHS2->Surface().GetType();
1535     
1536     switch (typs) {
1537       case GeomAbs_Plane:
1538         quad2.SetValue(myHS2->Surface().Plane());
1539         break;
1540       case GeomAbs_Cylinder:
1541         quad2.SetValue(myHS2->Surface().Cylinder());
1542         break;
1543       case GeomAbs_Cone:
1544         quad2.SetValue(myHS2->Surface().Cone());
1545         break;
1546       case GeomAbs_Sphere:
1547         quad2.SetValue(myHS2->Surface().Sphere());
1548         break;
1549     case GeomAbs_Torus:
1550       quad2.SetValue(myHS2->Surface().Torus());
1551       break;
1552       default:
1553         Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve 2");
1554       }
1555     //
1556     //=========
1557     IntPatch_ALineToWLine convert (quad1, quad2);
1558       
1559     if (!myApprox) {
1560       aNbParts=myLConstruct.NbParts();
1561       for (i=1; i<=aNbParts; i++) {
1562         myLConstruct.Part(i, fprm, lprm);
1563         Handle(IntPatch_WLine) WL = 
1564           convert.MakeWLine(Handle(IntPatch_ALine)::DownCast(L), fprm, lprm);
1565         //
1566         Handle(Geom2d_BSplineCurve) H1;
1567         Handle(Geom2d_BSplineCurve) H2;
1568
1569         if(myApprox1) {
1570           H1 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True);
1571         }
1572         
1573         if(myApprox2) {
1574           H2 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False);
1575         }
1576         //          
1577         mySeqOfCurve.Append(IntTools_Curve(MakeBSpline(WL,1,WL->NbPnts()), H1, H2));
1578       }
1579     } // if (!myApprox)
1580
1581     else { // myApprox=TRUE
1582       GeomInt_WLApprox theapp3d;
1583       // 
1584       Standard_Real tol2d = myTolApprox;
1585       //         
1586       theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_True);
1587       
1588       aNbParts=myLConstruct.NbParts();
1589       for (i=1; i<=aNbParts; i++) {
1590         myLConstruct.Part(i, fprm, lprm);
1591         Handle(IntPatch_WLine) WL = 
1592           convert.MakeWLine(Handle(IntPatch_ALine):: DownCast(L),fprm,lprm);
1593
1594         theapp3d.Perform(myHS1,myHS2,WL,Standard_True,myApprox1,myApprox2, 1, WL->NbPnts());
1595
1596         if (!theapp3d.IsDone()) {
1597           //
1598           Handle(Geom2d_BSplineCurve) H1;
1599           Handle(Geom2d_BSplineCurve) H2;
1600
1601           if(myApprox1) {
1602             H1 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True);
1603           }
1604           
1605           if(myApprox2) {
1606             H2 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False);
1607           }
1608           //          
1609           mySeqOfCurve.Append(IntTools_Curve(MakeBSpline(WL,1,WL->NbPnts()), H1, H2));
1610         }
1611
1612         else {
1613           if(myApprox1 || myApprox2) { 
1614             if( theapp3d.TolReached2d()>myTolReached2d || myTolReached2d==0) { 
1615               myTolReached2d = theapp3d.TolReached2d();
1616             }
1617           }
1618           
1619           if( theapp3d.TolReached3d()>myTolReached3d || myTolReached3d==0) { 
1620             myTolReached3d = theapp3d.TolReached3d();
1621           }
1622
1623           Standard_Integer aNbMultiCurves, nbpoles;
1624           aNbMultiCurves=theapp3d.NbMultiCurves();
1625           for (j=1; j<=aNbMultiCurves; j++) {
1626             const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
1627             nbpoles = mbspc.NbPoles();
1628             
1629             TColgp_Array1OfPnt tpoles(1, nbpoles);
1630             mbspc.Curve(1, tpoles);
1631             Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles,
1632                                                                mbspc.Knots(),
1633                                                                mbspc.Multiplicities(),
1634                                                                mbspc.Degree());
1635             
1636             GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK);
1637             Check.FixTangent(Standard_True,Standard_True);
1638             // 
1639             IntTools_Curve aCurve;
1640             aCurve.SetCurve(BS);
1641             
1642             if(myApprox1) { 
1643               TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
1644               mbspc.Curve(2,tpoles2d);
1645               Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d,
1646                                                                       mbspc.Knots(),
1647                                                                       mbspc.Multiplicities(),
1648                                                                       mbspc.Degree());
1649
1650               GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK);
1651               newCheck.FixTangent(Standard_True,Standard_True);
1652               //                 
1653               aCurve.SetFirstCurve2d(BS2);
1654             }
1655             else {
1656               Handle(Geom2d_BSplineCurve) H1;
1657               aCurve.SetFirstCurve2d(H1);
1658             }
1659             
1660             if(myApprox2) { 
1661               TColgp_Array1OfPnt2d tpoles2d(1, nbpoles);
1662               Standard_Integer TwoOrThree;
1663               TwoOrThree=myApprox1 ? 3 : 2;
1664               mbspc.Curve(TwoOrThree, tpoles2d);
1665               Handle(Geom2d_BSplineCurve) BS2 =new Geom2d_BSplineCurve(tpoles2d,
1666                                                                        mbspc.Knots(),
1667                                                                        mbspc.Multiplicities(),
1668                                                                        mbspc.Degree());
1669                 
1670               GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK);
1671               newCheck.FixTangent(Standard_True,Standard_True);
1672               //         
1673               aCurve.SetSecondCurve2d(BS2);
1674             }
1675             else { 
1676               Handle(Geom2d_BSplineCurve) H2;
1677               aCurve.SetSecondCurve2d(H2);
1678             }
1679             // 
1680             mySeqOfCurve.Append(aCurve);
1681
1682           }// for (j=1; j<=aNbMultiCurves; j++) {
1683         }// else from if (!theapp3d.IsDone())
1684       }// for (i=1; i<=aNbParts; i++) {
1685     }// else { // myApprox=TRUE
1686   }// case IntPatch_Analytic:
1687     break;
1688
1689   case IntPatch_Walking:{
1690     Handle(IntPatch_WLine) WL = 
1691       Handle(IntPatch_WLine)::DownCast(L);
1692     //
1693     Standard_Integer ifprm, ilprm;
1694     //
1695     if (!myApprox) {
1696       aNbParts = 1;
1697       if(!bAvoidLineConstructor){
1698         aNbParts=myLConstruct.NbParts();
1699       }
1700       for (i=1; i<=aNbParts; ++i) {
1701         Handle(Geom2d_BSplineCurve) H1, H2;
1702         Handle(Geom_Curve) aBSp;
1703         //
1704         if(bAvoidLineConstructor) {
1705           ifprm = 1;
1706           ilprm = WL->NbPnts();
1707         }
1708         else {
1709           myLConstruct.Part(i, fprm, lprm);
1710           ifprm=(Standard_Integer)fprm;
1711           ilprm=(Standard_Integer)lprm;
1712         }
1713         //
1714         if(myApprox1) {
1715           H1 = MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
1716         }
1717         //
1718         if(myApprox2) {
1719           H2 = MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
1720         }
1721         //           
1722         aBSp=MakeBSpline(WL, ifprm, ilprm);
1723         IntTools_Curve aIC(aBSp, H1, H2);
1724         mySeqOfCurve.Append(aIC);
1725       }// for (i=1; i<=aNbParts; ++i) {
1726     }// if (!myApprox) {
1727     //
1728     else { // X
1729       Standard_Boolean bIsDecomposited;
1730       Standard_Integer nbiter, aNbSeqOfL;
1731       Standard_Real tol2d, aTolApproxImp;
1732       IntPatch_SequenceOfLine aSeqOfL;
1733       GeomInt_WLApprox theapp3d;
1734       Approx_ParametrizationType aParType = Approx_ChordLength;
1735       //
1736       Standard_Boolean anApprox1 = myApprox1;
1737       Standard_Boolean anApprox2 = myApprox2;
1738       //
1739       aTolApproxImp=1.e-5;
1740       tol2d = myTolApprox;
1741
1742       GeomAbs_SurfaceType typs1, typs2;
1743       typs1 = myHS1->Surface().GetType();
1744       typs2 = myHS2->Surface().GetType();
1745       Standard_Boolean anWithPC = Standard_True;
1746
1747       if(typs1 == GeomAbs_Cylinder && typs2 == GeomAbs_Sphere) {
1748         anWithPC = 
1749           ApproxWithPCurves(myHS1->Surface().Cylinder(), myHS2->Surface().Sphere());
1750       }
1751       else if (typs1 == GeomAbs_Sphere && typs2 == GeomAbs_Cylinder) {
1752         anWithPC = 
1753           ApproxWithPCurves(myHS2->Surface().Cylinder(), myHS1->Surface().Sphere());
1754       }
1755       //
1756       if(!anWithPC) {
1757         myTolApprox = aTolApproxImp;//1.e-5; 
1758         anApprox1 = Standard_False;
1759         anApprox2 = Standard_False;
1760         //         
1761         tol2d = myTolApprox;
1762       }
1763         
1764       if(myHS1 == myHS2) { 
1765         theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False, aParType);
1766         rejectSurface = Standard_True;
1767       }
1768       else { 
1769         if(reApprox && !rejectSurface)
1770           theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False, aParType);
1771         else {
1772           Standard_Integer iDegMax, iDegMin, iNbIter;
1773           //
1774           ApproxParameters(myHS1, myHS2, iDegMin, iDegMax, iNbIter);
1775           theapp3d.SetParameters(myTolApprox, tol2d, iDegMin, iDegMax, iNbIter, Standard_True, aParType);
1776         }
1777       }
1778       //
1779       Standard_Real aReachedTol = Precision::Confusion();
1780       bIsDecomposited=DecompositionOfWLine(WL,
1781                                            myHS1, 
1782                                            myHS2, 
1783                                            myFace1, 
1784                                            myFace2, 
1785                                            myLConstruct, 
1786                                            bAvoidLineConstructor, 
1787                                            aSeqOfL, 
1788                                            aReachedTol,
1789                                            myContext);
1790       if ( bIsDecomposited && ( myTolReached3d < aReachedTol ) ) {
1791         myTolReached3d = aReachedTol;
1792       }
1793       //
1794       aNbSeqOfL=aSeqOfL.Length();
1795       //
1796       if (bIsDecomposited) {
1797         nbiter=aNbSeqOfL;
1798       }
1799       else {
1800         nbiter=1;
1801         aNbParts=1;
1802         if (!bAvoidLineConstructor) {
1803           aNbParts=myLConstruct.NbParts();
1804           nbiter=aNbParts;
1805         }
1806       }
1807       //
1808       for(i = 1; i <= nbiter; ++i) {
1809         if(bIsDecomposited) {
1810           WL = Handle(IntPatch_WLine)::DownCast(aSeqOfL.Value(i));
1811           ifprm = 1;
1812           ilprm = WL->NbPnts();
1813         }
1814         else {
1815           if(bAvoidLineConstructor) {
1816             ifprm = 1;
1817             ilprm = WL->NbPnts();
1818           }
1819           else {
1820             myLConstruct.Part(i, fprm, lprm);
1821             ifprm = (Standard_Integer)fprm;
1822             ilprm = (Standard_Integer)lprm;
1823           }
1824         }
1825         //-- lbr : 
1826         //-- Si une des surfaces est un plan , on approxime en 2d
1827         //-- sur cette surface et on remonte les points 2d en 3d.
1828         if(typs1 == GeomAbs_Plane) { 
1829           theapp3d.Perform(myHS1, myHS2, WL, Standard_False,Standard_True, myApprox2,ifprm,ilprm);
1830         }          
1831         else if(typs2 == GeomAbs_Plane) { 
1832           theapp3d.Perform(myHS1,myHS2,WL,Standard_False,myApprox1,Standard_True,ifprm,ilprm);
1833         }
1834         else { 
1835           //
1836           if (myHS1 != myHS2){
1837             if ((typs1==GeomAbs_BezierSurface || typs1==GeomAbs_BSplineSurface) &&
1838                 (typs2==GeomAbs_BezierSurface || typs2==GeomAbs_BSplineSurface)) {
1839              
1840               theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_True, aParType);
1841               
1842               Standard_Boolean bUseSurfaces;
1843               bUseSurfaces=NotUseSurfacesForApprox(myFace1, myFace2, WL, ifprm,  ilprm);
1844               if (bUseSurfaces) {
1845                 // ######
1846                 rejectSurface = Standard_True;
1847                 // ######
1848                 theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False, aParType);
1849               }
1850             }
1851           }
1852           //
1853           theapp3d.Perform(myHS1,myHS2,WL,Standard_True,anApprox1,anApprox2,ifprm,ilprm);
1854         }
1855           //           
1856         if (!theapp3d.IsDone()) {
1857           Handle(Geom2d_BSplineCurve) H1;
1858           Handle(Geom2d_BSplineCurve) H2;
1859           //           
1860           Handle(Geom_Curve) aBSp=MakeBSpline(WL,ifprm, ilprm);
1861           //
1862           if(myApprox1) {
1863             H1 = MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
1864           }
1865           //
1866           if(myApprox2) {
1867             H2 = MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
1868           }
1869           //           
1870           IntTools_Curve aIC(aBSp, H1, H2);
1871           mySeqOfCurve.Append(aIC);
1872         }
1873         
1874         else {
1875           if(myApprox1 || myApprox2 || (typs1==GeomAbs_Plane || typs2==GeomAbs_Plane)) { 
1876             if( theapp3d.TolReached2d()>myTolReached2d || myTolReached2d==0.) { 
1877               myTolReached2d = theapp3d.TolReached2d();
1878             }
1879           }
1880           if(typs1==GeomAbs_Plane || typs2==GeomAbs_Plane) { 
1881             myTolReached3d = myTolReached2d;
1882             //
1883             if (typs1==GeomAbs_Torus || typs2==GeomAbs_Torus) {
1884               if (myTolReached3d<1.e-6) {
1885                 myTolReached3d = theapp3d.TolReached3d();
1886                 myTolReached3d=1.e-6;
1887               }
1888             }
1889           }
1890           else  if( theapp3d.TolReached3d()>myTolReached3d || myTolReached3d==0.) { 
1891             myTolReached3d = theapp3d.TolReached3d();
1892           }
1893           
1894           Standard_Integer aNbMultiCurves, nbpoles;
1895           aNbMultiCurves=theapp3d.NbMultiCurves(); 
1896           for (j=1; j<=aNbMultiCurves; j++) {
1897             if(typs1 == GeomAbs_Plane) {
1898               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
1899               nbpoles = mbspc.NbPoles();
1900               
1901               TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
1902               TColgp_Array1OfPnt   tpoles(1,nbpoles);
1903               
1904               mbspc.Curve(1,tpoles2d);
1905               const gp_Pln&  Pln = myHS1->Surface().Plane();
1906               //
1907               Standard_Integer ik; 
1908               for(ik = 1; ik<= nbpoles; ik++) { 
1909                 tpoles.SetValue(ik,
1910                                 ElSLib::Value(tpoles2d.Value(ik).X(),
1911                                               tpoles2d.Value(ik).Y(),
1912                                               Pln));
1913               }
1914               //
1915               Handle(Geom_BSplineCurve) BS = 
1916                 new Geom_BSplineCurve(tpoles,
1917                                       mbspc.Knots(),
1918                                       mbspc.Multiplicities(),
1919                                       mbspc.Degree());
1920               GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK);
1921               Check.FixTangent(Standard_True, Standard_True);
1922               //         
1923               IntTools_Curve aCurve;
1924               aCurve.SetCurve(BS);
1925
1926               if(myApprox1) { 
1927                 Handle(Geom2d_BSplineCurve) BS1 = 
1928                   new Geom2d_BSplineCurve(tpoles2d,
1929                                           mbspc.Knots(),
1930                                           mbspc.Multiplicities(),
1931                                           mbspc.Degree());
1932                 GeomLib_Check2dBSplineCurve Check1(BS1,TOLCHECK,TOLANGCHECK);
1933                 Check1.FixTangent(Standard_True,Standard_True);
1934                 //
1935                 // ############################################
1936                 if(!rejectSurface && !reApprox) {
1937                   Standard_Boolean isValid = IsCurveValid(BS1);
1938                   if(!isValid) {
1939                     reApprox = Standard_True;
1940                     goto reapprox;
1941                   }
1942                 }
1943                 // ############################################
1944                 aCurve.SetFirstCurve2d(BS1);
1945               }
1946               else {
1947                 Handle(Geom2d_BSplineCurve) H1;
1948                 aCurve.SetFirstCurve2d(H1);
1949               }
1950
1951               if(myApprox2) { 
1952                 mbspc.Curve(2, tpoles2d);
1953                 
1954                 Handle(Geom2d_BSplineCurve) BS2 = new Geom2d_BSplineCurve(tpoles2d,
1955                                                                           mbspc.Knots(),
1956                                                                           mbspc.Multiplicities(),
1957                                                                           mbspc.Degree());
1958                 GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK);
1959                 newCheck.FixTangent(Standard_True,Standard_True);
1960                 
1961                 // ###########################################
1962                 if(!rejectSurface && !reApprox) {
1963                   Standard_Boolean isValid = IsCurveValid(BS2);
1964                   if(!isValid) {
1965                     reApprox = Standard_True;
1966                     goto reapprox;
1967                   }
1968                 }
1969                 // ###########################################
1970                 // 
1971                 aCurve.SetSecondCurve2d(BS2);
1972               }
1973               else { 
1974                 Handle(Geom2d_BSplineCurve) H2;
1975                 //                 
1976                   aCurve.SetSecondCurve2d(H2);
1977               }
1978               //
1979               mySeqOfCurve.Append(aCurve);
1980             }//if(typs1 == GeomAbs_Plane) {
1981             
1982             else if(typs2 == GeomAbs_Plane) { 
1983               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
1984               nbpoles = mbspc.NbPoles();
1985               
1986               TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
1987               TColgp_Array1OfPnt   tpoles(1,nbpoles);
1988               mbspc.Curve((myApprox1==Standard_True)? 2 : 1,tpoles2d);
1989               const gp_Pln&  Pln = myHS2->Surface().Plane();
1990               //
1991               Standard_Integer ik; 
1992               for(ik = 1; ik<= nbpoles; ik++) { 
1993                 tpoles.SetValue(ik,
1994                                 ElSLib::Value(tpoles2d.Value(ik).X(),
1995                                               tpoles2d.Value(ik).Y(),
1996                                               Pln));
1997                 
1998               }
1999               //
2000               Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles,
2001                                                                  mbspc.Knots(),
2002                                                                  mbspc.Multiplicities(),
2003                                                                  mbspc.Degree());
2004               GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK);
2005               Check.FixTangent(Standard_True,Standard_True);
2006               //         
2007               IntTools_Curve aCurve;
2008               aCurve.SetCurve(BS);
2009
2010               if(myApprox2) {
2011                 Handle(Geom2d_BSplineCurve) BS1=new Geom2d_BSplineCurve(tpoles2d,
2012                                                                         mbspc.Knots(),
2013                                                                         mbspc.Multiplicities(),
2014                                                                         mbspc.Degree());
2015                 GeomLib_Check2dBSplineCurve Check1(BS1,TOLCHECK,TOLANGCHECK);
2016                 Check1.FixTangent(Standard_True,Standard_True);
2017                 //         
2018                 // ###########################################
2019                 if(!rejectSurface && !reApprox) {
2020                   Standard_Boolean isValid = IsCurveValid(BS1);
2021                   if(!isValid) {
2022                     reApprox = Standard_True;
2023                     goto reapprox;
2024                   }
2025                 }
2026                 // ###########################################
2027                 bPCurvesOk = CheckPCurve(BS1, myFace2);
2028                 aCurve.SetSecondCurve2d(BS1);
2029               }
2030               else {
2031                 Handle(Geom2d_BSplineCurve) H2;
2032                 aCurve.SetSecondCurve2d(H2);
2033               }
2034               
2035               if(myApprox1) { 
2036                 mbspc.Curve(1,tpoles2d);
2037                 Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d,
2038                                                                         mbspc.Knots(),
2039                                                                         mbspc.Multiplicities(),
2040                                                                         mbspc.Degree());
2041                 GeomLib_Check2dBSplineCurve Check2(BS2,TOLCHECK,TOLANGCHECK);
2042                 Check2.FixTangent(Standard_True,Standard_True);
2043                 //
2044                 // ###########################################
2045                 if(!rejectSurface && !reApprox) {
2046                   Standard_Boolean isValid = IsCurveValid(BS2);
2047                   if(!isValid) {
2048                     reApprox = Standard_True;
2049                     goto reapprox;
2050                   }
2051                 }
2052                 // ###########################################
2053                 bPCurvesOk = bPCurvesOk && CheckPCurve(BS2, myFace1);
2054                 aCurve.SetFirstCurve2d(BS2);
2055               }
2056               else { 
2057                 Handle(Geom2d_BSplineCurve) H1;
2058                 //                 
2059                 aCurve.SetFirstCurve2d(H1);
2060               }
2061               //
2062               //if points of the pcurves are out of the faces bounds
2063               //create 3d and 2d curves without approximation
2064               if (!bPCurvesOk) {
2065                 Handle(Geom2d_BSplineCurve) H1, H2;
2066                 bPCurvesOk = Standard_True;
2067                 //           
2068                 Handle(Geom_Curve) aBSp=MakeBSpline(WL,ifprm, ilprm);
2069                 
2070                 if(myApprox1) {
2071                   H1 = MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
2072                   bPCurvesOk = CheckPCurve(H1, myFace1);
2073                 }
2074                 
2075                 if(myApprox2) {
2076                   H2 = MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
2077                   bPCurvesOk = bPCurvesOk && CheckPCurve(H2, myFace2);
2078                 }
2079                 //
2080                 //if pcurves created without approximation are out of the 
2081                 //faces bounds, use approximated 3d and 2d curves
2082                 if (bPCurvesOk) {
2083                   IntTools_Curve aIC(aBSp, H1, H2);
2084                   mySeqOfCurve.Append(aIC);
2085                 } else {
2086                   mySeqOfCurve.Append(aCurve);
2087                 }
2088               } else {
2089                 mySeqOfCurve.Append(aCurve);
2090               }
2091             }// else if(typs2 == GeomAbs_Plane)
2092             //
2093             else { //typs2 != GeomAbs_Plane && typs1 != GeomAbs_Plane
2094               Standard_Boolean bIsValid1, bIsValid2;
2095               Handle(Geom_BSplineCurve) BS;
2096               Handle(Geom2d_BSplineCurve) aH2D;        
2097               IntTools_Curve aCurve; 
2098               //
2099               bIsValid1=Standard_True;
2100               bIsValid2=Standard_True;
2101               //
2102               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
2103               nbpoles = mbspc.NbPoles();
2104               TColgp_Array1OfPnt tpoles(1,nbpoles);
2105               mbspc.Curve(1,tpoles);
2106               BS=new Geom_BSplineCurve(tpoles,
2107                                                                  mbspc.Knots(),
2108                                                                  mbspc.Multiplicities(),
2109                                                                  mbspc.Degree());
2110               GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK);
2111               Check.FixTangent(Standard_True,Standard_True);
2112               //                 
2113               aCurve.SetCurve(BS);
2114               aCurve.SetFirstCurve2d(aH2D);
2115               aCurve.SetSecondCurve2d(aH2D);
2116               //
2117               if(myApprox1) { 
2118                 if(anApprox1) {
2119                   Handle(Geom2d_BSplineCurve) BS1;
2120                   TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
2121                   mbspc.Curve(2,tpoles2d);
2122                   //
2123                   BS1=new Geom2d_BSplineCurve(tpoles2d,
2124                                                                         mbspc.Knots(),
2125                                                                         mbspc.Multiplicities(),
2126                                                                         mbspc.Degree());
2127                   GeomLib_Check2dBSplineCurve newCheck(BS1,TOLCHECK,TOLANGCHECK);
2128                   newCheck.FixTangent(Standard_True,Standard_True);
2129                   //         
2130                   if (!reApprox) {
2131                     bIsValid1=CheckPCurve(BS1, myFace1);
2132                   }
2133                   //
2134                   aCurve.SetFirstCurve2d(BS1);
2135                 }
2136                 else {
2137                   Handle(Geom2d_BSplineCurve) BS1;
2138                   fprm = BS->FirstParameter();
2139                   lprm = BS->LastParameter();
2140
2141                   Handle(Geom2d_Curve) C2d;
2142                   Standard_Real aTol = myTolApprox;
2143                   GeomInt_IntSS::BuildPCurves(fprm, lprm, aTol,
2144                             myHS1->ChangeSurface().Surface(), BS, C2d);
2145                   BS1 = Handle(Geom2d_BSplineCurve)::DownCast(C2d);
2146                   aCurve.SetFirstCurve2d(BS1);
2147                 }
2148               } // if(myApprox1) { 
2149                 //                 
2150               if(myApprox2) { 
2151                 if(anApprox2) {
2152                   Handle(Geom2d_BSplineCurve) BS2;
2153                   TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
2154                   mbspc.Curve((myApprox1==Standard_True)? 3 : 2,tpoles2d);
2155                   BS2=new Geom2d_BSplineCurve(tpoles2d,
2156                                                                         mbspc.Knots(),
2157                                                                         mbspc.Multiplicities(),
2158                                                                         mbspc.Degree());
2159                   GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK);
2160                   newCheck.FixTangent(Standard_True,Standard_True);
2161                 //                 
2162                   if (!reApprox) {
2163                     bIsValid2=CheckPCurve(BS2, myFace2);        
2164                   }
2165                   aCurve.SetSecondCurve2d(BS2);
2166                 }
2167                 else {
2168                   Handle(Geom2d_BSplineCurve) BS2;
2169                   fprm = BS->FirstParameter();
2170                   lprm = BS->LastParameter();
2171
2172                   Handle(Geom2d_Curve) C2d;
2173                   Standard_Real aTol = myTolApprox;
2174                   GeomInt_IntSS::BuildPCurves(fprm, lprm, aTol,
2175                             myHS2->ChangeSurface().Surface(), BS, C2d);
2176                   BS2 = Handle(Geom2d_BSplineCurve)::DownCast(C2d);
2177                   aCurve.SetSecondCurve2d(BS2);
2178                 }
2179               } //if(myApprox2) { 
2180               if (!bIsValid1 || !bIsValid2) {
2181                 myTolApprox=aTolApproxImp;//1.e-5;
2182                 tol2d = myTolApprox;
2183                 reApprox = Standard_True;
2184                 goto reapprox;
2185               }
2186                 //                 
2187               mySeqOfCurve.Append(aCurve);
2188             }
2189           }
2190         }
2191       }
2192     }// else { // X
2193   }// case IntPatch_Walking:{
2194     break;
2195     
2196   case IntPatch_Restriction: 
2197     {
2198       GeomAbs_SurfaceType typS1 = myHS1->Surface().GetType();
2199       GeomAbs_SurfaceType typS2 = myHS2->Surface().GetType();
2200       Standard_Boolean isAnalS1 = Standard_False;
2201       switch (typS1)
2202       {
2203       case GeomAbs_Plane:
2204       case GeomAbs_Cylinder:
2205       case GeomAbs_Sphere:
2206       case GeomAbs_Cone: 
2207       case GeomAbs_Torus: isAnalS1 = Standard_True; break;
2208       default: break;
2209       }
2210
2211       Standard_Integer isAnalS2 = Standard_False;
2212       switch (typS2)
2213       {
2214       case GeomAbs_Plane:
2215       case GeomAbs_Cylinder:
2216       case GeomAbs_Sphere:
2217       case GeomAbs_Cone: 
2218       case GeomAbs_Torus: isAnalS2 = Standard_True; break;
2219       default: break;
2220       }
2221
2222       Handle(IntPatch_RLine) RL = 
2223         Handle(IntPatch_RLine)::DownCast(L);
2224       Handle(Geom_Curve) aC3d;
2225       Handle(Geom2d_Curve) aC2d1, aC2d2;
2226       Standard_Real aTolReached;
2227       GeomInt_IntSS::TreatRLine(RL, myHS1, myHS2, aC3d,
2228                                   aC2d1, aC2d2, aTolReached);
2229
2230       if(aC3d.IsNull())
2231         break;
2232
2233       Bnd_Box2d aBox1, aBox2;
2234
2235       const Standard_Real aU1f = myHS1->FirstUParameter(),
2236                           aV1f = myHS1->FirstVParameter(),
2237                           aU1l = myHS1->LastUParameter(),
2238                           aV1l = myHS1->LastVParameter();
2239       const Standard_Real aU2f = myHS2->FirstUParameter(),
2240                           aV2f = myHS2->FirstVParameter(),
2241                           aU2l = myHS2->LastUParameter(),
2242                           aV2l = myHS2->LastVParameter();
2243
2244       aBox1.Add(gp_Pnt2d(aU1f, aV1f));
2245       aBox1.Add(gp_Pnt2d(aU1l, aV1l));
2246       aBox2.Add(gp_Pnt2d(aU2f, aV2f));
2247       aBox2.Add(gp_Pnt2d(aU2l, aV2l));
2248
2249       GeomInt_VectorOfReal anArrayOfParameters;
2250         
2251       //We consider here that the intersection line is same-parameter-line
2252       anArrayOfParameters.Append(aC3d->FirstParameter());
2253       anArrayOfParameters.Append(aC3d->LastParameter());
2254
2255       GeomInt_IntSS::
2256         TrimILineOnSurfBoundaries(aC2d1, aC2d2, aBox1, aBox2, anArrayOfParameters);
2257
2258       const Standard_Integer aNbIntersSolutionsm1 = anArrayOfParameters.Length() - 1;
2259
2260       //Trim RLine found.
2261       for(Standard_Integer anInd = 0; anInd < aNbIntersSolutionsm1; anInd++)
2262       {
2263         const Standard_Real aParF = anArrayOfParameters(anInd),
2264                             aParL = anArrayOfParameters(anInd+1);
2265
2266         if((aParL - aParF) <= Precision::PConfusion())
2267           continue;
2268
2269         const Standard_Real aPar = 0.5*(aParF + aParL);
2270         gp_Pnt2d aPt;
2271
2272         Handle(Geom2d_Curve) aCurv2d1, aCurv2d2;
2273         if(!aC2d1.IsNull())
2274         {
2275           aC2d1->D0(aPar, aPt);
2276
2277           if(aBox1.IsOut(aPt))
2278             continue;
2279
2280           if(myApprox1)
2281             aCurv2d1 = new Geom2d_TrimmedCurve(aC2d1, aParF, aParL);
2282         }
2283
2284         if(!aC2d2.IsNull())
2285         {
2286           aC2d2->D0(aPar, aPt);
2287
2288           if(aBox2.IsOut(aPt))
2289             continue;
2290
2291           if(myApprox2)
2292             aCurv2d2 = new Geom2d_TrimmedCurve(aC2d2, aParF, aParL);
2293         }
2294
2295         Handle(Geom_Curve) aCurv3d = new Geom_TrimmedCurve(aC3d, aParF, aParL);
2296
2297         IntTools_Curve aIC(aCurv3d, aCurv2d1, aCurv2d2);
2298         mySeqOfCurve.Append(aIC);
2299       }
2300     }
2301     break;
2302   default:
2303     break;
2304
2305   }
2306 }
2307
2308 //=======================================================================
2309 //function : Parameters
2310 //purpose  : 
2311 //=======================================================================
2312  void Parameters(const Handle(GeomAdaptor_HSurface)& HS1,
2313                  const Handle(GeomAdaptor_HSurface)& HS2,
2314                  const gp_Pnt& Ptref,
2315                  Standard_Real& U1,
2316                  Standard_Real& V1,
2317                  Standard_Real& U2,
2318                  Standard_Real& V2)
2319 {
2320
2321   IntSurf_Quadric quad1,quad2;
2322   GeomAbs_SurfaceType typs = HS1->Surface().GetType();
2323
2324   switch (typs) {
2325   case GeomAbs_Plane:
2326     quad1.SetValue(HS1->Surface().Plane());
2327     break;
2328   case GeomAbs_Cylinder:
2329     quad1.SetValue(HS1->Surface().Cylinder());
2330     break;
2331   case GeomAbs_Cone:
2332     quad1.SetValue(HS1->Surface().Cone());
2333     break;
2334   case GeomAbs_Sphere:
2335     quad1.SetValue(HS1->Surface().Sphere());
2336     break;
2337   case GeomAbs_Torus:
2338     quad1.SetValue(HS1->Surface().Torus());
2339     break;
2340   default:
2341     Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve");
2342   }
2343   
2344   typs = HS2->Surface().GetType();
2345   switch (typs) {
2346   case GeomAbs_Plane:
2347     quad2.SetValue(HS2->Surface().Plane());
2348     break;
2349   case GeomAbs_Cylinder:
2350     quad2.SetValue(HS2->Surface().Cylinder());
2351     break;
2352   case GeomAbs_Cone:
2353     quad2.SetValue(HS2->Surface().Cone());
2354     break;
2355   case GeomAbs_Sphere:
2356     quad2.SetValue(HS2->Surface().Sphere());
2357     break;
2358   case GeomAbs_Torus:
2359     quad2.SetValue(HS2->Surface().Torus());
2360     break;
2361   default:
2362     Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve");
2363   }
2364
2365   quad1.Parameters(Ptref,U1,V1);
2366   quad2.Parameters(Ptref,U2,V2);
2367 }
2368
2369 //=======================================================================
2370 //function : MakeBSpline
2371 //purpose  : 
2372 //=======================================================================
2373 Handle(Geom_Curve) MakeBSpline  (const Handle(IntPatch_WLine)& WL,
2374                                  const Standard_Integer ideb,
2375                                  const Standard_Integer ifin)
2376 {
2377   Standard_Integer i,nbpnt = ifin-ideb+1;
2378   TColgp_Array1OfPnt poles(1,nbpnt);
2379   TColStd_Array1OfReal knots(1,nbpnt);
2380   TColStd_Array1OfInteger mults(1,nbpnt);
2381   Standard_Integer ipidebm1;
2382   for(i=1,ipidebm1=i+ideb-1; i<=nbpnt;ipidebm1++, i++) {
2383     poles(i) = WL->Point(ipidebm1).Value();
2384     mults(i) = 1;
2385     knots(i) = i-1;
2386   }
2387   mults(1) = mults(nbpnt) = 2;
2388   return
2389     new Geom_BSplineCurve(poles,knots,mults,1);
2390 }
2391 //
2392
2393 //=======================================================================
2394 //function : MakeBSpline2d
2395 //purpose  : 
2396 //=======================================================================
2397 Handle(Geom2d_BSplineCurve) MakeBSpline2d(const Handle(IntPatch_WLine)& theWLine,
2398                                           const Standard_Integer ideb,
2399                                           const Standard_Integer ifin,
2400                                           const Standard_Boolean onFirst)
2401 {
2402   Standard_Integer i, nbpnt = ifin-ideb+1;
2403   TColgp_Array1OfPnt2d poles(1,nbpnt);
2404   TColStd_Array1OfReal knots(1,nbpnt);
2405   TColStd_Array1OfInteger mults(1,nbpnt);
2406   Standard_Integer ipidebm1;
2407
2408   for(i = 1, ipidebm1 = i+ideb-1; i <= nbpnt; ipidebm1++, i++) {
2409       Standard_Real U, V;
2410       if(onFirst)
2411         theWLine->Point(ipidebm1).ParametersOnS1(U, V);
2412       else
2413         theWLine->Point(ipidebm1).ParametersOnS2(U, V);
2414       poles(i).SetCoord(U, V);
2415       mults(i) = 1;
2416       knots(i) = i-1;
2417     }
2418     mults(1) = mults(nbpnt) = 2;
2419
2420   return new Geom2d_BSplineCurve(poles,knots,mults,1);
2421 }
2422 //=======================================================================
2423 //function : PrepareLines3D
2424 //purpose  : 
2425 //=======================================================================
2426   void IntTools_FaceFace::PrepareLines3D(const Standard_Boolean bToSplit)
2427 {
2428   Standard_Integer i, aNbCurves;
2429   GeomAbs_SurfaceType aType1, aType2;
2430   IntTools_SequenceOfCurves aNewCvs;
2431   //
2432   // 1. Treatment closed  curves
2433   aNbCurves=mySeqOfCurve.Length();
2434   for (i=1; i<=aNbCurves; ++i) {
2435     const IntTools_Curve& aIC=mySeqOfCurve(i);
2436     //
2437     if (bToSplit) {
2438       Standard_Integer j, aNbC;
2439       IntTools_SequenceOfCurves aSeqCvs;
2440       //
2441       aNbC=IntTools_Tools::SplitCurve(aIC, aSeqCvs);
2442       if (aNbC) {
2443         for (j=1; j<=aNbC; ++j) {
2444           const IntTools_Curve& aICNew=aSeqCvs(j);
2445           aNewCvs.Append(aICNew);
2446         }
2447       }
2448       else {
2449         aNewCvs.Append(aIC);
2450       }
2451     }
2452     else {
2453       aNewCvs.Append(aIC);
2454     }
2455   }
2456   //
2457   // 2. Plane\Cone intersection when we had 4 curves
2458   aType1=myHS1->GetType();
2459   aType2=myHS2->GetType();
2460   aNbCurves=aNewCvs.Length();
2461   //
2462   if ((aType1==GeomAbs_Plane && aType2==GeomAbs_Cone) ||
2463       (aType2==GeomAbs_Plane && aType1==GeomAbs_Cone)) {
2464     if (aNbCurves==4) {
2465       GeomAbs_CurveType aCType1;
2466       //
2467       aCType1=aNewCvs(1).Type();
2468       if (aCType1==GeomAbs_Line) {
2469         IntTools_SequenceOfCurves aSeqIn, aSeqOut;
2470         //
2471         for (i=1; i<=aNbCurves; ++i) {
2472           const IntTools_Curve& aIC=aNewCvs(i);
2473           aSeqIn.Append(aIC);
2474         }
2475         //
2476         IntTools_Tools::RejectLines(aSeqIn, aSeqOut);
2477         //
2478         aNewCvs.Clear();
2479         aNbCurves=aSeqOut.Length(); 
2480         for (i=1; i<=aNbCurves; ++i) {
2481           const IntTools_Curve& aIC=aSeqOut(i);
2482           aNewCvs.Append(aIC);
2483         }
2484       }
2485     }
2486   }// if ((aType1==GeomAbs_Plane && aType2==GeomAbs_Cone)...
2487   //
2488   // 3. Fill  mySeqOfCurve
2489   mySeqOfCurve.Clear();
2490   aNbCurves=aNewCvs.Length();
2491   for (i=1; i<=aNbCurves; ++i) {
2492     const IntTools_Curve& aIC=aNewCvs(i);
2493     mySeqOfCurve.Append(aIC);
2494   }
2495 }
2496 //=======================================================================
2497 //function : CorrectSurfaceBoundaries
2498 //purpose  : 
2499 //=======================================================================
2500  void CorrectSurfaceBoundaries(const TopoDS_Face&  theFace,
2501                               const Standard_Real theTolerance,
2502                               Standard_Real&      theumin,
2503                               Standard_Real&      theumax, 
2504                               Standard_Real&      thevmin, 
2505                               Standard_Real&      thevmax) 
2506 {
2507   Standard_Boolean enlarge, isuperiodic, isvperiodic;
2508   Standard_Real uinf, usup, vinf, vsup, delta;
2509   GeomAbs_SurfaceType aType;
2510   Handle(Geom_Surface) aSurface;
2511   //
2512   aSurface = BRep_Tool::Surface(theFace);
2513   aSurface->Bounds(uinf, usup, vinf, vsup);
2514   delta = theTolerance;
2515   enlarge = Standard_False;
2516   //
2517   GeomAdaptor_Surface anAdaptorSurface(aSurface);
2518   //
2519   if(aSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
2520     Handle(Geom_Surface) aBasisSurface = 
2521       (Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface))->BasisSurface();
2522     
2523     if(aBasisSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)) ||
2524        aBasisSurface->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
2525       return;
2526     }
2527   }
2528   //
2529   if(aSurface->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
2530     Handle(Geom_Surface) aBasisSurface = 
2531       (Handle(Geom_OffsetSurface)::DownCast(aSurface))->BasisSurface();
2532     
2533     if(aBasisSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)) ||
2534        aBasisSurface->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
2535       return;
2536     }
2537   }
2538   //
2539   isuperiodic = anAdaptorSurface.IsUPeriodic();
2540   isvperiodic = anAdaptorSurface.IsVPeriodic();
2541   //
2542   aType=anAdaptorSurface.GetType();
2543   if((aType==GeomAbs_BezierSurface) ||
2544      (aType==GeomAbs_BSplineSurface) ||
2545      (aType==GeomAbs_SurfaceOfExtrusion) ||
2546      (aType==GeomAbs_SurfaceOfRevolution) ||
2547      (aType==GeomAbs_Cylinder)) {
2548     enlarge=Standard_True;
2549   }
2550   //
2551   if(!isuperiodic && enlarge) {
2552
2553     if(!Precision::IsInfinite(theumin) &&
2554         ((theumin - uinf) > delta))
2555       theumin -= delta;
2556     else {
2557       theumin = uinf;
2558     }
2559
2560     if(!Precision::IsInfinite(theumax) &&
2561         ((usup - theumax) > delta))
2562       theumax += delta;
2563     else
2564       theumax = usup;
2565   }
2566   //
2567   if(!isvperiodic && enlarge) {
2568     if(!Precision::IsInfinite(thevmin) &&
2569         ((thevmin - vinf) > delta)) {
2570       thevmin -= delta;
2571     }
2572     else { 
2573       thevmin = vinf;
2574     }
2575     if(!Precision::IsInfinite(thevmax) &&
2576         ((vsup - thevmax) > delta)) {
2577       thevmax += delta;
2578     }
2579     else {
2580       thevmax = vsup;
2581     }
2582   }
2583   //
2584   {
2585     Standard_Integer aNbP;
2586     Standard_Real aXP, dXfact, aXmid, aX1, aX2, aTolPA;
2587     //
2588     aTolPA=Precision::Angular();
2589     // U
2590     if (isuperiodic) {
2591       aXP=anAdaptorSurface.UPeriod();
2592       dXfact=theumax-theumin;
2593       if (dXfact-aTolPA>aXP) {
2594         aXmid=0.5*(theumax+theumin);
2595         aNbP=RealToInt(aXmid/aXP);
2596         if (aXmid<0.) {
2597           aNbP=aNbP-1;
2598         }
2599         aX1=aNbP*aXP;
2600         if (theumin>aTolPA) {
2601           aX1=theumin+aNbP*aXP;
2602         }
2603         aX2=aX1+aXP;
2604         if (theumin<aX1) {
2605           theumin=aX1;
2606         }
2607         if (theumax>aX2) {
2608           theumax=aX2;
2609         }
2610       }
2611     }
2612     // V
2613     if (isvperiodic) {
2614       aXP=anAdaptorSurface.VPeriod();
2615       dXfact=thevmax-thevmin;
2616       if (dXfact-aTolPA>aXP) {
2617         aXmid=0.5*(thevmax+thevmin);
2618         aNbP=RealToInt(aXmid/aXP);
2619         if (aXmid<0.) {
2620           aNbP=aNbP-1;
2621         }
2622         aX1=aNbP*aXP;
2623         if (thevmin>aTolPA) {
2624           aX1=thevmin+aNbP*aXP;
2625         }
2626         aX2=aX1+aXP;
2627         if (thevmin<aX1) {
2628           thevmin=aX1;
2629         }
2630         if (thevmax>aX2) {
2631           thevmax=aX2;
2632         }
2633       }
2634     }
2635   }
2636   //
2637   if(isuperiodic || isvperiodic) {
2638     Standard_Boolean correct = Standard_False;
2639     Standard_Boolean correctU = Standard_False;
2640     Standard_Boolean correctV = Standard_False;
2641     Bnd_Box2d aBox;
2642     TopExp_Explorer anExp;
2643
2644     for(anExp.Init(theFace, TopAbs_EDGE); anExp.More(); anExp.Next()) {
2645       if(BRep_Tool::IsClosed(TopoDS::Edge(anExp.Current()), theFace)) {
2646         correct = Standard_True;
2647         Standard_Real f, l;
2648         TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
2649         
2650         for(Standard_Integer i = 0; i < 2; i++) {
2651           if(i==0) {
2652             anEdge.Orientation(TopAbs_FORWARD);
2653           }
2654           else {
2655             anEdge.Orientation(TopAbs_REVERSED);
2656           }
2657           Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, f, l);
2658           
2659           if(aCurve.IsNull()) {
2660             correct = Standard_False;
2661             break;
2662           }
2663           Handle(Geom2d_Line) aLine = Handle(Geom2d_Line)::DownCast(aCurve);
2664
2665           if(aLine.IsNull()) {
2666             correct = Standard_False;
2667             break;
2668           }
2669           gp_Dir2d anUDir(1., 0.);
2670           gp_Dir2d aVDir(0., 1.);
2671           Standard_Real anAngularTolerance = Precision::Angular();
2672
2673           correctU = correctU || aLine->Position().Direction().IsParallel(aVDir, anAngularTolerance);
2674           correctV = correctV || aLine->Position().Direction().IsParallel(anUDir, anAngularTolerance);
2675           
2676           gp_Pnt2d pp1 = aCurve->Value(f);
2677           aBox.Add(pp1);
2678           gp_Pnt2d pp2 = aCurve->Value(l);
2679           aBox.Add(pp2);
2680         }
2681         if(!correct)
2682           break;
2683       }
2684     }
2685
2686     if(correct) {
2687       Standard_Real umin, vmin, umax, vmax;
2688       aBox.Get(umin, vmin, umax, vmax);
2689
2690       if(isuperiodic && correctU) {
2691         
2692         if(theumin < umin)
2693           theumin = umin;
2694         
2695         if(theumax > umax) {
2696           theumax = umax;
2697         }
2698       }
2699       if(isvperiodic && correctV) {
2700         
2701         if(thevmin < vmin)
2702           thevmin = vmin;
2703         if(thevmax > vmax)
2704           thevmax = vmax;
2705       }
2706     }
2707   }
2708 }
2709 //
2710 //
2711 // The block is dedicated to determine whether WLine [ifprm, ilprm]
2712 // crosses the degenerated zone on each given surface or not.
2713 // If Yes -> We will not use info about surfaces during approximation
2714 // because inside degenerated zone of the surface the approx. algo.
2715 // uses wrong values of normal, etc., and resulting curve will have
2716 // oscillations that we would not like to have. 
2717  
2718
2719
2720 static
2721   Standard_Boolean IsDegeneratedZone(const gp_Pnt2d& aP2d,
2722                                      const Handle(Geom_Surface)& aS,
2723                                      const Standard_Integer iDir);
2724 static
2725   Standard_Boolean IsPointInDegeneratedZone(const IntSurf_PntOn2S& aP2S,
2726                                             const TopoDS_Face& aF1,
2727                                             const TopoDS_Face& aF2);
2728 //=======================================================================
2729 //function :  NotUseSurfacesForApprox
2730 //purpose  : 
2731 //=======================================================================
2732 Standard_Boolean NotUseSurfacesForApprox(const TopoDS_Face& aF1,
2733                                          const TopoDS_Face& aF2,
2734                                          const Handle(IntPatch_WLine)& WL,
2735                                          const Standard_Integer ifprm,
2736                                          const Standard_Integer ilprm)
2737 {
2738   Standard_Boolean bPInDZ;
2739
2740   Handle(IntSurf_LineOn2S) aLineOn2S=WL->Curve();
2741   
2742   const IntSurf_PntOn2S& aP2Sfprm=aLineOn2S->Value(ifprm);
2743   bPInDZ=IsPointInDegeneratedZone(aP2Sfprm, aF1, aF2);
2744   if (bPInDZ) {
2745     return bPInDZ;
2746   }
2747
2748   const IntSurf_PntOn2S& aP2Slprm=aLineOn2S->Value(ilprm);
2749   bPInDZ=IsPointInDegeneratedZone(aP2Slprm, aF1, aF2);
2750   
2751   return bPInDZ;
2752 }
2753 //=======================================================================
2754 //function : IsPointInDegeneratedZone
2755 //purpose  : 
2756 //=======================================================================
2757 Standard_Boolean IsPointInDegeneratedZone(const IntSurf_PntOn2S& aP2S,
2758                                           const TopoDS_Face& aF1,
2759                                           const TopoDS_Face& aF2)
2760                                           
2761 {
2762   Standard_Boolean bFlag=Standard_True;
2763   Standard_Real US11, US12, VS11, VS12, US21, US22, VS21, VS22;
2764   Standard_Real U1, V1, U2, V2, aDelta, aD;
2765   gp_Pnt2d aP2d;
2766
2767   Handle(Geom_Surface)aS1 = BRep_Tool::Surface(aF1);
2768   aS1->Bounds(US11, US12, VS11, VS12);
2769   GeomAdaptor_Surface aGAS1(aS1);
2770
2771   Handle(Geom_Surface)aS2 = BRep_Tool::Surface(aF2);
2772   aS1->Bounds(US21, US22, VS21, VS22);
2773   GeomAdaptor_Surface aGAS2(aS2);
2774   //
2775   //const gp_Pnt& aP=aP2S.Value();
2776   aP2S.Parameters(U1, V1, U2, V2);
2777   //
2778   aDelta=1.e-7;
2779   // Check on Surf 1
2780   aD=aGAS1.UResolution(aDelta);
2781   aP2d.SetCoord(U1, V1);
2782   if (fabs(U1-US11) < aD) {
2783     bFlag=IsDegeneratedZone(aP2d, aS1, 1);
2784     if (bFlag) {
2785       return bFlag;
2786     }
2787   }
2788   if (fabs(U1-US12) < aD) {
2789     bFlag=IsDegeneratedZone(aP2d, aS1, 1);
2790     if (bFlag) {
2791       return bFlag;
2792     }
2793   }
2794   aD=aGAS1.VResolution(aDelta);
2795   if (fabs(V1-VS11) < aDelta) {
2796     bFlag=IsDegeneratedZone(aP2d, aS1, 2);
2797     if (bFlag) {
2798       return bFlag;
2799     }
2800   }
2801   if (fabs(V1-VS12) < aDelta) {
2802     bFlag=IsDegeneratedZone(aP2d, aS1, 2);
2803     if (bFlag) {
2804       return bFlag;
2805     }
2806   }
2807   // Check on Surf 2
2808   aD=aGAS2.UResolution(aDelta);
2809   aP2d.SetCoord(U2, V2);
2810   if (fabs(U2-US21) < aDelta) {
2811     bFlag=IsDegeneratedZone(aP2d, aS2, 1);
2812     if (bFlag) {
2813       return bFlag;
2814     }
2815   }
2816   if (fabs(U2-US22) < aDelta) {
2817     bFlag=IsDegeneratedZone(aP2d, aS2, 1);
2818     if (bFlag) {
2819       return bFlag;
2820     }
2821   }
2822   aD=aGAS2.VResolution(aDelta);
2823   if (fabs(V2-VS21) < aDelta) {
2824     bFlag=IsDegeneratedZone(aP2d, aS2, 2);
2825     if (bFlag) {  
2826       return bFlag;
2827     }
2828   }
2829   if (fabs(V2-VS22) < aDelta) {
2830     bFlag=IsDegeneratedZone(aP2d, aS2, 2);
2831     if (bFlag) {
2832       return bFlag;
2833     }
2834   }
2835   return !bFlag;
2836 }
2837
2838 //=======================================================================
2839 //function : IsDegeneratedZone
2840 //purpose  : 
2841 //=======================================================================
2842 Standard_Boolean IsDegeneratedZone(const gp_Pnt2d& aP2d,
2843                                    const Handle(Geom_Surface)& aS,
2844                                    const Standard_Integer iDir)
2845 {
2846   Standard_Boolean bFlag=Standard_True;
2847   Standard_Real US1, US2, VS1, VS2, dY, dX, d1, d2, dD;
2848   Standard_Real aXm, aYm, aXb, aYb, aXe, aYe;
2849   aS->Bounds(US1, US2, VS1, VS2); 
2850
2851   gp_Pnt aPm, aPb, aPe;
2852   
2853   aXm=aP2d.X();
2854   aYm=aP2d.Y();
2855   
2856   aS->D0(aXm, aYm, aPm); 
2857   
2858   dX=1.e-5;
2859   dY=1.e-5;
2860   dD=1.e-12;
2861
2862   if (iDir==1) {
2863     aXb=aXm;
2864     aXe=aXm;
2865     aYb=aYm-dY;
2866     if (aYb < VS1) {
2867       aYb=VS1;
2868     }
2869     aYe=aYm+dY;
2870     if (aYe > VS2) {
2871       aYe=VS2;
2872     }
2873     aS->D0(aXb, aYb, aPb);
2874     aS->D0(aXe, aYe, aPe);
2875     
2876     d1=aPm.Distance(aPb);
2877     d2=aPm.Distance(aPe);
2878     if (d1 < dD && d2 < dD) {
2879       return bFlag;
2880     }
2881     return !bFlag;
2882   }
2883   //
2884   else if (iDir==2) {
2885     aYb=aYm;
2886     aYe=aYm;
2887     aXb=aXm-dX;
2888     if (aXb < US1) {
2889       aXb=US1;
2890     }
2891     aXe=aXm+dX;
2892     if (aXe > US2) {
2893       aXe=US2;
2894     }
2895     aS->D0(aXb, aYb, aPb);
2896     aS->D0(aXe, aYe, aPe);
2897     
2898     d1=aPm.Distance(aPb);
2899     d2=aPm.Distance(aPe);
2900     if (d1 < dD && d2 < dD) {
2901       return bFlag;
2902     }
2903     return !bFlag;
2904   }
2905   return !bFlag;
2906 }
2907
2908 //=========================================================================
2909 // static function : ComputePurgedWLine
2910 // purpose : Removes equal points (leave one of equal points) from theWLine
2911 //           and recompute vertex parameters.
2912 //           Returns new WLine or null WLine if the number
2913 //           of the points is less than 2.
2914 //=========================================================================
2915 Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine)& theWLine) {
2916  
2917   Standard_Integer i, k, v, nb, nbvtx;
2918   Handle(IntPatch_WLine) aResult;
2919   nbvtx = theWLine->NbVertex();
2920   nb = theWLine->NbPnts();
2921   if (nb==2) {
2922     const IntSurf_PntOn2S& p1 = theWLine->Point(1);
2923     const IntSurf_PntOn2S& p2 = theWLine->Point(2);
2924     if(p1.Value().IsEqual(p2.Value(), gp::Resolution())) {
2925       return aResult;
2926     }
2927   }
2928   //
2929   Handle(IntPatch_WLine) aLocalWLine;
2930   Handle(IntPatch_WLine) aTmpWLine = theWLine;
2931   Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
2932   aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
2933   for(i = 1; i <= nb; i++) {
2934     aLineOn2S->Add(theWLine->Point(i));
2935   }
2936
2937   for(v = 1; v <= nbvtx; v++) {
2938     aLocalWLine->AddVertex(theWLine->Vertex(v));
2939   }
2940   
2941   for(i = 1; i <= aLineOn2S->NbPoints(); i++) {
2942     Standard_Integer aStartIndex = i + 1;
2943     Standard_Integer anEndIndex = i + 5;
2944     nb = aLineOn2S->NbPoints();
2945     anEndIndex = (anEndIndex > nb) ? nb : anEndIndex;
2946
2947     if((aStartIndex > nb) || (anEndIndex <= 1)) {
2948       continue;
2949     }
2950     k = aStartIndex;
2951
2952     while(k <= anEndIndex) {
2953       
2954       if(i != k) {
2955         IntSurf_PntOn2S p1 = aLineOn2S->Value(i);
2956         IntSurf_PntOn2S p2 = aLineOn2S->Value(k);
2957         
2958         if(p1.Value().IsEqual(p2.Value(), gp::Resolution())) {
2959           aTmpWLine = aLocalWLine;
2960           aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
2961
2962           for(v = 1; v <= aTmpWLine->NbVertex(); v++) {
2963             IntPatch_Point aVertex = aTmpWLine->Vertex(v);
2964             Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
2965
2966             if(avertexindex >= k) {
2967               aVertex.SetParameter(aVertex.ParameterOnLine() - 1.);
2968             }
2969             aLocalWLine->AddVertex(aVertex);
2970           }
2971           aLineOn2S->RemovePoint(k);
2972           anEndIndex--;
2973           continue;
2974         }
2975       }
2976       k++;
2977     }
2978   }
2979
2980   if(aLineOn2S->NbPoints() > 1) {
2981     aResult = aLocalWLine;
2982   }
2983   return aResult;
2984 }
2985
2986 //=======================================================================
2987 //function : TolR3d
2988 //purpose  : 
2989 //=======================================================================
2990 void TolR3d(const TopoDS_Face& aF1,
2991             const TopoDS_Face& aF2,
2992             Standard_Real& myTolReached3d)
2993 {
2994   Standard_Real aTolF1, aTolF2, aTolFMax, aTolTresh;
2995       
2996   aTolTresh=2.999999e-3;
2997   aTolF1 = BRep_Tool::Tolerance(aF1);
2998   aTolF2 = BRep_Tool::Tolerance(aF2);
2999   aTolFMax=Max(aTolF1, aTolF2);
3000   
3001   if (aTolFMax>aTolTresh) {
3002     myTolReached3d=aTolFMax;
3003   }
3004 }
3005 //=======================================================================
3006 //function : IsPointOnBoundary
3007 //purpose  : 
3008 //=======================================================================
3009 Standard_Boolean IsPointOnBoundary(const Standard_Real theParameter,
3010                                    const Standard_Real theFirstBoundary,
3011                                    const Standard_Real theSecondBoundary,
3012                                    const Standard_Real theResolution,
3013                                    Standard_Boolean&   IsOnFirstBoundary) 
3014 {
3015   Standard_Boolean bRet;
3016   Standard_Integer i;
3017   Standard_Real adist;
3018   //
3019   bRet=Standard_False;
3020   for(i = 0; i < 2; ++i) {
3021     IsOnFirstBoundary = (i == 0);
3022     if (IsOnFirstBoundary) {
3023       adist = fabs(theParameter - theFirstBoundary);
3024     }
3025     else {
3026       adist = fabs(theParameter - theSecondBoundary);
3027     }
3028     if(adist < theResolution) {
3029       return !bRet;
3030     }
3031   }
3032   return bRet;
3033 }
3034 // ------------------------------------------------------------------------------------------------
3035 // static function: FindPoint
3036 // purpose:
3037 // ------------------------------------------------------------------------------------------------
3038 Standard_Boolean FindPoint(const gp_Pnt2d&     theFirstPoint,
3039                            const gp_Pnt2d&     theLastPoint,
3040                            const Standard_Real theUmin, 
3041                            const Standard_Real theUmax,
3042                            const Standard_Real theVmin,
3043                            const Standard_Real theVmax,
3044                            gp_Pnt2d&           theNewPoint) {
3045   
3046   gp_Vec2d aVec(theFirstPoint, theLastPoint);
3047   Standard_Integer i = 0, j = 0;
3048
3049   for(i = 0; i < 4; i++) {
3050     gp_Vec2d anOtherVec;
3051     gp_Vec2d anOtherVecNormal;
3052     gp_Pnt2d aprojpoint = theLastPoint;    
3053
3054     if((i % 2) == 0) {
3055       anOtherVec.SetX(0.);
3056       anOtherVec.SetY(1.);
3057       anOtherVecNormal.SetX(1.);
3058       anOtherVecNormal.SetY(0.);
3059
3060       if(i < 2)
3061         aprojpoint.SetX(theUmin);
3062       else
3063         aprojpoint.SetX(theUmax);
3064     }
3065     else {
3066       anOtherVec.SetX(1.);
3067       anOtherVec.SetY(0.);
3068       anOtherVecNormal.SetX(0.);
3069       anOtherVecNormal.SetY(1.);
3070
3071       if(i < 2)
3072         aprojpoint.SetY(theVmin);
3073       else
3074         aprojpoint.SetY(theVmax);
3075     }
3076     gp_Vec2d anormvec = aVec;
3077     anormvec.Normalize();
3078     RefineVector(anormvec);
3079     Standard_Real adot1 = anormvec.Dot(anOtherVecNormal);
3080
3081     if(fabs(adot1) < Precision::Angular())
3082       continue;
3083     Standard_Real adist = 0.;
3084     Standard_Boolean bIsOut = Standard_False;
3085
3086     if((i % 2) == 0) {
3087       adist = (i < 2) ? fabs(theLastPoint.X() - theUmin) : fabs(theLastPoint.X() - theUmax);
3088       bIsOut = (i < 2) ? (theLastPoint.X() < theUmin) : (theLastPoint.X() > theUmax);
3089     }
3090     else {
3091       adist = (i < 2) ? fabs(theLastPoint.Y() - theVmin) : fabs(theLastPoint.Y() - theVmax);
3092       bIsOut = (i < 2) ? (theLastPoint.Y() < theVmin) : (theLastPoint.Y() > theVmax);
3093     }
3094     Standard_Real anoffset = adist * anOtherVec.Dot(anormvec) / adot1;
3095
3096     for(j = 0; j < 2; j++) {
3097       anoffset = (j == 0) ? anoffset : -anoffset;
3098       gp_Pnt2d acurpoint(aprojpoint.XY() + (anOtherVec.XY()*anoffset));
3099       gp_Vec2d acurvec(theLastPoint, acurpoint);
3100       if ( bIsOut )
3101         acurvec.Reverse();
3102
3103       Standard_Real aDotX, anAngleX;
3104       //
3105       aDotX = aVec.Dot(acurvec);
3106       anAngleX = aVec.Angle(acurvec);
3107       //
3108       if(aDotX > 0. && fabs(anAngleX) < Precision::PConfusion()) {
3109         if((i % 2) == 0) {
3110           if((acurpoint.Y() >= theVmin) &&
3111              (acurpoint.Y() <= theVmax)) {
3112             theNewPoint = acurpoint;
3113             return Standard_True;
3114           }
3115         }
3116         else {
3117           if((acurpoint.X() >= theUmin) &&
3118              (acurpoint.X() <= theUmax)) {
3119             theNewPoint = acurpoint;
3120             return Standard_True;
3121           }
3122         }
3123       }
3124     }
3125   }
3126   return Standard_False;
3127 }
3128
3129
3130 // ------------------------------------------------------------------------------------------------
3131 // static function: FindPoint
3132 // purpose: Find point on the boundary of radial tangent zone
3133 // ------------------------------------------------------------------------------------------------
3134 Standard_Boolean FindPoint(const gp_Pnt2d&     theFirstPoint,
3135                            const gp_Pnt2d&     theLastPoint,
3136                            const Standard_Real theUmin, 
3137                            const Standard_Real theUmax,
3138                            const Standard_Real theVmin,
3139                            const Standard_Real theVmax,
3140                            const gp_Pnt2d&     theTanZoneCenter,
3141                            const Standard_Real theZoneRadius,
3142                            Handle(GeomAdaptor_HSurface) theGASurface,
3143                            gp_Pnt2d&           theNewPoint) {
3144   theNewPoint = theLastPoint;
3145
3146   if ( !IsInsideTanZone( theLastPoint, theTanZoneCenter, theZoneRadius, theGASurface) )
3147     return Standard_False;
3148
3149   Standard_Real aUResolution = theGASurface->UResolution( theZoneRadius );
3150   Standard_Real aVResolution = theGASurface->VResolution( theZoneRadius );
3151
3152   Standard_Real aRadius = ( aUResolution < aVResolution ) ? aUResolution : aVResolution;
3153   gp_Ax22d anAxis( theTanZoneCenter, gp_Dir2d(1, 0), gp_Dir2d(0, 1) );
3154   gp_Circ2d aCircle( anAxis, aRadius );
3155   
3156   //
3157   gp_Vec2d aDir( theLastPoint.XY() - theFirstPoint.XY() );
3158   Standard_Real aLength = aDir.Magnitude();
3159   if ( aLength <= gp::Resolution() )
3160     return Standard_False;
3161   gp_Lin2d aLine( theFirstPoint, aDir );
3162
3163   //
3164   Handle(Geom2d_Line) aCLine = new Geom2d_Line( aLine );
3165   Handle(Geom2d_TrimmedCurve) aC1 = new Geom2d_TrimmedCurve( aCLine, 0, aLength );
3166   Handle(Geom2d_Circle) aC2 = new Geom2d_Circle( aCircle );
3167
3168   Standard_Real aTol = aRadius * 0.001;
3169   aTol = ( aTol < Precision::PConfusion() ) ? Precision::PConfusion() : aTol;
3170
3171   Geom2dAPI_InterCurveCurve anIntersector;
3172   anIntersector.Init( aC1, aC2, aTol );
3173
3174   if ( anIntersector.NbPoints() == 0 )
3175     return Standard_False;
3176
3177   Standard_Boolean aFound = Standard_False;
3178   Standard_Real aMinDist = aLength * aLength;
3179   Standard_Integer i = 0;
3180   for ( i = 1; i <= anIntersector.NbPoints(); i++ ) {
3181     gp_Pnt2d aPInt = anIntersector.Point( i );
3182     if ( aPInt.SquareDistance( theFirstPoint ) < aMinDist ) {
3183       if ( ( aPInt.X() >= theUmin ) && ( aPInt.X() <= theUmax ) &&
3184            ( aPInt.Y() >= theVmin ) && ( aPInt.Y() <= theVmax ) ) {
3185         theNewPoint = aPInt;
3186         aFound = Standard_True;
3187       }
3188     }
3189   }
3190
3191   return aFound;
3192 }
3193
3194 // ------------------------------------------------------------------------------------------------
3195 // static function: IsInsideTanZone
3196 // purpose: Check if point is inside a radial tangent zone
3197 // ------------------------------------------------------------------------------------------------
3198 Standard_Boolean IsInsideTanZone(const gp_Pnt2d&     thePoint,
3199                                  const gp_Pnt2d&     theTanZoneCenter,
3200                                  const Standard_Real theZoneRadius,
3201                                  Handle(GeomAdaptor_HSurface) theGASurface) {
3202
3203   Standard_Real aUResolution = theGASurface->UResolution( theZoneRadius );
3204   Standard_Real aVResolution = theGASurface->VResolution( theZoneRadius );
3205   Standard_Real aRadiusSQR = ( aUResolution < aVResolution ) ? aUResolution : aVResolution;
3206   aRadiusSQR *= aRadiusSQR;
3207   if ( thePoint.SquareDistance( theTanZoneCenter ) <= aRadiusSQR )
3208     return Standard_True;
3209   return Standard_False;
3210 }
3211
3212 // ------------------------------------------------------------------------------------------------
3213 // static function: CheckTangentZonesExist
3214 // purpose: Check if tangent zone exists
3215 // ------------------------------------------------------------------------------------------------
3216 Standard_Boolean CheckTangentZonesExist( const Handle(GeomAdaptor_HSurface)& theSurface1,
3217                                         const Handle(GeomAdaptor_HSurface)&  theSurface2 ) 
3218 {
3219   if ( ( theSurface1->GetType() != GeomAbs_Torus ) ||
3220       ( theSurface2->GetType() != GeomAbs_Torus ) )
3221     return Standard_False;
3222
3223   gp_Torus aTor1 = theSurface1->Torus();
3224   gp_Torus aTor2 = theSurface2->Torus();
3225
3226   if ( aTor1.Location().Distance( aTor2.Location() ) > Precision::Confusion() )
3227     return Standard_False;
3228
3229   if ( ( fabs( aTor1.MajorRadius() - aTor2.MajorRadius() ) > Precision::Confusion() ) ||
3230        ( fabs( aTor1.MinorRadius() - aTor2.MinorRadius() ) > Precision::Confusion() ) )
3231     return Standard_False;
3232
3233   if ( ( aTor1.MajorRadius() < aTor1.MinorRadius() ) ||
3234        ( aTor2.MajorRadius() < aTor2.MinorRadius() ) )
3235     return Standard_False;
3236   return Standard_True;
3237 }
3238
3239 // ------------------------------------------------------------------------------------------------
3240 // static function: ComputeTangentZones
3241 // purpose: 
3242 // ------------------------------------------------------------------------------------------------
3243 Standard_Integer ComputeTangentZones( const Handle(GeomAdaptor_HSurface)& theSurface1,
3244                                      const Handle(GeomAdaptor_HSurface)&  theSurface2,
3245                                      const TopoDS_Face&                   theFace1,
3246                                      const TopoDS_Face&                   theFace2,
3247                                      Handle(TColgp_HArray1OfPnt2d)&       theResultOnS1,
3248                                      Handle(TColgp_HArray1OfPnt2d)&       theResultOnS2,
3249                                      Handle(TColStd_HArray1OfReal)&       theResultRadius,
3250                                      const Handle(IntTools_Context)& aContext)
3251 {
3252   Standard_Integer aResult = 0;
3253   if ( !CheckTangentZonesExist( theSurface1, theSurface2 ) )
3254     return aResult;
3255
3256
3257   TColgp_SequenceOfPnt2d aSeqResultS1, aSeqResultS2;
3258   TColStd_SequenceOfReal aSeqResultRad;
3259
3260   gp_Torus aTor1 = theSurface1->Torus();
3261   gp_Torus aTor2 = theSurface2->Torus();
3262
3263   gp_Ax2 anax1( aTor1.Location(), aTor1.Axis().Direction() );
3264   gp_Ax2 anax2( aTor2.Location(), aTor2.Axis().Direction() );
3265   Standard_Integer j = 0;
3266
3267   for ( j = 0; j < 2; j++ ) {
3268     Standard_Real aCoef = ( j == 0 ) ? -1 : 1;
3269     Standard_Real aRadius1 = fabs(aTor1.MajorRadius() + aCoef * aTor1.MinorRadius());
3270     Standard_Real aRadius2 = fabs(aTor2.MajorRadius() + aCoef * aTor2.MinorRadius());
3271
3272     gp_Circ aCircle1( anax1, aRadius1 );
3273     gp_Circ aCircle2( anax2, aRadius2 );
3274
3275     // roughly compute radius of tangent zone for perpendicular case
3276     Standard_Real aCriteria = Precision::Confusion() * 0.5;
3277
3278     Standard_Real aT1 = aCriteria;
3279     Standard_Real aT2 = aCriteria;
3280     if ( j == 0 ) {
3281       // internal tangency
3282       Standard_Real aR = ( aRadius1 > aTor2.MinorRadius() ) ? aRadius1 : aTor2.MinorRadius();
3283       //aT1 = aCriteria * aCriteria + aR * aR - ( aR - aCriteria ) * ( aR - aCriteria );
3284       aT1 = 2. * aR * aCriteria;
3285       aT2 = aT1;
3286     }
3287     else {
3288       // external tangency
3289       Standard_Real aRb = ( aRadius1 > aTor2.MinorRadius() ) ? aRadius1 : aTor2.MinorRadius();
3290       Standard_Real aRm = ( aRadius1 < aTor2.MinorRadius() ) ? aRadius1 : aTor2.MinorRadius();
3291       Standard_Real aDelta = aRb - aCriteria;
3292       aDelta *= aDelta;
3293       aDelta -= aRm * aRm;
3294       aDelta /= 2. * (aRb - aRm);
3295       aDelta -= 0.5 * (aRb - aRm);
3296       
3297       aT1 = 2. * aRm * (aRm - aDelta);
3298       aT2 = aT1;
3299     }
3300     aCriteria = ( aT1 > aT2) ? aT1 : aT2;
3301     if ( aCriteria > 0 )
3302       aCriteria = sqrt( aCriteria );
3303
3304     if ( aCriteria > 0.5 * aTor1.MinorRadius() ) {
3305       // too big zone -> drop to minimum
3306       aCriteria = Precision::Confusion();
3307     }
3308
3309     GeomAdaptor_Curve aC1( new Geom_Circle(aCircle1) );
3310     GeomAdaptor_Curve aC2( new Geom_Circle(aCircle2) );
3311     Extrema_ExtCC anExtrema(aC1, aC2, 0, 2. * M_PI, 0, 2. * M_PI, 
3312                             Precision::PConfusion(), Precision::PConfusion());
3313             
3314     if ( anExtrema.IsDone() ) {
3315
3316       Standard_Integer i = 0;
3317       for ( i = 1; i <= anExtrema.NbExt(); i++ ) {
3318         if ( anExtrema.SquareDistance(i) > aCriteria * aCriteria )
3319           continue;
3320
3321         Extrema_POnCurv P1, P2;
3322         anExtrema.Points( i, P1, P2 );
3323
3324         Standard_Boolean bFoundResult = Standard_True;
3325         gp_Pnt2d pr1, pr2;
3326
3327         Standard_Integer surfit = 0;
3328         for ( surfit = 0; surfit < 2; surfit++ ) {
3329           GeomAPI_ProjectPointOnSurf& aProjector = 
3330             (surfit == 0) ? aContext->ProjPS(theFace1) : aContext->ProjPS(theFace2);
3331
3332           gp_Pnt aP3d = (surfit == 0) ? P1.Value() : P2.Value();
3333           aProjector.Perform(aP3d);
3334
3335           if(!aProjector.IsDone())
3336             bFoundResult = Standard_False;
3337           else {
3338             if(aProjector.LowerDistance() > aCriteria) {
3339               bFoundResult = Standard_False;
3340             }
3341             else {
3342               Standard_Real foundU = 0, foundV = 0;
3343               aProjector.LowerDistanceParameters(foundU, foundV);
3344               if ( surfit == 0 )
3345                 pr1 = gp_Pnt2d( foundU, foundV );
3346               else
3347                 pr2 = gp_Pnt2d( foundU, foundV );
3348             }
3349           }
3350         }
3351         if ( bFoundResult ) {
3352           aSeqResultS1.Append( pr1 );
3353           aSeqResultS2.Append( pr2 );
3354           aSeqResultRad.Append( aCriteria );
3355
3356           // torus is u and v periodic
3357           const Standard_Real twoPI = M_PI + M_PI;
3358           Standard_Real arr1tmp[2] = {pr1.X(), pr1.Y()};
3359           Standard_Real arr2tmp[2] = {pr2.X(), pr2.Y()};
3360
3361           // iteration on period bounds
3362           for ( Standard_Integer k1 = 0; k1 < 2; k1++ ) {
3363             Standard_Real aBound = ( k1 == 0 ) ? 0 : twoPI;
3364             Standard_Real aShift = ( k1 == 0 ) ? twoPI : -twoPI;
3365
3366             // iteration on surfaces
3367             for ( Standard_Integer k2 = 0; k2 < 2; k2++ ) {
3368               Standard_Real* arr1 = ( k2 == 0 ) ? arr1tmp : arr2tmp;
3369               Standard_Real* arr2 = ( k2 != 0 ) ? arr1tmp : arr2tmp;
3370               TColgp_SequenceOfPnt2d& aSeqS1 = ( k2 == 0 ) ? aSeqResultS1 : aSeqResultS2; 
3371               TColgp_SequenceOfPnt2d& aSeqS2 = ( k2 != 0 ) ? aSeqResultS1 : aSeqResultS2; 
3372
3373               if (fabs(arr1[0] - aBound) < Precision::PConfusion()) {
3374                 aSeqS1.Append( gp_Pnt2d( arr1[0] + aShift, arr1[1] ) );
3375                 aSeqS2.Append( gp_Pnt2d( arr2[0], arr2[1] ) );
3376                 aSeqResultRad.Append( aCriteria );
3377               }
3378               if (fabs(arr1[1] - aBound) < Precision::PConfusion()) {
3379                 aSeqS1.Append( gp_Pnt2d( arr1[0], arr1[1] + aShift) );
3380                 aSeqS2.Append( gp_Pnt2d( arr2[0], arr2[1] ) );
3381                 aSeqResultRad.Append( aCriteria );
3382               }
3383             }