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             }
3384           } //
3385         }
3386       }
3387     }
3388   }
3389   aResult = aSeqResultRad.Length();
3390
3391   if ( aResult > 0 ) {
3392     theResultOnS1 = new TColgp_HArray1OfPnt2d( 1, aResult );
3393     theResultOnS2 = new TColgp_HArray1OfPnt2d( 1, aResult );
3394     theResultRadius = new TColStd_HArray1OfReal( 1, aResult );
3395
3396     for ( Standard_Integer i = 1 ; i <= aResult; i++ ) {
3397       theResultOnS1->SetValue( i, aSeqResultS1.Value(i) );
3398       theResultOnS2->SetValue( i, aSeqResultS2.Value(i) );
3399       theResultRadius->SetValue( i, aSeqResultRad.Value(i) );
3400     }
3401   }
3402   return aResult;
3403 }
3404
3405 // ------------------------------------------------------------------------------------------------
3406 // static function: AdjustByNeighbour
3407 // purpose:
3408 // ------------------------------------------------------------------------------------------------
3409 gp_Pnt2d AdjustByNeighbour(const gp_Pnt2d&     theaNeighbourPoint,
3410                            const gp_Pnt2d&     theOriginalPoint,
3411                            Handle(GeomAdaptor_HSurface) theGASurface) {
3412   
3413   gp_Pnt2d ap1 = theaNeighbourPoint;
3414   gp_Pnt2d ap2 = theOriginalPoint;
3415
3416   if ( theGASurface->IsUPeriodic() ) {
3417     Standard_Real aPeriod     = theGASurface->UPeriod();
3418     gp_Pnt2d aPTest = ap2;
3419     Standard_Real aSqDistMin = 1.e+100;
3420
3421     for ( Standard_Integer pIt = -1; pIt <= 1; pIt++) {
3422       aPTest.SetX( theOriginalPoint.X() + aPeriod * pIt );
3423       Standard_Real dd = ap1.SquareDistance( aPTest );
3424
3425       if ( dd < aSqDistMin ) {
3426         ap2 = aPTest;
3427         aSqDistMin = dd;
3428       }
3429     }
3430   }
3431   if ( theGASurface->IsVPeriodic() ) {
3432     Standard_Real aPeriod     = theGASurface->VPeriod();
3433     gp_Pnt2d aPTest = ap2;
3434     Standard_Real aSqDistMin = 1.e+100;
3435
3436     for ( Standard_Integer pIt = -1; pIt <= 1; pIt++) {
3437       aPTest.SetY( theOriginalPoint.Y() + aPeriod * pIt );
3438       Standard_Real dd = ap1.SquareDistance( aPTest );
3439
3440       if ( dd < aSqDistMin ) {
3441         ap2 = aPTest;
3442         aSqDistMin = dd;
3443       }
3444     }
3445   }
3446   return ap2;
3447 }
3448
3449 // ------------------------------------------------------------------------------------------------
3450 //function: DecompositionOfWLine
3451 // purpose:
3452 // ------------------------------------------------------------------------------------------------
3453 Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
3454                                       const Handle(GeomAdaptor_HSurface)&            theSurface1, 
3455                                       const Handle(GeomAdaptor_HSurface)&            theSurface2,
3456                                       const TopoDS_Face&                             theFace1,
3457                                       const TopoDS_Face&                             theFace2,
3458                                       const GeomInt_LineConstructor&                 theLConstructor,
3459                                       const Standard_Boolean                         theAvoidLConstructor,
3460                                       IntPatch_SequenceOfLine&                       theNewLines,
3461                                       Standard_Real&                                 theReachedTol3d,
3462                                       const Handle(IntTools_Context)& aContext) 
3463 {
3464
3465   Standard_Boolean bRet, bAvoidLineConstructor;
3466   Standard_Integer aNbPnts, aNbParts;
3467   //
3468   bRet=Standard_False;
3469   aNbPnts=theWLine->NbPnts();
3470   bAvoidLineConstructor=theAvoidLConstructor;
3471   //
3472   if(!aNbPnts){
3473     return bRet;
3474   }
3475   if (!bAvoidLineConstructor) {
3476     aNbParts=theLConstructor.NbParts();
3477     if (!aNbParts) {
3478       return bRet;
3479     }
3480   }
3481   //
3482   Standard_Boolean bIsPrevPointOnBoundary, bIsPointOnBoundary, bIsCurrentPointOnBoundary;
3483   Standard_Integer nblines, pit, i, j;
3484   Standard_Real aTol;
3485   TColStd_Array1OfListOfInteger anArrayOfLines(1, aNbPnts); 
3486   TColStd_Array1OfInteger       anArrayOfLineType(1, aNbPnts);
3487   TColStd_ListOfInteger aListOfPointIndex;
3488   
3489   Handle(TColgp_HArray1OfPnt2d) aTanZoneS1;
3490   Handle(TColgp_HArray1OfPnt2d) aTanZoneS2;
3491   Handle(TColStd_HArray1OfReal) aTanZoneRadius;
3492   Standard_Integer aNbZone = ComputeTangentZones( theSurface1, theSurface2, theFace1, theFace2,
3493                                                  aTanZoneS1, aTanZoneS2, aTanZoneRadius, aContext);
3494   
3495   //
3496   nblines=0;
3497   aTol=Precision::Confusion();
3498   aTol=0.5*aTol;
3499   bIsPrevPointOnBoundary=Standard_False;
3500   bIsPointOnBoundary=Standard_False;
3501   //
3502   // 1. ...
3503   //
3504   // Points
3505   for(pit = 1; pit <= aNbPnts; ++pit) {
3506     Standard_Boolean bIsOnFirstBoundary, isperiodic;
3507     Standard_Real aResolution, aPeriod, alowerboundary, aupperboundary, U, V;
3508     Standard_Real aParameter, anoffset, anAdjustPar;
3509     Standard_Real umin, umax, vmin, vmax;
3510     //
3511     bIsCurrentPointOnBoundary = Standard_False;
3512     const IntSurf_PntOn2S& aPoint = theWLine->Point(pit);
3513     //
3514     // Surface
3515     for(i = 0; i < 2; ++i) {
3516       Handle(GeomAdaptor_HSurface) aGASurface = (!i) ? theSurface1 : theSurface2;
3517       aGASurface->ChangeSurface().Surface()->Bounds(umin, umax, vmin, vmax);
3518       if(!i) {
3519         aPoint.ParametersOnS1(U, V);
3520       }
3521       else {
3522         aPoint.ParametersOnS2(U, V);
3523       }
3524       // U, V
3525       for(j = 0; j < 2; j++) {
3526         isperiodic = (!j) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
3527         if(!isperiodic){
3528           continue;
3529         }
3530         //
3531         if (!j) {
3532           aResolution=aGASurface->UResolution(aTol);
3533           aPeriod=aGASurface->UPeriod();
3534           alowerboundary=umin;
3535           aupperboundary=umax;
3536           aParameter=U;
3537         }
3538         else {
3539           aResolution=aGASurface->VResolution(aTol);
3540           aPeriod=aGASurface->VPeriod();
3541           alowerboundary=vmin;
3542           aupperboundary=vmax;
3543           aParameter=V;
3544         }
3545         
3546         GeomInt::AdjustPeriodic(aParameter, 
3547                                        alowerboundary, 
3548                                        aupperboundary, 
3549                                        aPeriod,
3550                                        anAdjustPar,
3551                                        anoffset);
3552         //
3553         bIsOnFirstBoundary = Standard_True;// ?
3554         bIsPointOnBoundary=
3555           IsPointOnBoundary(anAdjustPar, 
3556                             alowerboundary, 
3557                             aupperboundary,
3558                             aResolution, 
3559                             bIsOnFirstBoundary);
3560         //
3561         if(bIsPointOnBoundary) {
3562           bIsCurrentPointOnBoundary = Standard_True;
3563           break;
3564         }
3565         else {
3566           // check if a point belong to a tangent zone. Begin
3567           Standard_Integer zIt = 0;
3568           for ( zIt = 1; zIt <= aNbZone; zIt++ ) {
3569             gp_Pnt2d aPZone = (i == 0) ? aTanZoneS1->Value(zIt) : aTanZoneS2->Value(zIt);
3570             Standard_Real aZoneRadius = aTanZoneRadius->Value(zIt);
3571
3572             if ( IsInsideTanZone(gp_Pnt2d( U, V ), aPZone, aZoneRadius, aGASurface ) ) {
3573               // set boundary flag to split the curve by a tangent zone
3574               bIsPointOnBoundary = Standard_True;
3575               bIsCurrentPointOnBoundary = Standard_True;
3576               if ( theReachedTol3d < aZoneRadius ) {
3577                 theReachedTol3d = aZoneRadius;
3578               }
3579               break;
3580             }
3581           }
3582         }
3583       }//for(j = 0; j < 2; j++) {
3584
3585       if(bIsCurrentPointOnBoundary){
3586         break;
3587       }
3588     }//for(i = 0; i < 2; ++i) {
3589     //
3590     if((bIsCurrentPointOnBoundary != bIsPrevPointOnBoundary)) {
3591       if(!aListOfPointIndex.IsEmpty()) {
3592         nblines++;
3593         anArrayOfLines.SetValue(nblines, aListOfPointIndex);
3594         anArrayOfLineType.SetValue(nblines, bIsPrevPointOnBoundary);
3595         aListOfPointIndex.Clear();
3596       }
3597       bIsPrevPointOnBoundary = bIsCurrentPointOnBoundary;
3598     }
3599     aListOfPointIndex.Append(pit);
3600   } //for(pit = 1; pit <= aNbPnts; ++pit) {
3601   //
3602   if(!aListOfPointIndex.IsEmpty()) {
3603     nblines++;
3604     anArrayOfLines.SetValue(nblines, aListOfPointIndex);
3605     anArrayOfLineType.SetValue(nblines, bIsPrevPointOnBoundary);
3606     aListOfPointIndex.Clear();
3607   }
3608   //
3609   if(nblines<=1) {
3610     return bRet; //Standard_False;
3611   }
3612   //
3613   // 
3614   // 2. Correct wlines.begin
3615   TColStd_Array1OfListOfInteger anArrayOfLineEnds(1, nblines);
3616   Handle(IntSurf_LineOn2S) aSeqOfPntOn2S = new IntSurf_LineOn2S();
3617   //
3618   for(i = 1; i <= nblines; i++) {
3619     if(anArrayOfLineType.Value(i) != 0) {
3620       continue;
3621     }
3622     const TColStd_ListOfInteger& aListOfIndex = anArrayOfLines.Value(i);
3623     TColStd_ListOfInteger aListOfFLIndex;
3624
3625     for(j = 0; j < 2; j++) {
3626       Standard_Integer aneighbourindex = (j == 0) ? (i - 1) : (i + 1);
3627
3628       if((aneighbourindex < 1) || (aneighbourindex > nblines))
3629         continue;
3630
3631       if(anArrayOfLineType.Value(aneighbourindex) == 0)
3632         continue;
3633       const TColStd_ListOfInteger& aNeighbour = anArrayOfLines.Value(aneighbourindex);
3634       Standard_Integer anIndex = (j == 0) ? aNeighbour.Last() : aNeighbour.First();
3635       const IntSurf_PntOn2S& aPoint = theWLine->Point(anIndex);
3636
3637       IntSurf_PntOn2S aNewP = aPoint;
3638       if(aListOfIndex.Extent() < 2) {
3639         aSeqOfPntOn2S->Add(aNewP);
3640         aListOfFLIndex.Append(aSeqOfPntOn2S->NbPoints());
3641         continue;
3642       }
3643       //
3644       Standard_Integer iFirst = aListOfIndex.First();
3645       Standard_Integer iLast  = aListOfIndex.Last();
3646       //
3647       for(Standard_Integer surfit = 0; surfit < 2; surfit++) {
3648
3649         Handle(GeomAdaptor_HSurface) aGASurface = (surfit == 0) ? theSurface1 : theSurface2;
3650         Standard_Real umin=0., umax=0., vmin=0., vmax=0.;
3651         aGASurface->ChangeSurface().Surface()->Bounds(umin, umax, vmin, vmax);
3652         Standard_Real U=0., V=0.;
3653
3654         if(surfit == 0)
3655           aNewP.ParametersOnS1(U, V);
3656         else
3657           aNewP.ParametersOnS2(U, V);
3658         Standard_Integer nbboundaries = 0;
3659
3660         Standard_Boolean bIsNearBoundary = Standard_False;
3661         Standard_Integer aZoneIndex = 0;
3662         Standard_Integer bIsUBoundary = Standard_False; // use if nbboundaries == 1
3663         Standard_Integer bIsFirstBoundary = Standard_False; // use if nbboundaries == 1
3664         
3665
3666         for(Standard_Integer parit = 0; parit < 2; parit++) {
3667           Standard_Boolean isperiodic = (parit == 0) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
3668
3669           Standard_Real aResolution = (parit == 0) ? aGASurface->UResolution(aTol) : aGASurface->VResolution(aTol);
3670           Standard_Real alowerboundary = (parit == 0) ? umin : vmin;
3671           Standard_Real aupperboundary = (parit == 0) ? umax : vmax;
3672
3673           Standard_Real aParameter = (parit == 0) ? U : V;
3674           Standard_Boolean bIsOnFirstBoundary = Standard_True;
3675   
3676           if(!isperiodic) {
3677             bIsPointOnBoundary=
3678               IsPointOnBoundary(aParameter, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary);
3679             if(bIsPointOnBoundary) {
3680               bIsUBoundary = (parit == 0);
3681               bIsFirstBoundary = bIsOnFirstBoundary;
3682               nbboundaries++;
3683             }
3684           }
3685           else {
3686             Standard_Real aPeriod     = (parit == 0) ? aGASurface->UPeriod() : aGASurface->VPeriod();
3687             Standard_Real anoffset, anAdjustPar;
3688             GeomInt::AdjustPeriodic(aParameter, alowerboundary, aupperboundary,
3689                                            aPeriod, anAdjustPar, anoffset);
3690
3691             bIsPointOnBoundary=
3692               IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary);
3693             if(bIsPointOnBoundary) {
3694               bIsUBoundary = (parit == 0);
3695               bIsFirstBoundary = bIsOnFirstBoundary;
3696               nbboundaries++;
3697             }
3698             else {
3699             //check neighbourhood of boundary
3700             Standard_Real anEpsilon = aResolution * 100.;
3701             Standard_Real aPart = ( aupperboundary - alowerboundary ) * 0.1;
3702             anEpsilon = ( anEpsilon > aPart ) ? aPart : anEpsilon;
3703             
3704               bIsNearBoundary = IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary, 
3705                                                   anEpsilon, bIsOnFirstBoundary);
3706
3707             }
3708           }
3709         }
3710
3711         // check if a point belong to a tangent zone. Begin
3712         for ( Standard_Integer zIt = 1; zIt <= aNbZone; zIt++ ) {
3713           gp_Pnt2d aPZone = (surfit == 0) ? aTanZoneS1->Value(zIt) : aTanZoneS2->Value(zIt);
3714           Standard_Real aZoneRadius = aTanZoneRadius->Value(zIt);
3715
3716           Standard_Integer aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
3717           const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
3718           Standard_Real nU1, nV1;
3719             
3720           if(surfit == 0)
3721             aNeighbourPoint.ParametersOnS1(nU1, nV1);
3722           else
3723             aNeighbourPoint.ParametersOnS2(nU1, nV1);
3724           gp_Pnt2d ap1(nU1, nV1);
3725           gp_Pnt2d ap2 = AdjustByNeighbour( ap1, gp_Pnt2d( U, V ), aGASurface );
3726
3727
3728           if ( IsInsideTanZone( ap2, aPZone, aZoneRadius, aGASurface ) ) {
3729             aZoneIndex = zIt;
3730             bIsNearBoundary = Standard_True;
3731             if ( theReachedTol3d < aZoneRadius ) {
3732               theReachedTol3d = aZoneRadius;
3733             }
3734           }
3735         }
3736         // check if a point belong to a tangent zone. End
3737         Standard_Boolean bComputeLineEnd = Standard_False;
3738
3739         if(nbboundaries == 2) {
3740           //xf
3741           bComputeLineEnd = Standard_True;
3742           //xt
3743         }
3744         else if(nbboundaries == 1) {
3745           Standard_Boolean isperiodic = (bIsUBoundary) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
3746
3747           if(isperiodic) {
3748             Standard_Real alowerboundary = (bIsUBoundary) ? umin : vmin;
3749             Standard_Real aupperboundary = (bIsUBoundary) ? umax : vmax;
3750             Standard_Real aPeriod     = (bIsUBoundary) ? aGASurface->UPeriod() : aGASurface->VPeriod();
3751             Standard_Real aParameter = (bIsUBoundary) ? U : V;
3752             Standard_Real anoffset, anAdjustPar;
3753             GeomInt::AdjustPeriodic(aParameter, alowerboundary, aupperboundary, 
3754                                            aPeriod, anAdjustPar, anoffset);
3755
3756             Standard_Real adist = (bIsFirstBoundary) ? fabs(anAdjustPar - alowerboundary) : fabs(anAdjustPar - aupperboundary);
3757             Standard_Real anotherPar = (bIsFirstBoundary) ? (aupperboundary - adist) : (alowerboundary + adist);
3758             anotherPar += anoffset;
3759             Standard_Integer aneighbourpointindex = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
3760             const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex);
3761             Standard_Real nU1, nV1;
3762
3763             if(surfit == 0)
3764               aNeighbourPoint.ParametersOnS1(nU1, nV1);
3765             else
3766               aNeighbourPoint.ParametersOnS2(nU1, nV1);
3767             
3768             Standard_Real adist1 = (bIsUBoundary) ? fabs(nU1 - U) : fabs(nV1 - V);
3769             Standard_Real adist2 = (bIsUBoundary) ? fabs(nU1 - anotherPar) : fabs(nV1 - anotherPar);
3770             bComputeLineEnd = Standard_True;
3771             Standard_Boolean bCheckAngle1 = Standard_False;
3772             Standard_Boolean bCheckAngle2 = Standard_False;
3773             gp_Vec2d aNewVec;
3774             Standard_Real anewU = (bIsUBoundary) ? anotherPar : U;
3775             Standard_Real anewV = (bIsUBoundary) ? V : anotherPar;
3776
3777             if(((adist1 - adist2) > Precision::PConfusion()) && 
3778                (adist2 < (aPeriod / 4.))) {
3779               bCheckAngle1 = Standard_True;
3780               aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(anewU, anewV));
3781
3782               if(aNewVec.SquareMagnitude() < gp::Resolution()) {
3783                 aNewP.SetValue((surfit == 0), anewU, anewV);
3784                 bCheckAngle1 = Standard_False;
3785               }
3786             }
3787             else if(adist1 < (aPeriod / 4.)) {
3788               bCheckAngle2 = Standard_True;
3789               aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(U, V));
3790
3791               if(aNewVec.SquareMagnitude() < gp::Resolution()) {
3792                 bCheckAngle2 = Standard_False;
3793               }
3794             }
3795
3796             if(bCheckAngle1 || bCheckAngle2) {
3797               // assume there are at least two points in line (see "if" above)
3798               Standard_Integer anindexother = aneighbourpointindex;
3799
3800               while((anindexother <= iLast) && (anindexother >= iFirst)) {
3801                 anindexother = (j == 0) ? (anindexother + 1) : (anindexother - 1);
3802                 const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(anindexother);
3803                 Standard_Real nU2, nV2;
3804                 
3805                 if(surfit == 0)
3806                   aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
3807                 else
3808                   aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
3809                 gp_Vec2d aVecOld(gp_Pnt2d(nU2, nV2), gp_Pnt2d(nU1, nV1));
3810
3811                 if(aVecOld.SquareMagnitude() <= gp::Resolution()) {
3812                   continue;
3813                 }
3814                 else {
3815                   Standard_Real anAngle = aNewVec.Angle(aVecOld);
3816
3817                   if((fabs(anAngle) < (M_PI * 0.25)) && (aNewVec.Dot(aVecOld) > 0.)) {
3818
3819                     if(bCheckAngle1) {
3820                       Standard_Real U1, U2, V1, V2;
3821                       IntSurf_PntOn2S atmppoint = aNewP;
3822                       atmppoint.SetValue((surfit == 0), anewU, anewV);
3823                       atmppoint.Parameters(U1, V1, U2, V2);
3824                       gp_Pnt P1 = theSurface1->Value(U1, V1);
3825                       gp_Pnt P2 = theSurface2->Value(U2, V2);
3826                       gp_Pnt P0 = aPoint.Value();
3827
3828                       if(P0.IsEqual(P1, aTol) &&
3829                          P0.IsEqual(P2, aTol) &&
3830                          P1.IsEqual(P2, aTol)) {
3831                         bComputeLineEnd = Standard_False;
3832                         aNewP.SetValue((surfit == 0), anewU, anewV);
3833                       }
3834                     }
3835
3836                     if(bCheckAngle2) {
3837                       bComputeLineEnd = Standard_False;
3838                     }
3839                   }
3840                   break;
3841                 }
3842               } // end while(anindexother...)
3843             }
3844           }
3845         }
3846         else if ( bIsNearBoundary ) {
3847           bComputeLineEnd = Standard_True;
3848         }
3849
3850         if(bComputeLineEnd) {
3851
3852           gp_Pnt2d anewpoint;
3853           Standard_Boolean found = Standard_False;
3854
3855           if ( bIsNearBoundary ) {
3856             // re-compute point near natural boundary or near tangent zone
3857             Standard_Real u1, v1, u2, v2;
3858             aNewP.Parameters( u1, v1, u2, v2 );
3859             if(surfit == 0)
3860               anewpoint = gp_Pnt2d( u1, v1 );
3861             else
3862               anewpoint = gp_Pnt2d( u2, v2 );
3863             
3864             Standard_Integer aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
3865             const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
3866             Standard_Real nU1, nV1;
3867             
3868             if(surfit == 0)
3869               aNeighbourPoint.ParametersOnS1(nU1, nV1);
3870             else
3871               aNeighbourPoint.ParametersOnS2(nU1, nV1);
3872             gp_Pnt2d ap1(nU1, nV1);
3873             gp_Pnt2d ap2;
3874
3875
3876             if ( aZoneIndex ) {
3877               // exclude point from a tangent zone
3878               anewpoint = AdjustByNeighbour( ap1, anewpoint, aGASurface );
3879               gp_Pnt2d aPZone = (surfit == 0) ? aTanZoneS1->Value(aZoneIndex) : aTanZoneS2->Value(aZoneIndex);
3880               Standard_Real aZoneRadius = aTanZoneRadius->Value(aZoneIndex);
3881
3882               if ( FindPoint(ap1, anewpoint, umin, umax, vmin, vmax, 
3883                              aPZone, aZoneRadius, aGASurface, ap2) ) {
3884                 anewpoint = ap2;
3885                 found = Standard_True;
3886               }
3887             }
3888             else if ( aGASurface->IsUPeriodic() || aGASurface->IsVPeriodic() ) {
3889               // re-compute point near boundary if shifted on a period
3890               ap2 = AdjustByNeighbour( ap1, anewpoint, aGASurface );
3891
3892               if ( ( ap2.X() < umin ) || ( ap2.X() > umax ) ||
3893                   ( ap2.Y() < vmin ) || ( ap2.Y() > vmax ) ) {
3894                 found = FindPoint(ap1, ap2, umin, umax, vmin, vmax, anewpoint);
3895               }
3896               else {
3897                 anewpoint = ap2;
3898                 aNewP.SetValue( (surfit == 0), anewpoint.X(), anewpoint.Y() );
3899               }
3900             }
3901           }
3902           else {
3903
3904             Standard_Integer aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
3905             const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
3906             Standard_Real nU1, nV1;
3907
3908             if(surfit == 0)
3909               aNeighbourPoint.ParametersOnS1(nU1, nV1);
3910             else
3911               aNeighbourPoint.ParametersOnS2(nU1, nV1);
3912             gp_Pnt2d ap1(nU1, nV1);
3913             gp_Pnt2d ap2(nU1, nV1);
3914             Standard_Integer aneighbourpointindex2 = aneighbourpointindex1;
3915
3916             while((aneighbourpointindex2 <= iLast) && (aneighbourpointindex2 >= iFirst)) {
3917               aneighbourpointindex2 = (j == 0) ? (aneighbourpointindex2 + 1) : (aneighbourpointindex2 - 1);
3918               const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(aneighbourpointindex2);
3919               Standard_Real nU2, nV2;
3920
3921               if(surfit == 0)
3922                 aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
3923               else
3924                 aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
3925               ap2.SetX(nU2);
3926               ap2.SetY(nV2);
3927
3928               if(ap1.SquareDistance(ap2) > gp::Resolution()) {
3929                 break;
3930               }
3931             }  
3932             found = FindPoint(ap2, ap1, umin, umax, vmin, vmax, anewpoint);
3933           }
3934
3935           if(found) {
3936             // check point
3937             Standard_Real aCriteria = BRep_Tool::Tolerance(theFace1) + BRep_Tool::Tolerance(theFace2);
3938             GeomAPI_ProjectPointOnSurf& aProjector = 
3939               (surfit == 0) ? aContext->ProjPS(theFace2) : aContext->ProjPS(theFace1);
3940             Handle(GeomAdaptor_HSurface) aSurface = (surfit == 0) ? theSurface1 : theSurface2;
3941
3942             Handle(GeomAdaptor_HSurface) aSurfaceOther = (surfit == 0) ? theSurface2 : theSurface1;
3943
3944             gp_Pnt aP3d = aSurface->Value(anewpoint.X(), anewpoint.Y());
3945             aProjector.Perform(aP3d);
3946
3947             if(aProjector.IsDone()) {
3948               if(aProjector.LowerDistance() < aCriteria) {
3949                 Standard_Real foundU = U, foundV = V;
3950                 aProjector.LowerDistanceParameters(foundU, foundV);
3951
3952                 //Correction of projected coordinates. Begin
3953                 //Note, it may be shifted on a period
3954                 Standard_Integer aneindex1 = (j == 0) ? iFirst : iLast;
3955                 const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneindex1);
3956                 Standard_Real nUn, nVn;
3957                 
3958                 if(surfit == 0)
3959                   aNeighbourPoint.ParametersOnS2(nUn, nVn);
3960                 else
3961                   aNeighbourPoint.ParametersOnS1(nUn, nVn);
3962                 gp_Pnt2d aNeighbour2d(nUn, nVn);
3963                 gp_Pnt2d anAdjustedPoint = AdjustByNeighbour( aNeighbour2d, gp_Pnt2d(foundU, foundV), aSurfaceOther );
3964                 foundU = anAdjustedPoint.X();
3965                 foundV = anAdjustedPoint.Y();
3966
3967                 if ( ( anAdjustedPoint.X() < umin ) && ( anAdjustedPoint.X() > umax ) &&
3968                     ( anAdjustedPoint.Y() < vmin ) && ( anAdjustedPoint.Y() > vmax ) ) {
3969                   // attempt to roughly re-compute point
3970                   foundU = ( foundU < umin ) ? umin : foundU;
3971                   foundU = ( foundU > umax ) ? umax : foundU;
3972                   foundV = ( foundV < vmin ) ? vmin : foundV;
3973                   foundV = ( foundV > vmax ) ? vmax : foundV;
3974
3975                   GeomAPI_ProjectPointOnSurf& aProjector2 = 
3976                     (surfit == 0) ? aContext->ProjPS(theFace1) : aContext->ProjPS(theFace2);
3977
3978                   aP3d = aSurfaceOther->Value(foundU, foundV);
3979                   aProjector2.Perform(aP3d);
3980                   
3981                   if(aProjector2.IsDone()) {
3982                     if(aProjector2.LowerDistance() < aCriteria) {
3983                       Standard_Real foundU2 = anewpoint.X(), foundV2 = anewpoint.Y();
3984                       aProjector2.LowerDistanceParameters(foundU2, foundV2);
3985                       anewpoint.SetX(foundU2);
3986                       anewpoint.SetY(foundV2);
3987                     }
3988                   }
3989                 }
3990                 //Correction of projected coordinates. End
3991
3992                 if(surfit == 0)
3993                   aNewP.SetValue(aP3d, anewpoint.X(), anewpoint.Y(), foundU, foundV);
3994                 else
3995                   aNewP.SetValue(aP3d, foundU, foundV, anewpoint.X(), anewpoint.Y());
3996               }
3997             }
3998           }
3999         }
4000       }
4001       aSeqOfPntOn2S->Add(aNewP);
4002       aListOfFLIndex.Append(aSeqOfPntOn2S->NbPoints());
4003     }
4004     anArrayOfLineEnds.SetValue(i, aListOfFLIndex);
4005   }
4006   // Correct wlines.end
4007
4008   // Split wlines.begin
4009   Standard_Integer nbiter;
4010   //
4011   nbiter=1;
4012   if (!bAvoidLineConstructor) {
4013     nbiter=theLConstructor.NbParts();
4014   }
4015   //
4016   for(j = 1; j <= nbiter; ++j) {
4017     Standard_Real fprm, lprm;
4018     Standard_Integer ifprm, ilprm;
4019     //
4020     if(bAvoidLineConstructor) {
4021       ifprm = 1;
4022       ilprm = theWLine->NbPnts();
4023     }
4024     else {
4025       theLConstructor.Part(j, fprm, lprm);
4026       ifprm = (Standard_Integer)fprm;
4027       ilprm = (Standard_Integer)lprm;
4028     }
4029
4030     Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
4031     //
4032     for(i = 1; i <= nblines; i++) {
4033       if(anArrayOfLineType.Value(i) != 0) {
4034         continue;
4035       }
4036       const TColStd_ListOfInteger& aListOfIndex = anArrayOfLines.Value(i);
4037       const TColStd_ListOfInteger& aListOfFLIndex = anArrayOfLineEnds.Value(i);
4038       Standard_Boolean bhasfirstpoint = (aListOfFLIndex.Extent() == 2);
4039       Standard_Boolean bhaslastpoint = (aListOfFLIndex.Extent() == 2);
4040
4041       if(!bhasfirstpoint && !aListOfFLIndex.IsEmpty()) {
4042         bhasfirstpoint = (i != 1);
4043       }
4044
4045       if(!bhaslastpoint && !aListOfFLIndex.IsEmpty()) {
4046         bhaslastpoint = (i != nblines);
4047       }
4048       
4049       Standard_Integer iFirst = aListOfIndex.First();
4050       Standard_Integer iLast  = aListOfIndex.Last();
4051       Standard_Boolean bIsFirstInside = ((ifprm >= iFirst) && (ifprm <= iLast));
4052       Standard_Boolean bIsLastInside =  ((ilprm >= iFirst) && (ilprm <= iLast));
4053
4054       if(!bIsFirstInside && !bIsLastInside) {
4055         if((ifprm < iFirst) && (ilprm > iLast)) {
4056           // append whole line, and boundaries if neccesary
4057           if(bhasfirstpoint) {
4058             pit = aListOfFLIndex.First();
4059             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
4060             aLineOn2S->Add(aP);
4061           }
4062           TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
4063
4064           for(; anIt.More(); anIt.Next()) {
4065             pit = anIt.Value();
4066             const IntSurf_PntOn2S& aP = theWLine->Point(pit);
4067             aLineOn2S->Add(aP);
4068           }
4069
4070           if(bhaslastpoint) {
4071             pit = aListOfFLIndex.Last();
4072             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
4073             aLineOn2S->Add(aP);
4074           }
4075
4076           // check end of split line (end is almost always)
4077           Standard_Integer aneighbour = i + 1;
4078           Standard_Boolean bIsEndOfLine = Standard_True;
4079
4080           if(aneighbour <= nblines) {
4081             const TColStd_ListOfInteger& aListOfNeighbourIndex = anArrayOfLines.Value(aneighbour);
4082
4083             if((anArrayOfLineType.Value(aneighbour) != 0) &&
4084                (aListOfNeighbourIndex.IsEmpty())) {
4085               bIsEndOfLine = Standard_False;
4086             }
4087           }
4088
4089           if(bIsEndOfLine) {
4090             if(aLineOn2S->NbPoints() > 1) {
4091               Handle(IntPatch_WLine) aNewWLine = 
4092                 new IntPatch_WLine(aLineOn2S, Standard_False);
4093               theNewLines.Append(aNewWLine);
4094             }
4095             aLineOn2S = new IntSurf_LineOn2S();
4096           }
4097         }
4098         continue;
4099       }
4100       // end if(!bIsFirstInside && !bIsLastInside)
4101
4102       if(bIsFirstInside && bIsLastInside) {
4103         // append inside points between ifprm and ilprm
4104         TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
4105
4106         for(; anIt.More(); anIt.Next()) {
4107           pit = anIt.Value();
4108           if((pit < ifprm) || (pit > ilprm))
4109             continue;
4110           const IntSurf_PntOn2S& aP = theWLine->Point(pit);
4111           aLineOn2S->Add(aP);
4112         }
4113       }
4114       else {
4115
4116         if(bIsFirstInside) {
4117           // append points from ifprm to last point + boundary point
4118           TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
4119
4120           for(; anIt.More(); anIt.Next()) {
4121             pit = anIt.Value();
4122             if(pit < ifprm)
4123               continue;
4124             const IntSurf_PntOn2S& aP = theWLine->Point(pit);
4125             aLineOn2S->Add(aP);
4126           }
4127
4128           if(bhaslastpoint) {
4129             pit = aListOfFLIndex.Last();
4130             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
4131             aLineOn2S->Add(aP);
4132           }
4133           // check end of split line (end is almost always)
4134           Standard_Integer aneighbour = i + 1;
4135           Standard_Boolean bIsEndOfLine = Standard_True;
4136
4137           if(aneighbour <= nblines) {
4138             const TColStd_ListOfInteger& aListOfNeighbourIndex = anArrayOfLines.Value(aneighbour);
4139
4140             if((anArrayOfLineType.Value(aneighbour) != 0) &&
4141                (aListOfNeighbourIndex.IsEmpty())) {
4142               bIsEndOfLine = Standard_False;
4143             }
4144           }
4145
4146           if(bIsEndOfLine) {
4147             if(aLineOn2S->NbPoints() > 1) {
4148               Handle(IntPatch_WLine) aNewWLine = 
4149                 new IntPatch_WLine(aLineOn2S, Standard_False);
4150               theNewLines.Append(aNewWLine);
4151             }
4152             aLineOn2S = new IntSurf_LineOn2S();
4153           }
4154         }
4155         // end if(bIsFirstInside)
4156
4157         if(bIsLastInside) {
4158           // append points from first boundary point to ilprm
4159           if(bhasfirstpoint) {
4160             pit = aListOfFLIndex.First();
4161             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
4162             aLineOn2S->Add(aP);
4163           }
4164           TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
4165
4166           for(; anIt.More(); anIt.Next()) {
4167             pit = anIt.Value();
4168             if(pit > ilprm)
4169               continue;
4170             const IntSurf_PntOn2S& aP = theWLine->Point(pit);
4171             aLineOn2S->Add(aP);
4172           }
4173         }
4174         //end if(bIsLastInside)
4175       }
4176     }
4177
4178     if(aLineOn2S->NbPoints() > 1) {
4179       Handle(IntPatch_WLine) aNewWLine = 
4180         new IntPatch_WLine(aLineOn2S, Standard_False);
4181       theNewLines.Append(aNewWLine);
4182     }
4183   }
4184   // Split wlines.end
4185
4186   return Standard_True;
4187 }
4188
4189 // ------------------------------------------------------------------------------------------------
4190 // static function: ParameterOutOfBoundary
4191 // purpose:         Computes a new parameter for given curve. The corresponding 2d points 
4192 //                  does not lay on any boundary of given faces
4193 // ------------------------------------------------------------------------------------------------
4194 Standard_Boolean ParameterOutOfBoundary(const Standard_Real       theParameter, 
4195                                         const Handle(Geom_Curve)& theCurve, 
4196                                         const TopoDS_Face&        theFace1, 
4197                                         const TopoDS_Face&        theFace2,
4198                                         const Standard_Real       theOtherParameter,
4199                                         const Standard_Boolean    bIncreasePar,
4200                                         Standard_Real&            theNewParameter,
4201                                         const Handle(IntTools_Context)& aContext)
4202 {
4203   Standard_Boolean bIsComputed = Standard_False;
4204   theNewParameter = theParameter;
4205
4206   Standard_Real acurpar = theParameter;
4207   TopAbs_State aState = TopAbs_ON;
4208   Standard_Integer iter = 0;
4209   Standard_Real asumtol = BRep_Tool::Tolerance(theFace1) + BRep_Tool::Tolerance(theFace2);
4210   Standard_Real adelta = asumtol * 0.1;
4211   adelta = (adelta < Precision::Confusion()) ? Precision::Confusion() : adelta;
4212   Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(theFace1);
4213   Handle(Geom_Surface) aSurf2 = BRep_Tool::Surface(theFace2);
4214
4215   Standard_Real u1, u2, v1, v2;
4216
4217   GeomAPI_ProjectPointOnSurf aPrj1;
4218   aSurf1->Bounds(u1, u2, v1, v2);
4219   aPrj1.Init(aSurf1, u1, u2, v1, v2);
4220
4221   GeomAPI_ProjectPointOnSurf aPrj2;
4222   aSurf2->Bounds(u1, u2, v1, v2);
4223   aPrj2.Init(aSurf2, u1, u2, v1, v2);
4224
4225   while(aState == TopAbs_ON) {
4226     if(bIncreasePar)
4227       acurpar += adelta;
4228     else
4229       acurpar -= adelta;
4230     gp_Pnt aPCurrent = theCurve->Value(acurpar);
4231     aPrj1.Perform(aPCurrent);
4232     Standard_Real U=0., V=0.;
4233
4234     if(aPrj1.IsDone()) {
4235       aPrj1.LowerDistanceParameters(U, V);
4236       aState = aContext->StatePointFace(theFace1, gp_Pnt2d(U, V));
4237     }
4238
4239     if(aState != TopAbs_ON) {
4240       aPrj2.Perform(aPCurrent);
4241                 
4242       if(aPrj2.IsDone()) {
4243         aPrj2.LowerDistanceParameters(U, V);
4244         aState = aContext->StatePointFace(theFace2, gp_Pnt2d(U, V));
4245       }
4246     }
4247
4248     if(iter > 11) {
4249       break;
4250     }
4251     iter++;
4252   }
4253
4254   if(iter <= 11) {
4255     theNewParameter = acurpar;
4256     bIsComputed = Standard_True;
4257
4258     if(bIncreasePar) {
4259       if(acurpar >= theOtherParameter)
4260         theNewParameter = theOtherParameter;
4261     }
4262     else {
4263       if(acurpar <= theOtherParameter)
4264         theNewParameter = theOtherParameter;
4265     }
4266   }
4267   return bIsComputed;
4268 }
4269
4270 //=======================================================================
4271 //function : IsCurveValid
4272 //purpose  : 
4273 //=======================================================================
4274 Standard_Boolean IsCurveValid(Handle(Geom2d_Curve)& thePCurve)
4275 {
4276   if(thePCurve.IsNull())
4277     return Standard_False;
4278
4279   Standard_Real tolint = 1.e-10;
4280   Geom2dAdaptor_Curve PCA;
4281   IntRes2d_Domain PCD;
4282   Geom2dInt_GInter PCI;
4283
4284   Standard_Real pf = 0., pl = 0.;
4285   gp_Pnt2d pntf, pntl;
4286
4287   if(!thePCurve->IsClosed() && !thePCurve->IsPeriodic()) {
4288     pf = thePCurve->FirstParameter();
4289     pl = thePCurve->LastParameter();
4290     pntf = thePCurve->Value(pf);
4291     pntl = thePCurve->Value(pl);
4292     PCA.Load(thePCurve);
4293     if(!PCA.IsPeriodic()) {
4294       if(PCA.FirstParameter() > pf) pf = PCA.FirstParameter();
4295       if(PCA.LastParameter()  < pl) pl = PCA.LastParameter();
4296     }
4297     PCD.SetValues(pntf,pf,tolint,pntl,pl,tolint);
4298     PCI.Perform(PCA,PCD,tolint,tolint);
4299     if(PCI.IsDone())
4300       if(PCI.NbPoints() > 0) {
4301         return Standard_False;
4302       }
4303   }
4304
4305   return Standard_True;
4306 }
4307
4308 //=======================================================================
4309 //static function : ApproxWithPCurves
4310 //purpose  : for bug 20964 only
4311 //=======================================================================
4312 Standard_Boolean ApproxWithPCurves(const gp_Cylinder& theCyl, 
4313                                    const gp_Sphere& theSph)
4314 {
4315   Standard_Boolean bRes = Standard_True;
4316   Standard_Real R1 = theCyl.Radius(), R2 = theSph.Radius();
4317   //
4318   {
4319     Standard_Real aD2, aRc2, aEps;
4320     gp_Pnt aApexSph;
4321     //
4322     aEps=1.E-7;
4323     aRc2=R1*R1;
4324     //
4325     const gp_Ax3& aAx3Sph=theSph.Position();
4326     const gp_Pnt& aLocSph=aAx3Sph.Location();
4327     const gp_Dir& aDirSph=aAx3Sph.Direction();
4328     //
4329     const gp_Ax1& aAx1Cyl=theCyl.Axis();
4330     gp_Lin aLinCyl(aAx1Cyl);
4331     //
4332     aApexSph.SetXYZ(aLocSph.XYZ()+R2*aDirSph.XYZ());
4333     aD2=aLinCyl.SquareDistance(aApexSph);
4334     if (fabs(aD2-aRc2)<aEps) {
4335       return !bRes;
4336     }
4337     //
4338     aApexSph.SetXYZ(aLocSph.XYZ()-R2*aDirSph.XYZ());
4339     aD2=aLinCyl.SquareDistance(aApexSph);
4340     if (fabs(aD2-aRc2)<aEps) {
4341       return !bRes;
4342     }
4343   }
4344   //
4345     
4346   if(R1 < 2.*R2) {
4347     return bRes;
4348   }
4349   gp_Lin anCylAx(theCyl.Axis());
4350
4351   Standard_Real aDist = anCylAx.Distance(theSph.Location());
4352   Standard_Real aDRel = Abs(aDist - R1)/R2;
4353
4354   if(aDRel > .2) return bRes;
4355
4356   Standard_Real par = ElCLib::Parameter(anCylAx, theSph.Location());
4357   gp_Pnt aP = ElCLib::Value(par, anCylAx);
4358   gp_Vec aV(aP, theSph.Location());
4359
4360   Standard_Real dd = aV.Dot(theSph.Position().XDirection());
4361
4362   if(aDist < R1 && dd > 0.) return Standard_False;
4363   if(aDist > R1 && dd < 0.) return Standard_False;
4364
4365   
4366   return bRes;
4367 }
4368 //=======================================================================
4369 //function : PerformPlanes
4370 //purpose  : 
4371 //=======================================================================
4372 void  PerformPlanes(const Handle(GeomAdaptor_HSurface)& theS1, 
4373                     const Handle(GeomAdaptor_HSurface)& theS2, 
4374                     const Standard_Real TolAng, 
4375                     const Standard_Real TolTang, 
4376                     const Standard_Boolean theApprox1,
4377                     const Standard_Boolean theApprox2,
4378                     IntTools_SequenceOfCurves& theSeqOfCurve, 
4379                     Standard_Boolean& theTangentFaces)
4380 {
4381
4382   gp_Pln aPln1 = theS1->Surface().Plane();
4383   gp_Pln aPln2 = theS2->Surface().Plane();
4384
4385   IntAna_QuadQuadGeo aPlnInter(aPln1, aPln2, TolAng, TolTang);
4386
4387   if(!aPlnInter.IsDone()) {
4388     theTangentFaces = Standard_False;
4389     return;
4390   }
4391
4392   IntAna_ResultType aResType = aPlnInter.TypeInter();
4393
4394   if(aResType == IntAna_Same) {
4395     theTangentFaces = Standard_True;
4396     return;
4397   }
4398
4399   theTangentFaces = Standard_False;
4400
4401   if(aResType == IntAna_Empty) {
4402     return;
4403   }
4404
4405   gp_Lin aLin = aPlnInter.Line(1);
4406
4407   ProjLib_Plane aProj;
4408
4409   aProj.Init(aPln1);
4410   aProj.Project(aLin);
4411   gp_Lin2d aLin2d1 = aProj.Line();
4412   //
4413   aProj.Init(aPln2);
4414   aProj.Project(aLin);
4415   gp_Lin2d aLin2d2 = aProj.Line();
4416   //
4417   //classify line2d1 relatively first plane
4418   Standard_Real P11, P12;
4419   Standard_Boolean IsCrossed = ClassifyLin2d(theS1, aLin2d1, TolTang, P11, P12);
4420   if(!IsCrossed) return;
4421   //classify line2d2 relatively second plane
4422   Standard_Real P21, P22;
4423   IsCrossed = ClassifyLin2d(theS2, aLin2d2, TolTang, P21, P22);
4424   if(!IsCrossed) return;
4425
4426   //Analysis of parametric intervals: must have common part
4427
4428   if(P21 >= P12) return;
4429   if(P22 <= P11) return;
4430
4431   Standard_Real pmin, pmax;
4432   pmin = Max(P11, P21);
4433   pmax = Min(P12, P22);
4434
4435   if(pmax - pmin <= TolTang) return;
4436
4437   Handle(Geom_Line) aGLin = new Geom_Line(aLin);
4438
4439   IntTools_Curve aCurve;
4440   Handle(Geom_TrimmedCurve) aGTLin = new Geom_TrimmedCurve(aGLin, pmin, pmax);
4441
4442   aCurve.SetCurve(aGTLin);
4443
4444   if(theApprox1) { 
4445     Handle(Geom2d_Line) C2d = new Geom2d_Line(aLin2d1);
4446     aCurve.SetFirstCurve2d(new Geom2d_TrimmedCurve(C2d, pmin, pmax));
4447   }
4448   else { 
4449     Handle(Geom2d_Curve) H1;
4450     aCurve.SetFirstCurve2d(H1);
4451   }
4452   if(theApprox2) { 
4453     Handle(Geom2d_Line) C2d = new Geom2d_Line(aLin2d2);
4454     aCurve.SetSecondCurve2d(new Geom2d_TrimmedCurve(C2d, pmin, pmax));
4455   }
4456   else { 
4457     Handle(Geom2d_Curve) H1;
4458     aCurve.SetFirstCurve2d(H1);
4459   }
4460
4461   theSeqOfCurve.Append(aCurve);
4462  
4463 }
4464
4465 //=======================================================================
4466 //function : ClassifyLin2d
4467 //purpose  : 
4468 //=======================================================================
4469 static inline Standard_Boolean INTER(const Standard_Real d1, 
4470                                      const Standard_Real d2, 
4471                                      const Standard_Real tol) 
4472 {
4473   return (d1 > tol && d2 < -tol) || 
4474          (d1 < -tol && d2 > tol) ||
4475          ((d1 <= tol && d1 >= -tol) && (d2 > tol || d2 < -tol)) || 
4476          ((d2 <= tol && d2 >= -tol) && (d1 > tol || d1 < -tol));
4477 }
4478 static inline Standard_Boolean COINC(const Standard_Real d1, 
4479                                      const Standard_Real d2, 
4480                                      const Standard_Real tol) 
4481 {
4482   return (d1 <= tol && d1 >= -tol) && (d2 <= tol && d2 >= -tol);
4483 }
4484 Standard_Boolean ClassifyLin2d(const Handle(GeomAdaptor_HSurface)& theS, 
4485                                const gp_Lin2d& theLin2d, 
4486                                const Standard_Real theTol,
4487                                Standard_Real& theP1, 
4488                                Standard_Real& theP2)
4489
4490 {
4491   Standard_Real xmin, xmax, ymin, ymax, d1, d2, A, B, C;
4492   Standard_Real par[2];
4493   Standard_Integer nbi = 0;
4494
4495   xmin = theS->Surface().FirstUParameter();
4496   xmax = theS->Surface().LastUParameter();
4497   ymin = theS->Surface().FirstVParameter();
4498   ymax = theS->Surface().LastVParameter();
4499
4500   theLin2d.Coefficients(A, B, C);
4501
4502   //xmin, ymin <-> xmin, ymax
4503   d1 = A*xmin + B*ymin + C;
4504   d2 = A*xmin + B*ymax + C;
4505
4506   if(INTER(d1, d2, theTol)) {
4507     //Intersection with boundary
4508     Standard_Real y = -(C + A*xmin)/B;
4509     par[nbi] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, y));
4510     nbi++;
4511   }
4512   else if (COINC(d1, d2, theTol)) {
4513     //Coincidence with boundary
4514     par[0] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, ymin));
4515     par[1] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, ymax));
4516     nbi = 2;
4517   }
4518
4519   if(nbi == 2) {
4520
4521     if(fabs(par[0]-par[1]) > theTol) {
4522       theP1 = Min(par[0], par[1]);
4523       theP2 = Max(par[0], par[1]);
4524       return Standard_True;
4525     }
4526     else return Standard_False;
4527
4528   }
4529
4530   //xmin, ymax <-> xmax, ymax
4531   d1 = d2;
4532   d2 = A*xmax + B*ymax + C;
4533
4534   if(d1 > theTol || d1 < -theTol) {//to avoid checking of
4535                                    //coincidence with the same point
4536     if(INTER(d1, d2, theTol)) {
4537       Standard_Real x = -(C + B*ymax)/A;
4538       par[nbi] = ElCLib::Parameter(theLin2d, gp_Pnt2d(x, ymax));
4539       nbi++;
4540     }
4541     else if (COINC(d1, d2, theTol)) {
4542       par[0] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, ymax));
4543       par[1] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, ymax));
4544       nbi = 2;
4545     }
4546   }
4547
4548   if(nbi == 2) {
4549
4550     if(fabs(par[0]-par[1]) > theTol) {
4551       theP1 = Min(par[0], par[1]);
4552       theP2 = Max(par[0], par[1]);
4553       return Standard_True;
4554     }
4555     else return Standard_False;
4556
4557   }
4558
4559   //xmax, ymax <-> xmax, ymin
4560   d1 = d2;
4561   d2 = A*xmax + B*ymin + C;
4562
4563   if(d1 > theTol || d1 < -theTol) {
4564     if(INTER(d1, d2, theTol)) {
4565       Standard_Real y = -(C + A*xmax)/B;
4566       par[nbi] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, y));
4567       nbi++;
4568     }
4569     else if (COINC(d1, d2, theTol)) {
4570       par[0] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, ymax));
4571       par[1] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, ymin));
4572       nbi = 2;
4573     }
4574   }
4575
4576   if(nbi == 2) {
4577     if(fabs(par[0]-par[1]) > theTol) {
4578       theP1 = Min(par[0], par[1]);
4579       theP2 = Max(par[0], par[1]);
4580       return Standard_True;
4581     }
4582     else return Standard_False;
4583   }
4584
4585   //xmax, ymin <-> xmin, ymin 
4586   d1 = d2;
4587   d2 = A*xmin + B*ymin + C;
4588
4589   if(d1 > theTol || d1 < -theTol) {
4590     if(INTER(d1, d2, theTol)) {
4591       Standard_Real x = -(C + B*ymin)/A;
4592       par[nbi] = ElCLib::Parameter(theLin2d, gp_Pnt2d(x, ymin));
4593       nbi++;
4594     }
4595     else if (COINC(d1, d2, theTol)) {
4596       par[0] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, ymin));
4597       par[1] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, ymin));
4598       nbi = 2;
4599     }
4600   }
4601
4602   if(nbi == 2) {
4603     if(fabs(par[0]-par[1]) > theTol) {
4604       theP1 = Min(par[0], par[1]);
4605       theP2 = Max(par[0], par[1]);
4606       return Standard_True;
4607     }
4608     else return Standard_False;
4609   }
4610
4611   return Standard_False;
4612
4613 }
4614 //
4615 //=======================================================================
4616 //function : ApproxParameters
4617 //purpose  : 
4618 //=======================================================================
4619 void ApproxParameters(const Handle(GeomAdaptor_HSurface)& aHS1,
4620                       const Handle(GeomAdaptor_HSurface)& aHS2,
4621                       Standard_Integer& iDegMin,
4622                       Standard_Integer& iDegMax,
4623                       Standard_Integer& iNbIter)
4624
4625 {
4626   GeomAbs_SurfaceType aTS1, aTS2;
4627   
4628   //
4629   iNbIter=0;
4630   iDegMin=4;
4631   iDegMax=8;
4632   //
4633   aTS1=aHS1->Surface().GetType();
4634   aTS2=aHS2->Surface().GetType();
4635   //
4636   // Cylinder/Torus
4637   if ((aTS1==GeomAbs_Cylinder && aTS2==GeomAbs_Torus) ||
4638       (aTS2==GeomAbs_Cylinder && aTS1==GeomAbs_Torus)) {
4639     Standard_Real aRC, aRT, dR, aPC;
4640     gp_Cylinder aCylinder;
4641     gp_Torus aTorus;
4642     //
4643     aPC=Precision::Confusion();
4644     //
4645     aCylinder=(aTS1==GeomAbs_Cylinder)? aHS1->Surface().Cylinder() : aHS2->Surface().Cylinder();
4646     aTorus=(aTS1==GeomAbs_Torus)? aHS1->Surface().Torus() : aHS2->Surface().Torus();
4647     //
4648     aRC=aCylinder.Radius();
4649     aRT=aTorus.MinorRadius();
4650     dR=aRC-aRT;
4651     if (dR<0.) {
4652       dR=-dR;
4653     }
4654     //
4655     if (dR<aPC) {
4656       iDegMax=6;
4657     }
4658   }
4659   if (aTS1==GeomAbs_Cylinder && aTS2==GeomAbs_Cylinder) {
4660     iNbIter=1; 
4661   }
4662 }
4663 //=======================================================================
4664 //function : Tolerances
4665 //purpose  : 
4666 //=======================================================================
4667 void Tolerances(const Handle(GeomAdaptor_HSurface)& aHS1,
4668                 const Handle(GeomAdaptor_HSurface)& aHS2,
4669                 Standard_Real& aTolTang)
4670 {
4671   GeomAbs_SurfaceType aTS1, aTS2;
4672   //
4673   aTS1=aHS1->Surface().GetType();
4674   aTS2=aHS2->Surface().GetType();
4675   //
4676   // Cylinder/Torus
4677   if ((aTS1==GeomAbs_Cylinder && aTS2==GeomAbs_Torus) ||
4678       (aTS2==GeomAbs_Cylinder && aTS1==GeomAbs_Torus)) {
4679     Standard_Real aRC, aRT, dR, aPC;
4680     gp_Cylinder aCylinder;
4681     gp_Torus aTorus;
4682     //
4683     aPC=Precision::Confusion();
4684     //
4685     aCylinder=(aTS1==GeomAbs_Cylinder)? aHS1->Surface().Cylinder() : aHS2->Surface().Cylinder();
4686     aTorus=(aTS1==GeomAbs_Torus)? aHS1->Surface().Torus() : aHS2->Surface().Torus();
4687     //
4688     aRC=aCylinder.Radius();
4689     aRT=aTorus.MinorRadius();
4690     dR=aRC-aRT;
4691     if (dR<0.) {
4692       dR=-dR;
4693     }
4694     //
4695     if (dR<aPC) {
4696       aTolTang=0.1*aTolTang;
4697     }
4698   }
4699 }
4700 //=======================================================================
4701 //function : SortTypes
4702 //purpose  : 
4703 //=======================================================================
4704 Standard_Boolean SortTypes(const GeomAbs_SurfaceType aType1,
4705                            const GeomAbs_SurfaceType aType2)
4706 {
4707   Standard_Boolean bRet;
4708   Standard_Integer aI1, aI2;
4709   //
4710   bRet=Standard_False;
4711   //
4712   aI1=IndexType(aType1);
4713   aI2=IndexType(aType2);
4714   if (aI1<aI2){
4715     bRet=!bRet;
4716   }
4717   return bRet;
4718 }
4719 //=======================================================================
4720 //function : IndexType
4721 //purpose  : 
4722 //=======================================================================
4723 Standard_Integer IndexType(const GeomAbs_SurfaceType aType)
4724 {
4725   Standard_Integer aIndex;
4726   //
4727   aIndex=11;
4728   //
4729   if (aType==GeomAbs_Plane) {
4730     aIndex=0;
4731   }
4732   else if (aType==GeomAbs_Cylinder) {
4733     aIndex=1;
4734   } 
4735   else if (aType==GeomAbs_Cone) {
4736     aIndex=2;
4737   } 
4738   else if (aType==GeomAbs_Sphere) {
4739     aIndex=3;
4740   } 
4741   else if (aType==GeomAbs_Torus) {
4742     aIndex=4;
4743   } 
4744   else if (aType==GeomAbs_BezierSurface) {
4745     aIndex=5;
4746   } 
4747   else if (aType==GeomAbs_BSplineSurface) {
4748     aIndex=6;
4749   } 
4750   else if (aType==GeomAbs_SurfaceOfRevolution) {
4751     aIndex=7;
4752   } 
4753   else if (aType==GeomAbs_SurfaceOfExtrusion) {
4754     aIndex=8;
4755   } 
4756   else if (aType==GeomAbs_OffsetSurface) {
4757     aIndex=9;
4758   } 
4759   else if (aType==GeomAbs_OtherSurface) {
4760     aIndex=10;
4761   } 
4762   return aIndex;
4763 }
4764 #ifdef OCCT_DEBUG_DUMPWLINE
4765 //=======================================================================
4766 //function : DumpWLine
4767 //purpose  : 
4768 //=======================================================================
4769 void DumpWLine(const Handle(IntPatch_WLine)& aWLine)
4770 {
4771   Standard_Integer i, aNbPnts; 
4772   Standard_Real aX, aY, aZ, aU1, aV1, aU2, aV2;
4773   //
4774   printf(" *WLine\n");
4775   aNbPnts=aWLine->NbPnts();
4776   for (i=1; i<=aNbPnts; ++i) {
4777     const IntSurf_PntOn2S aPntOn2S=aWLine->Point(i);
4778     const gp_Pnt& aP3D=aPntOn2S.Value();
4779     aP3D.Coord(aX, aY, aZ);
4780     aPntOn2S.Parameters(aU1, aV1, aU2, aV2);
4781     //
4782     printf("point p_%d %lf %lf %lf\n", i, aX, aY, aZ);
4783     //printf("point p_%d %20.15lf %20.15lf %20.15lf %20.15lf %20.15lf %20.15lf %20.15lf\n",
4784         //   i, aX, aY, aZ, aU1, aV1, aU2, aV2);
4785   }
4786 }
4787 #endif
4788 //=======================================================================
4789 //function : RefineVector
4790 //purpose  : 
4791 //=======================================================================
4792 void RefineVector(gp_Vec2d& aV2D)
4793 {
4794   Standard_Integer k,m;
4795   Standard_Real aC[2], aEps, aR1, aR2, aNum;
4796   //
4797   aEps=RealEpsilon();
4798   aR1=1.-aEps;
4799   aR2=1.+aEps;
4800   //
4801   aV2D.Coord(aC[0], aC[1]);
4802   //
4803   for (k=0; k<2; ++k) {
4804     m=(k+1)%2;
4805     aNum=fabs(aC[k]);
4806     if (aNum>aR1 && aNum<aR2) {
4807       if (aC[k]<0.) {
4808         aC[k]=-1.;
4809       }          
4810       else {
4811         aC[k]=1.;
4812       }
4813       aC[m]=0.;
4814       break;
4815     }
4816   }
4817   aV2D.SetCoord(aC[0], aC[1]);
4818 }
4819
4820 //=======================================================================
4821 // Function : MaxDistance
4822 // purpose : 
4823 //=======================================================================
4824 Standard_Real MaxDistance(const Handle(Geom_Curve)& theC,
4825                           const Standard_Real aT,
4826                           GeomAPI_ProjectPointOnSurf& theProjPS)
4827 {
4828   Standard_Real aD;
4829   gp_Pnt aP;
4830   //
4831   theC->D0(aT, aP);
4832   theProjPS.Perform(aP);
4833   aD = theProjPS.NbPoints() ? theProjPS.LowerDistance() : 0.;
4834   //
4835   return aD;
4836 }
4837
4838 //=======================================================================
4839 //function : CheckPCurve
4840 //purpose  : Checks if points of the pcurve are out of the face bounds.
4841 //=======================================================================
4842   Standard_Boolean CheckPCurve(const Handle(Geom2d_Curve)& aPC, 
4843                                const TopoDS_Face& aFace) 
4844 {
4845   const Standard_Integer NPoints = 23;
4846   Standard_Integer i;
4847   Standard_Real umin,umax,vmin,vmax;
4848
4849   BRepTools::UVBounds(aFace, umin, umax, vmin, vmax);
4850   Standard_Real tolU = Max ((umax-umin)*0.01, Precision::Confusion());
4851   Standard_Real tolV = Max ((vmax-vmin)*0.01, Precision::Confusion());
4852   Standard_Real fp = aPC->FirstParameter();
4853   Standard_Real lp = aPC->LastParameter();
4854
4855
4856   // adjust domain for periodic surfaces
4857   TopLoc_Location aLoc;
4858   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc);
4859   if (aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
4860     aSurf = (Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurf))->BasisSurface();
4861   }
4862   gp_Pnt2d pnt = aPC->Value((fp+lp)/2);
4863   Standard_Real u,v;
4864   pnt.Coord(u,v);
4865   //
4866   if (aSurf->IsUPeriodic()) {
4867     Standard_Real aPer = aSurf->UPeriod();
4868     Standard_Integer nshift = (Standard_Integer) ((u-umin)/aPer);
4869     if (u < umin+aPer*nshift) nshift--;
4870     umin += aPer*nshift;
4871     umax += aPer*nshift;
4872   }
4873   if (aSurf->IsVPeriodic()) {
4874     Standard_Real aPer = aSurf->VPeriod();
4875     Standard_Integer nshift = (Standard_Integer) ((v-vmin)/aPer);
4876     if (v < vmin+aPer*nshift) nshift--;
4877     vmin += aPer*nshift;
4878     vmax += aPer*nshift;
4879   }
4880   //
4881   //--------------------------------------------------------
4882   Standard_Boolean bRet;
4883   Standard_Integer j, aNbIntervals;
4884   Standard_Real aT, dT;
4885   gp_Pnt2d aP2D; 
4886   //
4887   Geom2dAdaptor_Curve aGAC(aPC);
4888   aNbIntervals=aGAC.NbIntervals(GeomAbs_CN);
4889   //
4890   TColStd_Array1OfReal aTI(1, aNbIntervals+1);
4891   aGAC.Intervals(aTI,GeomAbs_CN);
4892   //
4893   bRet=Standard_False;
4894   //
4895   aT=aGAC.FirstParameter();
4896   for (j=1; j<=aNbIntervals; ++j) {
4897     dT=(aTI(j+1)-aTI(j))/NPoints;
4898     //
4899     for (i=1; i<NPoints; i++) {
4900       aT=aT+dT;
4901       aGAC.D0(aT, aP2D);
4902       aP2D.Coord(u,v);
4903     if (umin-u > tolU || u-umax > tolU ||
4904           vmin-v > tolV || v-vmax > tolV) {
4905         return bRet;
4906   }
4907 }
4908   }
4909   return !bRet;
4910 }
4911 //=======================================================================
4912 //function : CorrectPlaneBoundaries
4913 //purpose  : 
4914 //=======================================================================
4915  void CorrectPlaneBoundaries(Standard_Real& aUmin,
4916                              Standard_Real& aUmax, 
4917                              Standard_Real& aVmin, 
4918                              Standard_Real& aVmax) 
4919 {
4920   if (!(Precision::IsInfinite(aUmin) ||
4921         Precision::IsInfinite(aUmax))) { 
4922     Standard_Real dU;
4923     //
4924     dU=0.1*(aUmax-aUmin);
4925     aUmin=aUmin-dU;
4926     aUmax=aUmax+dU;
4927   }
4928   if (!(Precision::IsInfinite(aVmin) ||
4929         Precision::IsInfinite(aVmax))) { 
4930     Standard_Real dV;
4931     //
4932     dV=0.1*(aVmax-aVmin);
4933     aVmin=aVmin-dV;
4934     aVmax=aVmax+dV;
4935   }
4936 }