0024750: Replace instantiations of TCollection generic classes by NCollection templat...
[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     const Handle(Geom_BSplineCurve)& aBS=
967       Handle(Geom_BSplineCurve)::DownCast(aC3D);
968     if (aBS.IsNull()) {
969       return;
970     }
971     //
972     aT1=aBS->FirstParameter();
973     aT2=aBS->LastParameter();
974     //
975     aPln  =(aType1==GeomAbs_Plane) ? myHS1->Plane() : myHS2->Plane();
976     aTorus=(aType1==GeomAbs_Plane) ? myHS2->Torus() : myHS1->Torus();
977     //
978     aDmax=-1.;
979     aNbP=11;
980     dT=(aT2-aT1)/(aNbP-1);
981     for (i=0; i<aNbP; ++i) {
982       aT=aT1+i*dT;
983       if (i==aNbP-1) {
984         aT=aT2;
985       }
986       //
987       aC3D->D0(aT, aP);
988       //
989       ElSLib::Parameters(aPln, aP, aUP, aVP);
990       aPP=ElSLib::Value(aUP, aVP, aPln);
991       aDP=aP.SquareDistance(aPP);
992       if (aDP>aDmax) {
993         aDmax=aDP;
994       }
995       //
996       ElSLib::Parameters(aTorus, aP, aUT, aVT);
997       aPT=ElSLib::Value(aUT, aVT, aTorus);
998       aDT=aP.SquareDistance(aPT);
999       if (aDT>aDmax) {
1000         aDmax=aDT;
1001       }
1002     }
1003     //
1004     if (aDmax > myTolReached3d*myTolReached3d) {
1005       myTolReached3d=sqrt(aDmax);
1006       myTolReached3d=1.1*myTolReached3d;
1007     }
1008   }// if ((aType1==GeomAbs_Plane && aType2==GeomAbs_Torus) ||
1009   //
1010   else if ((aType1==GeomAbs_SurfaceOfRevolution && aType2==GeomAbs_Cylinder) ||
1011            (aType2==GeomAbs_SurfaceOfRevolution && aType1==GeomAbs_Cylinder) ||
1012            (aType1==GeomAbs_Plane && aType2==GeomAbs_Sphere) ||
1013            (aType2==GeomAbs_Plane && aType1==GeomAbs_Sphere) ||
1014            (aType1==GeomAbs_Plane && aType2==GeomAbs_SurfaceOfExtrusion) ||
1015            (aType2==GeomAbs_Plane && aType1==GeomAbs_SurfaceOfExtrusion) ||
1016            (aType1==GeomAbs_Plane && aType2==GeomAbs_BSplineSurface) ||
1017            (aType2==GeomAbs_Plane && aType1==GeomAbs_BSplineSurface) ||
1018            !myApprox) {
1019     //
1020     Standard_Real aDMax;
1021     //
1022     aDMax = ComputeTolerance();
1023     if (aDMax > myTolReached3d) {
1024       myTolReached3d = aDMax;
1025     }
1026   }
1027 }
1028
1029 //=======================================================================
1030 //function : MakeCurve
1031 //purpose  : 
1032 //=======================================================================
1033   void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
1034                                     const Handle(Adaptor3d_TopolTool)& dom1,
1035                                     const Handle(Adaptor3d_TopolTool)& dom2) 
1036 {
1037   Standard_Boolean bDone, rejectSurface, reApprox, bAvoidLineConstructor;
1038   Standard_Boolean ok, bPCurvesOk;
1039   Standard_Integer i, j, aNbParts;
1040   Standard_Real fprm, lprm;
1041   Standard_Real Tolpc;
1042   Handle(IntPatch_Line) L;
1043   IntPatch_IType typl;
1044   Handle(Geom_Curve) newc;
1045   //
1046   const Standard_Real TOLCHECK   =0.0000001;
1047   const Standard_Real TOLANGCHECK=0.1;
1048   //
1049   rejectSurface = Standard_False;
1050   reApprox = Standard_False;
1051   //
1052   bPCurvesOk = Standard_True;
1053  
1054  reapprox:;
1055   
1056   Tolpc = myTolApprox;
1057   bAvoidLineConstructor = Standard_False;
1058   L = myIntersector.Line(Index);
1059   typl = L->ArcType();
1060   //
1061   if(typl==IntPatch_Walking) {
1062     Handle(IntPatch_Line) anewL;
1063     //
1064     const Handle(IntPatch_WLine)& aWLine=
1065       Handle(IntPatch_WLine)::DownCast(L);
1066     //DumpWLine(aWLine);
1067
1068     anewL = ComputePurgedWLine(aWLine);
1069     if(anewL.IsNull()) {
1070       return;
1071     }
1072     L = anewL;
1073     
1074     //const Handle(IntPatch_WLine)& aWLineX = Handle(IntPatch_WLine)::DownCast(L);
1075     //DumpWLine(aWLineX);
1076
1077     //
1078     if(!myListOfPnts.IsEmpty()) {
1079       bAvoidLineConstructor = Standard_True;
1080     }
1081
1082     Standard_Integer nbp = aWLine->NbPnts();
1083     const IntSurf_PntOn2S& p1 = aWLine->Point(1);
1084     const IntSurf_PntOn2S& p2 = aWLine->Point(nbp);
1085
1086     const gp_Pnt& P1 = p1.Value();
1087     const gp_Pnt& P2 = p2.Value();
1088
1089     if(P1.SquareDistance(P2) < 1.e-14) {
1090       bAvoidLineConstructor = Standard_False;
1091     }
1092   }
1093
1094   typl=L->ArcType();
1095
1096   //
1097   // Line Constructor
1098   if(!bAvoidLineConstructor) {
1099     myLConstruct.Perform(L);
1100     //
1101     bDone=myLConstruct.IsDone();
1102     if(!bDone)
1103     {
1104       return;
1105     }
1106
1107     if(typl != IntPatch_Restriction)
1108     {
1109       aNbParts=myLConstruct.NbParts();
1110       if (aNbParts <= 0)
1111       {
1112         return;
1113       }
1114     }
1115   }
1116   // Do the Curve
1117   
1118   
1119   switch (typl) {
1120   //########################################  
1121   // Line, Parabola, Hyperbola
1122   //########################################  
1123   case IntPatch_Lin:
1124   case IntPatch_Parabola: 
1125   case IntPatch_Hyperbola: {
1126     if (typl == IntPatch_Lin) {
1127       newc = 
1128         new Geom_Line (Handle(IntPatch_GLine)::DownCast(L)->Line());
1129     }
1130
1131     else if (typl == IntPatch_Parabola) {
1132       newc = 
1133         new Geom_Parabola(Handle(IntPatch_GLine)::DownCast(L)->Parabola());
1134     }
1135     
1136     else if (typl == IntPatch_Hyperbola) {
1137       newc = 
1138         new Geom_Hyperbola (Handle(IntPatch_GLine)::DownCast(L)->Hyperbola());
1139     }
1140     //
1141     // myTolReached3d
1142     if (typl == IntPatch_Lin) {
1143       TolR3d (myFace1, myFace2, myTolReached3d);
1144     }
1145     //
1146     aNbParts=myLConstruct.NbParts();
1147     for (i=1; i<=aNbParts; i++) {
1148       Standard_Boolean bFNIt, bLPIt;
1149       //
1150       myLConstruct.Part(i, fprm, lprm);
1151         //
1152       bFNIt=Precision::IsNegativeInfinite(fprm);
1153       bLPIt=Precision::IsPositiveInfinite(lprm);
1154       //
1155       if (!bFNIt && !bLPIt) {
1156         //
1157         IntTools_Curve aCurve;
1158         //
1159         Handle(Geom_TrimmedCurve) aCT3D=new Geom_TrimmedCurve(newc, fprm, lprm);
1160         aCurve.SetCurve(aCT3D);
1161         if (typl == IntPatch_Parabola) {
1162           Standard_Real aTolF1, aTolF2, aTolBase;
1163           
1164           aTolF1 = BRep_Tool::Tolerance(myFace1);
1165           aTolF2 = BRep_Tool::Tolerance(myFace2);
1166           aTolBase=aTolF1+aTolF2;
1167           myTolReached3d=IntTools_Tools::CurveTolerance(aCT3D, aTolBase);
1168         }
1169         //
1170         aCurve.SetCurve(new Geom_TrimmedCurve(newc, fprm, lprm));
1171         if(myApprox1) { 
1172           Handle (Geom2d_Curve) C2d;
1173           GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc,
1174                 myHS1->ChangeSurface().Surface(), newc, C2d);
1175           if(Tolpc>myTolReached2d || myTolReached2d==0.) { 
1176             myTolReached2d=Tolpc;
1177           }
1178             //            
1179             aCurve.SetFirstCurve2d(new Geom2d_TrimmedCurve(C2d,fprm,lprm));
1180           }
1181           else { 
1182             Handle(Geom2d_BSplineCurve) H1;
1183             //
1184             aCurve.SetFirstCurve2d(H1);
1185           }
1186         //
1187         if(myApprox2) { 
1188           Handle (Geom2d_Curve) C2d;
1189           GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc,
1190                     myHS2->ChangeSurface().Surface(), newc, C2d);
1191           if(Tolpc>myTolReached2d || myTolReached2d==0.) { 
1192             myTolReached2d=Tolpc;
1193           }
1194           //
1195           aCurve.SetSecondCurve2d(new Geom2d_TrimmedCurve(C2d,fprm,lprm));
1196           }
1197         else { 
1198           Handle(Geom2d_BSplineCurve) H1;
1199           //
1200           aCurve.SetSecondCurve2d(H1);
1201         }
1202         mySeqOfCurve.Append(aCurve);
1203       } //if (!bFNIt && !bLPIt) {
1204       else {
1205         //  on regarde si on garde
1206         //
1207         Standard_Real aTestPrm, dT=100.;
1208         //
1209         aTestPrm=0.;
1210         if (bFNIt && !bLPIt) {
1211           aTestPrm=lprm-dT;
1212         }
1213         else if (!bFNIt && bLPIt) {
1214           aTestPrm=fprm+dT;
1215         }
1216         else {
1217           // i.e, if (bFNIt && bLPIt)
1218           aTestPrm=IntTools_Tools::IntermediatePoint(-dT, dT);
1219         }
1220         //
1221         gp_Pnt ptref(newc->Value(aTestPrm));
1222         //
1223         GeomAbs_SurfaceType typS1 = myHS1->GetType();
1224         GeomAbs_SurfaceType typS2 = myHS2->GetType();
1225         if( typS1 == GeomAbs_SurfaceOfExtrusion ||
1226             typS1 == GeomAbs_OffsetSurface ||
1227             typS1 == GeomAbs_SurfaceOfRevolution ||
1228             typS2 == GeomAbs_SurfaceOfExtrusion ||
1229             typS2 == GeomAbs_OffsetSurface ||
1230             typS2 == GeomAbs_SurfaceOfRevolution) {
1231           Handle(Geom2d_BSplineCurve) H1;
1232           mySeqOfCurve.Append(IntTools_Curve(newc, H1, H1));
1233           continue;
1234         }
1235
1236         Standard_Real u1, v1, u2, v2, Tol;
1237         
1238         Tol = Precision::Confusion();
1239         Parameters(myHS1, myHS2, ptref,  u1, v1, u2, v2);
1240         ok = (dom1->Classify(gp_Pnt2d(u1, v1), Tol) != TopAbs_OUT);
1241         if(ok) { 
1242           ok = (dom2->Classify(gp_Pnt2d(u2,v2),Tol) != TopAbs_OUT); 
1243         }
1244         if (ok) {
1245           Handle(Geom2d_BSplineCurve) H1;
1246           mySeqOfCurve.Append(IntTools_Curve(newc, H1, H1));
1247         }
1248       }
1249     }// for (i=1; i<=aNbParts; i++) {
1250   }// case IntPatch_Lin:  case IntPatch_Parabola:  case IntPatch_Hyperbola:
1251     break;
1252
1253   //########################################  
1254   // Circle and Ellipse
1255   //########################################  
1256   case IntPatch_Circle: 
1257   case IntPatch_Ellipse: {
1258
1259     if (typl == IntPatch_Circle) {
1260       newc = new Geom_Circle
1261         (Handle(IntPatch_GLine)::DownCast(L)->Circle());
1262     }
1263     else { //IntPatch_Ellipse
1264       newc = new Geom_Ellipse
1265         (Handle(IntPatch_GLine)::DownCast(L)->Ellipse());
1266     }
1267     //
1268     // myTolReached3d
1269     TolR3d (myFace1, myFace2, myTolReached3d);
1270     //
1271     aNbParts=myLConstruct.NbParts();
1272     //
1273     Standard_Real aPeriod, aNul;
1274     TColStd_SequenceOfReal aSeqFprm,  aSeqLprm;
1275     
1276     aNul=0.;
1277     aPeriod=M_PI+M_PI;
1278
1279     for (i=1; i<=aNbParts; i++) {
1280       myLConstruct.Part(i, fprm, lprm);
1281
1282       if (fprm < aNul && lprm > aNul) {
1283         // interval that goes through 0. is divided on two intervals;
1284         while (fprm<aNul || fprm>aPeriod) fprm=fprm+aPeriod;
1285         while (lprm<aNul || lprm>aPeriod) lprm=lprm+aPeriod;
1286         //
1287         if((aPeriod - fprm) > Tolpc) {
1288           aSeqFprm.Append(fprm);
1289           aSeqLprm.Append(aPeriod);
1290         }
1291         else {
1292           gp_Pnt P1 = newc->Value(fprm);
1293           gp_Pnt P2 = newc->Value(aPeriod);
1294           Standard_Real aTolDist = BRep_Tool::Tolerance(myFace1) + BRep_Tool::Tolerance(myFace2);
1295           aTolDist = (myTolReached3d > aTolDist) ? myTolReached3d : aTolDist;
1296
1297           if(P1.Distance(P2) > aTolDist) {
1298             Standard_Real anewpar = fprm;
1299
1300             if(ParameterOutOfBoundary(fprm, newc, myFace1, myFace2, 
1301                                       lprm, Standard_False, anewpar, myContext)) {
1302               fprm = anewpar;
1303             }
1304             aSeqFprm.Append(fprm);
1305             aSeqLprm.Append(aPeriod);
1306           }
1307         }
1308
1309         //
1310         if((lprm - aNul) > Tolpc) {
1311           aSeqFprm.Append(aNul);
1312           aSeqLprm.Append(lprm);
1313         }
1314         else {
1315           gp_Pnt P1 = newc->Value(aNul);
1316           gp_Pnt P2 = newc->Value(lprm);
1317           Standard_Real aTolDist = BRep_Tool::Tolerance(myFace1) + BRep_Tool::Tolerance(myFace2);
1318           aTolDist = (myTolReached3d > aTolDist) ? myTolReached3d : aTolDist;
1319
1320           if(P1.Distance(P2) > aTolDist) {
1321             Standard_Real anewpar = lprm;
1322
1323             if(ParameterOutOfBoundary(lprm, newc, myFace1, myFace2, 
1324                                       fprm, Standard_True, anewpar, myContext)) {
1325               lprm = anewpar;
1326             }
1327             aSeqFprm.Append(aNul);
1328             aSeqLprm.Append(lprm);
1329           }
1330         }
1331       }
1332       else {
1333         // usual interval 
1334         aSeqFprm.Append(fprm);
1335         aSeqLprm.Append(lprm);
1336       }
1337     }
1338     
1339     //
1340     aNbParts=aSeqFprm.Length();
1341     for (i=1; i<=aNbParts; i++) {
1342       fprm=aSeqFprm(i);
1343       lprm=aSeqLprm(i);
1344       //
1345       Standard_Real aRealEpsilon=RealEpsilon();
1346       if (Abs(fprm) > aRealEpsilon || Abs(lprm-2.*M_PI) > aRealEpsilon) {
1347         //==============================================
1348         ////
1349         IntTools_Curve aCurve;
1350         Handle(Geom_TrimmedCurve) aTC3D=new Geom_TrimmedCurve(newc,fprm,lprm);
1351         aCurve.SetCurve(aTC3D);
1352         fprm=aTC3D->FirstParameter();
1353         lprm=aTC3D->LastParameter ();
1354         ////         
1355         if (typl == IntPatch_Circle || typl == IntPatch_Ellipse) {//// 
1356           if(myApprox1) { 
1357             Handle (Geom2d_Curve) C2d;
1358             GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc, 
1359                         myHS1->ChangeSurface().Surface(), newc, C2d);
1360             if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1361               myTolReached2d=Tolpc;
1362             }
1363             //
1364             aCurve.SetFirstCurve2d(C2d);
1365           }
1366           else { //// 
1367             Handle(Geom2d_BSplineCurve) H1;
1368             aCurve.SetFirstCurve2d(H1);
1369           }
1370
1371
1372           if(myApprox2) { 
1373             Handle (Geom2d_Curve) C2d;
1374             GeomInt_IntSS::BuildPCurves(fprm,lprm,Tolpc,
1375                     myHS2->ChangeSurface().Surface(),newc,C2d);
1376             if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1377               myTolReached2d=Tolpc;
1378             }
1379             //
1380             aCurve.SetSecondCurve2d(C2d);
1381           }
1382           else { 
1383             Handle(Geom2d_BSplineCurve) H1;
1384             aCurve.SetSecondCurve2d(H1);
1385           }
1386         }
1387         
1388         else { 
1389           Handle(Geom2d_BSplineCurve) H1;
1390           aCurve.SetFirstCurve2d(H1);
1391           aCurve.SetSecondCurve2d(H1);
1392         }
1393         mySeqOfCurve.Append(aCurve);
1394           //==============================================        
1395       } //if (Abs(fprm) > RealEpsilon() || Abs(lprm-2.*M_PI) > RealEpsilon())
1396
1397       else {
1398         //  on regarde si on garde
1399         //
1400         if (aNbParts==1) {
1401 //           if (Abs(fprm) < RealEpsilon() &&  Abs(lprm-2.*M_PI) < RealEpsilon()) {
1402           if (Abs(fprm) <= aRealEpsilon && Abs(lprm-2.*M_PI) <= aRealEpsilon) {
1403             IntTools_Curve aCurve;
1404             Handle(Geom_TrimmedCurve) aTC3D=new Geom_TrimmedCurve(newc,fprm,lprm);
1405             aCurve.SetCurve(aTC3D);
1406             fprm=aTC3D->FirstParameter();
1407             lprm=aTC3D->LastParameter ();
1408             
1409             if(myApprox1) { 
1410               Handle (Geom2d_Curve) C2d;
1411               GeomInt_IntSS::BuildPCurves(fprm,lprm,Tolpc,
1412                     myHS1->ChangeSurface().Surface(),newc,C2d);
1413               if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1414                 myTolReached2d=Tolpc;
1415               }
1416               //
1417               aCurve.SetFirstCurve2d(C2d);
1418             }
1419             else { //// 
1420               Handle(Geom2d_BSplineCurve) H1;
1421               aCurve.SetFirstCurve2d(H1);
1422             }
1423
1424             if(myApprox2) { 
1425               Handle (Geom2d_Curve) C2d;
1426               GeomInt_IntSS::BuildPCurves(fprm,lprm,Tolpc,
1427                     myHS2->ChangeSurface().Surface(),newc,C2d);
1428               if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1429                 myTolReached2d=Tolpc;
1430               }
1431               //
1432               aCurve.SetSecondCurve2d(C2d);
1433             }
1434             else { 
1435               Handle(Geom2d_BSplineCurve) H1;
1436               aCurve.SetSecondCurve2d(H1);
1437             }
1438             mySeqOfCurve.Append(aCurve);
1439             break;
1440           }
1441         }
1442         //
1443         Standard_Real aTwoPIdiv17, u1, v1, u2, v2, Tol;
1444
1445         aTwoPIdiv17=2.*M_PI/17.;
1446
1447         for (j=0; j<=17; j++) {
1448           gp_Pnt ptref (newc->Value (j*aTwoPIdiv17));
1449           Tol = Precision::Confusion();
1450
1451           Parameters(myHS1, myHS2, ptref, u1, v1, u2, v2);
1452           ok = (dom1->Classify(gp_Pnt2d(u1,v1),Tol) != TopAbs_OUT);
1453           if(ok) { 
1454             ok = (dom2->Classify(gp_Pnt2d(u2,v2),Tol) != TopAbs_OUT);
1455           }
1456           if (ok) {
1457             IntTools_Curve aCurve;
1458             aCurve.SetCurve(newc);
1459             //==============================================
1460             if (typl == IntPatch_Circle || typl == IntPatch_Ellipse) {
1461               
1462               if(myApprox1) { 
1463                 Handle (Geom2d_Curve) C2d;
1464                 GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc, 
1465                         myHS1->ChangeSurface().Surface(), newc, C2d);
1466                 if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1467                   myTolReached2d=Tolpc;
1468                 }
1469                 // 
1470                 aCurve.SetFirstCurve2d(C2d);
1471               }
1472               else { 
1473                 Handle(Geom2d_BSplineCurve) H1;
1474                 aCurve.SetFirstCurve2d(H1);
1475               }
1476                 
1477               if(myApprox2) { 
1478                 Handle (Geom2d_Curve) C2d;
1479                 GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc,
1480                         myHS2->ChangeSurface().Surface(), newc, C2d);
1481                 if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1482                   myTolReached2d=Tolpc;
1483                 }
1484                 //                 
1485                 aCurve.SetSecondCurve2d(C2d);
1486               }
1487                 
1488               else { 
1489                 Handle(Geom2d_BSplineCurve) H1;
1490                 aCurve.SetSecondCurve2d(H1);
1491               }
1492             }//  end of if (typl == IntPatch_Circle || typl == IntPatch_Ellipse)
1493              
1494             else { 
1495               Handle(Geom2d_BSplineCurve) H1;
1496               //         
1497               aCurve.SetFirstCurve2d(H1);
1498               aCurve.SetSecondCurve2d(H1);
1499             }
1500             //==============================================        
1501             //
1502             mySeqOfCurve.Append(aCurve);
1503             break;
1504
1505             }//  end of if (ok) {
1506           }//  end of for (Standard_Integer j=0; j<=17; j++)
1507         }//  end of else { on regarde si on garde
1508       }// for (i=1; i<=myLConstruct.NbParts(); i++)
1509     }// IntPatch_Circle: IntPatch_Ellipse:
1510     break;
1511     
1512   case IntPatch_Analytic: {
1513     IntSurf_Quadric quad1,quad2;
1514     GeomAbs_SurfaceType typs = myHS1->Surface().GetType();
1515     
1516     switch (typs) {
1517       case GeomAbs_Plane:
1518         quad1.SetValue(myHS1->Surface().Plane());
1519         break;
1520       case GeomAbs_Cylinder:
1521         quad1.SetValue(myHS1->Surface().Cylinder());
1522         break;
1523       case GeomAbs_Cone:
1524         quad1.SetValue(myHS1->Surface().Cone());
1525         break;
1526       case GeomAbs_Sphere:
1527         quad1.SetValue(myHS1->Surface().Sphere());
1528         break;
1529     case GeomAbs_Torus:
1530       quad1.SetValue(myHS1->Surface().Torus());
1531       break;
1532       default:
1533         Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve 1");
1534       }
1535       
1536     typs = myHS2->Surface().GetType();
1537     
1538     switch (typs) {
1539       case GeomAbs_Plane:
1540         quad2.SetValue(myHS2->Surface().Plane());
1541         break;
1542       case GeomAbs_Cylinder:
1543         quad2.SetValue(myHS2->Surface().Cylinder());
1544         break;
1545       case GeomAbs_Cone:
1546         quad2.SetValue(myHS2->Surface().Cone());
1547         break;
1548       case GeomAbs_Sphere:
1549         quad2.SetValue(myHS2->Surface().Sphere());
1550         break;
1551     case GeomAbs_Torus:
1552       quad2.SetValue(myHS2->Surface().Torus());
1553       break;
1554       default:
1555         Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve 2");
1556       }
1557     //
1558     //=========
1559     IntPatch_ALineToWLine convert (quad1, quad2);
1560       
1561     if (!myApprox) {
1562       aNbParts=myLConstruct.NbParts();
1563       for (i=1; i<=aNbParts; i++) {
1564         myLConstruct.Part(i, fprm, lprm);
1565         Handle(IntPatch_WLine) WL = 
1566           convert.MakeWLine(Handle(IntPatch_ALine)::DownCast(L), fprm, lprm);
1567         //
1568         Handle(Geom2d_BSplineCurve) H1;
1569         Handle(Geom2d_BSplineCurve) H2;
1570
1571         if(myApprox1) {
1572           H1 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True);
1573         }
1574         
1575         if(myApprox2) {
1576           H2 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False);
1577         }
1578         //          
1579         mySeqOfCurve.Append(IntTools_Curve(MakeBSpline(WL,1,WL->NbPnts()), H1, H2));
1580       }
1581     } // if (!myApprox)
1582
1583     else { // myApprox=TRUE
1584       GeomInt_WLApprox theapp3d;
1585       // 
1586       Standard_Real tol2d = myTolApprox;
1587       //         
1588       theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_True);
1589       
1590       aNbParts=myLConstruct.NbParts();
1591       for (i=1; i<=aNbParts; i++) {
1592         myLConstruct.Part(i, fprm, lprm);
1593         Handle(IntPatch_WLine) WL = 
1594           convert.MakeWLine(Handle(IntPatch_ALine):: DownCast(L),fprm,lprm);
1595
1596         theapp3d.Perform(myHS1,myHS2,WL,Standard_True,myApprox1,myApprox2, 1, WL->NbPnts());
1597
1598         if (!theapp3d.IsDone()) {
1599           //
1600           Handle(Geom2d_BSplineCurve) H1;
1601           Handle(Geom2d_BSplineCurve) H2;
1602
1603           if(myApprox1) {
1604             H1 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True);
1605           }
1606           
1607           if(myApprox2) {
1608             H2 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False);
1609           }
1610           //          
1611           mySeqOfCurve.Append(IntTools_Curve(MakeBSpline(WL,1,WL->NbPnts()), H1, H2));
1612         }
1613
1614         else {
1615           if(myApprox1 || myApprox2) { 
1616             if( theapp3d.TolReached2d()>myTolReached2d || myTolReached2d==0) { 
1617               myTolReached2d = theapp3d.TolReached2d();
1618             }
1619           }
1620           
1621           if( theapp3d.TolReached3d()>myTolReached3d || myTolReached3d==0) { 
1622             myTolReached3d = theapp3d.TolReached3d();
1623           }
1624
1625           Standard_Integer aNbMultiCurves, nbpoles;
1626           aNbMultiCurves=theapp3d.NbMultiCurves();
1627           for (j=1; j<=aNbMultiCurves; j++) {
1628             const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
1629             nbpoles = mbspc.NbPoles();
1630             
1631             TColgp_Array1OfPnt tpoles(1, nbpoles);
1632             mbspc.Curve(1, tpoles);
1633             Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles,
1634                                                                mbspc.Knots(),
1635                                                                mbspc.Multiplicities(),
1636                                                                mbspc.Degree());
1637             
1638             GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK);
1639             Check.FixTangent(Standard_True,Standard_True);
1640             // 
1641             IntTools_Curve aCurve;
1642             aCurve.SetCurve(BS);
1643             
1644             if(myApprox1) { 
1645               TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
1646               mbspc.Curve(2,tpoles2d);
1647               Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d,
1648                                                                       mbspc.Knots(),
1649                                                                       mbspc.Multiplicities(),
1650                                                                       mbspc.Degree());
1651
1652               GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK);
1653               newCheck.FixTangent(Standard_True,Standard_True);
1654               //                 
1655               aCurve.SetFirstCurve2d(BS2);
1656             }
1657             else {
1658               Handle(Geom2d_BSplineCurve) H1;
1659               aCurve.SetFirstCurve2d(H1);
1660             }
1661             
1662             if(myApprox2) { 
1663               TColgp_Array1OfPnt2d tpoles2d(1, nbpoles);
1664               Standard_Integer TwoOrThree;
1665               TwoOrThree=myApprox1 ? 3 : 2;
1666               mbspc.Curve(TwoOrThree, tpoles2d);
1667               Handle(Geom2d_BSplineCurve) BS2 =new Geom2d_BSplineCurve(tpoles2d,
1668                                                                        mbspc.Knots(),
1669                                                                        mbspc.Multiplicities(),
1670                                                                        mbspc.Degree());
1671                 
1672               GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK);
1673               newCheck.FixTangent(Standard_True,Standard_True);
1674               //         
1675               aCurve.SetSecondCurve2d(BS2);
1676             }
1677             else { 
1678               Handle(Geom2d_BSplineCurve) H2;
1679               aCurve.SetSecondCurve2d(H2);
1680             }
1681             // 
1682             mySeqOfCurve.Append(aCurve);
1683
1684           }// for (j=1; j<=aNbMultiCurves; j++) {
1685         }// else from if (!theapp3d.IsDone())
1686       }// for (i=1; i<=aNbParts; i++) {
1687     }// else { // myApprox=TRUE
1688   }// case IntPatch_Analytic:
1689     break;
1690
1691   case IntPatch_Walking:{
1692     Handle(IntPatch_WLine) WL = 
1693       Handle(IntPatch_WLine)::DownCast(L);
1694     //
1695     Standard_Integer ifprm, ilprm;
1696     //
1697     if (!myApprox) {
1698       aNbParts = 1;
1699       if(!bAvoidLineConstructor){
1700         aNbParts=myLConstruct.NbParts();
1701       }
1702       for (i=1; i<=aNbParts; ++i) {
1703         Handle(Geom2d_BSplineCurve) H1, H2;
1704         Handle(Geom_Curve) aBSp;
1705         //
1706         if(bAvoidLineConstructor) {
1707           ifprm = 1;
1708           ilprm = WL->NbPnts();
1709         }
1710         else {
1711           myLConstruct.Part(i, fprm, lprm);
1712           ifprm=(Standard_Integer)fprm;
1713           ilprm=(Standard_Integer)lprm;
1714         }
1715         //
1716         if(myApprox1) {
1717           H1 = MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
1718         }
1719         //
1720         if(myApprox2) {
1721           H2 = MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
1722         }
1723         //           
1724         aBSp=MakeBSpline(WL, ifprm, ilprm);
1725         IntTools_Curve aIC(aBSp, H1, H2);
1726         mySeqOfCurve.Append(aIC);
1727       }// for (i=1; i<=aNbParts; ++i) {
1728     }// if (!myApprox) {
1729     //
1730     else { // X
1731       Standard_Boolean bIsDecomposited;
1732       Standard_Integer nbiter, aNbSeqOfL;
1733       Standard_Real tol2d, aTolApproxImp;
1734       IntPatch_SequenceOfLine aSeqOfL;
1735       GeomInt_WLApprox theapp3d;
1736       Approx_ParametrizationType aParType = Approx_ChordLength;
1737       //
1738       Standard_Boolean anApprox1 = myApprox1;
1739       Standard_Boolean anApprox2 = myApprox2;
1740       //
1741       aTolApproxImp=1.e-5;
1742       tol2d = myTolApprox;
1743
1744       GeomAbs_SurfaceType typs1, typs2;
1745       typs1 = myHS1->Surface().GetType();
1746       typs2 = myHS2->Surface().GetType();
1747       Standard_Boolean anWithPC = Standard_True;
1748
1749       if(typs1 == GeomAbs_Cylinder && typs2 == GeomAbs_Sphere) {
1750         anWithPC = 
1751           ApproxWithPCurves(myHS1->Surface().Cylinder(), myHS2->Surface().Sphere());
1752       }
1753       else if (typs1 == GeomAbs_Sphere && typs2 == GeomAbs_Cylinder) {
1754         anWithPC = 
1755           ApproxWithPCurves(myHS2->Surface().Cylinder(), myHS1->Surface().Sphere());
1756       }
1757       //
1758       if(!anWithPC) {
1759         myTolApprox = aTolApproxImp;//1.e-5; 
1760         anApprox1 = Standard_False;
1761         anApprox2 = Standard_False;
1762         //         
1763         tol2d = myTolApprox;
1764       }
1765         
1766       if(myHS1 == myHS2) { 
1767         theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False, aParType);
1768         rejectSurface = Standard_True;
1769       }
1770       else { 
1771         if(reApprox && !rejectSurface)
1772           theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False, aParType);
1773         else {
1774           Standard_Integer iDegMax, iDegMin, iNbIter;
1775           //
1776           ApproxParameters(myHS1, myHS2, iDegMin, iDegMax, iNbIter);
1777           theapp3d.SetParameters(myTolApprox, tol2d, iDegMin, iDegMax, iNbIter, Standard_True, aParType);
1778         }
1779       }
1780       //
1781       Standard_Real aReachedTol = Precision::Confusion();
1782       bIsDecomposited=DecompositionOfWLine(WL,
1783                                            myHS1, 
1784                                            myHS2, 
1785                                            myFace1, 
1786                                            myFace2, 
1787                                            myLConstruct, 
1788                                            bAvoidLineConstructor, 
1789                                            aSeqOfL, 
1790                                            aReachedTol,
1791                                            myContext);
1792       if ( bIsDecomposited && ( myTolReached3d < aReachedTol ) ) {
1793         myTolReached3d = aReachedTol;
1794       }
1795       //
1796       aNbSeqOfL=aSeqOfL.Length();
1797       //
1798       if (bIsDecomposited) {
1799         nbiter=aNbSeqOfL;
1800       }
1801       else {
1802         nbiter=1;
1803         aNbParts=1;
1804         if (!bAvoidLineConstructor) {
1805           aNbParts=myLConstruct.NbParts();
1806           nbiter=aNbParts;
1807         }
1808       }
1809       //
1810       for(i = 1; i <= nbiter; ++i) {
1811         if(bIsDecomposited) {
1812           WL = Handle(IntPatch_WLine)::DownCast(aSeqOfL.Value(i));
1813           ifprm = 1;
1814           ilprm = WL->NbPnts();
1815         }
1816         else {
1817           if(bAvoidLineConstructor) {
1818             ifprm = 1;
1819             ilprm = WL->NbPnts();
1820           }
1821           else {
1822             myLConstruct.Part(i, fprm, lprm);
1823             ifprm = (Standard_Integer)fprm;
1824             ilprm = (Standard_Integer)lprm;
1825           }
1826         }
1827         //-- lbr : 
1828         //-- Si une des surfaces est un plan , on approxime en 2d
1829         //-- sur cette surface et on remonte les points 2d en 3d.
1830         if(typs1 == GeomAbs_Plane) { 
1831           theapp3d.Perform(myHS1, myHS2, WL, Standard_False,Standard_True, myApprox2,ifprm,ilprm);
1832         }          
1833         else if(typs2 == GeomAbs_Plane) { 
1834           theapp3d.Perform(myHS1,myHS2,WL,Standard_False,myApprox1,Standard_True,ifprm,ilprm);
1835         }
1836         else { 
1837           //
1838           if (myHS1 != myHS2){
1839             if ((typs1==GeomAbs_BezierSurface || typs1==GeomAbs_BSplineSurface) &&
1840                 (typs2==GeomAbs_BezierSurface || typs2==GeomAbs_BSplineSurface)) {
1841              
1842               theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_True, aParType);
1843               
1844               Standard_Boolean bUseSurfaces;
1845               bUseSurfaces=NotUseSurfacesForApprox(myFace1, myFace2, WL, ifprm,  ilprm);
1846               if (bUseSurfaces) {
1847                 // ######
1848                 rejectSurface = Standard_True;
1849                 // ######
1850                 theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False, aParType);
1851               }
1852             }
1853           }
1854           //
1855           theapp3d.Perform(myHS1,myHS2,WL,Standard_True,anApprox1,anApprox2,ifprm,ilprm);
1856         }
1857           //           
1858         if (!theapp3d.IsDone()) {
1859           Handle(Geom2d_BSplineCurve) H1;
1860           Handle(Geom2d_BSplineCurve) H2;
1861           //           
1862           Handle(Geom_Curve) aBSp=MakeBSpline(WL,ifprm, ilprm);
1863           //
1864           if(myApprox1) {
1865             H1 = MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
1866           }
1867           //
1868           if(myApprox2) {
1869             H2 = MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
1870           }
1871           //           
1872           IntTools_Curve aIC(aBSp, H1, H2);
1873           mySeqOfCurve.Append(aIC);
1874         }
1875         
1876         else {
1877           if(myApprox1 || myApprox2 || (typs1==GeomAbs_Plane || typs2==GeomAbs_Plane)) { 
1878             if( theapp3d.TolReached2d()>myTolReached2d || myTolReached2d==0.) { 
1879               myTolReached2d = theapp3d.TolReached2d();
1880             }
1881           }
1882           if(typs1==GeomAbs_Plane || typs2==GeomAbs_Plane) { 
1883             myTolReached3d = myTolReached2d;
1884             //
1885             if (typs1==GeomAbs_Torus || typs2==GeomAbs_Torus) {
1886               if (myTolReached3d<1.e-6) {
1887                 myTolReached3d = theapp3d.TolReached3d();
1888                 myTolReached3d=1.e-6;
1889               }
1890             }
1891           }
1892           else  if( theapp3d.TolReached3d()>myTolReached3d || myTolReached3d==0.) { 
1893             myTolReached3d = theapp3d.TolReached3d();
1894           }
1895           
1896           Standard_Integer aNbMultiCurves, nbpoles;
1897           aNbMultiCurves=theapp3d.NbMultiCurves(); 
1898           for (j=1; j<=aNbMultiCurves; j++) {
1899             if(typs1 == GeomAbs_Plane) {
1900               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
1901               nbpoles = mbspc.NbPoles();
1902               
1903               TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
1904               TColgp_Array1OfPnt   tpoles(1,nbpoles);
1905               
1906               mbspc.Curve(1,tpoles2d);
1907               const gp_Pln&  Pln = myHS1->Surface().Plane();
1908               //
1909               Standard_Integer ik; 
1910               for(ik = 1; ik<= nbpoles; ik++) { 
1911                 tpoles.SetValue(ik,
1912                                 ElSLib::Value(tpoles2d.Value(ik).X(),
1913                                               tpoles2d.Value(ik).Y(),
1914                                               Pln));
1915               }
1916               //
1917               Handle(Geom_BSplineCurve) BS = 
1918                 new Geom_BSplineCurve(tpoles,
1919                                       mbspc.Knots(),
1920                                       mbspc.Multiplicities(),
1921                                       mbspc.Degree());
1922               GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK);
1923               Check.FixTangent(Standard_True, Standard_True);
1924               //         
1925               IntTools_Curve aCurve;
1926               aCurve.SetCurve(BS);
1927
1928               if(myApprox1) { 
1929                 Handle(Geom2d_BSplineCurve) BS1 = 
1930                   new Geom2d_BSplineCurve(tpoles2d,
1931                                           mbspc.Knots(),
1932                                           mbspc.Multiplicities(),
1933                                           mbspc.Degree());
1934                 GeomLib_Check2dBSplineCurve Check1(BS1,TOLCHECK,TOLANGCHECK);
1935                 Check1.FixTangent(Standard_True,Standard_True);
1936                 //
1937                 // ############################################
1938                 if(!rejectSurface && !reApprox) {
1939                   Standard_Boolean isValid = IsCurveValid(BS1);
1940                   if(!isValid) {
1941                     reApprox = Standard_True;
1942                     goto reapprox;
1943                   }
1944                 }
1945                 // ############################################
1946                 aCurve.SetFirstCurve2d(BS1);
1947               }
1948               else {
1949                 Handle(Geom2d_BSplineCurve) H1;
1950                 aCurve.SetFirstCurve2d(H1);
1951               }
1952
1953               if(myApprox2) { 
1954                 mbspc.Curve(2, tpoles2d);
1955                 
1956                 Handle(Geom2d_BSplineCurve) BS2 = new Geom2d_BSplineCurve(tpoles2d,
1957                                                                           mbspc.Knots(),
1958                                                                           mbspc.Multiplicities(),
1959                                                                           mbspc.Degree());
1960                 GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK);
1961                 newCheck.FixTangent(Standard_True,Standard_True);
1962                 
1963                 // ###########################################
1964                 if(!rejectSurface && !reApprox) {
1965                   Standard_Boolean isValid = IsCurveValid(BS2);
1966                   if(!isValid) {
1967                     reApprox = Standard_True;
1968                     goto reapprox;
1969                   }
1970                 }
1971                 // ###########################################
1972                 // 
1973                 aCurve.SetSecondCurve2d(BS2);
1974               }
1975               else { 
1976                 Handle(Geom2d_BSplineCurve) H2;
1977                 //                 
1978                   aCurve.SetSecondCurve2d(H2);
1979               }
1980               //
1981               mySeqOfCurve.Append(aCurve);
1982             }//if(typs1 == GeomAbs_Plane) {
1983             
1984             else if(typs2 == GeomAbs_Plane) { 
1985               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
1986               nbpoles = mbspc.NbPoles();
1987               
1988               TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
1989               TColgp_Array1OfPnt   tpoles(1,nbpoles);
1990               mbspc.Curve((myApprox1==Standard_True)? 2 : 1,tpoles2d);
1991               const gp_Pln&  Pln = myHS2->Surface().Plane();
1992               //
1993               Standard_Integer ik; 
1994               for(ik = 1; ik<= nbpoles; ik++) { 
1995                 tpoles.SetValue(ik,
1996                                 ElSLib::Value(tpoles2d.Value(ik).X(),
1997                                               tpoles2d.Value(ik).Y(),
1998                                               Pln));
1999                 
2000               }
2001               //
2002               Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles,
2003                                                                  mbspc.Knots(),
2004                                                                  mbspc.Multiplicities(),
2005                                                                  mbspc.Degree());
2006               GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK);
2007               Check.FixTangent(Standard_True,Standard_True);
2008               //         
2009               IntTools_Curve aCurve;
2010               aCurve.SetCurve(BS);
2011
2012               if(myApprox2) {
2013                 Handle(Geom2d_BSplineCurve) BS1=new Geom2d_BSplineCurve(tpoles2d,
2014                                                                         mbspc.Knots(),
2015                                                                         mbspc.Multiplicities(),
2016                                                                         mbspc.Degree());
2017                 GeomLib_Check2dBSplineCurve Check1(BS1,TOLCHECK,TOLANGCHECK);
2018                 Check1.FixTangent(Standard_True,Standard_True);
2019                 //         
2020                 // ###########################################
2021                 if(!rejectSurface && !reApprox) {
2022                   Standard_Boolean isValid = IsCurveValid(BS1);
2023                   if(!isValid) {
2024                     reApprox = Standard_True;
2025                     goto reapprox;
2026                   }
2027                 }
2028                 // ###########################################
2029                 bPCurvesOk = CheckPCurve(BS1, myFace2);
2030                 aCurve.SetSecondCurve2d(BS1);
2031               }
2032               else {
2033                 Handle(Geom2d_BSplineCurve) H2;
2034                 aCurve.SetSecondCurve2d(H2);
2035               }
2036               
2037               if(myApprox1) { 
2038                 mbspc.Curve(1,tpoles2d);
2039                 Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d,
2040                                                                         mbspc.Knots(),
2041                                                                         mbspc.Multiplicities(),
2042                                                                         mbspc.Degree());
2043                 GeomLib_Check2dBSplineCurve Check2(BS2,TOLCHECK,TOLANGCHECK);
2044                 Check2.FixTangent(Standard_True,Standard_True);
2045                 //
2046                 // ###########################################
2047                 if(!rejectSurface && !reApprox) {
2048                   Standard_Boolean isValid = IsCurveValid(BS2);
2049                   if(!isValid) {
2050                     reApprox = Standard_True;
2051                     goto reapprox;
2052                   }
2053                 }
2054                 // ###########################################
2055                 bPCurvesOk = bPCurvesOk && CheckPCurve(BS2, myFace1);
2056                 aCurve.SetFirstCurve2d(BS2);
2057               }
2058               else { 
2059                 Handle(Geom2d_BSplineCurve) H1;
2060                 //                 
2061                 aCurve.SetFirstCurve2d(H1);
2062               }
2063               //
2064               //if points of the pcurves are out of the faces bounds
2065               //create 3d and 2d curves without approximation
2066               if (!bPCurvesOk) {
2067                 Handle(Geom2d_BSplineCurve) H1, H2;
2068                 bPCurvesOk = Standard_True;
2069                 //           
2070                 Handle(Geom_Curve) aBSp=MakeBSpline(WL,ifprm, ilprm);
2071                 
2072                 if(myApprox1) {
2073                   H1 = MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
2074                   bPCurvesOk = CheckPCurve(H1, myFace1);
2075                 }
2076                 
2077                 if(myApprox2) {
2078                   H2 = MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
2079                   bPCurvesOk = bPCurvesOk && CheckPCurve(H2, myFace2);
2080                 }
2081                 //
2082                 //if pcurves created without approximation are out of the 
2083                 //faces bounds, use approximated 3d and 2d curves
2084                 if (bPCurvesOk) {
2085                   IntTools_Curve aIC(aBSp, H1, H2);
2086                   mySeqOfCurve.Append(aIC);
2087                 } else {
2088                   mySeqOfCurve.Append(aCurve);
2089                 }
2090               } else {
2091                 mySeqOfCurve.Append(aCurve);
2092               }
2093             }// else if(typs2 == GeomAbs_Plane)
2094             //
2095             else { //typs2 != GeomAbs_Plane && typs1 != GeomAbs_Plane
2096               Standard_Boolean bIsValid1, bIsValid2;
2097               Handle(Geom_BSplineCurve) BS;
2098               Handle(Geom2d_BSplineCurve) aH2D;        
2099               IntTools_Curve aCurve; 
2100               //
2101               bIsValid1=Standard_True;
2102               bIsValid2=Standard_True;
2103               //
2104               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
2105               nbpoles = mbspc.NbPoles();
2106               TColgp_Array1OfPnt tpoles(1,nbpoles);
2107               mbspc.Curve(1,tpoles);
2108               BS=new Geom_BSplineCurve(tpoles,
2109                                                                  mbspc.Knots(),
2110                                                                  mbspc.Multiplicities(),
2111                                                                  mbspc.Degree());
2112               GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK);
2113               Check.FixTangent(Standard_True,Standard_True);
2114               //                 
2115               aCurve.SetCurve(BS);
2116               aCurve.SetFirstCurve2d(aH2D);
2117               aCurve.SetSecondCurve2d(aH2D);
2118               //
2119               if(myApprox1) { 
2120                 if(anApprox1) {
2121                   Handle(Geom2d_BSplineCurve) BS1;
2122                   TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
2123                   mbspc.Curve(2,tpoles2d);
2124                   //
2125                   BS1=new Geom2d_BSplineCurve(tpoles2d,
2126                                                                         mbspc.Knots(),
2127                                                                         mbspc.Multiplicities(),
2128                                                                         mbspc.Degree());
2129                   GeomLib_Check2dBSplineCurve newCheck(BS1,TOLCHECK,TOLANGCHECK);
2130                   newCheck.FixTangent(Standard_True,Standard_True);
2131                   //         
2132                   if (!reApprox) {
2133                     bIsValid1=CheckPCurve(BS1, myFace1);
2134                   }
2135                   //
2136                   aCurve.SetFirstCurve2d(BS1);
2137                 }
2138                 else {
2139                   Handle(Geom2d_BSplineCurve) BS1;
2140                   fprm = BS->FirstParameter();
2141                   lprm = BS->LastParameter();
2142
2143                   Handle(Geom2d_Curve) C2d;
2144                   Standard_Real aTol = myTolApprox;
2145                   GeomInt_IntSS::BuildPCurves(fprm, lprm, aTol,
2146                             myHS1->ChangeSurface().Surface(), BS, C2d);
2147                   BS1 = Handle(Geom2d_BSplineCurve)::DownCast(C2d);
2148                   aCurve.SetFirstCurve2d(BS1);
2149                 }
2150               } // if(myApprox1) { 
2151                 //                 
2152               if(myApprox2) { 
2153                 if(anApprox2) {
2154                   Handle(Geom2d_BSplineCurve) BS2;
2155                   TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
2156                   mbspc.Curve((myApprox1==Standard_True)? 3 : 2,tpoles2d);
2157                   BS2=new Geom2d_BSplineCurve(tpoles2d,
2158                                                                         mbspc.Knots(),
2159                                                                         mbspc.Multiplicities(),
2160                                                                         mbspc.Degree());
2161                   GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK);
2162                   newCheck.FixTangent(Standard_True,Standard_True);
2163                 //                 
2164                   if (!reApprox) {
2165                     bIsValid2=CheckPCurve(BS2, myFace2);        
2166                   }
2167                   aCurve.SetSecondCurve2d(BS2);
2168                 }
2169                 else {
2170                   Handle(Geom2d_BSplineCurve) BS2;
2171                   fprm = BS->FirstParameter();
2172                   lprm = BS->LastParameter();
2173
2174                   Handle(Geom2d_Curve) C2d;
2175                   Standard_Real aTol = myTolApprox;
2176                   GeomInt_IntSS::BuildPCurves(fprm, lprm, aTol,
2177                             myHS2->ChangeSurface().Surface(), BS, C2d);
2178                   BS2 = Handle(Geom2d_BSplineCurve)::DownCast(C2d);
2179                   aCurve.SetSecondCurve2d(BS2);
2180                 }
2181               } //if(myApprox2) { 
2182               if (!bIsValid1 || !bIsValid2) {
2183                 myTolApprox=aTolApproxImp;//1.e-5;
2184                 tol2d = myTolApprox;
2185                 reApprox = Standard_True;
2186                 goto reapprox;
2187               }
2188                 //                 
2189               mySeqOfCurve.Append(aCurve);
2190             }
2191           }
2192         }
2193       }
2194     }// else { // X
2195   }// case IntPatch_Walking:{
2196     break;
2197     
2198   case IntPatch_Restriction: 
2199     {
2200       GeomAbs_SurfaceType typS1 = myHS1->Surface().GetType();
2201       GeomAbs_SurfaceType typS2 = myHS2->Surface().GetType();
2202       Standard_Boolean isAnalS1 = Standard_False;
2203       switch (typS1)
2204       {
2205       case GeomAbs_Plane:
2206       case GeomAbs_Cylinder:
2207       case GeomAbs_Sphere:
2208       case GeomAbs_Cone: 
2209       case GeomAbs_Torus: isAnalS1 = Standard_True; break;
2210       default: break;
2211       }
2212
2213       Standard_Integer isAnalS2 = Standard_False;
2214       switch (typS2)
2215       {
2216       case GeomAbs_Plane:
2217       case GeomAbs_Cylinder:
2218       case GeomAbs_Sphere:
2219       case GeomAbs_Cone: 
2220       case GeomAbs_Torus: isAnalS2 = Standard_True; break;
2221       default: break;
2222       }
2223
2224       Handle(IntPatch_RLine) RL = 
2225         Handle(IntPatch_RLine)::DownCast(L);
2226       Handle(Geom_Curve) aC3d;
2227       Handle(Geom2d_Curve) aC2d1, aC2d2;
2228       Standard_Real aTolReached;
2229       GeomInt_IntSS::TreatRLine(RL, myHS1, myHS2, aC3d,
2230                                   aC2d1, aC2d2, aTolReached);
2231
2232       if(aC3d.IsNull())
2233         break;
2234
2235       Bnd_Box2d aBox1, aBox2;
2236
2237       const Standard_Real aU1f = myHS1->FirstUParameter(),
2238                           aV1f = myHS1->FirstVParameter(),
2239                           aU1l = myHS1->LastUParameter(),
2240                           aV1l = myHS1->LastVParameter();
2241       const Standard_Real aU2f = myHS2->FirstUParameter(),
2242                           aV2f = myHS2->FirstVParameter(),
2243                           aU2l = myHS2->LastUParameter(),
2244                           aV2l = myHS2->LastVParameter();
2245
2246       aBox1.Add(gp_Pnt2d(aU1f, aV1f));
2247       aBox1.Add(gp_Pnt2d(aU1l, aV1l));
2248       aBox2.Add(gp_Pnt2d(aU2f, aV2f));
2249       aBox2.Add(gp_Pnt2d(aU2l, aV2l));
2250
2251       GeomInt_VectorOfReal anArrayOfParameters;
2252         
2253       //We consider here that the intersection line is same-parameter-line
2254       anArrayOfParameters.Append(aC3d->FirstParameter());
2255       anArrayOfParameters.Append(aC3d->LastParameter());
2256
2257       GeomInt_IntSS::
2258         TrimILineOnSurfBoundaries(aC2d1, aC2d2, aBox1, aBox2, anArrayOfParameters);
2259
2260       const Standard_Integer aNbIntersSolutionsm1 = anArrayOfParameters.Length() - 1;
2261
2262       //Trim RLine found.
2263       for(Standard_Integer anInd = 0; anInd < aNbIntersSolutionsm1; anInd++)
2264       {
2265         const Standard_Real aParF = anArrayOfParameters(anInd),
2266                             aParL = anArrayOfParameters(anInd+1);
2267
2268         if((aParL - aParF) <= Precision::PConfusion())
2269           continue;
2270
2271         const Standard_Real aPar = 0.5*(aParF + aParL);
2272         gp_Pnt2d aPt;
2273
2274         Handle(Geom2d_Curve) aCurv2d1, aCurv2d2;
2275         if(!aC2d1.IsNull())
2276         {
2277           aC2d1->D0(aPar, aPt);
2278
2279           if(aBox1.IsOut(aPt))
2280             continue;
2281
2282           if(myApprox1)
2283             aCurv2d1 = new Geom2d_TrimmedCurve(aC2d1, aParF, aParL);
2284         }
2285
2286         if(!aC2d2.IsNull())
2287         {
2288           aC2d2->D0(aPar, aPt);
2289
2290           if(aBox2.IsOut(aPt))
2291             continue;
2292
2293           if(myApprox2)
2294             aCurv2d2 = new Geom2d_TrimmedCurve(aC2d2, aParF, aParL);
2295         }
2296
2297         Handle(Geom_Curve) aCurv3d = new Geom_TrimmedCurve(aC3d, aParF, aParL);
2298
2299         IntTools_Curve aIC(aCurv3d, aCurv2d1, aCurv2d2);
2300         mySeqOfCurve.Append(aIC);
2301       }
2302     }
2303     break;
2304   default:
2305     break;
2306
2307   }
2308 }
2309
2310 //=======================================================================
2311 //function : Parameters
2312 //purpose  : 
2313 //=======================================================================
2314  void Parameters(const Handle(GeomAdaptor_HSurface)& HS1,
2315                  const Handle(GeomAdaptor_HSurface)& HS2,
2316                  const gp_Pnt& Ptref,
2317                  Standard_Real& U1,
2318                  Standard_Real& V1,
2319                  Standard_Real& U2,
2320                  Standard_Real& V2)
2321 {
2322
2323   IntSurf_Quadric quad1,quad2;
2324   GeomAbs_SurfaceType typs = HS1->Surface().GetType();
2325
2326   switch (typs) {
2327   case GeomAbs_Plane:
2328     quad1.SetValue(HS1->Surface().Plane());
2329     break;
2330   case GeomAbs_Cylinder:
2331     quad1.SetValue(HS1->Surface().Cylinder());
2332     break;
2333   case GeomAbs_Cone:
2334     quad1.SetValue(HS1->Surface().Cone());
2335     break;
2336   case GeomAbs_Sphere:
2337     quad1.SetValue(HS1->Surface().Sphere());
2338     break;
2339   case GeomAbs_Torus:
2340     quad1.SetValue(HS1->Surface().Torus());
2341     break;
2342   default:
2343     Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve");
2344   }
2345   
2346   typs = HS2->Surface().GetType();
2347   switch (typs) {
2348   case GeomAbs_Plane:
2349     quad2.SetValue(HS2->Surface().Plane());
2350     break;
2351   case GeomAbs_Cylinder:
2352     quad2.SetValue(HS2->Surface().Cylinder());
2353     break;
2354   case GeomAbs_Cone:
2355     quad2.SetValue(HS2->Surface().Cone());
2356     break;
2357   case GeomAbs_Sphere:
2358     quad2.SetValue(HS2->Surface().Sphere());
2359     break;
2360   case GeomAbs_Torus:
2361     quad2.SetValue(HS2->Surface().Torus());
2362     break;
2363   default:
2364     Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve");
2365   }
2366
2367   quad1.Parameters(Ptref,U1,V1);
2368   quad2.Parameters(Ptref,U2,V2);
2369 }
2370
2371 //=======================================================================
2372 //function : MakeBSpline
2373 //purpose  : 
2374 //=======================================================================
2375 Handle(Geom_Curve) MakeBSpline  (const Handle(IntPatch_WLine)& WL,
2376                                  const Standard_Integer ideb,
2377                                  const Standard_Integer ifin)
2378 {
2379   Standard_Integer i,nbpnt = ifin-ideb+1;
2380   TColgp_Array1OfPnt poles(1,nbpnt);
2381   TColStd_Array1OfReal knots(1,nbpnt);
2382   TColStd_Array1OfInteger mults(1,nbpnt);
2383   Standard_Integer ipidebm1;
2384   for(i=1,ipidebm1=i+ideb-1; i<=nbpnt;ipidebm1++, i++) {
2385     poles(i) = WL->Point(ipidebm1).Value();
2386     mults(i) = 1;
2387     knots(i) = i-1;
2388   }
2389   mults(1) = mults(nbpnt) = 2;
2390   return
2391     new Geom_BSplineCurve(poles,knots,mults,1);
2392 }
2393 //
2394
2395 //=======================================================================
2396 //function : MakeBSpline2d
2397 //purpose  : 
2398 //=======================================================================
2399 Handle(Geom2d_BSplineCurve) MakeBSpline2d(const Handle(IntPatch_WLine)& theWLine,
2400                                           const Standard_Integer ideb,
2401                                           const Standard_Integer ifin,
2402                                           const Standard_Boolean onFirst)
2403 {
2404   Standard_Integer i, nbpnt = ifin-ideb+1;
2405   TColgp_Array1OfPnt2d poles(1,nbpnt);
2406   TColStd_Array1OfReal knots(1,nbpnt);
2407   TColStd_Array1OfInteger mults(1,nbpnt);
2408   Standard_Integer ipidebm1;
2409
2410   for(i = 1, ipidebm1 = i+ideb-1; i <= nbpnt; ipidebm1++, i++) {
2411       Standard_Real U, V;
2412       if(onFirst)
2413         theWLine->Point(ipidebm1).ParametersOnS1(U, V);
2414       else
2415         theWLine->Point(ipidebm1).ParametersOnS2(U, V);
2416       poles(i).SetCoord(U, V);
2417       mults(i) = 1;
2418       knots(i) = i-1;
2419     }
2420     mults(1) = mults(nbpnt) = 2;
2421
2422   return new Geom2d_BSplineCurve(poles,knots,mults,1);
2423 }
2424 //=======================================================================
2425 //function : PrepareLines3D
2426 //purpose  : 
2427 //=======================================================================
2428   void IntTools_FaceFace::PrepareLines3D(const Standard_Boolean bToSplit)
2429 {
2430   Standard_Integer i, aNbCurves;
2431   GeomAbs_SurfaceType aType1, aType2;
2432   IntTools_SequenceOfCurves aNewCvs;
2433   //
2434   // 1. Treatment closed  curves
2435   aNbCurves=mySeqOfCurve.Length();
2436   for (i=1; i<=aNbCurves; ++i) {
2437     const IntTools_Curve& aIC=mySeqOfCurve(i);
2438     //
2439     if (bToSplit) {
2440       Standard_Integer j, aNbC;
2441       IntTools_SequenceOfCurves aSeqCvs;
2442       //
2443       aNbC=IntTools_Tools::SplitCurve(aIC, aSeqCvs);
2444       if (aNbC) {
2445         for (j=1; j<=aNbC; ++j) {
2446           const IntTools_Curve& aICNew=aSeqCvs(j);
2447           aNewCvs.Append(aICNew);
2448         }
2449       }
2450       else {
2451         aNewCvs.Append(aIC);
2452       }
2453     }
2454     else {
2455       aNewCvs.Append(aIC);
2456     }
2457   }
2458   //
2459   // 2. Plane\Cone intersection when we had 4 curves
2460   aType1=myHS1->GetType();
2461   aType2=myHS2->GetType();
2462   aNbCurves=aNewCvs.Length();
2463   //
2464   if ((aType1==GeomAbs_Plane && aType2==GeomAbs_Cone) ||
2465       (aType2==GeomAbs_Plane && aType1==GeomAbs_Cone)) {
2466     if (aNbCurves==4) {
2467       GeomAbs_CurveType aCType1;
2468       //
2469       aCType1=aNewCvs(1).Type();
2470       if (aCType1==GeomAbs_Line) {
2471         IntTools_SequenceOfCurves aSeqIn, aSeqOut;
2472         //
2473         for (i=1; i<=aNbCurves; ++i) {
2474           const IntTools_Curve& aIC=aNewCvs(i);
2475           aSeqIn.Append(aIC);
2476         }
2477         //
2478         IntTools_Tools::RejectLines(aSeqIn, aSeqOut);
2479         //
2480         aNewCvs.Clear();
2481         aNbCurves=aSeqOut.Length(); 
2482         for (i=1; i<=aNbCurves; ++i) {
2483           const IntTools_Curve& aIC=aSeqOut(i);
2484           aNewCvs.Append(aIC);
2485         }
2486       }
2487     }
2488   }// if ((aType1==GeomAbs_Plane && aType2==GeomAbs_Cone)...
2489   //
2490   // 3. Fill  mySeqOfCurve
2491   mySeqOfCurve.Clear();
2492   aNbCurves=aNewCvs.Length();
2493   for (i=1; i<=aNbCurves; ++i) {
2494     const IntTools_Curve& aIC=aNewCvs(i);
2495     mySeqOfCurve.Append(aIC);
2496   }
2497 }
2498 //=======================================================================
2499 //function : CorrectSurfaceBoundaries
2500 //purpose  : 
2501 //=======================================================================
2502  void CorrectSurfaceBoundaries(const TopoDS_Face&  theFace,
2503                               const Standard_Real theTolerance,
2504                               Standard_Real&      theumin,
2505                               Standard_Real&      theumax, 
2506                               Standard_Real&      thevmin, 
2507                               Standard_Real&      thevmax) 
2508 {
2509   Standard_Boolean enlarge, isuperiodic, isvperiodic;
2510   Standard_Real uinf, usup, vinf, vsup, delta;
2511   GeomAbs_SurfaceType aType;
2512   Handle(Geom_Surface) aSurface;
2513   //
2514   aSurface = BRep_Tool::Surface(theFace);
2515   aSurface->Bounds(uinf, usup, vinf, vsup);
2516   delta = theTolerance;
2517   enlarge = Standard_False;
2518   //
2519   GeomAdaptor_Surface anAdaptorSurface(aSurface);
2520   //
2521   if(aSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
2522     Handle(Geom_Surface) aBasisSurface = 
2523       (Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface))->BasisSurface();
2524     
2525     if(aBasisSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)) ||
2526        aBasisSurface->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
2527       return;
2528     }
2529   }
2530   //
2531   if(aSurface->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
2532     Handle(Geom_Surface) aBasisSurface = 
2533       (Handle(Geom_OffsetSurface)::DownCast(aSurface))->BasisSurface();
2534     
2535     if(aBasisSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)) ||
2536        aBasisSurface->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
2537       return;
2538     }
2539   }
2540   //
2541   isuperiodic = anAdaptorSurface.IsUPeriodic();
2542   isvperiodic = anAdaptorSurface.IsVPeriodic();
2543   //
2544   aType=anAdaptorSurface.GetType();
2545   if((aType==GeomAbs_BezierSurface) ||
2546      (aType==GeomAbs_BSplineSurface) ||
2547      (aType==GeomAbs_SurfaceOfExtrusion) ||
2548      (aType==GeomAbs_SurfaceOfRevolution) ||
2549      (aType==GeomAbs_Cylinder)) {
2550     enlarge=Standard_True;
2551   }
2552   //
2553   if(!isuperiodic && enlarge) {
2554
2555     if(!Precision::IsInfinite(theumin) &&
2556         ((theumin - uinf) > delta))
2557       theumin -= delta;
2558     else {
2559       theumin = uinf;
2560     }
2561
2562     if(!Precision::IsInfinite(theumax) &&
2563         ((usup - theumax) > delta))
2564       theumax += delta;
2565     else
2566       theumax = usup;
2567   }
2568   //
2569   if(!isvperiodic && enlarge) {
2570     if(!Precision::IsInfinite(thevmin) &&
2571         ((thevmin - vinf) > delta)) {
2572       thevmin -= delta;
2573     }
2574     else { 
2575       thevmin = vinf;
2576     }
2577     if(!Precision::IsInfinite(thevmax) &&
2578         ((vsup - thevmax) > delta)) {
2579       thevmax += delta;
2580     }
2581     else {
2582       thevmax = vsup;
2583     }
2584   }
2585   //
2586   {
2587     Standard_Integer aNbP;
2588     Standard_Real aXP, dXfact, aXmid, aX1, aX2, aTolPA;
2589     //
2590     aTolPA=Precision::Angular();
2591     // U
2592     if (isuperiodic) {
2593       aXP=anAdaptorSurface.UPeriod();
2594       dXfact=theumax-theumin;
2595       if (dXfact-aTolPA>aXP) {
2596         aXmid=0.5*(theumax+theumin);
2597         aNbP=RealToInt(aXmid/aXP);
2598         if (aXmid<0.) {
2599           aNbP=aNbP-1;
2600         }
2601         aX1=aNbP*aXP;
2602         if (theumin>aTolPA) {
2603           aX1=theumin+aNbP*aXP;
2604         }
2605         aX2=aX1+aXP;
2606         if (theumin<aX1) {
2607           theumin=aX1;
2608         }
2609         if (theumax>aX2) {
2610           theumax=aX2;
2611         }
2612       }
2613     }
2614     // V
2615     if (isvperiodic) {
2616       aXP=anAdaptorSurface.VPeriod();
2617       dXfact=thevmax-thevmin;
2618       if (dXfact-aTolPA>aXP) {
2619         aXmid=0.5*(thevmax+thevmin);
2620         aNbP=RealToInt(aXmid/aXP);
2621         if (aXmid<0.) {
2622           aNbP=aNbP-1;
2623         }
2624         aX1=aNbP*aXP;
2625         if (thevmin>aTolPA) {
2626           aX1=thevmin+aNbP*aXP;
2627         }
2628         aX2=aX1+aXP;
2629         if (thevmin<aX1) {
2630           thevmin=aX1;
2631         }
2632         if (thevmax>aX2) {
2633           thevmax=aX2;
2634         }
2635       }
2636     }
2637   }
2638   //
2639   if(isuperiodic || isvperiodic) {
2640     Standard_Boolean correct = Standard_False;
2641     Standard_Boolean correctU = Standard_False;
2642     Standard_Boolean correctV = Standard_False;
2643     Bnd_Box2d aBox;
2644     TopExp_Explorer anExp;
2645
2646     for(anExp.Init(theFace, TopAbs_EDGE); anExp.More(); anExp.Next()) {
2647       if(BRep_Tool::IsClosed(TopoDS::Edge(anExp.Current()), theFace)) {
2648         correct = Standard_True;
2649         Standard_Real f, l;
2650         TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
2651         
2652         for(Standard_Integer i = 0; i < 2; i++) {
2653           if(i==0) {
2654             anEdge.Orientation(TopAbs_FORWARD);
2655           }
2656           else {
2657             anEdge.Orientation(TopAbs_REVERSED);
2658           }
2659           Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, f, l);
2660           
2661           if(aCurve.IsNull()) {
2662             correct = Standard_False;
2663             break;
2664           }
2665           Handle(Geom2d_Line) aLine = Handle(Geom2d_Line)::DownCast(aCurve);
2666
2667           if(aLine.IsNull()) {
2668             correct = Standard_False;
2669             break;
2670           }
2671           gp_Dir2d anUDir(1., 0.);
2672           gp_Dir2d aVDir(0., 1.);
2673           Standard_Real anAngularTolerance = Precision::Angular();
2674
2675           correctU = correctU || aLine->Position().Direction().IsParallel(aVDir, anAngularTolerance);
2676           correctV = correctV || aLine->Position().Direction().IsParallel(anUDir, anAngularTolerance);
2677           
2678           gp_Pnt2d pp1 = aCurve->Value(f);
2679           aBox.Add(pp1);
2680           gp_Pnt2d pp2 = aCurve->Value(l);
2681           aBox.Add(pp2);
2682         }
2683         if(!correct)
2684           break;
2685       }
2686     }
2687
2688     if(correct) {
2689       Standard_Real umin, vmin, umax, vmax;
2690       aBox.Get(umin, vmin, umax, vmax);
2691
2692       if(isuperiodic && correctU) {
2693         
2694         if(theumin < umin)
2695           theumin = umin;
2696         
2697         if(theumax > umax) {
2698           theumax = umax;
2699         }
2700       }
2701       if(isvperiodic && correctV) {
2702         
2703         if(thevmin < vmin)
2704           thevmin = vmin;
2705         if(thevmax > vmax)
2706           thevmax = vmax;
2707       }
2708     }
2709   }
2710 }
2711 //
2712 //
2713 // The block is dedicated to determine whether WLine [ifprm, ilprm]
2714 // crosses the degenerated zone on each given surface or not.
2715 // If Yes -> We will not use info about surfaces during approximation
2716 // because inside degenerated zone of the surface the approx. algo.
2717 // uses wrong values of normal, etc., and resulting curve will have
2718 // oscillations that we would not like to have. 
2719  
2720
2721
2722 static
2723   Standard_Boolean IsDegeneratedZone(const gp_Pnt2d& aP2d,
2724                                      const Handle(Geom_Surface)& aS,
2725                                      const Standard_Integer iDir);
2726 static
2727   Standard_Boolean IsPointInDegeneratedZone(const IntSurf_PntOn2S& aP2S,
2728                                             const TopoDS_Face& aF1,
2729                                             const TopoDS_Face& aF2);
2730 //=======================================================================
2731 //function :  NotUseSurfacesForApprox
2732 //purpose  : 
2733 //=======================================================================
2734 Standard_Boolean NotUseSurfacesForApprox(const TopoDS_Face& aF1,
2735                                          const TopoDS_Face& aF2,
2736                                          const Handle(IntPatch_WLine)& WL,
2737                                          const Standard_Integer ifprm,
2738                                          const Standard_Integer ilprm)
2739 {
2740   Standard_Boolean bPInDZ;
2741
2742   Handle(IntSurf_LineOn2S) aLineOn2S=WL->Curve();
2743   
2744   const IntSurf_PntOn2S& aP2Sfprm=aLineOn2S->Value(ifprm);
2745   bPInDZ=IsPointInDegeneratedZone(aP2Sfprm, aF1, aF2);
2746   if (bPInDZ) {
2747     return bPInDZ;
2748   }
2749
2750   const IntSurf_PntOn2S& aP2Slprm=aLineOn2S->Value(ilprm);
2751   bPInDZ=IsPointInDegeneratedZone(aP2Slprm, aF1, aF2);
2752   
2753   return bPInDZ;
2754 }
2755 //=======================================================================
2756 //function : IsPointInDegeneratedZone
2757 //purpose  : 
2758 //=======================================================================
2759 Standard_Boolean IsPointInDegeneratedZone(const IntSurf_PntOn2S& aP2S,
2760                                           const TopoDS_Face& aF1,
2761                                           const TopoDS_Face& aF2)
2762                                           
2763 {
2764   Standard_Boolean bFlag=Standard_True;
2765   Standard_Real US11, US12, VS11, VS12, US21, US22, VS21, VS22;
2766   Standard_Real U1, V1, U2, V2, aDelta, aD;
2767   gp_Pnt2d aP2d;
2768
2769   Handle(Geom_Surface)aS1 = BRep_Tool::Surface(aF1);
2770   aS1->Bounds(US11, US12, VS11, VS12);
2771   GeomAdaptor_Surface aGAS1(aS1);
2772
2773   Handle(Geom_Surface)aS2 = BRep_Tool::Surface(aF2);
2774   aS1->Bounds(US21, US22, VS21, VS22);
2775   GeomAdaptor_Surface aGAS2(aS2);
2776   //
2777   //const gp_Pnt& aP=aP2S.Value();
2778   aP2S.Parameters(U1, V1, U2, V2);
2779   //
2780   aDelta=1.e-7;
2781   // Check on Surf 1
2782   aD=aGAS1.UResolution(aDelta);
2783   aP2d.SetCoord(U1, V1);
2784   if (fabs(U1-US11) < aD) {
2785     bFlag=IsDegeneratedZone(aP2d, aS1, 1);
2786     if (bFlag) {
2787       return bFlag;
2788     }
2789   }
2790   if (fabs(U1-US12) < aD) {
2791     bFlag=IsDegeneratedZone(aP2d, aS1, 1);
2792     if (bFlag) {
2793       return bFlag;
2794     }
2795   }
2796   aD=aGAS1.VResolution(aDelta);
2797   if (fabs(V1-VS11) < aDelta) {
2798     bFlag=IsDegeneratedZone(aP2d, aS1, 2);
2799     if (bFlag) {
2800       return bFlag;
2801     }
2802   }
2803   if (fabs(V1-VS12) < aDelta) {
2804     bFlag=IsDegeneratedZone(aP2d, aS1, 2);
2805     if (bFlag) {
2806       return bFlag;
2807     }
2808   }
2809   // Check on Surf 2
2810   aD=aGAS2.UResolution(aDelta);
2811   aP2d.SetCoord(U2, V2);
2812   if (fabs(U2-US21) < aDelta) {
2813     bFlag=IsDegeneratedZone(aP2d, aS2, 1);
2814     if (bFlag) {
2815       return bFlag;
2816     }
2817   }
2818   if (fabs(U2-US22) < aDelta) {
2819     bFlag=IsDegeneratedZone(aP2d, aS2, 1);
2820     if (bFlag) {
2821       return bFlag;
2822     }
2823   }
2824   aD=aGAS2.VResolution(aDelta);
2825   if (fabs(V2-VS21) < aDelta) {
2826     bFlag=IsDegeneratedZone(aP2d, aS2, 2);
2827     if (bFlag) {  
2828       return bFlag;
2829     }
2830   }
2831   if (fabs(V2-VS22) < aDelta) {
2832     bFlag=IsDegeneratedZone(aP2d, aS2, 2);
2833     if (bFlag) {
2834       return bFlag;
2835     }
2836   }
2837   return !bFlag;
2838 }
2839
2840 //=======================================================================
2841 //function : IsDegeneratedZone
2842 //purpose  : 
2843 //=======================================================================
2844 Standard_Boolean IsDegeneratedZone(const gp_Pnt2d& aP2d,
2845                                    const Handle(Geom_Surface)& aS,
2846                                    const Standard_Integer iDir)
2847 {
2848   Standard_Boolean bFlag=Standard_True;
2849   Standard_Real US1, US2, VS1, VS2, dY, dX, d1, d2, dD;
2850   Standard_Real aXm, aYm, aXb, aYb, aXe, aYe;
2851   aS->Bounds(US1, US2, VS1, VS2); 
2852
2853   gp_Pnt aPm, aPb, aPe;
2854   
2855   aXm=aP2d.X();
2856   aYm=aP2d.Y();
2857   
2858   aS->D0(aXm, aYm, aPm); 
2859   
2860   dX=1.e-5;
2861   dY=1.e-5;
2862   dD=1.e-12;
2863
2864   if (iDir==1) {
2865     aXb=aXm;
2866     aXe=aXm;
2867     aYb=aYm-dY;
2868     if (aYb < VS1) {
2869       aYb=VS1;
2870     }
2871     aYe=aYm+dY;
2872     if (aYe > VS2) {
2873       aYe=VS2;
2874     }
2875     aS->D0(aXb, aYb, aPb);
2876     aS->D0(aXe, aYe, aPe);
2877     
2878     d1=aPm.Distance(aPb);
2879     d2=aPm.Distance(aPe);
2880     if (d1 < dD && d2 < dD) {
2881       return bFlag;
2882     }
2883     return !bFlag;
2884   }
2885   //
2886   else if (iDir==2) {
2887     aYb=aYm;
2888     aYe=aYm;
2889     aXb=aXm-dX;
2890     if (aXb < US1) {
2891       aXb=US1;
2892     }
2893     aXe=aXm+dX;
2894     if (aXe > US2) {
2895       aXe=US2;
2896     }
2897     aS->D0(aXb, aYb, aPb);
2898     aS->D0(aXe, aYe, aPe);
2899     
2900     d1=aPm.Distance(aPb);
2901     d2=aPm.Distance(aPe);
2902     if (d1 < dD && d2 < dD) {
2903       return bFlag;
2904     }
2905     return !bFlag;
2906   }
2907   return !bFlag;
2908 }
2909
2910 //=========================================================================
2911 // static function : ComputePurgedWLine
2912 // purpose : Removes equal points (leave one of equal points) from theWLine
2913 //           and recompute vertex parameters.
2914 //           Returns new WLine or null WLine if the number
2915 //           of the points is less than 2.
2916 //=========================================================================
2917 Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine)& theWLine) {
2918  
2919   Standard_Integer i, k, v, nb, nbvtx;
2920   Handle(IntPatch_WLine) aResult;
2921   nbvtx = theWLine->NbVertex();
2922   nb = theWLine->NbPnts();
2923   if (nb==2) {
2924     const IntSurf_PntOn2S& p1 = theWLine->Point(1);
2925     const IntSurf_PntOn2S& p2 = theWLine->Point(2);
2926     if(p1.Value().IsEqual(p2.Value(), gp::Resolution())) {
2927       return aResult;
2928     }
2929   }
2930   //
2931   Handle(IntPatch_WLine) aLocalWLine;
2932   Handle(IntPatch_WLine) aTmpWLine = theWLine;
2933   Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
2934   aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
2935   for(i = 1; i <= nb; i++) {
2936     aLineOn2S->Add(theWLine->Point(i));
2937   }
2938
2939   for(v = 1; v <= nbvtx; v++) {
2940     aLocalWLine->AddVertex(theWLine->Vertex(v));
2941   }
2942   
2943   for(i = 1; i <= aLineOn2S->NbPoints(); i++) {
2944     Standard_Integer aStartIndex = i + 1;
2945     Standard_Integer anEndIndex = i + 5;
2946     nb = aLineOn2S->NbPoints();
2947     anEndIndex = (anEndIndex > nb) ? nb : anEndIndex;
2948
2949     if((aStartIndex > nb) || (anEndIndex <= 1)) {
2950       continue;
2951     }
2952     k = aStartIndex;
2953
2954     while(k <= anEndIndex) {
2955       
2956       if(i != k) {
2957         IntSurf_PntOn2S p1 = aLineOn2S->Value(i);
2958         IntSurf_PntOn2S p2 = aLineOn2S->Value(k);
2959         
2960         if(p1.Value().IsEqual(p2.Value(), gp::Resolution())) {
2961           aTmpWLine = aLocalWLine;
2962           aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
2963
2964           for(v = 1; v <= aTmpWLine->NbVertex(); v++) {
2965             IntPatch_Point aVertex = aTmpWLine->Vertex(v);
2966             Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
2967
2968             if(avertexindex >= k) {
2969               aVertex.SetParameter(aVertex.ParameterOnLine() - 1.);
2970             }
2971             aLocalWLine->AddVertex(aVertex);
2972           }
2973           aLineOn2S->RemovePoint(k);
2974           anEndIndex--;
2975           continue;
2976         }
2977       }
2978       k++;
2979     }
2980   }
2981
2982   if(aLineOn2S->NbPoints() > 1) {
2983     aResult = aLocalWLine;
2984   }
2985   return aResult;
2986 }
2987
2988 //=======================================================================
2989 //function : TolR3d
2990 //purpose  : 
2991 //=======================================================================
2992 void TolR3d(const TopoDS_Face& aF1,
2993             const TopoDS_Face& aF2,
2994             Standard_Real& myTolReached3d)
2995 {
2996   Standard_Real aTolF1, aTolF2, aTolFMax, aTolTresh;
2997       
2998   aTolTresh=2.999999e-3;
2999   aTolF1 = BRep_Tool::Tolerance(aF1);
3000   aTolF2 = BRep_Tool::Tolerance(aF2);
3001   aTolFMax=Max(aTolF1, aTolF2);
3002   
3003   if (aTolFMax>aTolTresh) {
3004     myTolReached3d=aTolFMax;
3005   }
3006 }
3007 //=======================================================================
3008 //function : IsPointOnBoundary
3009 //purpose  : 
3010 //=======================================================================
3011 Standard_Boolean IsPointOnBoundary(const Standard_Real theParameter,
3012                                    const Standard_Real theFirstBoundary,
3013                                    const Standard_Real theSecondBoundary,
3014                                    const Standard_Real theResolution,
3015                                    Standard_Boolean&   IsOnFirstBoundary) 
3016 {
3017   Standard_Boolean bRet;
3018   Standard_Integer i;
3019   Standard_Real adist;
3020   //
3021   bRet=Standard_False;
3022   for(i = 0; i < 2; ++i) {
3023     IsOnFirstBoundary = (i == 0);
3024     if (IsOnFirstBoundary) {
3025       adist = fabs(theParameter - theFirstBoundary);
3026     }
3027     else {
3028       adist = fabs(theParameter - theSecondBoundary);
3029     }
3030     if(adist < theResolution) {
3031       return !bRet;
3032     }
3033   }
3034   return bRet;
3035 }
3036 // ------------------------------------------------------------------------------------------------
3037 // static function: FindPoint
3038 // purpose:
3039 // ------------------------------------------------------------------------------------------------
3040 Standard_Boolean FindPoint(const gp_Pnt2d&     theFirstPoint,
3041                            const gp_Pnt2d&     theLastPoint,
3042                            const Standard_Real theUmin, 
3043                            const Standard_Real theUmax,
3044                            const Standard_Real theVmin,
3045                            const Standard_Real theVmax,
3046                            gp_Pnt2d&           theNewPoint) {
3047   
3048   gp_Vec2d aVec(theFirstPoint, theLastPoint);
3049   Standard_Integer i = 0, j = 0;
3050
3051   for(i = 0; i < 4; i++) {
3052     gp_Vec2d anOtherVec;
3053     gp_Vec2d anOtherVecNormal;
3054     gp_Pnt2d aprojpoint = theLastPoint;    
3055
3056     if((i % 2) == 0) {
3057       anOtherVec.SetX(0.);
3058       anOtherVec.SetY(1.);
3059       anOtherVecNormal.SetX(1.);
3060       anOtherVecNormal.SetY(0.);
3061
3062       if(i < 2)
3063         aprojpoint.SetX(theUmin);
3064       else
3065         aprojpoint.SetX(theUmax);
3066     }
3067     else {
3068       anOtherVec.SetX(1.);
3069       anOtherVec.SetY(0.);
3070       anOtherVecNormal.SetX(0.);
3071       anOtherVecNormal.SetY(1.);
3072
3073       if(i < 2)
3074         aprojpoint.SetY(theVmin);
3075       else
3076         aprojpoint.SetY(theVmax);
3077     }
3078     gp_Vec2d anormvec = aVec;
3079     anormvec.Normalize();
3080     RefineVector(anormvec);
3081     Standard_Real adot1 = anormvec.Dot(anOtherVecNormal);
3082
3083     if(fabs(adot1) < Precision::Angular())
3084       continue;
3085     Standard_Real adist = 0.;
3086     Standard_Boolean bIsOut = Standard_False;
3087
3088     if((i % 2) == 0) {
3089       adist = (i < 2) ? fabs(theLastPoint.X() - theUmin) : fabs(theLastPoint.X() - theUmax);
3090       bIsOut = (i < 2) ? (theLastPoint.X() < theUmin) : (theLastPoint.X() > theUmax);
3091     }
3092     else {
3093       adist = (i < 2) ? fabs(theLastPoint.Y() - theVmin) : fabs(theLastPoint.Y() - theVmax);
3094       bIsOut = (i < 2) ? (theLastPoint.Y() < theVmin) : (theLastPoint.Y() > theVmax);
3095     }
3096     Standard_Real anoffset = adist * anOtherVec.Dot(anormvec) / adot1;
3097
3098     for(j = 0; j < 2; j++) {
3099       anoffset = (j == 0) ? anoffset : -anoffset;
3100       gp_Pnt2d acurpoint(aprojpoint.XY() + (anOtherVec.XY()*anoffset));
3101       gp_Vec2d acurvec(theLastPoint, acurpoint);
3102       if ( bIsOut )
3103         acurvec.Reverse();
3104
3105       Standard_Real aDotX, anAngleX;
3106       //
3107       aDotX = aVec.Dot(acurvec);
3108       anAngleX = aVec.Angle(acurvec);
3109       //
3110       if(aDotX > 0. && fabs(anAngleX) < Precision::PConfusion()) {
3111         if((i % 2) == 0) {
3112           if((acurpoint.Y() >= theVmin) &&
3113              (acurpoint.Y() <= theVmax)) {
3114             theNewPoint = acurpoint;
3115             return Standard_True;
3116           }
3117         }
3118         else {
3119           if((acurpoint.X() >= theUmin) &&
3120              (acurpoint.X() <= theUmax)) {
3121             theNewPoint = acurpoint;
3122             return Standard_True;
3123           }
3124         }
3125       }
3126     }
3127   }
3128   return Standard_False;
3129 }
3130
3131
3132 // ------------------------------------------------------------------------------------------------
3133 // static function: FindPoint
3134 // purpose: Find point on the boundary of radial tangent zone
3135 // ------------------------------------------------------------------------------------------------
3136 Standard_Boolean FindPoint(const gp_Pnt2d&     theFirstPoint,
3137                            const gp_Pnt2d&     theLastPoint,
3138                            const Standard_Real theUmin, 
3139                            const Standard_Real theUmax,
3140                            const Standard_Real theVmin,
3141                            const Standard_Real theVmax,
3142                            const gp_Pnt2d&     theTanZoneCenter,
3143                            const Standard_Real theZoneRadius,
3144                            Handle(GeomAdaptor_HSurface) theGASurface,
3145                            gp_Pnt2d&           theNewPoint) {
3146   theNewPoint = theLastPoint;
3147
3148   if ( !IsInsideTanZone( theLastPoint, theTanZoneCenter, theZoneRadius, theGASurface) )
3149     return Standard_False;
3150
3151   Standard_Real aUResolution = theGASurface->UResolution( theZoneRadius );
3152   Standard_Real aVResolution = theGASurface->VResolution( theZoneRadius );
3153
3154   Standard_Real aRadius = ( aUResolution < aVResolution ) ? aUResolution : aVResolution;
3155   gp_Ax22d anAxis( theTanZoneCenter, gp_Dir2d(1, 0), gp_Dir2d(0, 1) );
3156   gp_Circ2d aCircle( anAxis, aRadius );
3157   
3158   //
3159   gp_Vec2d aDir( theLastPoint.XY() - theFirstPoint.XY() );
3160   Standard_Real aLength = aDir.Magnitude();
3161   if ( aLength <= gp::Resolution() )
3162     return Standard_False;
3163   gp_Lin2d aLine( theFirstPoint, aDir );
3164
3165   //
3166   Handle(Geom2d_Line) aCLine = new Geom2d_Line( aLine );
3167   Handle(Geom2d_TrimmedCurve) aC1 = new Geom2d_TrimmedCurve( aCLine, 0, aLength );
3168   Handle(Geom2d_Circle) aC2 = new Geom2d_Circle( aCircle );
3169
3170   Standard_Real aTol = aRadius * 0.001;
3171   aTol = ( aTol < Precision::PConfusion() ) ? Precision::PConfusion() : aTol;
3172
3173   Geom2dAPI_InterCurveCurve anIntersector;
3174   anIntersector.Init( aC1, aC2, aTol );
3175
3176   if ( anIntersector.NbPoints() == 0 )
3177     return Standard_False;
3178
3179   Standard_Boolean aFound = Standard_False;
3180   Standard_Real aMinDist = aLength * aLength;
3181   Standard_Integer i = 0;
3182   for ( i = 1; i <= anIntersector.NbPoints(); i++ ) {
3183     gp_Pnt2d aPInt = anIntersector.Point( i );
3184     if ( aPInt.SquareDistance( theFirstPoint ) < aMinDist ) {
3185       if ( ( aPInt.X() >= theUmin ) && ( aPInt.X() <= theUmax ) &&
3186            ( aPInt.Y() >= theVmin ) && ( aPInt.Y() <= theVmax ) ) {
3187         theNewPoint = aPInt;
3188         aFound = Standard_True;
3189       }
3190     }
3191   }
3192
3193   return aFound;
3194 }
3195
3196 // ------------------------------------------------------------------------------------------------
3197 // static function: IsInsideTanZone
3198 // purpose: Check if point is inside a radial tangent zone
3199 // ------------------------------------------------------------------------------------------------
3200 Standard_Boolean IsInsideTanZone(const gp_Pnt2d&     thePoint,
3201                                  const gp_Pnt2d&     theTanZoneCenter,
3202                                  const Standard_Real theZoneRadius,
3203                                  Handle(GeomAdaptor_HSurface) theGASurface) {
3204
3205   Standard_Real aUResolution = theGASurface->UResolution( theZoneRadius );
3206   Standard_Real aVResolution = theGASurface->VResolution( theZoneRadius );
3207   Standard_Real aRadiusSQR = ( aUResolution < aVResolution ) ? aUResolution : aVResolution;
3208   aRadiusSQR *= aRadiusSQR;
3209   if ( thePoint.SquareDistance( theTanZoneCenter ) <= aRadiusSQR )
3210     return Standard_True;
3211   return Standard_False;
3212 }
3213
3214 // ------------------------------------------------------------------------------------------------
3215 // static function: CheckTangentZonesExist
3216 // purpose: Check if tangent zone exists
3217 // ------------------------------------------------------------------------------------------------
3218 Standard_Boolean CheckTangentZonesExist( const Handle(GeomAdaptor_HSurface)& theSurface1,
3219                                         const Handle(GeomAdaptor_HSurface)&  theSurface2 ) 
3220 {
3221   if ( ( theSurface1->GetType() != GeomAbs_Torus ) ||
3222       ( theSurface2->GetType() != GeomAbs_Torus ) )
3223     return Standard_False;
3224
3225   gp_Torus aTor1 = theSurface1->Torus();
3226   gp_Torus aTor2 = theSurface2->Torus();
3227
3228   if ( aTor1.Location().Distance( aTor2.Location() ) > Precision::Confusion() )
3229     return Standard_False;
3230
3231   if ( ( fabs( aTor1.MajorRadius() - aTor2.MajorRadius() ) > Precision::Confusion() ) ||
3232        ( fabs( aTor1.MinorRadius() - aTor2.MinorRadius() ) > Precision::Confusion() ) )
3233     return Standard_False;
3234
3235   if ( ( aTor1.MajorRadius() < aTor1.MinorRadius() ) ||
3236        ( aTor2.MajorRadius() < aTor2.MinorRadius() ) )
3237     return Standard_False;
3238   return Standard_True;
3239 }
3240
3241 // ------------------------------------------------------------------------------------------------
3242 // static function: ComputeTangentZones
3243 // purpose: 
3244 // ------------------------------------------------------------------------------------------------
3245 Standard_Integer ComputeTangentZones( const Handle(GeomAdaptor_HSurface)& theSurface1,
3246                                      const Handle(GeomAdaptor_HSurface)&  theSurface2,
3247                                      const TopoDS_Face&                   theFace1,
3248                                      const TopoDS_Face&                   theFace2,
3249                                      Handle(TColgp_HArray1OfPnt2d)&       theResultOnS1,
3250                                      Handle(TColgp_HArray1OfPnt2d)&       theResultOnS2,
3251                                      Handle(TColStd_HArray1OfReal)&       theResultRadius,
3252                                      const Handle(IntTools_Context)& aContext)
3253 {
3254   Standard_Integer aResult = 0;
3255   if ( !CheckTangentZonesExist( theSurface1, theSurface2 ) )
3256     return aResult;
3257
3258
3259   TColgp_SequenceOfPnt2d aSeqResultS1, aSeqResultS2;
3260   TColStd_SequenceOfReal aSeqResultRad;
3261
3262   gp_Torus aTor1 = theSurface1->Torus();
3263   gp_Torus aTor2 = theSurface2->Torus();
3264
3265   gp_Ax2 anax1( aTor1.Location(), aTor1.Axis().Direction() );
3266   gp_Ax2 anax2( aTor2.Location(), aTor2.Axis().Direction() );
3267   Standard_Integer j = 0;
3268
3269   for ( j = 0; j < 2; j++ ) {
3270     Standard_Real aCoef = ( j == 0 ) ? -1 : 1;
3271     Standard_Real aRadius1 = fabs(aTor1.MajorRadius() + aCoef * aTor1.MinorRadius());
3272     Standard_Real aRadius2 = fabs(aTor2.MajorRadius() + aCoef * aTor2.MinorRadius());
3273
3274     gp_Circ aCircle1( anax1, aRadius1 );
3275     gp_Circ aCircle2( anax2, aRadius2 );
3276
3277     // roughly compute radius of tangent zone for perpendicular case
3278     Standard_Real aCriteria = Precision::Confusion() * 0.5;
3279
3280     Standard_Real aT1 = aCriteria;
3281     Standard_Real aT2 = aCriteria;
3282     if ( j == 0 ) {
3283       // internal tangency
3284       Standard_Real aR = ( aRadius1 > aTor2.MinorRadius() ) ? aRadius1 : aTor2.MinorRadius();
3285       //aT1 = aCriteria * aCriteria + aR * aR - ( aR - aCriteria ) * ( aR - aCriteria );
3286       aT1 = 2. * aR * aCriteria;
3287       aT2 = aT1;
3288     }
3289     else {
3290       // external tangency
3291       Standard_Real aRb = ( aRadius1 > aTor2.MinorRadius() ) ? aRadius1 : aTor2.MinorRadius();
3292       Standard_Real aRm = ( aRadius1 < aTor2.MinorRadius() ) ? aRadius1 : aTor2.MinorRadius();
3293       Standard_Real aDelta = aRb - aCriteria;
3294       aDelta *= aDelta;
3295       aDelta -= aRm * aRm;
3296       aDelta /= 2. * (aRb - aRm);
3297       aDelta -= 0.5 * (aRb - aRm);
3298       
3299       aT1 = 2. * aRm * (aRm - aDelta);
3300       aT2 = aT1;
3301     }
3302     aCriteria = ( aT1 > aT2) ? aT1 : aT2;
3303     if ( aCriteria > 0 )
3304       aCriteria = sqrt( aCriteria );
3305
3306     if ( aCriteria > 0.5 * aTor1.MinorRadius() ) {
3307       // too big zone -> drop to minimum
3308       aCriteria = Precision::Confusion();
3309     }
3310
3311     GeomAdaptor_Curve aC1( new Geom_Circle(aCircle1) );
3312     GeomAdaptor_Curve aC2( new Geom_Circle(aCircle2) );
3313     Extrema_ExtCC anExtrema(aC1, aC2, 0, 2. * M_PI, 0, 2. * M_PI, 
3314                             Precision::PConfusion(), Precision::PConfusion());
3315             
3316     if ( anExtrema.IsDone() ) {
3317
3318       Standard_Integer i = 0;
3319       for ( i = 1; i <= anExtrema.NbExt(); i++ ) {
3320         if ( anExtrema.SquareDistance(i) > aCriteria * aCriteria )
3321           continue;
3322
3323         Extrema_POnCurv P1, P2;
3324         anExtrema.Points( i, P1, P2 );
3325
3326         Standard_Boolean bFoundResult = Standard_True;
3327         gp_Pnt2d pr1, pr2;
3328
3329         Standard_Integer surfit = 0;
3330         for ( surfit = 0; surfit < 2; surfit++ ) {
3331           GeomAPI_ProjectPointOnSurf& aProjector = 
3332             (surfit == 0) ? aContext->ProjPS(theFace1) : aContext->ProjPS(theFace2);
3333
3334           gp_Pnt aP3d = (surfit == 0) ? P1.Value() : P2.Value();
3335           aProjector.Perform(aP3d);
3336
3337           if(!aProjector.IsDone())
3338             bFoundResult = Standard_False;
3339           else {
3340             if(aProjector.LowerDistance() > aCriteria) {
3341               bFoundResult = Standard_False;
3342             }
3343             else {
3344               Standard_Real foundU = 0, foundV = 0;
3345               aProjector.LowerDistanceParameters(foundU, foundV);
3346               if ( surfit == 0 )
3347                 pr1 = gp_Pnt2d( foundU, foundV );
3348               else
3349                 pr2 = gp_Pnt2d( foundU, foundV );
3350             }
3351           }
3352         }
3353         if ( bFoundResult ) {
3354           aSeqResultS1.Append( pr1 );
3355           aSeqResultS2.Append( pr2 );
3356           aSeqResultRad.Append( aCriteria );
3357
3358           // torus is u and v periodic
3359           const Standard_Real twoPI = M_PI + M_PI;
3360           Standard_Real arr1tmp[2] = {pr1.X(), pr1.Y()};
3361           Standard_Real arr2tmp[2] = {pr2.X(), pr2.Y()};
3362
3363           // iteration on period bounds
3364           for ( Standard_Integer k1 = 0; k1 < 2; k1++ ) {
3365             Standard_Real aBound = ( k1 == 0 ) ? 0 : twoPI;
3366             Standard_Real aShift = ( k1 == 0 ) ? twoPI : -twoPI;
3367
3368             // iteration on surfaces
3369             for ( Standard_Integer k2 = 0; k2 < 2; k2++ ) {
3370               Standard_Real* arr1 = ( k2 == 0 ) ? arr1tmp : arr2tmp;
3371               Standard_Real* arr2 = ( k2 != 0 ) ? arr1tmp : arr2tmp;
3372               TColgp_SequenceOfPnt2d& aSeqS1 = ( k2 == 0 ) ? aSeqResultS1 : aSeqResultS2; 
3373               TColgp_SequenceOfPnt2d& aSeqS2 = ( k2 != 0 ) ? aSeqResultS1 : aSeqResultS2; 
3374
3375               if (fabs(arr1[0] - aBound) < Precision::PConfusion()) {
3376                 aSeqS1.Append( gp_Pnt2d( arr1[0] + aShift, arr1[1] ) );
3377                 aSeqS2.Append( gp_Pnt2d( arr2[0], arr2[1] ) );
3378                 aSeqResultRad.Append( aCriteria );
3379               }
3380               if (fabs(arr1[1] - aBound) < Precision::PConfusion()) {
3381                 aSeqS1.Append( gp_Pnt2d( arr1[0], arr1[1] + aShift) );
3382                 aSeqS2.Append( gp_Pnt2d( arr2[0], arr2[1] ) );
3383                 aSeqResultRad.Append( aCriteria );
3384               }
3385             }
3386           } //
3387         }
3388       }
3389     }
3390   }
3391   aResult = aSeqResultRad.Length();
3392
3393   if ( aResult > 0 ) {
3394     theResultOnS1 = new TColgp_HArray1OfPnt2d( 1, aResult );
3395     theResultOnS2 = new TColgp_HArray1OfPnt2d( 1, aResult );
3396     theResultRadius = new TColStd_HArray1OfReal( 1, aResult );
3397
3398     for ( Standard_Integer i = 1 ; i <= aResult; i++ ) {
3399       theResultOnS1->SetValue( i, aSeqResultS1.Value(i) );
3400       theResultOnS2->SetValue( i, aSeqResultS2.Value(i) );
3401       theResultRadius->SetValue( i, aSeqResultRad.Value(i) );
3402     }
3403   }
3404   return aResult;
3405 }
3406
3407 // ------------------------------------------------------------------------------------------------
3408 // static function: AdjustByNeighbour
3409 // purpose:
3410 // ------------------------------------------------------------------------------------------------
3411 gp_Pnt2d AdjustByNeighbour(const gp_Pnt2d&     theaNeighbourPoint,
3412                            const gp_Pnt2d&     theOriginalPoint,
3413                            Handle(GeomAdaptor_HSurface) theGASurface) {
3414   
3415   gp_Pnt2d ap1 = theaNeighbourPoint;
3416   gp_Pnt2d ap2 = theOriginalPoint;
3417
3418   if ( theGASurface->IsUPeriodic() ) {
3419     Standard_Real aPeriod     = theGASurface->UPeriod();
3420     gp_Pnt2d aPTest = ap2;
3421     Standard_Real aSqDistMin = 1.e+100;
3422
3423     for ( Standard_Integer pIt = -1; pIt <= 1; pIt++) {
3424       aPTest.SetX( theOriginalPoint.X() + aPeriod * pIt );
3425       Standard_Real dd = ap1.SquareDistance( aPTest );
3426
3427       if ( dd < aSqDistMin ) {
3428         ap2 = aPTest;
3429         aSqDistMin = dd;
3430       }
3431     }
3432   }
3433   if ( theGASurface->IsVPeriodic() ) {
3434     Standard_Real aPeriod     = theGASurface->VPeriod();
3435     gp_Pnt2d aPTest = ap2;
3436     Standard_Real aSqDistMin = 1.e+100;
3437
3438     for ( Standard_Integer pIt = -1; pIt <= 1; pIt++) {
3439       aPTest.SetY( theOriginalPoint.Y() + aPeriod * pIt );
3440       Standard_Real dd = ap1.SquareDistance( aPTest );
3441
3442       if ( dd < aSqDistMin ) {
3443         ap2 = aPTest;
3444         aSqDistMin = dd;
3445       }
3446     }
3447   }
3448   return ap2;
3449 }
3450
3451 // ------------------------------------------------------------------------------------------------
3452 //function: DecompositionOfWLine
3453 // purpose:
3454 // ------------------------------------------------------------------------------------------------
3455 Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
3456                                       const Handle(GeomAdaptor_HSurface)&            theSurface1, 
3457                                       const Handle(GeomAdaptor_HSurface)&            theSurface2,
3458                                       const TopoDS_Face&                             theFace1,
3459                                       const TopoDS_Face&                             theFace2,
3460                                       const GeomInt_LineConstructor&                 theLConstructor,
3461                                       const Standard_Boolean                         theAvoidLConstructor,
3462                                       IntPatch_SequenceOfLine&                       theNewLines,
3463                                       Standard_Real&                                 theReachedTol3d,
3464                                       const Handle(IntTools_Context)& aContext) 
3465 {
3466
3467   Standard_Boolean bRet, bAvoidLineConstructor;
3468   Standard_Integer aNbPnts, aNbParts;
3469   //
3470   bRet=Standard_False;
3471   aNbPnts=theWLine->NbPnts();
3472   bAvoidLineConstructor=theAvoidLConstructor;
3473   //
3474   if(!aNbPnts){
3475     return bRet;
3476   }
3477   if (!bAvoidLineConstructor) {
3478     aNbParts=theLConstructor.NbParts();
3479     if (!aNbParts) {
3480       return bRet;
3481     }
3482   }
3483   //
3484   Standard_Boolean bIsPrevPointOnBoundary, bIsPointOnBoundary, bIsCurrentPointOnBoundary;
3485   Standard_Integer nblines, pit, i, j;
3486   Standard_Real aTol;
3487   TColStd_Array1OfListOfInteger anArrayOfLines(1, aNbPnts); 
3488   TColStd_Array1OfInteger       anArrayOfLineType(1, aNbPnts);
3489   TColStd_ListOfInteger aListOfPointIndex;
3490   
3491   Handle(TColgp_HArray1OfPnt2d) aTanZoneS1;
3492   Handle(TColgp_HArray1OfPnt2d) aTanZoneS2;
3493   Handle(TColStd_HArray1OfReal) aTanZoneRadius;
3494   Standard_Integer aNbZone = ComputeTangentZones( theSurface1, theSurface2, theFace1, theFace2,
3495                                                  aTanZoneS1, aTanZoneS2, aTanZoneRadius, aContext);
3496   
3497   //
3498   nblines=0;
3499   aTol=Precision::Confusion();
3500   aTol=0.5*aTol;
3501   bIsPrevPointOnBoundary=Standard_False;
3502   bIsPointOnBoundary=Standard_False;
3503   //
3504   // 1. ...
3505   //
3506   // Points
3507   for(pit = 1; pit <= aNbPnts; ++pit) {
3508     Standard_Boolean bIsOnFirstBoundary, isperiodic;
3509     Standard_Real aResolution, aPeriod, alowerboundary, aupperboundary, U, V;
3510     Standard_Real aParameter, anoffset, anAdjustPar;
3511     Standard_Real umin, umax, vmin, vmax;
3512     //
3513     bIsCurrentPointOnBoundary = Standard_False;
3514     const IntSurf_PntOn2S& aPoint = theWLine->Point(pit);
3515     //
3516     // Surface
3517     for(i = 0; i < 2; ++i) {
3518       Handle(GeomAdaptor_HSurface) aGASurface = (!i) ? theSurface1 : theSurface2;
3519       aGASurface->ChangeSurface().Surface()->Bounds(umin, umax, vmin, vmax);
3520       if(!i) {
3521         aPoint.ParametersOnS1(U, V);
3522       }
3523       else {
3524         aPoint.ParametersOnS2(U, V);
3525       }
3526       // U, V
3527       for(j = 0; j < 2; j++) {
3528         isperiodic = (!j) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
3529         if(!isperiodic){
3530           continue;
3531         }
3532         //
3533         if (!j) {
3534           aResolution=aGASurface->UResolution(aTol);
3535           aPeriod=aGASurface->UPeriod();
3536           alowerboundary=umin;
3537           aupperboundary=umax;
3538           aParameter=U;
3539         }
3540         else {
3541           aResolution=aGASurface->VResolution(aTol);
3542           aPeriod=aGASurface->VPeriod();
3543           alowerboundary=vmin;
3544           aupperboundary=vmax;
3545           aParameter=V;
3546         }
3547         
3548         GeomInt::AdjustPeriodic(aParameter, 
3549                                        alowerboundary, 
3550                                        aupperboundary, 
3551                                        aPeriod,
3552                                        anAdjustPar,
3553                                        anoffset);
3554         //
3555         bIsOnFirstBoundary = Standard_True;// ?
3556         bIsPointOnBoundary=
3557           IsPointOnBoundary(anAdjustPar, 
3558                             alowerboundary, 
3559                             aupperboundary,
3560                             aResolution, 
3561                             bIsOnFirstBoundary);
3562         //
3563         if(bIsPointOnBoundary) {
3564           bIsCurrentPointOnBoundary = Standard_True;
3565           break;
3566         }
3567         else {
3568           // check if a point belong to a tangent zone. Begin
3569           Standard_Integer zIt = 0;
3570           for ( zIt = 1; zIt <= aNbZone; zIt++ ) {
3571             gp_Pnt2d aPZone = (i == 0) ? aTanZoneS1->Value(zIt) : aTanZoneS2->Value(zIt);
3572             Standard_Real aZoneRadius = aTanZoneRadius->Value(zIt);
3573
3574             if ( IsInsideTanZone(gp_Pnt2d( U, V ), aPZone, aZoneRadius, aGASurface ) ) {
3575               // set boundary flag to split the curve by a tangent zone
3576               bIsPointOnBoundary = Standard_True;
3577               bIsCurrentPointOnBoundary = Standard_True;
3578               if ( theReachedTol3d < aZoneRadius ) {
3579                 theReachedTol3d = aZoneRadius;
3580               }
3581               break;
3582             }
3583           }
3584         }
3585       }//for(j = 0; j < 2; j++) {
3586
3587       if(bIsCurrentPointOnBoundary){
3588         break;
3589       }
3590     }//for(i = 0; i < 2; ++i) {
3591     //
3592     if((bIsCurrentPointOnBoundary != bIsPrevPointOnBoundary)) {
3593       if(!aListOfPointIndex.IsEmpty()) {
3594         nblines++;
3595         anArrayOfLines.SetValue(nblines, aListOfPointIndex);
3596         anArrayOfLineType.SetValue(nblines, bIsPrevPointOnBoundary);
3597         aListOfPointIndex.Clear();
3598       }
3599       bIsPrevPointOnBoundary = bIsCurrentPointOnBoundary;
3600     }
3601     aListOfPointIndex.Append(pit);
3602   } //for(pit = 1; pit <= aNbPnts; ++pit) {
3603   //
3604   if(!aListOfPointIndex.IsEmpty()) {
3605     nblines++;
3606     anArrayOfLines.SetValue(nblines, aListOfPointIndex);
3607     anArrayOfLineType.SetValue(nblines, bIsPrevPointOnBoundary);
3608     aListOfPointIndex.Clear();
3609   }
3610   //
3611   if(nblines<=1) {
3612     return bRet; //Standard_False;
3613   }
3614   //
3615   // 
3616   // 2. Correct wlines.begin
3617   TColStd_Array1OfListOfInteger anArrayOfLineEnds(1, nblines);
3618   Handle(IntSurf_LineOn2S) aSeqOfPntOn2S = new IntSurf_LineOn2S();
3619   //
3620   for(i = 1; i <= nblines; i++) {
3621     if(anArrayOfLineType.Value(i) != 0) {
3622       continue;
3623     }
3624     const TColStd_ListOfInteger& aListOfIndex = anArrayOfLines.Value(i);
3625     TColStd_ListOfInteger aListOfFLIndex;
3626
3627     for(j = 0; j < 2; j++) {
3628       Standard_Integer aneighbourindex = (j == 0) ? (i - 1) : (i + 1);
3629
3630       if((aneighbourindex < 1) || (aneighbourindex > nblines))
3631         continue;
3632
3633       if(anArrayOfLineType.Value(aneighbourindex) == 0)
3634         continue;
3635       const TColStd_ListOfInteger& aNeighbour = anArrayOfLines.Value(aneighbourindex);
3636       Standard_Integer anIndex = (j == 0) ? aNeighbour.Last() : aNeighbour.First();
3637       const IntSurf_PntOn2S& aPoint = theWLine->Point(anIndex);
3638
3639       IntSurf_PntOn2S aNewP = aPoint;
3640       if(aListOfIndex.Extent() < 2) {
3641         aSeqOfPntOn2S->Add(aNewP);
3642         aListOfFLIndex.Append(aSeqOfPntOn2S->NbPoints());
3643         continue;
3644       }
3645       //
3646       Standard_Integer iFirst = aListOfIndex.First();
3647       Standard_Integer iLast  = aListOfIndex.Last();
3648       //
3649       for(Standard_Integer surfit = 0; surfit < 2; surfit++) {
3650
3651         Handle(GeomAdaptor_HSurface) aGASurface = (surfit == 0) ? theSurface1 : theSurface2;
3652         Standard_Real umin=0., umax=0., vmin=0., vmax=0.;
3653         aGASurface->ChangeSurface().Surface()->Bounds(umin, umax, vmin, vmax);
3654         Standard_Real U=0., V=0.;
3655
3656         if(surfit == 0)
3657           aNewP.ParametersOnS1(U, V);
3658         else
3659           aNewP.ParametersOnS2(U, V);
3660         Standard_Integer nbboundaries = 0;
3661
3662         Standard_Boolean bIsNearBoundary = Standard_False;
3663         Standard_Integer aZoneIndex = 0;
3664         Standard_Integer bIsUBoundary = Standard_False; // use if nbboundaries == 1
3665         Standard_Integer bIsFirstBoundary = Standard_False; // use if nbboundaries == 1
3666         
3667
3668         for(Standard_Integer parit = 0; parit < 2; parit++) {
3669           Standard_Boolean isperiodic = (parit == 0) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
3670
3671           Standard_Real aResolution = (parit == 0) ? aGASurface->UResolution(aTol) : aGASurface->VResolution(aTol);
3672           Standard_Real alowerboundary = (parit == 0) ? umin : vmin;
3673           Standard_Real aupperboundary = (parit == 0) ? umax : vmax;
3674
3675           Standard_Real aParameter = (parit == 0) ? U : V;
3676           Standard_Boolean bIsOnFirstBoundary = Standard_True;
3677   
3678           if(!isperiodic) {
3679             bIsPointOnBoundary=
3680               IsPointOnBoundary(aParameter, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary);
3681             if(bIsPointOnBoundary) {
3682               bIsUBoundary = (parit == 0);
3683               bIsFirstBoundary = bIsOnFirstBoundary;
3684               nbboundaries++;
3685             }
3686           }
3687           else {
3688             Standard_Real aPeriod     = (parit == 0) ? aGASurface->UPeriod() : aGASurface->VPeriod();
3689             Standard_Real anoffset, anAdjustPar;
3690             GeomInt::AdjustPeriodic(aParameter, alowerboundary, aupperboundary,
3691                                            aPeriod, anAdjustPar, anoffset);
3692
3693             bIsPointOnBoundary=
3694               IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary);
3695             if(bIsPointOnBoundary) {
3696               bIsUBoundary = (parit == 0);
3697               bIsFirstBoundary = bIsOnFirstBoundary;
3698               nbboundaries++;
3699             }
3700             else {
3701             //check neighbourhood of boundary
3702             Standard_Real anEpsilon = aResolution * 100.;
3703             Standard_Real aPart = ( aupperboundary - alowerboundary ) * 0.1;
3704             anEpsilon = ( anEpsilon > aPart ) ? aPart : anEpsilon;
3705             
3706               bIsNearBoundary = IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary, 
3707                                                   anEpsilon, bIsOnFirstBoundary);
3708
3709             }
3710           }
3711         }
3712
3713         // check if a point belong to a tangent zone. Begin
3714         for ( Standard_Integer zIt = 1; zIt <= aNbZone; zIt++ ) {
3715           gp_Pnt2d aPZone = (surfit == 0) ? aTanZoneS1->Value(zIt) : aTanZoneS2->Value(zIt);
3716           Standard_Real aZoneRadius = aTanZoneRadius->Value(zIt);
3717
3718           Standard_Integer aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
3719           const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
3720           Standard_Real nU1, nV1;
3721             
3722           if(surfit == 0)
3723             aNeighbourPoint.ParametersOnS1(nU1, nV1);
3724           else
3725             aNeighbourPoint.ParametersOnS2(nU1, nV1);
3726           gp_Pnt2d ap1(nU1, nV1);
3727           gp_Pnt2d ap2 = AdjustByNeighbour( ap1, gp_Pnt2d( U, V ), aGASurface );
3728
3729
3730           if ( IsInsideTanZone( ap2, aPZone, aZoneRadius, aGASurface ) ) {
3731             aZoneIndex = zIt;
3732             bIsNearBoundary = Standard_True;
3733             if ( theReachedTol3d < aZoneRadius ) {
3734               theReachedTol3d = aZoneRadius;
3735             }
3736           }
3737         }
3738         // check if a point belong to a tangent zone. End
3739         Standard_Boolean bComputeLineEnd = Standard_False;
3740
3741         if(nbboundaries == 2) {
3742           //xf
3743           bComputeLineEnd = Standard_True;
3744           //xt
3745         }
3746         else if(nbboundaries == 1) {
3747           Standard_Boolean isperiodic = (bIsUBoundary) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
3748
3749           if(isperiodic) {
3750             Standard_Real alowerboundary = (bIsUBoundary) ? umin : vmin;
3751             Standard_Real aupperboundary = (bIsUBoundary) ? umax : vmax;
3752             Standard_Real aPeriod     = (bIsUBoundary) ? aGASurface->UPeriod() : aGASurface->VPeriod();
3753             Standard_Real aParameter = (bIsUBoundary) ? U : V;
3754             Standard_Real anoffset, anAdjustPar;
3755             GeomInt::AdjustPeriodic(aParameter, alowerboundary, aupperboundary, 
3756                                            aPeriod, anAdjustPar, anoffset);
3757
3758             Standard_Real adist = (bIsFirstBoundary) ? fabs(anAdjustPar - alowerboundary) : fabs(anAdjustPar - aupperboundary);
3759             Standard_Real anotherPar = (bIsFirstBoundary) ? (aupperboundary - adist) : (alowerboundary + adist);
3760             anotherPar += anoffset;
3761             Standard_Integer aneighbourpointindex = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
3762             const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex);
3763             Standard_Real nU1, nV1;
3764
3765             if(surfit == 0)
3766               aNeighbourPoint.ParametersOnS1(nU1, nV1);
3767             else
3768               aNeighbourPoint.ParametersOnS2(nU1, nV1);
3769             
3770             Standard_Real adist1 = (bIsUBoundary) ? fabs(nU1 - U) : fabs(nV1 - V);
3771             Standard_Real adist2 = (bIsUBoundary) ? fabs(nU1 - anotherPar) : fabs(nV1 - anotherPar);
3772             bComputeLineEnd = Standard_True;
3773             Standard_Boolean bCheckAngle1 = Standard_False;
3774             Standard_Boolean bCheckAngle2 = Standard_False;
3775             gp_Vec2d aNewVec;
3776             Standard_Real anewU = (bIsUBoundary) ? anotherPar : U;
3777             Standard_Real anewV = (bIsUBoundary) ? V : anotherPar;
3778
3779             if(((adist1 - adist2) > Precision::PConfusion()) && 
3780                (adist2 < (aPeriod / 4.))) {
3781               bCheckAngle1 = Standard_True;
3782               aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(anewU, anewV));
3783
3784               if(aNewVec.SquareMagnitude() < gp::Resolution()) {
3785                 aNewP.SetValue((surfit == 0), anewU, anewV);
3786                 bCheckAngle1 = Standard_False;
3787               }
3788             }
3789             else if(adist1 < (aPeriod / 4.)) {
3790               bCheckAngle2 = Standard_True;
3791               aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(U, V));
3792
3793               if(aNewVec.SquareMagnitude() < gp::Resolution()) {
3794                 bCheckAngle2 = Standard_False;
3795               }
3796             }
3797
3798             if(bCheckAngle1 || bCheckAngle2) {
3799               // assume there are at least two points in line (see "if" above)
3800               Standard_Integer anindexother = aneighbourpointindex;
3801
3802               while((anindexother <= iLast) && (anindexother >= iFirst)) {
3803                 anindexother = (j == 0) ? (anindexother + 1) : (anindexother - 1);
3804                 const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(anindexother);
3805                 Standard_Real nU2, nV2;
3806                 
3807                 if(surfit == 0)
3808                   aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
3809                 else
3810                   aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
3811                 gp_Vec2d aVecOld(gp_Pnt2d(nU2, nV2), gp_Pnt2d(nU1, nV1));
3812
3813                 if(aVecOld.SquareMagnitude() <= gp::Resolution()) {
3814                   continue;
3815                 }
3816                 else {
3817                   Standard_Real anAngle = aNewVec.Angle(aVecOld);
3818
3819                   if((fabs(anAngle) < (M_PI * 0.25)) && (aNewVec.Dot(aVecOld) > 0.)) {
3820
3821                     if(bCheckAngle1) {
3822                       Standard_Real U1, U2, V1, V2;
3823                       IntSurf_PntOn2S atmppoint = aNewP;
3824                       atmppoint.SetValue((surfit == 0), anewU, anewV);
3825                       atmppoint.Parameters(U1, V1, U2, V2);
3826                       gp_Pnt P1 = theSurface1->Value(U1, V1);
3827                       gp_Pnt P2 = theSurface2->Value(U2, V2);
3828                       gp_Pnt P0 = aPoint.Value();
3829
3830                       if(P0.IsEqual(P1, aTol) &&
3831                          P0.IsEqual(P2, aTol) &&
3832                          P1.IsEqual(P2, aTol)) {
3833                         bComputeLineEnd = Standard_False;
3834                         aNewP.SetValue((surfit == 0), anewU, anewV);
3835                       }
3836                     }
3837
3838                     if(bCheckAngle2) {
3839                       bComputeLineEnd = Standard_False;
3840                     }
3841                   }
3842                   break;
3843                 }
3844               } // end while(anindexother...)
3845             }
3846           }
3847         }
3848         else if ( bIsNearBoundary ) {
3849           bComputeLineEnd = Standard_True;
3850         }
3851
3852         if(bComputeLineEnd) {
3853
3854           gp_Pnt2d anewpoint;
3855           Standard_Boolean found = Standard_False;
3856
3857           if ( bIsNearBoundary ) {
3858             // re-compute point near natural boundary or near tangent zone
3859             Standard_Real u1, v1, u2, v2;
3860             aNewP.Parameters( u1, v1, u2, v2 );
3861             if(surfit == 0)
3862               anewpoint = gp_Pnt2d( u1, v1 );
3863             else
3864               anewpoint = gp_Pnt2d( u2, v2 );
3865             
3866             Standard_Integer aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
3867             const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
3868             Standard_Real nU1, nV1;
3869             
3870             if(surfit == 0)
3871               aNeighbourPoint.ParametersOnS1(nU1, nV1);
3872             else
3873               aNeighbourPoint.ParametersOnS2(nU1, nV1);
3874             gp_Pnt2d ap1(nU1, nV1);
3875             gp_Pnt2d ap2;
3876
3877
3878             if ( aZoneIndex ) {
3879               // exclude point from a tangent zone
3880               anewpoint = AdjustByNeighbour( ap1, anewpoint, aGASurface );
3881               gp_Pnt2d aPZone = (surfit == 0) ? aTanZoneS1->Value(aZoneIndex) : aTanZoneS2->Value(aZoneIndex);
3882               Standard_Real aZoneRadius = aTanZoneRadius->Value(aZoneIndex);
3883
3884               if ( FindPoint(ap1, anewpoint, umin, umax, vmin, vmax, 
3885                              aPZone, aZoneRadius, aGASurface, ap2) ) {
3886                 anewpoint = ap2;
3887                 found = Standard_True;
3888               }
3889             }
3890             else if ( aGASurface->IsUPeriodic() || aGASurface->IsVPeriodic() ) {
3891               // re-compute point near boundary if shifted on a period
3892               ap2 = AdjustByNeighbour( ap1, anewpoint, aGASurface );
3893
3894               if ( ( ap2.X() < umin ) || ( ap2.X() > umax ) ||
3895                   ( ap2.Y() < vmin ) || ( ap2.Y() > vmax ) ) {
3896                 found = FindPoint(ap1, ap2, umin, umax, vmin, vmax, anewpoint);
3897               }
3898               else {
3899                 anewpoint = ap2;
3900                 aNewP.SetValue( (surfit == 0), anewpoint.X(), anewpoint.Y() );
3901               }
3902             }
3903           }
3904           else {
3905
3906             Standard_Integer aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
3907             const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
3908             Standard_Real nU1, nV1;
3909
3910             if(surfit == 0)
3911               aNeighbourPoint.ParametersOnS1(nU1, nV1);
3912             else
3913               aNeighbourPoint.ParametersOnS2(nU1, nV1);
3914             gp_Pnt2d ap1(nU1, nV1);
3915             gp_Pnt2d ap2(nU1, nV1);
3916             Standard_Integer aneighbourpointindex2 = aneighbourpointindex1;
3917
3918             while((aneighbourpointindex2 <= iLast) && (aneighbourpointindex2 >= iFirst)) {
3919               aneighbourpointindex2 = (j == 0) ? (aneighbourpointindex2 + 1) : (aneighbourpointindex2 - 1);
3920               const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(aneighbourpointindex2);
3921               Standard_Real nU2, nV2;
3922
3923               if(surfit == 0)
3924                 aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
3925               else
3926                 aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
3927               ap2.SetX(nU2);
3928               ap2.SetY(nV2);
3929
3930               if(ap1.SquareDistance(ap2) > gp::Resolution()) {
3931                 break;
3932               }
3933             }  
3934             found = FindPoint(ap2, ap1, umin, umax, vmin, vmax, anewpoint);
3935           }
3936
3937           if(found) {
3938             // check point
3939             Standard_Real aCriteria = BRep_Tool::Tolerance(theFace1) + BRep_Tool::Tolerance(theFace2);
3940             GeomAPI_ProjectPointOnSurf& aProjector = 
3941               (surfit == 0) ? aContext->ProjPS(theFace2) : aContext->ProjPS(theFace1);
3942             Handle(GeomAdaptor_HSurface) aSurface = (surfit == 0) ? theSurface1 : theSurface2;
3943
3944             Handle(GeomAdaptor_HSurface) aSurfaceOther = (surfit == 0) ? theSurface2 : theSurface1;
3945
3946             gp_Pnt aP3d = aSurface->Value(anewpoint.X(), anewpoint.Y());
3947             aProjector.Perform(aP3d);
3948
3949             if(aProjector.IsDone()) {
3950               if(aProjector.LowerDistance() < aCriteria) {
3951                 Standard_Real foundU = U, foundV = V;
3952                 aProjector.LowerDistanceParameters(foundU, foundV);
3953
3954                 //Correction of projected coordinates. Begin
3955                 //Note, it may be shifted on a period
3956                 Standard_Integer aneindex1 = (j == 0) ? iFirst : iLast;
3957                 const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneindex1);
3958                 Standard_Real nUn, nVn;
3959                 
3960                 if(surfit == 0)
3961                   aNeighbourPoint.ParametersOnS2(nUn, nVn);
3962                 else
3963                   aNeighbourPoint.ParametersOnS1(nUn, nVn);
3964                 gp_Pnt2d aNeighbour2d(nUn, nVn);
3965                 gp_Pnt2d anAdjustedPoint = AdjustByNeighbour( aNeighbour2d, gp_Pnt2d(foundU, foundV), aSurfaceOther );
3966                 foundU = anAdjustedPoint.X();
3967                 foundV = anAdjustedPoint.Y();
3968
3969                 if ( ( anAdjustedPoint.X() < umin ) && ( anAdjustedPoint.X() > umax ) &&
3970                     ( anAdjustedPoint.Y() < vmin ) && ( anAdjustedPoint.Y() > vmax ) ) {
3971                   // attempt to roughly re-compute point
3972                   foundU = ( foundU < umin ) ? umin : foundU;
3973                   foundU = ( foundU > umax ) ? umax : foundU;
3974                   foundV = ( foundV < vmin ) ? vmin : foundV;
3975                   foundV = ( foundV > vmax ) ? vmax : foundV;
3976
3977                   GeomAPI_ProjectPointOnSurf& aProjector2 = 
3978                     (surfit == 0) ? aContext->ProjPS(theFace1) : aContext->ProjPS(theFace2);
3979
3980                   aP3d = aSurfaceOther->Value(foundU, foundV);
3981                   aProjector2.Perform(aP3d);
3982                   
3983                   if(aProjector2.IsDone()) {
3984                     if(aProjector2.LowerDistance() < aCriteria) {
3985                       Standard_Real foundU2 = anewpoint.X(), foundV2 = anewpoint.Y();
3986                       aProjector2.LowerDistanceParameters(foundU2, foundV2);
3987                       anewpoint.SetX(foundU2);
3988                       anewpoint.SetY(foundV2);
3989                     }
3990                   }
3991                 }
3992                 //Correction of projected coordinates. End
3993
3994                 if(surfit == 0)
3995                   aNewP.SetValue(aP3d, anewpoint.X(), anewpoint.Y(), foundU, foundV);
3996                 else
3997                   aNewP.SetValue(aP3d, foundU, foundV, anewpoint.X(), anewpoint.Y());
3998               }
3999             }
4000           }
4001         }
4002       }
4003       aSeqOfPntOn2S->Add(aNewP);
4004       aListOfFLIndex.Append(aSeqOfPntOn2S->NbPoints());
4005     }
4006     anArrayOfLineEnds.SetValue(i, aListOfFLIndex);
4007   }
4008   // Correct wlines.end
4009
4010   // Split wlines.begin
4011   Standard_Integer nbiter;
4012   //
4013   nbiter=1;
4014   if (!bAvoidLineConstructor) {
4015     nbiter=theLConstructor.NbParts();
4016   }
4017   //
4018   for(j = 1; j <= nbiter; ++j) {
4019     Standard_Real fprm, lprm;
4020     Standard_Integer ifprm, ilprm;
4021     //
4022     if(bAvoidLineConstructor) {
4023       ifprm = 1;
4024       ilprm = theWLine->NbPnts();
4025     }
4026     else {
4027       theLConstructor.Part(j, fprm, lprm);
4028       ifprm = (Standard_Integer)fprm;
4029       ilprm = (Standard_Integer)lprm;
4030     }
4031
4032     Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
4033     //
4034     for(i = 1; i <= nblines; i++) {
4035       if(anArrayOfLineType.Value(i) != 0) {
4036         continue;
4037       }
4038       const TColStd_ListOfInteger& aListOfIndex = anArrayOfLines.Value(i);
4039       const TColStd_ListOfInteger& aListOfFLIndex = anArrayOfLineEnds.Value(i);
4040       Standard_Boolean bhasfirstpoint = (aListOfFLIndex.Extent() == 2);
4041       Standard_Boolean bhaslastpoint = (aListOfFLIndex.Extent() == 2);
4042
4043       if(!bhasfirstpoint && !aListOfFLIndex.IsEmpty()) {
4044         bhasfirstpoint = (i != 1);
4045       }
4046
4047       if(!bhaslastpoint && !aListOfFLIndex.IsEmpty()) {
4048         bhaslastpoint = (i != nblines);
4049       }
4050       
4051       Standard_Integer iFirst = aListOfIndex.First();
4052       Standard_Integer iLast  = aListOfIndex.Last();
4053       Standard_Boolean bIsFirstInside = ((ifprm >= iFirst) && (ifprm <= iLast));
4054       Standard_Boolean bIsLastInside =  ((ilprm >= iFirst) && (ilprm <= iLast));
4055
4056       if(!bIsFirstInside && !bIsLastInside) {
4057         if((ifprm < iFirst) && (ilprm > iLast)) {
4058           // append whole line, and boundaries if neccesary
4059           if(bhasfirstpoint) {
4060             pit = aListOfFLIndex.First();
4061             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
4062             aLineOn2S->Add(aP);
4063           }
4064           TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
4065
4066           for(; anIt.More(); anIt.Next()) {
4067             pit = anIt.Value();
4068             const IntSurf_PntOn2S& aP = theWLine->Point(pit);
4069             aLineOn2S->Add(aP);
4070           }
4071
4072           if(bhaslastpoint) {
4073             pit = aListOfFLIndex.Last();
4074             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
4075             aLineOn2S->Add(aP);
4076           }
4077
4078           // check end of split line (end is almost always)
4079           Standard_Integer aneighbour = i + 1;
4080           Standard_Boolean bIsEndOfLine = Standard_True;
4081
4082           if(aneighbour <= nblines) {
4083             const TColStd_ListOfInteger& aListOfNeighbourIndex = anArrayOfLines.Value(aneighbour);
4084
4085             if((anArrayOfLineType.Value(aneighbour) != 0) &&
4086                (aListOfNeighbourIndex.IsEmpty())) {
4087               bIsEndOfLine = Standard_False;
4088             }
4089           }
4090
4091           if(bIsEndOfLine) {
4092             if(aLineOn2S->NbPoints() > 1) {
4093               Handle(IntPatch_WLine) aNewWLine = 
4094                 new IntPatch_WLine(aLineOn2S, Standard_False);
4095               theNewLines.Append(aNewWLine);
4096             }
4097             aLineOn2S = new IntSurf_LineOn2S();
4098           }
4099         }
4100         continue;
4101       }
4102       // end if(!bIsFirstInside && !bIsLastInside)
4103
4104       if(bIsFirstInside && bIsLastInside) {
4105         // append inside points between ifprm and ilprm
4106         TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
4107
4108         for(; anIt.More(); anIt.Next()) {
4109           pit = anIt.Value();
4110           if((pit < ifprm) || (pit > ilprm))
4111             continue;
4112           const IntSurf_PntOn2S& aP = theWLine->Point(pit);
4113           aLineOn2S->Add(aP);
4114         }
4115       }
4116       else {
4117
4118         if(bIsFirstInside) {
4119           // append points from ifprm to last point + boundary point
4120           TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
4121
4122           for(; anIt.More(); anIt.Next()) {
4123             pit = anIt.Value();
4124             if(pit < ifprm)
4125               continue;
4126             const IntSurf_PntOn2S& aP = theWLine->Point(pit);
4127             aLineOn2S->Add(aP);
4128           }
4129
4130           if(bhaslastpoint) {
4131             pit = aListOfFLIndex.Last();
4132             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
4133             aLineOn2S->Add(aP);
4134           }
4135           // check end of split line (end is almost always)
4136           Standard_Integer aneighbour = i + 1;
4137           Standard_Boolean bIsEndOfLine = Standard_True;
4138
4139           if(aneighbour <= nblines) {
4140             const TColStd_ListOfInteger& aListOfNeighbourIndex = anArrayOfLines.Value(aneighbour);
4141
4142             if((anArrayOfLineType.Value(aneighbour) != 0) &&
4143                (aListOfNeighbourIndex.IsEmpty())) {
4144               bIsEndOfLine = Standard_False;
4145             }
4146           }
4147
4148           if(bIsEndOfLine) {
4149             if(aLineOn2S->NbPoints() > 1) {
4150               Handle(IntPatch_WLine) aNewWLine = 
4151                 new IntPatch_WLine(aLineOn2S, Standard_False);
4152               theNewLines.Append(aNewWLine);
4153             }
4154             aLineOn2S = new IntSurf_LineOn2S();
4155           }
4156         }
4157         // end if(bIsFirstInside)
4158
4159         if(bIsLastInside) {
4160           // append points from first boundary point to ilprm
4161           if(bhasfirstpoint) {
4162             pit = aListOfFLIndex.First();
4163             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
4164             aLineOn2S->Add(aP);
4165           }
4166           TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
4167
4168           for(; anIt.More(); anIt.Next()) {
4169             pit = anIt.Value();
4170             if(pit > ilprm)
4171               continue;
4172             const IntSurf_PntOn2S& aP = theWLine->Point(pit);
4173             aLineOn2S->Add(aP);
4174           }
4175         }
4176         //end if(bIsLastInside)
4177       }
4178     }
4179
4180     if(aLineOn2S->NbPoints() > 1) {
4181       Handle(IntPatch_WLine) aNewWLine = 
4182         new IntPatch_WLine(aLineOn2S, Standard_False);
4183       theNewLines.Append(aNewWLine);
4184     }
4185   }
4186   // Split wlines.end
4187
4188   return Standard_True;
4189 }
4190
4191 // ------------------------------------------------------------------------------------------------
4192 // static function: ParameterOutOfBoundary
4193 // purpose:         Computes a new parameter for given curve. The corresponding 2d points 
4194 //                  does not lay on any boundary of given faces
4195 // ------------------------------------------------------------------------------------------------
4196 Standard_Boolean ParameterOutOfBoundary(const Standard_Real       theParameter, 
4197                                         const Handle(Geom_Curve)& theCurve, 
4198                                         const TopoDS_Face&        theFace1, 
4199                                         const TopoDS_Face&        theFace2,
4200                                         const Standard_Real       theOtherParameter,
4201                                         const Standard_Boolean    bIncreasePar,
4202                                         Standard_Real&            theNewParameter,
4203                                         const Handle(IntTools_Context)& aContext)
4204 {
4205   Standard_Boolean bIsComputed = Standard_False;
4206   theNewParameter = theParameter;
4207
4208   Standard_Real acurpar = theParameter;
4209   TopAbs_State aState = TopAbs_ON;
4210   Standard_Integer iter = 0;
4211   Standard_Real asumtol = BRep_Tool::Tolerance(theFace1) + BRep_Tool::Tolerance(theFace2);
4212   Standard_Real adelta = asumtol * 0.1;
4213   adelta = (adelta < Precision::Confusion()) ? Precision::Confusion() : adelta;
4214   Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(theFace1);
4215   Handle(Geom_Surface) aSurf2 = BRep_Tool::Surface(theFace2);
4216
4217   Standard_Real u1, u2, v1, v2;
4218
4219   GeomAPI_ProjectPointOnSurf aPrj1;
4220   aSurf1->Bounds(u1, u2, v1, v2);
4221   aPrj1.Init(aSurf1, u1, u2, v1, v2);
4222
4223   GeomAPI_ProjectPointOnSurf aPrj2;
4224   aSurf2->Bounds(u1, u2, v1, v2);
4225   aPrj2.Init(aSurf2, u1, u2, v1, v2);
4226
4227   while(aState == TopAbs_ON) {
4228     if(bIncreasePar)
4229       acurpar += adelta;
4230     else
4231       acurpar -= adelta;
4232     gp_Pnt aPCurrent = theCurve->Value(acurpar);
4233     aPrj1.Perform(aPCurrent);
4234     Standard_Real U=0., V=0.;
4235
4236     if(aPrj1.IsDone()) {
4237       aPrj1.LowerDistanceParameters(U, V);
4238       aState = aContext->StatePointFace(theFace1, gp_Pnt2d(U, V));
4239     }
4240
4241     if(aState != TopAbs_ON) {
4242       aPrj2.Perform(aPCurrent);
4243                 
4244       if(aPrj2.IsDone()) {
4245         aPrj2.LowerDistanceParameters(U, V);
4246         aState = aContext->StatePointFace(theFace2, gp_Pnt2d(U, V));
4247       }
4248     }
4249
4250     if(iter > 11) {
4251       break;
4252     }
4253     iter++;
4254   }
4255
4256   if(iter <= 11) {
4257     theNewParameter = acurpar;
4258     bIsComputed = Standard_True;
4259
4260     if(bIncreasePar) {
4261       if(acurpar >= theOtherParameter)
4262         theNewParameter = theOtherParameter;
4263     }
4264     else {
4265       if(acurpar <= theOtherParameter)
4266         theNewParameter = theOtherParameter;
4267     }
4268   }
4269   return bIsComputed;
4270 }
4271
4272 //=======================================================================
4273 //function : IsCurveValid
4274 //purpose  : 
4275 //=======================================================================
4276 Standard_Boolean IsCurveValid(Handle(Geom2d_Curve)& thePCurve)
4277 {
4278   if(thePCurve.IsNull())
4279     return Standard_False;
4280
4281   Standard_Real tolint = 1.e-10;
4282   Geom2dAdaptor_Curve PCA;
4283   IntRes2d_Domain PCD;
4284   Geom2dInt_GInter PCI;
4285
4286   Standard_Real pf = 0., pl = 0.;
4287   gp_Pnt2d pntf, pntl;
4288
4289   if(!thePCurve->IsClosed() && !thePCurve->IsPeriodic()) {
4290     pf = thePCurve->FirstParameter();
4291     pl = thePCurve->LastParameter();
4292     pntf = thePCurve->Value(pf);
4293     pntl = thePCurve->Value(pl);
4294     PCA.Load(thePCurve);
4295     if(!PCA.IsPeriodic()) {
4296       if(PCA.FirstParameter() > pf) pf = PCA.FirstParameter();
4297       if(PCA.LastParameter()  < pl) pl = PCA.LastParameter();
4298     }
4299     PCD.SetValues(pntf,pf,tolint,pntl,pl,tolint);
4300     PCI.Perform(PCA,PCD,tolint,tolint);
4301     if(PCI.IsDone())
4302       if(PCI.NbPoints() > 0) {
4303         return Standard_False;
4304       }
4305   }
4306
4307   return Standard_True;
4308 }
4309
4310 //=======================================================================
4311 //static function : ApproxWithPCurves
4312 //purpose  : for bug 20964 only
4313 //=======================================================================
4314 Standard_Boolean ApproxWithPCurves(const gp_Cylinder& theCyl, 
4315                                    const gp_Sphere& theSph)
4316 {
4317   Standard_Boolean bRes = Standard_True;
4318   Standard_Real R1 = theCyl.Radius(), R2 = theSph.Radius();
4319   //
4320   {
4321     Standard_Real aD2, aRc2, aEps;
4322     gp_Pnt aApexSph;
4323     //
4324     aEps=1.E-7;
4325     aRc2=R1*R1;
4326     //
4327     const gp_Ax3& aAx3Sph=theSph.Position();
4328     const gp_Pnt& aLocSph=aAx3Sph.Location();
4329     const gp_Dir& aDirSph=aAx3Sph.Direction();
4330     //
4331     const gp_Ax1& aAx1Cyl=theCyl.Axis();
4332     gp_Lin aLinCyl(aAx1Cyl);
4333     //
4334     aApexSph.SetXYZ(aLocSph.XYZ()+R2*aDirSph.XYZ());
4335     aD2=aLinCyl.SquareDistance(aApexSph);
4336     if (fabs(aD2-aRc2)<aEps) {
4337       return !bRes;
4338     }
4339     //
4340     aApexSph.SetXYZ(aLocSph.XYZ()-R2*aDirSph.XYZ());
4341     aD2=aLinCyl.SquareDistance(aApexSph);
4342     if (fabs(aD2-aRc2)<aEps) {
4343       return !bRes;
4344     }
4345   }
4346   //
4347     
4348   if(R1 < 2.*R2) {
4349     return bRes;
4350   }
4351   gp_Lin anCylAx(theCyl.Axis());
4352
4353   Standard_Real aDist = anCylAx.Distance(theSph.Location());
4354   Standard_Real aDRel = Abs(aDist - R1)/R2;
4355
4356   if(aDRel > .2) return bRes;
4357
4358   Standard_Real par = ElCLib::Parameter(anCylAx, theSph.Location());
4359   gp_Pnt aP = ElCLib::Value(par, anCylAx);
4360   gp_Vec aV(aP, theSph.Location());
4361
4362   Standard_Real dd = aV.Dot(theSph.Position().XDirection());
4363
4364   if(aDist < R1 && dd > 0.) return Standard_False;
4365   if(aDist > R1 && dd < 0.) return Standard_False;
4366
4367   
4368   return bRes;
4369 }
4370 //=======================================================================
4371 //function : PerformPlanes
4372 //purpose  : 
4373 //=======================================================================
4374 void  PerformPlanes(const Handle(GeomAdaptor_HSurface)& theS1, 
4375                     const Handle(GeomAdaptor_HSurface)& theS2, 
4376                     const Standard_Real TolAng, 
4377                     const Standard_Real TolTang, 
4378                     const Standard_Boolean theApprox1,
4379                     const Standard_Boolean theApprox2,
4380                     IntTools_SequenceOfCurves& theSeqOfCurve, 
4381                     Standard_Boolean& theTangentFaces)
4382 {
4383
4384   gp_Pln aPln1 = theS1->Surface().Plane();
4385   gp_Pln aPln2 = theS2->Surface().Plane();
4386
4387   IntAna_QuadQuadGeo aPlnInter(aPln1, aPln2, TolAng, TolTang);
4388
4389   if(!aPlnInter.IsDone()) {
4390     theTangentFaces = Standard_False;
4391     return;
4392   }
4393
4394   IntAna_ResultType aResType = aPlnInter.TypeInter();
4395
4396   if(aResType == IntAna_Same) {
4397     theTangentFaces = Standard_True;
4398     return;
4399   }
4400
4401   theTangentFaces = Standard_False;
4402
4403   if(aResType == IntAna_Empty) {
4404     return;
4405   }
4406
4407   gp_Lin aLin = aPlnInter.Line(1);
4408
4409   ProjLib_Plane aProj;
4410
4411   aProj.Init(aPln1);
4412   aProj.Project(aLin);
4413   gp_Lin2d aLin2d1 = aProj.Line();
4414   //
4415   aProj.Init(aPln2);
4416   aProj.Project(aLin);
4417   gp_Lin2d aLin2d2 = aProj.Line();
4418   //
4419   //classify line2d1 relatively first plane
4420   Standard_Real P11, P12;
4421   Standard_Boolean IsCrossed = ClassifyLin2d(theS1, aLin2d1, TolTang, P11, P12);
4422   if(!IsCrossed) return;
4423   //classify line2d2 relatively second plane
4424   Standard_Real P21, P22;
4425   IsCrossed = ClassifyLin2d(theS2, aLin2d2, TolTang, P21, P22);
4426   if(!IsCrossed) return;
4427
4428   //Analysis of parametric intervals: must have common part
4429
4430   if(P21 >= P12) return;
4431   if(P22 <= P11) return;
4432
4433   Standard_Real pmin, pmax;
4434   pmin = Max(P11, P21);
4435   pmax = Min(P12, P22);
4436
4437   if(pmax - pmin <= TolTang) return;
4438
4439   Handle(Geom_Line) aGLin = new Geom_Line(aLin);
4440
4441   IntTools_Curve aCurve;
4442   Handle(Geom_TrimmedCurve) aGTLin = new Geom_TrimmedCurve(aGLin, pmin, pmax);
4443
4444   aCurve.SetCurve(aGTLin);
4445
4446   if(theApprox1) { 
4447     Handle(Geom2d_Line) C2d = new Geom2d_Line(aLin2d1);
4448     aCurve.SetFirstCurve2d(new Geom2d_TrimmedCurve(C2d, pmin, pmax));
4449   }
4450   else { 
4451     Handle(Geom2d_Curve) H1;
4452     aCurve.SetFirstCurve2d(H1);
4453   }
4454   if(theApprox2) { 
4455     Handle(Geom2d_Line) C2d = new Geom2d_Line(aLin2d2);
4456     aCurve.SetSecondCurve2d(new Geom2d_TrimmedCurve(C2d, pmin, pmax));
4457   }
4458   else { 
4459     Handle(Geom2d_Curve) H1;
4460     aCurve.SetFirstCurve2d(H1);
4461   }
4462
4463   theSeqOfCurve.Append(aCurve);
4464  
4465 }
4466
4467 //=======================================================================
4468 //function : ClassifyLin2d
4469 //purpose  : 
4470 //=======================================================================
4471 static inline Standard_Boolean INTER(const Standard_Real d1, 
4472                                      const Standard_Real d2, 
4473                                      const Standard_Real tol) 
4474 {
4475   return (d1 > tol && d2 < -tol) || 
4476          (d1 < -tol && d2 > tol) ||
4477          ((d1 <= tol && d1 >= -tol) && (d2 > tol || d2 < -tol)) || 
4478          ((d2 <= tol && d2 >= -tol) && (d1 > tol || d1 < -tol));
4479 }
4480 static inline Standard_Boolean COINC(const Standard_Real d1, 
4481                                      const Standard_Real d2, 
4482                                      const Standard_Real tol) 
4483 {
4484   return (d1 <= tol && d1 >= -tol) && (d2 <= tol && d2 >= -tol);
4485 }
4486 Standard_Boolean ClassifyLin2d(const Handle(GeomAdaptor_HSurface)& theS, 
4487                                const gp_Lin2d& theLin2d, 
4488                                const Standard_Real theTol,
4489                                Standard_Real& theP1, 
4490                                Standard_Real& theP2)
4491
4492 {
4493   Standard_Real xmin, xmax, ymin, ymax, d1, d2, A, B, C;
4494   Standard_Real par[2];
4495   Standard_Integer nbi = 0;
4496
4497   xmin = theS->Surface().FirstUParameter();
4498   xmax = theS->Surface().LastUParameter();
4499   ymin = theS->Surface().FirstVParameter();
4500   ymax = theS->Surface().LastVParameter();
4501
4502   theLin2d.Coefficients(A, B, C);
4503
4504   //xmin, ymin <-> xmin, ymax
4505   d1 = A*xmin + B*ymin + C;
4506   d2 = A*xmin + B*ymax + C;
4507
4508   if(INTER(d1, d2, theTol)) {
4509     //Intersection with boundary
4510     Standard_Real y = -(C + A*xmin)/B;
4511     par[nbi] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, y));
4512     nbi++;
4513   }
4514   else if (COINC(d1, d2, theTol)) {
4515     //Coincidence with boundary
4516     par[0] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, ymin));
4517     par[1] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, ymax));
4518     nbi = 2;
4519   }
4520
4521   if(nbi == 2) {
4522
4523     if(fabs(par[0]-par[1]) > theTol) {
4524       theP1 = Min(par[0], par[1]);
4525       theP2 = Max(par[0], par[1]);
4526       return Standard_True;
4527     }
4528     else return Standard_False;
4529
4530   }
4531
4532   //xmin, ymax <-> xmax, ymax
4533   d1 = d2;
4534   d2 = A*xmax + B*ymax + C;
4535
4536   if(d1 > theTol || d1 < -theTol) {//to avoid checking of
4537                                    //coincidence with the same point
4538     if(INTER(d1, d2, theTol)) {
4539       Standard_Real x = -(C + B*ymax)/A;
4540       par[nbi] = ElCLib::Parameter(theLin2d, gp_Pnt2d(x, ymax));
4541       nbi++;
4542     }
4543     else if (COINC(d1, d2, theTol)) {
4544       par[0] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, ymax));
4545       par[1] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, ymax));
4546       nbi = 2;
4547     }
4548   }
4549
4550   if(nbi == 2) {
4551
4552     if(fabs(par[0]-par[1]) > theTol) {
4553       theP1 = Min(par[0], par[1]);
4554       theP2 = Max(par[0], par[1]);
4555       return Standard_True;
4556     }
4557     else return Standard_False;
4558
4559   }
4560
4561   //xmax, ymax <-> xmax, ymin
4562   d1 = d2;
4563   d2 = A*xmax + B*ymin + C;
4564
4565   if(d1 > theTol || d1 < -theTol) {
4566     if(INTER(d1, d2, theTol)) {
4567       Standard_Real y = -(C + A*xmax)/B;
4568       par[nbi] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, y));
4569       nbi++;
4570     }
4571     else if (COINC(d1, d2, theTol)) {
4572       par[0] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, ymax));
4573       par[1] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, ymin));
4574       nbi = 2;
4575     }
4576   }
4577
4578   if(nbi == 2) {
4579     if(fabs(par[0]-par[1]) > theTol) {
4580       theP1 = Min(par[0], par[1]);
4581       theP2 = Max(par[0], par[1]);
4582       return Standard_True;
4583     }
4584     else return Standard_False;
4585   }
4586
4587   //xmax, ymin <-> xmin, ymin 
4588   d1 = d2;
4589   d2 = A*xmin + B*ymin + C;
4590
4591   if(d1 > theTol || d1 < -theTol) {
4592     if(INTER(d1, d2, theTol)) {
4593       Standard_Real x = -(C + B*ymin)/A;
4594       par[nbi] = ElCLib::Parameter(theLin2d, gp_Pnt2d(x, ymin));
4595       nbi++;
4596     }
4597     else if (COINC(d1, d2, theTol)) {
4598       par[0] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, ymin));
4599       par[1] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, ymin));
4600       nbi = 2;
4601     }
4602   }
4603
4604   if(nbi == 2) {
4605     if(fabs(par[0]-par[1]) > theTol) {
4606       theP1 = Min(par[0], par[1]);
4607       theP2 = Max(par[0], par[1]);
4608       return Standard_True;
4609     }
4610     else return Standard_False;
4611   }
4612
4613   return Standard_False;
4614
4615 }
4616 //
4617 //=======================================================================
4618 //function : ApproxParameters
4619 //purpose  : 
4620 //=======================================================================
4621 void ApproxParameters(const Handle(GeomAdaptor_HSurface)& aHS1,
4622                       const Handle(GeomAdaptor_HSurface)& aHS2,
4623                       Standard_Integer& iDegMin,
4624                       Standard_Integer& iDegMax,
4625                       Standard_Integer& iNbIter)
4626
4627 {
4628   GeomAbs_SurfaceType aTS1, aTS2;
4629   
4630   //
4631   iNbIter=0;
4632   iDegMin=4;
4633   iDegMax=8;
4634   //
4635   aTS1=aHS1->Surface().GetType();
4636   aTS2=aHS2->Surface().GetType();
4637   //
4638   // Cylinder/Torus
4639   if ((aTS1==GeomAbs_Cylinder && aTS2==GeomAbs_Torus) ||
4640       (aTS2==GeomAbs_Cylinder && aTS1==GeomAbs_Torus)) {
4641     Standard_Real aRC, aRT, dR, aPC;
4642     gp_Cylinder aCylinder;
4643     gp_Torus aTorus;
4644     //
4645     aPC=Precision::Confusion();
4646     //
4647     aCylinder=(aTS1==GeomAbs_Cylinder)? aHS1->Surface().Cylinder() : aHS2->Surface().Cylinder();
4648     aTorus=(aTS1==GeomAbs_Torus)? aHS1->Surface().Torus() : aHS2->Surface().Torus();
4649     //
4650     aRC=aCylinder.Radius();
4651     aRT=aTorus.MinorRadius();
4652     dR=aRC-aRT;
4653     if (dR<0.) {
4654       dR=-dR;
4655     }
4656     //
4657     if (dR<aPC) {
4658       iDegMax=6;
4659     }
4660   }
4661   if (aTS1==GeomAbs_Cylinder && aTS2==GeomAbs_Cylinder) {
4662     iNbIter=1; 
4663   }
4664 }
4665 //=======================================================================
4666 //function : Tolerances
4667 //purpose  : 
4668 //=======================================================================
4669 void Tolerances(const Handle(GeomAdaptor_HSurface)& aHS1,
4670                 const Handle(GeomAdaptor_HSurface)& aHS2,
4671                 Standard_Real& aTolTang)
4672 {
4673   GeomAbs_SurfaceType aTS1, aTS2;
4674   //
4675   aTS1=aHS1->Surface().GetType();
4676   aTS2=aHS2->Surface().GetType();
4677   //
4678   // Cylinder/Torus
4679   if ((aTS1==GeomAbs_Cylinder && aTS2==GeomAbs_Torus) ||
4680       (aTS2==GeomAbs_Cylinder && aTS1==GeomAbs_Torus)) {
4681     Standard_Real aRC, aRT, dR, aPC;
4682     gp_Cylinder aCylinder;
4683     gp_Torus aTorus;
4684     //
4685     aPC=Precision::Confusion();
4686     //
4687     aCylinder=(aTS1==GeomAbs_Cylinder)? aHS1->Surface().Cylinder() : aHS2->Surface().Cylinder();
4688     aTorus=(aTS1==GeomAbs_Torus)? aHS1->Surface().Torus() : aHS2->Surface().Torus();
4689     //
4690     aRC=aCylinder.Radius();
4691     aRT=aTorus.MinorRadius();
4692     dR=aRC-aRT;
4693     if (dR<0.) {
4694       dR=-dR;
4695     }
4696     //
4697     if (dR<aPC) {
4698       aTolTang=0.1*aTolTang;
4699     }
4700   }
4701 }
4702 //=======================================================================
4703 //function : SortTypes
4704 //purpose  : 
4705 //=======================================================================
4706 Standard_Boolean SortTypes(const GeomAbs_SurfaceType aType1,
4707                            const GeomAbs_SurfaceType aType2)
4708 {
4709   Standard_Boolean bRet;
4710   Standard_Integer aI1, aI2;
4711   //
4712   bRet=Standard_False;
4713   //
4714   aI1=IndexType(aType1);
4715   aI2=IndexType(aType2);
4716   if (aI1<aI2){
4717     bRet=!bRet;
4718   }
4719   return bRet;
4720 }
4721 //=======================================================================
4722 //function : IndexType
4723 //purpose  : 
4724 //=======================================================================
4725 Standard_Integer IndexType(const GeomAbs_SurfaceType aType)
4726 {
4727   Standard_Integer aIndex;
4728   //
4729   aIndex=11;
4730   //
4731   if (aType==GeomAbs_Plane) {
4732     aIndex=0;
4733   }
4734   else if (aType==GeomAbs_Cylinder) {
4735     aIndex=1;
4736   } 
4737   else if (aType==GeomAbs_Cone) {
4738     aIndex=2;
4739   } 
4740   else if (aType==GeomAbs_Sphere) {
4741     aIndex=3;
4742   } 
4743   else if (aType==GeomAbs_Torus) {
4744     aIndex=4;
4745   } 
4746   else if (aType==GeomAbs_BezierSurface) {
4747     aIndex=5;
4748   } 
4749   else if (aType==GeomAbs_BSplineSurface) {
4750     aIndex=6;
4751   } 
4752   else if (aType==GeomAbs_SurfaceOfRevolution) {
4753     aIndex=7;
4754   } 
4755   else if (aType==GeomAbs_SurfaceOfExtrusion) {
4756     aIndex=8;
4757   } 
4758   else if (aType==GeomAbs_OffsetSurface) {
4759     aIndex=9;
4760   } 
4761   else if (aType==GeomAbs_OtherSurface) {
4762     aIndex=10;
4763   } 
4764   return aIndex;
4765 }
4766 #ifdef OCCT_DEBUG_DUMPWLINE
4767 //=======================================================================
4768 //function : DumpWLine
4769 //purpose  : 
4770 //=======================================================================
4771 void DumpWLine(const Handle(IntPatch_WLine)& aWLine)
4772 {
4773   Standard_Integer i, aNbPnts; 
4774   Standard_Real aX, aY, aZ, aU1, aV1, aU2, aV2;
4775   //
4776   printf(" *WLine\n");
4777   aNbPnts=aWLine->NbPnts();
4778   for (i=1; i<=aNbPnts; ++i) {
4779     const IntSurf_PntOn2S aPntOn2S=aWLine->Point(i);
4780     const gp_Pnt& aP3D=aPntOn2S.Value();
4781     aP3D.Coord(aX, aY, aZ);
4782     aPntOn2S.Parameters(aU1, aV1, aU2, aV2);
4783     //
4784     printf("point p_%d %lf %lf %lf\n", i, aX, aY, aZ);
4785     //printf("point p_%d %20.15lf %20.15lf %20.15lf %20.15lf %20.15lf %20.15lf %20.15lf\n",
4786         //   i, aX, aY, aZ, aU1, aV1, aU2, aV2);
4787   }
4788 }
4789 #endif
4790 //=======================================================================
4791 //function : RefineVector
4792 //purpose  : 
4793 //=======================================================================
4794 void RefineVector(gp_Vec2d& aV2D)
4795 {
4796   Standard_Integer k,m;
4797   Standard_Real aC[2], aEps, aR1, aR2, aNum;
4798   //
4799   aEps=RealEpsilon();
4800   aR1=1.-aEps;
4801   aR2=1.+aEps;
4802   //
4803   aV2D.Coord(aC[0], aC[1]);
4804   //
4805   for (k=0; k<2; ++k) {
4806     m=(k+1)%2;
4807     aNum=fabs(aC[k]);
4808     if (aNum>aR1 && aNum<aR2) {
4809       if (aC[k]<0.) {
4810         aC[k]=-1.;
4811       }          
4812       else {
4813         aC[k]=1.;
4814       }
4815       aC[m]=0.;
4816       break;
4817     }
4818   }
4819   aV2D.SetCoord(aC[0], aC[1]);
4820 }
4821
4822 //=======================================================================
4823 // Function : MaxDistance
4824 // purpose : 
4825 //=======================================================================
4826 Standard_Real MaxDistance(const Handle(Geom_Curve)& theC,
4827                           const Standard_Real aT,
4828                           GeomAPI_ProjectPointOnSurf& theProjPS)
4829 {
4830   Standard_Real aD;
4831   gp_Pnt aP;
4832   //
4833   theC->D0(aT, aP);
4834   theProjPS.Perform(aP);
4835   aD = theProjPS.NbPoints() ? theProjPS.LowerDistance() : 0.;
4836   //
4837   return aD;
4838 }
4839
4840 //=======================================================================
4841 //function : CheckPCurve
4842 //purpose  : Checks if points of the pcurve are out of the face bounds.
4843 //=======================================================================
4844   Standard_Boolean CheckPCurve(const Handle(Geom2d_Curve)& aPC, 
4845                                const TopoDS_Face& aFace) 
4846 {
4847   const Standard_Integer NPoints = 23;
4848   Standard_Integer i;
4849   Standard_Real umin,umax,vmin,vmax;
4850
4851   BRepTools::UVBounds(aFace, umin, umax, vmin, vmax);
4852   Standard_Real tolU = Max ((umax-umin)*0.01, Precision::Confusion());
4853   Standard_Real tolV = Max ((vmax-vmin)*0.01, Precision::Confusion());
4854   Standard_Real fp = aPC->FirstParameter();
4855   Standard_Real lp = aPC->LastParameter();
4856
4857
4858   // adjust domain for periodic surfaces
4859   TopLoc_Location aLoc;
4860   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc);
4861   if (aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
4862     aSurf = (Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurf))->BasisSurface();
4863   }
4864   gp_Pnt2d pnt = aPC->Value((fp+lp)/2);
4865   Standard_Real u,v;
4866   pnt.Coord(u,v);
4867   //
4868   if (aSurf->IsUPeriodic()) {
4869     Standard_Real aPer = aSurf->UPeriod();
4870     Standard_Integer nshift = (Standard_Integer) ((u-umin)/aPer);
4871     if (u < umin+aPer*nshift) nshift--;
4872     umin += aPer*nshift;
4873     umax += aPer*nshift;
4874   }
4875   if (aSurf->IsVPeriodic()) {
4876     Standard_Real aPer = aSurf->VPeriod();
4877     Standard_Integer nshift = (Standard_Integer) ((v-vmin)/aPer);
4878     if (v < vmin+aPer*nshift) nshift--;
4879     vmin += aPer*nshift;
4880     vmax += aPer*nshift;
4881   }
4882   //
4883   //--------------------------------------------------------
4884   Standard_Boolean bRet;
4885   Standard_Integer j, aNbIntervals;
4886   Standard_Real aT, dT;
4887   gp_Pnt2d aP2D; 
4888   //
4889   Geom2dAdaptor_Curve aGAC(aPC);
4890   aNbIntervals=aGAC.NbIntervals(GeomAbs_CN);
4891   //
4892   TColStd_Array1OfReal aTI(1, aNbIntervals+1);
4893   aGAC.Intervals(aTI,GeomAbs_CN);
4894   //
4895   bRet=Standard_False;
4896   //
4897   aT=aGAC.FirstParameter();
4898   for (j=1; j<=aNbIntervals; ++j) {
4899     dT=(aTI(j+1)-aTI(j))/NPoints;
4900     //
4901     for (i=1; i<NPoints; i++) {
4902       aT=aT+dT;
4903       aGAC.D0(aT, aP2D);
4904       aP2D.Coord(u,v);
4905     if (umin-u > tolU || u-umax > tolU ||
4906           vmin-v > tolV || v-vmax > tolV) {
4907         return bRet;
4908   }
4909 }
4910   }
4911   return !bRet;
4912 }
4913 //=======================================================================
4914 //function : CorrectPlaneBoundaries
4915 //purpose  : 
4916 //=======================================================================
4917  void CorrectPlaneBoundaries(Standard_Real& aUmin,
4918                              Standard_Real& aUmax, 
4919                              Standard_Real& aVmin, 
4920                              Standard_Real& aVmax) 
4921 {
4922   if (!(Precision::IsInfinite(aUmin) ||
4923         Precision::IsInfinite(aUmax))) { 
4924     Standard_Real dU;
4925     //
4926     dU=0.1*(aUmax-aUmin);
4927     aUmin=aUmin-dU;
4928     aUmax=aUmax+dU;
4929   }
4930   if (!(Precision::IsInfinite(aVmin) ||
4931         Precision::IsInfinite(aVmax))) { 
4932     Standard_Real dV;
4933     //
4934     dV=0.1*(aVmax-aVmin);
4935     aVmin=aVmin-dV;
4936     aVmax=aVmax+dV;
4937   }
4938 }