Integration of OCCT 6.5.0 from SVN
[occt.git] / src / IntTools / IntTools_FaceFace.cxx
1 // File:      IntTools_FaceFace.cxx
2 // Created:   Thu Nov 23 14:52:53 2000
3 // Author:    Michael KLOKOV
4 // Copyright: OPEN CASCADE 2000
5
6
7 #include <IntTools_FaceFace.ixx>
8
9 #include <Precision.hxx>
10
11 #include <TColStd_HArray1OfReal.hxx>
12 #include <TColStd_Array1OfReal.hxx>
13 #include <TColStd_Array1OfInteger.hxx>
14 #include <TColStd_SequenceOfReal.hxx>
15 #include <TColStd_ListOfInteger.hxx>
16 #include <TColStd_ListIteratorOfListOfInteger.hxx>
17 #include <TColStd_Array1OfListOfInteger.hxx>
18
19 #include <gp_Lin2d.hxx>
20 #include <gp_Ax22d.hxx>
21 #include <gp_Circ2d.hxx>
22 #include <gp_Torus.hxx>
23 #include <gp_Cylinder.hxx>
24
25 #include <Bnd_Box.hxx>
26
27 #include <TColgp_HArray1OfPnt2d.hxx>
28 #include <TColgp_SequenceOfPnt2d.hxx>
29 #include <TColgp_Array1OfPnt.hxx>
30 #include <TColgp_Array1OfPnt2d.hxx>
31
32 #include <IntAna_QuadQuadGeo.hxx>
33
34 #include <IntSurf_PntOn2S.hxx>
35 #include <IntSurf_LineOn2S.hxx>
36 #include <IntSurf_PntOn2S.hxx>
37 #include <IntSurf_ListOfPntOn2S.hxx>
38 #include <IntRes2d_Domain.hxx>
39 #include <ProjLib_Plane.hxx>
40
41 #include <IntPatch_GLine.hxx>
42 #include <IntPatch_RLine.hxx>
43 #include <IntPatch_WLine.hxx>
44 #include <IntPatch_ALine.hxx>
45 #include <IntPatch_ALineToWLine.hxx>
46
47 #include <ElSLib.hxx>
48 #include <ElCLib.hxx>
49
50 #include <Extrema_ExtCC.hxx>
51 #include <Extrema_POnCurv.hxx>
52 #include <BndLib_AddSurface.hxx>
53
54 #include <Adaptor3d_SurfacePtr.hxx>
55 #include <Adaptor2d_HLine2d.hxx>
56
57 #include <GeomAbs_SurfaceType.hxx>
58 #include <GeomAbs_CurveType.hxx>
59
60 #include <Geom_Surface.hxx>
61 #include <Geom_Line.hxx>
62 #include <Geom_Circle.hxx>
63 #include <Geom_Ellipse.hxx>
64 #include <Geom_Parabola.hxx>
65 #include <Geom_Hyperbola.hxx>
66 #include <Geom_TrimmedCurve.hxx>
67 #include <Geom_BSplineCurve.hxx>
68 #include <Geom_RectangularTrimmedSurface.hxx>
69 #include <Geom_OffsetSurface.hxx>
70 #include <Geom_Curve.hxx>
71 #include <Geom_Conic.hxx>
72
73 #include <Geom2d_TrimmedCurve.hxx>
74 #include <Geom2d_BSplineCurve.hxx>
75 #include <Geom2d_Line.hxx>
76 #include <Geom2d_Curve.hxx>
77 #include <Geom2d_Circle.hxx>
78
79 #include <Geom2dAPI_InterCurveCurve.hxx>
80 #include <Geom2dInt_GInter.hxx>
81 #include <GeomAdaptor_Curve.hxx>
82 #include <GeomAdaptor_HSurface.hxx>
83 #include <GeomAdaptor_Surface.hxx>
84 #include <GeomLib_CheckBSplineCurve.hxx>
85 #include <GeomLib_Check2dBSplineCurve.hxx>
86
87 #include <GeomInt_WLApprox.hxx>
88 #include <GeomProjLib.hxx>
89 #include <GeomAPI_ProjectPointOnSurf.hxx>
90 #include <Geom2dAdaptor_Curve.hxx>
91 //
92 #include <TopoDS.hxx>
93 #include <TopoDS_Edge.hxx>
94 #include <TopExp_Explorer.hxx>
95
96 #include <BRep_Tool.hxx>
97 #include <BRepTools.hxx>
98 #include <BRepAdaptor_Surface.hxx>
99
100 #include <BOPTColStd_Dump.hxx>
101
102 #include <IntTools_Curve.hxx>
103 #include <IntTools_Tools.hxx>
104 #include <IntTools_Tools.hxx>
105 #include <IntTools_TopolTool.hxx>
106 #include <IntTools_PntOnFace.hxx>
107 #include <IntTools_PntOn2Faces.hxx>
108 #include <IntTools_Context.hxx>
109
110 //
111 static
112   void TolR3d(const TopoDS_Face& ,
113               const TopoDS_Face& ,
114               Standard_Real& );
115 static 
116   Handle(Geom_Curve) MakeBSpline (const Handle(IntPatch_WLine)&,
117                                   const Standard_Integer,
118                                   const Standard_Integer);
119
120 static 
121   void Parameters(const Handle(GeomAdaptor_HSurface)&,
122                   const Handle(GeomAdaptor_HSurface)&,
123                   const gp_Pnt&,
124                   Standard_Real&,
125                   Standard_Real&,
126                   Standard_Real&,
127                   Standard_Real&);
128
129 static 
130   void BuildPCurves (Standard_Real f,Standard_Real l,Standard_Real& Tol,
131                      const Handle (Geom_Surface)& S,
132                      const Handle (Geom_Curve)&   C,
133                      Handle (Geom2d_Curve)& C2d);
134
135 static 
136   void CorrectSurfaceBoundaries(const TopoDS_Face&  theFace,
137                                 const Standard_Real theTolerance,
138                                 Standard_Real&      theumin,
139                                 Standard_Real&      theumax, 
140                                 Standard_Real&      thevmin, 
141                                 Standard_Real&      thevmax);
142 static
143   Standard_Boolean NotUseSurfacesForApprox
144           (const TopoDS_Face& aF1,
145            const TopoDS_Face& aF2,
146            const Handle(IntPatch_WLine)& WL,
147            const Standard_Integer ifprm,
148            const Standard_Integer ilprm);
149
150 static 
151   Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine)& theWLine);
152
153 static 
154   Standard_Real AdjustPeriodic(const Standard_Real theParameter,
155                                const Standard_Real parmin,
156                                const Standard_Real parmax,
157                                const Standard_Real thePeriod,
158                                Standard_Real&      theOffset);
159
160 static 
161   Handle(Geom2d_BSplineCurve) MakeBSpline2d(const Handle(IntPatch_WLine)& theWLine,
162                                             const Standard_Integer                         ideb,
163                                             const Standard_Integer                         ifin,
164                                             const Standard_Boolean                         onFirst);
165
166 static 
167   Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
168                                         const Handle(GeomAdaptor_HSurface)&            theSurface1, 
169                                         const Handle(GeomAdaptor_HSurface)&            theSurface2,
170                                         const TopoDS_Face&                             theFace1,
171                                         const TopoDS_Face&                             theFace2,
172                                         const IntTools_LineConstructor&                theLConstructor,
173                                         const Standard_Boolean                         theAvoidLConstructor,
174                                         IntPatch_SequenceOfLine&                       theNewLines,
175                                         Standard_Real&                                 theReachedTol3d);
176
177 static 
178   Standard_Boolean ParameterOutOfBoundary(const Standard_Real       theParameter, 
179                                           const Handle(Geom_Curve)& theCurve, 
180                                           const TopoDS_Face&        theFace1, 
181                                           const TopoDS_Face&        theFace2,
182                                           const Standard_Real       theOtherParameter,
183                                           const Standard_Boolean    bIncreasePar,
184                                           Standard_Real&            theNewParameter);
185
186 static 
187   Standard_Boolean IsCurveValid(Handle(Geom2d_Curve)& thePCurve);
188
189 static 
190   Standard_Boolean IsPointOnBoundary(const Standard_Real theParameter,
191                                      const Standard_Real theFirstBoundary,
192                                      const Standard_Real theSecondBoundary,
193                                      const Standard_Real theResolution,
194                                      Standard_Boolean&   IsOnFirstBoundary);
195 static
196   Standard_Boolean FindPoint(const gp_Pnt2d&     theFirstPoint,
197                              const gp_Pnt2d&     theLastPoint,
198                              const Standard_Real theUmin, 
199                              const Standard_Real theUmax,
200                              const Standard_Real theVmin,
201                              const Standard_Real theVmax,
202                              gp_Pnt2d&           theNewPoint);
203
204
205 static 
206   Standard_Integer ComputeTangentZones( const Handle(GeomAdaptor_HSurface)& theSurface1,
207                                        const Handle(GeomAdaptor_HSurface)&  theSurface2,
208                                        const TopoDS_Face&                   theFace1,
209                                        const TopoDS_Face&                   theFace2,
210                                        Handle(TColgp_HArray1OfPnt2d)&       theResultOnS1,
211                                        Handle(TColgp_HArray1OfPnt2d)&       theResultOnS2,
212                                        Handle(TColStd_HArray1OfReal)&       theResultRadius);
213
214 static
215   Standard_Boolean FindPoint(const gp_Pnt2d&     theFirstPoint,
216                              const gp_Pnt2d&     theLastPoint,
217                              const Standard_Real theUmin, 
218                              const Standard_Real theUmax,
219                              const Standard_Real theVmin,
220                              const Standard_Real theVmax,
221                              const gp_Pnt2d&     theTanZoneCenter,
222                              const Standard_Real theZoneRadius,
223                              Handle(GeomAdaptor_HSurface) theGASurface,
224                              gp_Pnt2d&           theNewPoint);
225
226 static
227   Standard_Boolean IsInsideTanZone(const gp_Pnt2d&     thePoint,
228                                    const gp_Pnt2d&     theTanZoneCenter,
229                                    const Standard_Real theZoneRadius,
230                                    Handle(GeomAdaptor_HSurface) theGASurface);
231
232 static
233 gp_Pnt2d AdjustByNeighbour(const gp_Pnt2d&     theaNeighbourPoint,
234                            const gp_Pnt2d&     theOriginalPoint,
235                            Handle(GeomAdaptor_HSurface) theGASurface);
236 static
237 Standard_Boolean  ApproxWithPCurves(const gp_Cylinder& theCyl, 
238                                     const gp_Sphere& theSph);
239
240 static void  PerformPlanes(const Handle(GeomAdaptor_HSurface)& theS1, 
241                            const Handle(GeomAdaptor_HSurface)& theS2, 
242                            const Standard_Real TolAng, 
243                            const Standard_Real TolTang, 
244                            const Standard_Boolean theApprox1,
245                            const Standard_Boolean theApprox2,
246                            IntTools_SequenceOfCurves& theSeqOfCurve, 
247                            Standard_Boolean& theTangentFaces);
248
249 static Standard_Boolean ClassifyLin2d(const Handle(GeomAdaptor_HSurface)& theS, 
250                                       const gp_Lin2d& theLin2d, 
251                                       const Standard_Real theTol,
252                                       Standard_Real& theP1, 
253                                       Standard_Real& theP2);
254
255 static
256   void ApproxParameters(const Handle(GeomAdaptor_HSurface)& aHS1,
257                         const Handle(GeomAdaptor_HSurface)& aHS2,
258                         Standard_Integer& iDegMin,
259                         Standard_Integer& iDegMax,
260                         //modified by NIZNHY-PKV Thu Sep 23 08:38:47 2010f
261                         Standard_Integer& iNbIterMax,
262                         Standard_Boolean& anWithPC
263                         //modified by NIZNHY-PKV Thu Sep 23 08:38:55 2010t
264                         );
265
266 //
267 //=======================================================================
268 //function : 
269 //purpose  : 
270 //=======================================================================
271   IntTools_FaceFace::IntTools_FaceFace()
272 {
273   myTangentFaces=Standard_False;
274   //
275   myHS1 = new GeomAdaptor_HSurface ();
276   myHS2 = new GeomAdaptor_HSurface ();
277   myTolReached2d=0.; 
278   myTolReached3d=0.;
279   SetParameters(Standard_True, Standard_True, Standard_True, 1.e-07);
280 }
281 //=======================================================================
282 //function : Face1
283 //purpose  : 
284 //======================================================================= 
285   const TopoDS_Face&  IntTools_FaceFace::Face1() const
286 {
287   return myFace1;
288 }
289
290 //=======================================================================
291 //function : Face2
292 //purpose  : 
293 //======================================================================= 
294   const TopoDS_Face&  IntTools_FaceFace::Face2() const
295 {
296   return myFace2;
297 }
298
299 //=======================================================================
300 //function : TangentFaces
301 //purpose  : 
302 //======================================================================= 
303   Standard_Boolean IntTools_FaceFace::TangentFaces() const
304 {
305   return myTangentFaces;
306 }
307 //=======================================================================
308 //function : Points
309 //purpose  : 
310 //======================================================================= 
311   const  IntTools_SequenceOfPntOn2Faces& IntTools_FaceFace::Points() const
312 {
313   return myPnts;
314 }
315 //=======================================================================
316 //function : IsDone
317 //purpose  : 
318 //======================================================================= 
319   Standard_Boolean IntTools_FaceFace::IsDone() const
320 {
321   return myIsDone;
322 }
323 //=======================================================================
324 //function : TolReached3d
325 //purpose  : 
326 //=======================================================================
327   Standard_Real IntTools_FaceFace::TolReached3d() const
328 {
329   return myTolReached3d;
330 }
331 //=======================================================================
332 //function : Lines
333 //purpose  : return lines of intersection
334 //=======================================================================
335   const IntTools_SequenceOfCurves& IntTools_FaceFace::Lines() const
336 {
337   StdFail_NotDone_Raise_if(!myIsDone,
338                            "IntTools_FaceFace::Lines() => !myIntersector.IsDone()");
339   return mySeqOfCurve;
340 }
341
342 //=======================================================================
343 //function : TolReached2d
344 //purpose  : 
345 //=======================================================================
346   Standard_Real IntTools_FaceFace::TolReached2d() const
347 {
348   return myTolReached2d;
349 }
350 // =======================================================================
351 // function: SetParameters
352 //
353 // =======================================================================
354   void IntTools_FaceFace::SetParameters(const Standard_Boolean ToApproxC3d,
355                                         const Standard_Boolean ToApproxC2dOnS1,
356                                         const Standard_Boolean ToApproxC2dOnS2,
357                                         const Standard_Real ApproximationTolerance) 
358 {
359   myApprox = ToApproxC3d;
360   myApprox1 = ToApproxC2dOnS1;
361   myApprox2 = ToApproxC2dOnS2;
362   myTolApprox = ApproximationTolerance;
363 }
364 //=======================================================================
365 //function : SetList
366 //purpose  : 
367 //=======================================================================
368
369 void IntTools_FaceFace::SetList(IntSurf_ListOfPntOn2S& aListOfPnts)
370 {
371   myListOfPnts = aListOfPnts;  
372 }
373 //=======================================================================
374 //function : Perform
375 //purpose  : intersect surfaces of the faces
376 //=======================================================================
377   void IntTools_FaceFace::Perform(const TopoDS_Face& F1,
378                                   const TopoDS_Face& F2)
379 {
380   Standard_Boolean hasCone, RestrictLine, bTwoPlanes;
381   Standard_Integer aNbLin, aNbPnts, i;
382   Standard_Real TolArc, TolTang, Deflection, UVMaxStep;
383   Standard_Real umin, umax, vmin, vmax;
384   Standard_Real aTolF1, aTolF2;
385   GeomAbs_SurfaceType aType1, aType2;
386   Handle(Geom_Surface) S1, S2;
387   Handle(IntTools_TopolTool) dom1, dom2;
388   //
389   myFace1= F1;
390   myFace2= F2;
391   mySeqOfCurve.Clear();
392   //
393   myTolReached2d=0.;
394   myTolReached3d=0.;
395   //
396   myIsDone = Standard_False;
397   //
398   S1 = BRep_Tool::Surface(F1);
399   S2 = BRep_Tool::Surface(F2);
400   aTolF1 = BRep_Tool::Tolerance(F1);
401   aTolF2 = BRep_Tool::Tolerance(F2);
402   //
403   TolArc= aTolF1 + aTolF2;
404   TolTang = TolArc;
405   //
406   myNbrestr=0;//?
407   // 
408   BRepAdaptor_Surface aBAS1(F1, Standard_False);
409   BRepAdaptor_Surface aBAS2(F2, Standard_False);
410   //
411   aType1=aBAS1.GetType();
412   aType2=aBAS2.GetType();
413   hasCone = Standard_False;
414   bTwoPlanes = Standard_False;
415
416   Standard_Integer NbLinPP = 0;
417   if(aType1==GeomAbs_Plane && aType2==GeomAbs_Plane){
418     bTwoPlanes = Standard_True;
419
420     BRepTools::UVBounds(F1, umin, umax, vmin, vmax);
421     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
422     //
423     BRepTools::UVBounds(F2, umin, umax, vmin, vmax);
424     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
425     Standard_Real TolAng = 1.e-8;
426     PerformPlanes(myHS1, myHS2, TolAng, TolTang, 
427                   myApprox1, myApprox2, 
428                   mySeqOfCurve, myTangentFaces);
429
430     myIsDone = Standard_True;
431
432     if(myTangentFaces) return;
433
434     NbLinPP = mySeqOfCurve.Length();
435     if(NbLinPP == 0) return;
436
437
438     Standard_Real aTolFMax;
439     //
440     myTolReached3d = 1.e-7;
441     //
442     aTolFMax=Max(aTolF1, aTolF2);
443     //
444     if (aTolFMax>myTolReached3d) {
445       myTolReached3d=aTolFMax;
446     }
447     myTolReached2d = myTolReached3d;
448
449     return;
450        
451   }
452   //
453   if (aType1==GeomAbs_Plane && 
454       (aType2==GeomAbs_Cylinder ||
455        aType2==GeomAbs_Cone ||
456        aType2==GeomAbs_Torus)) {
457     Standard_Real dU, dV;
458     // F1
459     BRepTools::UVBounds(F1, umin, umax, vmin, vmax);
460     dU=0.1*(umax-umin);
461     dV=0.1*(vmax-vmin);
462     umin=umin-dU;
463     umax=umax+dU;
464     vmin=vmin-dV;
465     vmax=vmax+dV;
466     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
467     // F2
468     BRepTools::UVBounds(F2, umin, umax, vmin, vmax);
469     CorrectSurfaceBoundaries(F2, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
470     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
471     //
472     if( aType2==GeomAbs_Cone ) { 
473       TolArc = 0.0001; 
474       //TolArc = TolTang = 0.0001; 
475       hasCone = Standard_True; 
476     }
477   }
478   //
479   else if ((aType1==GeomAbs_Cylinder||
480             aType1==GeomAbs_Cone ||
481             aType1==GeomAbs_Torus) && 
482            aType2==GeomAbs_Plane) {
483     Standard_Real dU, dV;
484     //F1
485     BRepTools::UVBounds(F1, umin, umax, vmin, vmax);
486     CorrectSurfaceBoundaries(F1, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
487     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
488     // F2
489     BRepTools::UVBounds(F2, umin, umax, vmin, vmax);
490     dU=0.1*(umax-umin);
491     dV=0.1*(vmax-vmin);
492     umin=umin-dU;
493     umax=umax+dU;
494     vmin=vmin-dV;
495     vmax=vmax+dV;
496     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
497     //
498     if( aType1==GeomAbs_Cone ) {
499       TolArc = 0.0001; 
500       //TolArc = TolTang = 0.0001; 
501       hasCone = Standard_True; 
502     }
503   }
504   
505   //
506   else {
507     BRepTools::UVBounds(F1, umin, umax, vmin, vmax);
508       //
509     CorrectSurfaceBoundaries(F1, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
510     // 
511     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
512     //
513     BRepTools::UVBounds(F2, umin, umax, vmin, vmax);
514     // 
515     CorrectSurfaceBoundaries(F2, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
516     //   
517     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
518   }
519   //
520   dom1 = new IntTools_TopolTool(myHS1);
521   dom2 = new IntTools_TopolTool(myHS2);
522   //
523   myLConstruct.Load(dom1, dom2, myHS1, myHS2);
524   //
525   Deflection = (hasCone) ? 0.085 : 0.1;
526   UVMaxStep  = 0.001;
527   //
528   myIntersector.SetTolerances(TolArc, TolTang, UVMaxStep, Deflection);
529   //
530   RestrictLine = Standard_False;
531   //
532   if((myHS1->IsUClosed() && !myHS1->IsUPeriodic()) || 
533      (myHS1->IsVClosed() && !myHS1->IsVPeriodic()) ||
534      (myHS2->IsUClosed() && !myHS2->IsUPeriodic()) || 
535      (myHS2->IsVClosed() && !myHS2->IsVPeriodic())) {
536     RestrictLine = Standard_True;
537   }
538   //
539   if(((aType1 != GeomAbs_BSplineSurface) &&
540       (aType1 != GeomAbs_BezierSurface)  &&
541       (aType1 != GeomAbs_OtherSurface))  &&
542      ((aType2 != GeomAbs_BSplineSurface) &&
543       (aType2 != GeomAbs_BezierSurface)  &&
544       (aType2 != GeomAbs_OtherSurface))) {
545     RestrictLine = Standard_True;
546     //
547     if ((aType1 == GeomAbs_Torus) ||
548         (aType2 == GeomAbs_Torus) ) {
549       myListOfPnts.Clear();
550     }
551   }
552   //
553   if(!RestrictLine) {
554     TopExp_Explorer aExp;
555     //
556     for(i = 0; (!RestrictLine) && (i < 2); i++) {
557       const TopoDS_Face& aF=(!i) ? myFace1 : myFace2;
558       aExp.Init(aF, TopAbs_EDGE);
559       for(; aExp.More(); aExp.Next()) {
560         const TopoDS_Edge& aE=TopoDS::Edge(aExp.Current());
561         //
562         if(BRep_Tool::Degenerated(aE)) {
563           RestrictLine = Standard_True;
564           break;
565         }
566       }
567     }
568   }
569   //
570   myIntersector.Perform(myHS1, dom1, myHS2, dom2, 
571                         TolArc, TolTang, 
572                         myListOfPnts, RestrictLine); 
573   //
574   myIsDone = myIntersector.IsDone();
575   if (myIsDone) {
576     myTangentFaces=myIntersector.TangentFaces();
577     if (myTangentFaces) {
578       return;
579     }
580     //
581     if(RestrictLine) {
582       myListOfPnts.Clear(); // to use LineConstructor
583     }
584     //
585     aNbLin = myIntersector.NbLines();
586     for (i=1; i<=aNbLin; ++i) {
587       MakeCurve(i, dom1, dom2);
588     }
589     //
590     ComputeTolReached3d();
591     //
592     Standard_Real U1,V1,U2,V2;
593     IntTools_PntOnFace aPntOnF1, aPntOnF2;
594     //
595     aNbPnts=myIntersector.NbPnts();
596     for (i=1; i<=aNbPnts; ++i) {
597       const IntSurf_PntOn2S& aISPnt=myIntersector.Point(i).PntOn2S();
598       const gp_Pnt& aPnt=aISPnt.Value();
599       aISPnt.Parameters(U1,V1,U2,V2);
600       
601       aPntOnF1.Init(myFace1, aPnt, U1,V1);
602       aPntOnF2.Init(myFace2, aPnt, U2,V2);
603
604       IntTools_PntOn2Faces aPntOn2Faces(aPntOnF1, aPntOnF2);
605       myPnts.Append(aPntOn2Faces);
606     }
607     //
608   }
609 }
610 //=======================================================================
611 //function :ComputeTolReached3d 
612 //purpose  : 
613 //=======================================================================
614   void IntTools_FaceFace::ComputeTolReached3d()
615 {
616   Standard_Integer aNbLin;
617   GeomAbs_SurfaceType aType1, aType2;
618   //
619   aNbLin=myIntersector.NbLines();
620   //
621   aType1=myHS1->Surface().GetType();
622   aType2=myHS2->Surface().GetType();
623   //
624   if (aNbLin==2 &&
625       aType1==GeomAbs_Cylinder &&
626       aType2==GeomAbs_Cylinder) {
627     Handle(IntPatch_Line) aIL1, aIL2;
628     IntPatch_IType aTL1, aTL2;
629     //
630     aIL1=myIntersector.Line(1);
631     aIL2=myIntersector.Line(2);
632     aTL1=aIL1->ArcType();
633     aTL2=aIL2->ArcType();
634     if (aTL1==IntPatch_Lin && aTL2==IntPatch_Lin) {
635       Standard_Real aD, aDTresh, dTol;
636       gp_Lin aL1, aL2;
637       //
638       dTol=1.e-8;
639       aDTresh=1.5e-6;
640       //
641       aL1=Handle(IntPatch_GLine)::DownCast(aIL1)->Line();
642       aL2=Handle(IntPatch_GLine)::DownCast(aIL2)->Line();
643       aD=aL1.Distance(aL2);
644       aD=0.5*aD;
645       if (aD<aDTresh) {
646         myTolReached3d=aD+dTol;
647       }
648     }
649   }
650   //PKV  904/G3 f
651   if (aType1==GeomAbs_Plane &&
652       aType2==GeomAbs_Plane) {
653     Standard_Real aTolF1, aTolF2, aTolFMax, aTolTresh;
654     //
655     aTolTresh=1.e-7;
656     //
657     aTolF1 = BRep_Tool::Tolerance(myFace1);
658     aTolF2 = BRep_Tool::Tolerance(myFace2);
659     aTolFMax=Max(aTolF1, aTolF2);
660     //
661     if (aTolFMax>aTolTresh) {
662       myTolReached3d=aTolFMax;
663     }
664   }
665   //PKV t
666
667   //IFV Bug OCC20297 
668   if((aType1 == GeomAbs_Cylinder && aType2 == GeomAbs_Plane) ||
669      (aType2 == GeomAbs_Cylinder && aType1 == GeomAbs_Plane)) {
670     if(aNbLin == 1) {
671       const Handle(IntPatch_Line)& aIL1 = myIntersector.Line(1);
672       if(aIL1->ArcType() == IntPatch_Circle) {
673         gp_Circ aCir = Handle(IntPatch_GLine)::DownCast(aIL1)->Circle();
674         gp_XYZ aCirDir = aCir.Axis().Direction().XYZ();
675         gp_XYZ aPlDir;
676         gp_Pln aPln;
677         if(aType1 == GeomAbs_Plane) {
678           aPln = myHS1->Surface().Plane();
679         }
680         else {
681           aPln = myHS2->Surface().Plane();
682         }
683         aPlDir = aPln.Axis().Direction().XYZ();
684         Standard_Real cs = aCirDir*aPlDir;
685         if(cs < 0.) aPlDir.Reverse();
686         Standard_Real eps = 1.e-14;
687         if(!aPlDir.IsEqual(aCirDir, eps)) {
688           Standard_Integer aNbP = 11;
689           Standard_Real dt = 2.*PI / (aNbP - 1), t;
690           for(t = 0.; t < 2.*PI; t += dt) {
691             Standard_Real d = aPln.Distance(ElCLib::Value(t, aCir)); 
692             if(myTolReached3d < d) myTolReached3d = d;
693           }
694           myTolReached3d *= 1.1;
695         }
696       } //aIL1->ArcType() == IntPatch_Circle
697     } //aNbLin == 1
698   } // aType1 == GeomAbs_Cylinder && aType2 == GeomAbs_Plane) ...
699   //End IFV Bug OCC20297
700 }
701 //=======================================================================
702 //function : MakeCurve
703 //purpose  : 
704 //=======================================================================
705   void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
706                                     const Handle(Adaptor3d_TopolTool)& dom1,
707                                     const Handle(Adaptor3d_TopolTool)& dom2) 
708 {
709   Standard_Boolean bDone, rejectSurface, reApprox, bAvoidLineConstructor;
710   Standard_Boolean ok;
711   Standard_Integer i, j, aNbParts;
712   Standard_Real fprm, lprm;
713   Standard_Real Tolpc;
714   Handle(IntPatch_Line) L;
715   IntPatch_IType typl;
716   Handle(Geom_Curve) newc;
717   //
718   const Standard_Real TOLCHECK   =0.0000001;
719   const Standard_Real TOLANGCHECK=0.1;
720   //
721   rejectSurface = Standard_False;
722   reApprox = Standard_False;
723  
724  reapprox:;
725   
726   Tolpc = myTolApprox;
727   bAvoidLineConstructor = Standard_False;
728   L = myIntersector.Line(Index);
729   typl = L->ArcType();
730   //
731   if(typl==IntPatch_Walking) {
732     Handle(IntPatch_Line) anewL;
733     //
734     const Handle(IntPatch_WLine)& aWLine=
735       Handle(IntPatch_WLine)::DownCast(L);
736     //
737     anewL = ComputePurgedWLine(aWLine);
738     if(anewL.IsNull()) {
739       return;
740     }
741     L = anewL;
742     //
743     if(!myListOfPnts.IsEmpty()) {
744       bAvoidLineConstructor = Standard_True;
745     }
746
747     Standard_Integer nbp = aWLine->NbPnts();
748     const IntSurf_PntOn2S& p1 = aWLine->Point(1);
749     const IntSurf_PntOn2S& p2 = aWLine->Point(nbp);
750
751     const gp_Pnt& P1 = p1.Value();
752     const gp_Pnt& P2 = p2.Value();
753
754     if(P1.SquareDistance(P2) < 1.e-14) {
755       bAvoidLineConstructor = Standard_False;
756     }
757
758   }
759   //
760   // Line Constructor
761   if(!bAvoidLineConstructor) {
762     myLConstruct.Perform(L);
763     //
764     bDone=myLConstruct.IsDone();
765     aNbParts=myLConstruct.NbParts();
766     if (!bDone|| !aNbParts) {
767       return;
768     }
769   }
770   // Do the Curve
771   
772   
773   typl=L->ArcType();
774   switch (typl) {
775   //########################################  
776   // Line, Parabola, Hyperbola
777   //########################################  
778   case IntPatch_Lin:
779   case IntPatch_Parabola: 
780   case IntPatch_Hyperbola: {
781     if (typl == IntPatch_Lin) {
782       newc = 
783         new Geom_Line (Handle(IntPatch_GLine)::DownCast(L)->Line());
784     }
785
786     else if (typl == IntPatch_Parabola) {
787       newc = 
788         new Geom_Parabola(Handle(IntPatch_GLine)::DownCast(L)->Parabola());
789     }
790     
791     else if (typl == IntPatch_Hyperbola) {
792       newc = 
793         new Geom_Hyperbola (Handle(IntPatch_GLine)::DownCast(L)->Hyperbola());
794     }
795     //
796     // myTolReached3d
797     if (typl == IntPatch_Lin) {
798       TolR3d (myFace1, myFace2, myTolReached3d);
799     }
800     //
801     aNbParts=myLConstruct.NbParts();
802     for (i=1; i<=aNbParts; i++) {
803       myLConstruct.Part(i, fprm, lprm);
804       
805       if (!Precision::IsNegativeInfinite(fprm) && 
806           !Precision::IsPositiveInfinite(lprm)) {
807         //
808         IntTools_Curve aCurve;
809         //
810         Handle(Geom_TrimmedCurve) aCT3D=new Geom_TrimmedCurve(newc, fprm, lprm);
811         aCurve.SetCurve(aCT3D);
812         if (typl == IntPatch_Parabola) {
813           Standard_Real aTolF1, aTolF2, aTolBase;
814           
815           aTolF1 = BRep_Tool::Tolerance(myFace1);
816           aTolF2 = BRep_Tool::Tolerance(myFace2);
817           aTolBase=aTolF1+aTolF2;
818           myTolReached3d=IntTools_Tools::CurveTolerance(aCT3D, aTolBase);
819         }
820         //
821         aCurve.SetCurve(new Geom_TrimmedCurve(newc, fprm, lprm));
822         if(myApprox1) { 
823           Handle (Geom2d_Curve) C2d;
824           BuildPCurves(fprm, lprm, Tolpc, myHS1->ChangeSurface().Surface(), newc, C2d);
825           if(Tolpc>myTolReached2d || myTolReached2d==0.) { 
826             myTolReached2d=Tolpc;
827           }
828             //     
829             aCurve.SetFirstCurve2d(new Geom2d_TrimmedCurve(C2d,fprm,lprm));
830           }
831           else { 
832             Handle(Geom2d_BSplineCurve) H1;
833             //
834             aCurve.SetFirstCurve2d(H1);
835           }
836         
837         if(myApprox2) { 
838           Handle (Geom2d_Curve) C2d;
839           BuildPCurves(fprm,lprm,Tolpc,myHS2->ChangeSurface().Surface(),newc,C2d);
840           if(Tolpc>myTolReached2d || myTolReached2d==0.) { 
841             myTolReached2d=Tolpc;
842           }
843           //
844           aCurve.SetSecondCurve2d(new Geom2d_TrimmedCurve(C2d,fprm,lprm));
845           }
846         else { 
847           Handle(Geom2d_BSplineCurve) H1;
848           //
849           aCurve.SetSecondCurve2d(H1);
850         }
851         mySeqOfCurve.Append(aCurve);
852       } // end of if (!Precision::IsNegativeInfinite(fprm) &&  !Precision::IsPositiveInfinite(lprm))
853
854       else {
855         //  on regarde si on garde
856         //
857         Standard_Boolean bFNIt, bLPIt;
858         Standard_Real aTestPrm, dT=100.;
859
860         bFNIt=Precision::IsNegativeInfinite(fprm);
861         bLPIt=Precision::IsPositiveInfinite(lprm);
862         
863         aTestPrm=0.;
864         
865         if (bFNIt && !bLPIt) {
866           aTestPrm=lprm-dT;
867         }
868         else if (!bFNIt && bLPIt) {
869           aTestPrm=fprm+dT;
870         }
871         
872         gp_Pnt ptref(newc->Value(aTestPrm));
873         //
874
875         Standard_Real u1, v1, u2, v2, Tol;
876         
877         Tol = Precision::Confusion();
878         Parameters(myHS1, myHS2, ptref,  u1, v1, u2, v2);
879         ok = (dom1->Classify(gp_Pnt2d(u1, v1), Tol) != TopAbs_OUT);
880         if(ok) { 
881           ok = (dom2->Classify(gp_Pnt2d(u2,v2),Tol) != TopAbs_OUT); 
882         }
883         if (ok) {
884           Handle(Geom2d_BSplineCurve) H1;
885           mySeqOfCurve.Append(IntTools_Curve(newc, H1, H1));
886         }
887       }
888     }// end of for (i=1; i<=myLConstruct.NbParts(); i++)
889   }// case IntPatch_Lin:  case IntPatch_Parabola:  case IntPatch_Hyperbola:
890     break;
891
892   //########################################  
893   // Circle and Ellipse
894   //########################################  
895   case IntPatch_Circle: 
896   case IntPatch_Ellipse: {
897
898     if (typl == IntPatch_Circle) {
899       newc = new Geom_Circle
900         (Handle(IntPatch_GLine)::DownCast(L)->Circle());
901     }
902     else { //IntPatch_Ellipse
903       newc = new Geom_Ellipse
904         (Handle(IntPatch_GLine)::DownCast(L)->Ellipse());
905     }
906     //
907     // myTolReached3d
908     TolR3d (myFace1, myFace2, myTolReached3d);
909     //
910     aNbParts=myLConstruct.NbParts();
911     //
912     Standard_Real aPeriod, aNul;
913     TColStd_SequenceOfReal aSeqFprm,  aSeqLprm;
914     
915     aNul=0.;
916     aPeriod=PI+PI;
917
918     for (i=1; i<=aNbParts; i++) {
919       myLConstruct.Part(i, fprm, lprm);
920
921       if (fprm < aNul && lprm > aNul) {
922         // interval that goes through 0. is divided on two intervals;
923         while (fprm<aNul || fprm>aPeriod) fprm=fprm+aPeriod;
924         while (lprm<aNul || lprm>aPeriod) lprm=lprm+aPeriod;
925         //
926         if((aPeriod - fprm) > Tolpc) {
927           aSeqFprm.Append(fprm);
928           aSeqLprm.Append(aPeriod);
929         }
930         else {
931           gp_Pnt P1 = newc->Value(fprm);
932           gp_Pnt P2 = newc->Value(aPeriod);
933           Standard_Real aTolDist = BRep_Tool::Tolerance(myFace1) + BRep_Tool::Tolerance(myFace2);
934           aTolDist = (myTolReached3d > aTolDist) ? myTolReached3d : aTolDist;
935
936           if(P1.Distance(P2) > aTolDist) {
937             Standard_Real anewpar = fprm;
938
939             if(ParameterOutOfBoundary(fprm, newc, myFace1, myFace2, lprm, Standard_False, anewpar)) {
940               fprm = anewpar;
941             }
942             aSeqFprm.Append(fprm);
943             aSeqLprm.Append(aPeriod);
944           }
945         }
946
947         //
948         if((lprm - aNul) > Tolpc) {
949           aSeqFprm.Append(aNul);
950           aSeqLprm.Append(lprm);
951         }
952         else {
953           gp_Pnt P1 = newc->Value(aNul);
954           gp_Pnt P2 = newc->Value(lprm);
955           Standard_Real aTolDist = BRep_Tool::Tolerance(myFace1) + BRep_Tool::Tolerance(myFace2);
956           aTolDist = (myTolReached3d > aTolDist) ? myTolReached3d : aTolDist;
957
958           if(P1.Distance(P2) > aTolDist) {
959             Standard_Real anewpar = lprm;
960
961             if(ParameterOutOfBoundary(lprm, newc, myFace1, myFace2, fprm, Standard_True, anewpar)) {
962               lprm = anewpar;
963             }
964             aSeqFprm.Append(aNul);
965             aSeqLprm.Append(lprm);
966           }
967         }
968       }
969       else {
970         // usual interval 
971         aSeqFprm.Append(fprm);
972         aSeqLprm.Append(lprm);
973       }
974     }
975     
976     //
977     aNbParts=aSeqFprm.Length();
978     for (i=1; i<=aNbParts; i++) {
979       fprm=aSeqFprm(i);
980       lprm=aSeqLprm(i);
981       //
982       Standard_Real aRealEpsilon=RealEpsilon();
983       if (Abs(fprm) > aRealEpsilon || Abs(lprm-2.*PI) > aRealEpsilon) {
984         //==============================================
985         ////
986         IntTools_Curve aCurve;
987         Handle(Geom_TrimmedCurve) aTC3D=new Geom_TrimmedCurve(newc,fprm,lprm);
988         aCurve.SetCurve(aTC3D);
989         fprm=aTC3D->FirstParameter();
990         lprm=aTC3D->LastParameter ();
991         ////    
992         if (typl == IntPatch_Circle || typl == IntPatch_Ellipse) {//// 
993           if(myApprox1) { 
994             Handle (Geom2d_Curve) C2d;
995             BuildPCurves(fprm,lprm,Tolpc,myHS1->ChangeSurface().Surface(),newc,C2d);
996             if(Tolpc>myTolReached2d || myTolReached2d==0) { 
997               myTolReached2d=Tolpc;
998             }
999             //
1000             aCurve.SetFirstCurve2d(C2d);
1001           }
1002           else { //// 
1003             Handle(Geom2d_BSplineCurve) H1;
1004             aCurve.SetFirstCurve2d(H1);
1005           }
1006
1007
1008           if(myApprox2) { 
1009             Handle (Geom2d_Curve) C2d;
1010             BuildPCurves(fprm,lprm,Tolpc,myHS2->ChangeSurface().Surface(),newc,C2d);
1011             if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1012               myTolReached2d=Tolpc;
1013             }
1014             //
1015             aCurve.SetSecondCurve2d(C2d);
1016           }
1017           else { 
1018             Handle(Geom2d_BSplineCurve) H1;
1019             aCurve.SetSecondCurve2d(H1);
1020           }
1021         }
1022         
1023         else { 
1024           Handle(Geom2d_BSplineCurve) H1;
1025           aCurve.SetFirstCurve2d(H1);
1026           aCurve.SetSecondCurve2d(H1);
1027         }
1028         mySeqOfCurve.Append(aCurve);
1029           //==============================================      
1030       } //if (Abs(fprm) > RealEpsilon() || Abs(lprm-2.*PI) > RealEpsilon())
1031
1032       else {
1033         //  on regarde si on garde
1034         //
1035         if (aNbParts==1) {
1036 //        if (Abs(fprm) < RealEpsilon() &&  Abs(lprm-2.*PI) < RealEpsilon()) {
1037           if (Abs(fprm) <= aRealEpsilon && Abs(lprm-2.*PI) <= aRealEpsilon) {
1038             IntTools_Curve aCurve;
1039             Handle(Geom_TrimmedCurve) aTC3D=new Geom_TrimmedCurve(newc,fprm,lprm);
1040             aCurve.SetCurve(aTC3D);
1041             fprm=aTC3D->FirstParameter();
1042             lprm=aTC3D->LastParameter ();
1043             
1044             if(myApprox1) { 
1045               Handle (Geom2d_Curve) C2d;
1046               BuildPCurves(fprm,lprm,Tolpc,myHS1->ChangeSurface().Surface(),newc,C2d);
1047               if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1048                 myTolReached2d=Tolpc;
1049               }
1050               //
1051               aCurve.SetFirstCurve2d(C2d);
1052             }
1053             else { //// 
1054               Handle(Geom2d_BSplineCurve) H1;
1055               aCurve.SetFirstCurve2d(H1);
1056             }
1057
1058             if(myApprox2) { 
1059               Handle (Geom2d_Curve) C2d;
1060               BuildPCurves(fprm,lprm,Tolpc,myHS2->ChangeSurface().Surface(),newc,C2d);
1061               if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1062                 myTolReached2d=Tolpc;
1063               }
1064               //
1065               aCurve.SetSecondCurve2d(C2d);
1066             }
1067             else { 
1068               Handle(Geom2d_BSplineCurve) H1;
1069               aCurve.SetSecondCurve2d(H1);
1070             }
1071             mySeqOfCurve.Append(aCurve);
1072             break;
1073           }
1074         }
1075         //
1076         Standard_Real aTwoPIdiv17, u1, v1, u2, v2, Tol;
1077
1078         aTwoPIdiv17=2.*PI/17.;
1079
1080         for (j=0; j<=17; j++) {
1081           gp_Pnt ptref (newc->Value (j*aTwoPIdiv17));
1082           Tol = Precision::Confusion();
1083
1084           Parameters(myHS1, myHS2, ptref, u1, v1, u2, v2);
1085           ok = (dom1->Classify(gp_Pnt2d(u1,v1),Tol) != TopAbs_OUT);
1086           if(ok) { 
1087             ok = (dom2->Classify(gp_Pnt2d(u2,v2),Tol) != TopAbs_OUT);
1088           }
1089           if (ok) {
1090             IntTools_Curve aCurve;
1091             aCurve.SetCurve(newc);
1092             //==============================================
1093             if (typl == IntPatch_Circle || typl == IntPatch_Ellipse) {
1094               
1095               if(myApprox1) { 
1096                 Handle (Geom2d_Curve) C2d;
1097                 BuildPCurves(fprm, lprm, Tolpc, myHS1->ChangeSurface().Surface(), newc, C2d);
1098                 if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1099                   myTolReached2d=Tolpc;
1100                 }
1101                 // 
1102                 aCurve.SetFirstCurve2d(C2d);
1103               }
1104               else { 
1105                 Handle(Geom2d_BSplineCurve) H1;
1106                 aCurve.SetFirstCurve2d(H1);
1107               }
1108                 
1109               if(myApprox2) { 
1110                 Handle (Geom2d_Curve) C2d;
1111                 BuildPCurves(fprm, lprm, Tolpc,myHS2->ChangeSurface().Surface(), newc, C2d);
1112                 if(Tolpc>myTolReached2d || myTolReached2d==0) { 
1113                   myTolReached2d=Tolpc;
1114                 }
1115                 //              
1116                 aCurve.SetSecondCurve2d(C2d);
1117               }
1118                 
1119               else { 
1120                 Handle(Geom2d_BSplineCurve) H1;
1121                 aCurve.SetSecondCurve2d(H1);
1122               }
1123             }//  end of if (typl == IntPatch_Circle || typl == IntPatch_Ellipse)
1124              
1125             else { 
1126               Handle(Geom2d_BSplineCurve) H1;
1127               //        
1128               aCurve.SetFirstCurve2d(H1);
1129               aCurve.SetSecondCurve2d(H1);
1130             }
1131             //==============================================    
1132             //
1133             mySeqOfCurve.Append(aCurve);
1134             break;
1135
1136             }//  end of if (ok) {
1137           }//  end of for (Standard_Integer j=0; j<=17; j++)
1138         }//  end of else { on regarde si on garde
1139       }// for (i=1; i<=myLConstruct.NbParts(); i++)
1140     }// IntPatch_Circle: IntPatch_Ellipse:
1141     break;
1142     
1143   case IntPatch_Analytic: {
1144     IntSurf_Quadric quad1,quad2;
1145     GeomAbs_SurfaceType typs = myHS1->Surface().GetType();
1146     
1147     switch (typs) {
1148       case GeomAbs_Plane:
1149         quad1.SetValue(myHS1->Surface().Plane());
1150         break;
1151       case GeomAbs_Cylinder:
1152         quad1.SetValue(myHS1->Surface().Cylinder());
1153         break;
1154       case GeomAbs_Cone:
1155         quad1.SetValue(myHS1->Surface().Cone());
1156         break;
1157       case GeomAbs_Sphere:
1158         quad1.SetValue(myHS1->Surface().Sphere());
1159         break;
1160       default:
1161         Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve 1");
1162       }
1163       
1164     typs = myHS2->Surface().GetType();
1165     
1166     switch (typs) {
1167       case GeomAbs_Plane:
1168         quad2.SetValue(myHS2->Surface().Plane());
1169         break;
1170       case GeomAbs_Cylinder:
1171         quad2.SetValue(myHS2->Surface().Cylinder());
1172         break;
1173       case GeomAbs_Cone:
1174         quad2.SetValue(myHS2->Surface().Cone());
1175         break;
1176       case GeomAbs_Sphere:
1177         quad2.SetValue(myHS2->Surface().Sphere());
1178         break;
1179       default:
1180         Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve 2");
1181       }
1182     //
1183     //=========
1184     IntPatch_ALineToWLine convert (quad1, quad2);
1185       
1186     if (!myApprox) {
1187       aNbParts=myLConstruct.NbParts();
1188       for (i=1; i<=aNbParts; i++) {
1189         myLConstruct.Part(i, fprm, lprm);
1190         Handle(IntPatch_WLine) WL = 
1191           convert.MakeWLine(Handle(IntPatch_ALine)::DownCast(L), fprm, lprm);
1192         //
1193         Handle(Geom2d_BSplineCurve) H1;
1194         Handle(Geom2d_BSplineCurve) H2;
1195
1196         if(myApprox1) {
1197           H1 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True);
1198         }
1199         
1200         if(myApprox2) {
1201           H2 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False);
1202         }
1203         //       
1204         mySeqOfCurve.Append(IntTools_Curve(MakeBSpline(WL,1,WL->NbPnts()), H1, H2));
1205       }
1206     } // if (!myApprox)
1207
1208     else { // myApprox=TRUE
1209       GeomInt_WLApprox theapp3d;
1210       // 
1211       Standard_Real tol2d = myTolApprox;
1212       //        
1213       theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_True);
1214       
1215       aNbParts=myLConstruct.NbParts();
1216       for (i=1; i<=aNbParts; i++) {
1217         myLConstruct.Part(i, fprm, lprm);
1218         Handle(IntPatch_WLine) WL = 
1219           convert.MakeWLine(Handle(IntPatch_ALine):: DownCast(L),fprm,lprm);
1220
1221         theapp3d.Perform(myHS1,myHS2,WL,Standard_True,myApprox1,myApprox2, 1, WL->NbPnts());
1222
1223         if (!theapp3d.IsDone()) {
1224           //
1225           Handle(Geom2d_BSplineCurve) H1;
1226           Handle(Geom2d_BSplineCurve) H2;
1227
1228           if(myApprox1) {
1229             H1 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True);
1230           }
1231           
1232           if(myApprox2) {
1233             H2 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False);
1234           }
1235           //     
1236           mySeqOfCurve.Append(IntTools_Curve(MakeBSpline(WL,1,WL->NbPnts()), H1, H2));
1237         }
1238
1239         else {
1240           if(myApprox1 || myApprox2) { 
1241             if( theapp3d.TolReached2d()>myTolReached2d || myTolReached2d==0) { 
1242               myTolReached2d = theapp3d.TolReached2d();
1243             }
1244           }
1245           
1246           if( theapp3d.TolReached3d()>myTolReached3d || myTolReached3d==0) { 
1247             myTolReached3d = theapp3d.TolReached3d();
1248           }
1249
1250           Standard_Integer aNbMultiCurves, nbpoles;
1251           aNbMultiCurves=theapp3d.NbMultiCurves();
1252           for (j=1; j<=aNbMultiCurves; j++) {
1253             const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
1254             nbpoles = mbspc.NbPoles();
1255             
1256             TColgp_Array1OfPnt tpoles(1, nbpoles);
1257             mbspc.Curve(1, tpoles);
1258             Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles,
1259                                                                mbspc.Knots(),
1260                                                                mbspc.Multiplicities(),
1261                                                                mbspc.Degree());
1262             
1263             GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK);
1264             Check.FixTangent(Standard_True,Standard_True);
1265             // 
1266             IntTools_Curve aCurve;
1267             aCurve.SetCurve(BS);
1268             
1269             if(myApprox1) { 
1270               TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
1271               mbspc.Curve(2,tpoles2d);
1272               Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d,
1273                                                                       mbspc.Knots(),
1274                                                                       mbspc.Multiplicities(),
1275                                                                       mbspc.Degree());
1276
1277               GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK);
1278               newCheck.FixTangent(Standard_True,Standard_True);
1279               //                
1280               aCurve.SetFirstCurve2d(BS2);
1281             }
1282             else {
1283               Handle(Geom2d_BSplineCurve) H1;
1284               aCurve.SetFirstCurve2d(H1);
1285             }
1286             
1287             if(myApprox2) { 
1288               TColgp_Array1OfPnt2d tpoles2d(1, nbpoles);
1289               Standard_Integer TwoOrThree;
1290               TwoOrThree=myApprox1 ? 3 : 2;
1291               mbspc.Curve(TwoOrThree, tpoles2d);
1292               Handle(Geom2d_BSplineCurve) BS2 =new Geom2d_BSplineCurve(tpoles2d,
1293                                                                        mbspc.Knots(),
1294                                                                        mbspc.Multiplicities(),
1295                                                                        mbspc.Degree());
1296                 
1297               GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK);
1298               newCheck.FixTangent(Standard_True,Standard_True);
1299               //        
1300               aCurve.SetSecondCurve2d(BS2);
1301             }
1302             else { 
1303               Handle(Geom2d_BSplineCurve) H2;
1304               aCurve.SetSecondCurve2d(H2);
1305             }
1306             // 
1307             mySeqOfCurve.Append(aCurve);
1308
1309           }// for (j=1; j<=aNbMultiCurves; j++) {
1310         }// else from if (!theapp3d.IsDone())
1311       }// for (i=1; i<=aNbParts; i++) {
1312     }// else { // myApprox=TRUE
1313   }// case IntPatch_Analytic:
1314     break;
1315
1316   case IntPatch_Walking:{
1317     Handle(IntPatch_WLine) WL = 
1318       Handle(IntPatch_WLine)::DownCast(L);
1319     //
1320     Standard_Integer ifprm, ilprm;
1321     //
1322     if (!myApprox) {
1323       aNbParts = 1;
1324       if(!bAvoidLineConstructor){
1325         aNbParts=myLConstruct.NbParts();
1326       }
1327       for (i=1; i<=aNbParts; ++i) {
1328         Handle(Geom2d_BSplineCurve) H1, H2;
1329         Handle(Geom_Curve) aBSp;
1330         //
1331         if(bAvoidLineConstructor) {
1332           ifprm = 1;
1333           ilprm = WL->NbPnts();
1334         }
1335         else {
1336           myLConstruct.Part(i, fprm, lprm);
1337           ifprm=(Standard_Integer)fprm;
1338           ilprm=(Standard_Integer)lprm;
1339         }
1340         //
1341         if(myApprox1) {
1342           H1 = MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
1343         }
1344         //
1345         if(myApprox2) {
1346           H2 = MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
1347         }
1348         //        
1349         aBSp=MakeBSpline(WL, ifprm, ilprm);
1350         IntTools_Curve aIC(aBSp, H1, H2);
1351         mySeqOfCurve.Append(aIC);
1352       }// for (i=1; i<=aNbParts; ++i) {
1353     }// if (!myApprox) {
1354     //
1355     else { // X
1356       Standard_Boolean bIsDecomposited;
1357       Standard_Integer nbiter, aNbSeqOfL;
1358       Standard_Real tol2d;
1359       IntPatch_SequenceOfLine aSeqOfL;
1360       GeomInt_WLApprox theapp3d;
1361       Approx_ParametrizationType aParType = Approx_ChordLength;
1362       //
1363       Standard_Boolean anApprox1 = myApprox1;
1364       Standard_Boolean anApprox2 = myApprox2;
1365
1366       tol2d = myTolApprox;
1367
1368       GeomAbs_SurfaceType typs1, typs2;
1369       typs1 = myHS1->Surface().GetType();
1370       typs2 = myHS2->Surface().GetType();
1371       Standard_Boolean anWithPC = Standard_True;
1372
1373       if(typs1 == GeomAbs_Cylinder && typs2 == GeomAbs_Sphere) {
1374         anWithPC = 
1375           ApproxWithPCurves(myHS1->Surface().Cylinder(), myHS2->Surface().Sphere());
1376       }
1377       else if (typs1 == GeomAbs_Sphere && typs2 == GeomAbs_Cylinder) {
1378         anWithPC = 
1379           ApproxWithPCurves(myHS2->Surface().Cylinder(), myHS1->Surface().Sphere());
1380       }
1381       if(!anWithPC) {
1382         //aParType = Approx_Centripetal; 
1383         myTolApprox = 1.e-5; 
1384         anApprox1 = Standard_False;
1385         anApprox2 = Standard_False;
1386         //      
1387         tol2d = myTolApprox;
1388       }
1389         
1390       if(myHS1 == myHS2) { 
1391         //
1392         theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False, aParType);
1393         rejectSurface = Standard_True;
1394       }
1395       else { 
1396         if(reApprox && !rejectSurface)
1397           theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False, aParType);
1398         else {
1399           //modified by NIZNHY-PKV Thu Sep 23 08:34:09 2010f
1400           Standard_Integer iDegMax, iDegMin, iNbIterMax;
1401           //
1402           ApproxParameters(myHS1, myHS2, iDegMin, iDegMax, iNbIterMax, anWithPC);
1403           if(!anWithPC) {
1404             //myTolApprox = 1.e-5; 
1405             anApprox1 = Standard_False;
1406             anApprox2 = Standard_False;
1407             tol2d = myTolApprox;
1408           }
1409           //
1410           theapp3d.SetParameters(myTolApprox, tol2d, iDegMin, iDegMax, iNbIterMax,
1411                                  Standard_True, aParType);
1412           //theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_True, aParType);
1413           //modified by NIZNHY-PKV Thu Sep 23 08:36:17 2010t
1414         }
1415       }
1416       //
1417       Standard_Real aReachedTol = Precision::Confusion();
1418       bIsDecomposited=DecompositionOfWLine(WL,
1419                                            myHS1, 
1420                                            myHS2, 
1421                                            myFace1, 
1422                                            myFace2, 
1423                                            myLConstruct, 
1424                                            bAvoidLineConstructor, 
1425                                            aSeqOfL, 
1426                                            aReachedTol);
1427       if ( bIsDecomposited && ( myTolReached3d < aReachedTol ) )
1428         myTolReached3d = aReachedTol;
1429
1430       //
1431       aNbSeqOfL=aSeqOfL.Length();
1432       //
1433       if (bIsDecomposited) {
1434         nbiter=aNbSeqOfL;
1435       }
1436       else {
1437         nbiter=1;
1438         aNbParts=1;
1439         if (!bAvoidLineConstructor) {
1440           aNbParts=myLConstruct.NbParts();
1441           nbiter=aNbParts;
1442         }
1443       }
1444       //
1445       // nbiter=(bIsDecomposited) ? aSeqOfL.Length() :
1446       //   ((bAvoidLineConstructor) ? 1 :aNbParts);
1447       //
1448       for(i = 1; i <= nbiter; ++i) {
1449         if(bIsDecomposited) {
1450           WL = Handle(IntPatch_WLine)::DownCast(aSeqOfL.Value(i));
1451           ifprm = 1;
1452           ilprm = WL->NbPnts();
1453         }
1454         else {
1455           if(bAvoidLineConstructor) {
1456             ifprm = 1;
1457             ilprm = WL->NbPnts();
1458           }
1459           else {
1460             myLConstruct.Part(i, fprm, lprm);
1461             ifprm = (Standard_Integer)fprm;
1462             ilprm = (Standard_Integer)lprm;
1463           }
1464         }
1465         //-- lbr : 
1466         //-- Si une des surfaces est un plan , on approxime en 2d
1467         //-- sur cette surface et on remonte les points 2d en 3d.
1468         if(typs1 == GeomAbs_Plane) { 
1469           theapp3d.Perform(myHS1, myHS2, WL, Standard_False,Standard_True, myApprox2,ifprm,ilprm);
1470         }         
1471         else if(typs2 == GeomAbs_Plane) { 
1472           theapp3d.Perform(myHS1,myHS2,WL,Standard_False,myApprox1,Standard_True,ifprm,ilprm);
1473         }
1474         else { 
1475           //
1476           if (myHS1 != myHS2){
1477             if ((typs1==GeomAbs_BezierSurface || typs1==GeomAbs_BSplineSurface) &&
1478                 (typs2==GeomAbs_BezierSurface || typs2==GeomAbs_BSplineSurface)) {
1479              
1480               theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_True, aParType);
1481               
1482               Standard_Boolean bUseSurfaces;
1483               bUseSurfaces=NotUseSurfacesForApprox(myFace1, myFace2, WL, ifprm,  ilprm);
1484               if (bUseSurfaces) {
1485                 // ######
1486                 rejectSurface = Standard_True;
1487                 // ######
1488                 theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False, aParType);
1489               }
1490             }
1491           }
1492           //
1493           theapp3d.Perform(myHS1,myHS2,WL,Standard_True,anApprox1,anApprox2,ifprm,ilprm);
1494         }
1495          
1496         if (!theapp3d.IsDone()) {
1497           //      
1498           Handle(Geom2d_BSplineCurve) H1;
1499           //      
1500           Handle(Geom_Curve) aBSp=MakeBSpline(WL,ifprm, ilprm);
1501           Handle(Geom2d_BSplineCurve) H2;
1502
1503           if(myApprox1) {
1504             H1 = MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
1505           }
1506           
1507           if(myApprox2) {
1508             H2 = MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
1509           }
1510           //      
1511           IntTools_Curve aIC(aBSp, H1, H2);
1512           mySeqOfCurve.Append(aIC);
1513         }
1514         
1515         else {
1516           if(myApprox1 || myApprox2 || (typs1==GeomAbs_Plane || typs2==GeomAbs_Plane)) { 
1517             if( theapp3d.TolReached2d()>myTolReached2d || myTolReached2d==0.) { 
1518               myTolReached2d = theapp3d.TolReached2d();
1519             }
1520           }
1521           if(typs1==GeomAbs_Plane || typs2==GeomAbs_Plane) { 
1522             myTolReached3d = myTolReached2d;
1523             //
1524             if (typs1==GeomAbs_Torus || typs2==GeomAbs_Torus) {
1525               if (myTolReached3d<1.e-6) {
1526                 myTolReached3d = theapp3d.TolReached3d();
1527                 myTolReached3d=1.e-6;
1528               }
1529             }
1530             //
1531           }
1532           else  if( theapp3d.TolReached3d()>myTolReached3d || myTolReached3d==0.) { 
1533             myTolReached3d = theapp3d.TolReached3d();
1534           }
1535           
1536           Standard_Integer aNbMultiCurves, nbpoles;
1537           aNbMultiCurves=theapp3d.NbMultiCurves(); 
1538           for (j=1; j<=aNbMultiCurves; j++) {
1539             if(typs1 == GeomAbs_Plane) {
1540               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
1541               nbpoles = mbspc.NbPoles();
1542               
1543               TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
1544               TColgp_Array1OfPnt   tpoles(1,nbpoles);
1545               
1546               mbspc.Curve(1,tpoles2d);
1547               const gp_Pln&  Pln = myHS1->Surface().Plane();
1548               //
1549               Standard_Integer ik; 
1550               for(ik = 1; ik<= nbpoles; ik++) { 
1551                 tpoles.SetValue(ik,
1552                                 ElSLib::Value(tpoles2d.Value(ik).X(),
1553                                               tpoles2d.Value(ik).Y(),
1554                                               Pln));
1555               }
1556               //
1557               Handle(Geom_BSplineCurve) BS = 
1558                 new Geom_BSplineCurve(tpoles,
1559                                       mbspc.Knots(),
1560                                       mbspc.Multiplicities(),
1561                                       mbspc.Degree());
1562               GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK);
1563               Check.FixTangent(Standard_True, Standard_True);
1564               //        
1565               IntTools_Curve aCurve;
1566               aCurve.SetCurve(BS);
1567
1568               if(myApprox1) { 
1569                 Handle(Geom2d_BSplineCurve) BS1 = 
1570                   new Geom2d_BSplineCurve(tpoles2d,
1571                                           mbspc.Knots(),
1572                                           mbspc.Multiplicities(),
1573                                           mbspc.Degree());
1574                 GeomLib_Check2dBSplineCurve Check1(BS1,TOLCHECK,TOLANGCHECK);
1575                 Check1.FixTangent(Standard_True,Standard_True);
1576                 //
1577                 // ############################################
1578                 if(!rejectSurface && !reApprox) {
1579                   Standard_Boolean isValid = IsCurveValid(BS1);
1580                   if(!isValid) {
1581                     reApprox = Standard_True;
1582                     goto reapprox;
1583                   }
1584                 }
1585                 // ############################################
1586                 aCurve.SetFirstCurve2d(BS1);
1587               }
1588               else {
1589                 Handle(Geom2d_BSplineCurve) H1;
1590                 aCurve.SetFirstCurve2d(H1);
1591               }
1592
1593               if(myApprox2) { 
1594                 mbspc.Curve(2, tpoles2d);
1595                 
1596                 Handle(Geom2d_BSplineCurve) BS2 = new Geom2d_BSplineCurve(tpoles2d,
1597                                                                           mbspc.Knots(),
1598                                                                           mbspc.Multiplicities(),
1599                                                                           mbspc.Degree());
1600                 GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK);
1601                 newCheck.FixTangent(Standard_True,Standard_True);
1602                 
1603                 // ###########################################
1604                 if(!rejectSurface && !reApprox) {
1605                   Standard_Boolean isValid = IsCurveValid(BS2);
1606                   if(!isValid) {
1607                     reApprox = Standard_True;
1608                     goto reapprox;
1609                   }
1610                 }
1611                 // ###########################################
1612                 // 
1613                 aCurve.SetSecondCurve2d(BS2);
1614               }
1615               else { 
1616                 Handle(Geom2d_BSplineCurve) H2;
1617                 //              
1618                   aCurve.SetSecondCurve2d(H2);
1619               }
1620               //
1621               mySeqOfCurve.Append(aCurve);
1622             }
1623             
1624             else if(typs2 == GeomAbs_Plane) { 
1625               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
1626               nbpoles = mbspc.NbPoles();
1627               
1628               TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
1629               TColgp_Array1OfPnt   tpoles(1,nbpoles);
1630               mbspc.Curve((myApprox1==Standard_True)? 2 : 1,tpoles2d);
1631               const gp_Pln&  Pln = myHS2->Surface().Plane();
1632               //
1633               Standard_Integer ik; 
1634               for(ik = 1; ik<= nbpoles; ik++) { 
1635                 tpoles.SetValue(ik,
1636                                 ElSLib::Value(tpoles2d.Value(ik).X(),
1637                                               tpoles2d.Value(ik).Y(),
1638                                               Pln));
1639                 
1640               }
1641               //
1642               Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles,
1643                                                                  mbspc.Knots(),
1644                                                                  mbspc.Multiplicities(),
1645                                                                  mbspc.Degree());
1646               GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK);
1647               Check.FixTangent(Standard_True,Standard_True);
1648               //        
1649               IntTools_Curve aCurve;
1650               aCurve.SetCurve(BS);
1651
1652               if(myApprox2) {
1653                 Handle(Geom2d_BSplineCurve) BS1=new Geom2d_BSplineCurve(tpoles2d,
1654                                                                         mbspc.Knots(),
1655                                                                         mbspc.Multiplicities(),
1656                                                                         mbspc.Degree());
1657                 GeomLib_Check2dBSplineCurve Check1(BS1,TOLCHECK,TOLANGCHECK);
1658                 Check1.FixTangent(Standard_True,Standard_True);
1659                 //      
1660                 // ###########################################
1661                 if(!rejectSurface && !reApprox) {
1662                   Standard_Boolean isValid = IsCurveValid(BS1);
1663                   if(!isValid) {
1664                     reApprox = Standard_True;
1665                     goto reapprox;
1666                   }
1667                 }
1668                 // ###########################################
1669                 aCurve.SetSecondCurve2d(BS1);
1670               }
1671               else {
1672                 Handle(Geom2d_BSplineCurve) H2;
1673                 aCurve.SetSecondCurve2d(H2);
1674               }
1675               
1676               if(myApprox1) { 
1677                 mbspc.Curve(1,tpoles2d);
1678                 Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d,
1679                                                                         mbspc.Knots(),
1680                                                                         mbspc.Multiplicities(),
1681                                                                         mbspc.Degree());
1682                 GeomLib_Check2dBSplineCurve Check2(BS2,TOLCHECK,TOLANGCHECK);
1683                 Check2.FixTangent(Standard_True,Standard_True);
1684                 //
1685                 // ###########################################
1686                 if(!rejectSurface && !reApprox) {
1687                   Standard_Boolean isValid = IsCurveValid(BS2);
1688                   if(!isValid) {
1689                     reApprox = Standard_True;
1690                     goto reapprox;
1691                   }
1692                 }
1693                 // ###########################################
1694                 aCurve.SetFirstCurve2d(BS2);
1695               }
1696               else { 
1697                 Handle(Geom2d_BSplineCurve) H1;
1698                 //              
1699                 aCurve.SetFirstCurve2d(H1);
1700               }
1701               //
1702               mySeqOfCurve.Append(aCurve);
1703             }
1704             else { 
1705               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
1706               nbpoles = mbspc.NbPoles();
1707               TColgp_Array1OfPnt tpoles(1,nbpoles);
1708               mbspc.Curve(1,tpoles);
1709               Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles,
1710                                                                  mbspc.Knots(),
1711                                                                  mbspc.Multiplicities(),
1712                                                                  mbspc.Degree());
1713               GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK);
1714               Check.FixTangent(Standard_True,Standard_True);
1715               //                
1716               IntTools_Curve aCurve;
1717               aCurve.SetCurve(BS);
1718               
1719               if(myApprox1) { 
1720                 if(anApprox1) {
1721                   TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
1722                   mbspc.Curve(2,tpoles2d);
1723                   Handle(Geom2d_BSplineCurve) BS1=new Geom2d_BSplineCurve(tpoles2d,
1724                                                                         mbspc.Knots(),
1725                                                                         mbspc.Multiplicities(),
1726                                                                         mbspc.Degree());
1727                   GeomLib_Check2dBSplineCurve newCheck(BS1,TOLCHECK,TOLANGCHECK);
1728                   newCheck.FixTangent(Standard_True,Standard_True);
1729                   //    
1730                   aCurve.SetFirstCurve2d(BS1);
1731                 }
1732                 else {
1733                   Handle(Geom2d_BSplineCurve) BS1;
1734                   fprm = BS->FirstParameter();
1735                   lprm = BS->LastParameter();
1736
1737                   Handle(Geom2d_Curve) C2d;
1738                   Standard_Real aTol = myTolApprox;
1739                   BuildPCurves(fprm, lprm, aTol, myHS1->ChangeSurface().Surface(), BS, C2d);
1740                   BS1 = Handle(Geom2d_BSplineCurve)::DownCast(C2d);
1741                   aCurve.SetFirstCurve2d(BS1);
1742                 }
1743                 
1744               }
1745               else {
1746                 Handle(Geom2d_BSplineCurve) H1;
1747                 //              
1748                 aCurve.SetFirstCurve2d(H1);
1749               }
1750               if(myApprox2) { 
1751                 if(anApprox2) {
1752                   TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
1753                   mbspc.Curve((myApprox1==Standard_True)? 3 : 2,tpoles2d);
1754                   Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d,
1755                                                                         mbspc.Knots(),
1756                                                                         mbspc.Multiplicities(),
1757                                                                         mbspc.Degree());
1758                   GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK);
1759                   newCheck.FixTangent(Standard_True,Standard_True);
1760                 //              
1761                   aCurve.SetSecondCurve2d(BS2);
1762                 }
1763                 else {
1764                   Handle(Geom2d_BSplineCurve) BS2;
1765                   fprm = BS->FirstParameter();
1766                   lprm = BS->LastParameter();
1767
1768                   Handle(Geom2d_Curve) C2d;
1769                   Standard_Real aTol = myTolApprox;
1770                   BuildPCurves(fprm, lprm, aTol, myHS2->ChangeSurface().Surface(), BS, C2d);
1771                   BS2 = Handle(Geom2d_BSplineCurve)::DownCast(C2d);
1772                   aCurve.SetSecondCurve2d(BS2);
1773                 }
1774                 
1775               }
1776               else { 
1777                 Handle(Geom2d_BSplineCurve) H2;
1778                 //              
1779                 aCurve.SetSecondCurve2d(H2);
1780               }
1781               //
1782               mySeqOfCurve.Append(aCurve);
1783             }
1784           }
1785         }
1786       }
1787     }// else { // X
1788   }// case IntPatch_Walking:{
1789     break;
1790     
1791   case IntPatch_Restriction: 
1792     break;
1793
1794   }
1795 }
1796
1797 //=======================================================================
1798 //function : BuildPCurves
1799 //purpose  : 
1800 //=======================================================================
1801  void BuildPCurves (Standard_Real f,
1802                     Standard_Real l,
1803                     Standard_Real& Tol,
1804                     const Handle (Geom_Surface)& S,
1805                     const Handle (Geom_Curve)&   C,
1806                     Handle (Geom2d_Curve)& C2d)
1807 {
1808
1809   Standard_Real umin,umax,vmin,vmax;
1810   // 
1811
1812   if (C2d.IsNull()) {
1813
1814     // in class ProjLib_Function the range of parameters is shrank by 1.e-09
1815     if((l - f) > 2.e-09) {
1816       C2d = GeomProjLib::Curve2d(C,f,l,S,Tol);
1817       //
1818       if (C2d.IsNull()) {
1819         // proj. a circle that goes through the pole on a sphere to the sphere     
1820         Tol=Tol+1.e-7;
1821         C2d = GeomProjLib::Curve2d(C,f,l,S,Tol);
1822       }
1823     }
1824     else {
1825       if((l - f) > Epsilon(Abs(f))) {
1826         GeomAPI_ProjectPointOnSurf aProjector1, aProjector2;
1827         gp_Pnt P1 = C->Value(f);
1828         gp_Pnt P2 = C->Value(l);
1829         aProjector1.Init(P1, S);
1830         aProjector2.Init(P2, S);
1831
1832         if(aProjector1.IsDone() && aProjector2.IsDone()) {
1833           Standard_Real U=0., V=0.;
1834           aProjector1.LowerDistanceParameters(U, V);
1835           gp_Pnt2d p1(U, V);
1836
1837           aProjector2.LowerDistanceParameters(U, V);
1838           gp_Pnt2d p2(U, V);
1839
1840           if(p1.Distance(p2) > gp::Resolution()) {
1841             TColgp_Array1OfPnt2d poles(1,2);
1842             TColStd_Array1OfReal knots(1,2);
1843             TColStd_Array1OfInteger mults(1,2);
1844             poles(1) = p1;
1845             poles(2) = p2;
1846             knots(1) = f;
1847             knots(2) = l;
1848             mults(1) = mults(2) = 2;
1849
1850             C2d = new Geom2d_BSplineCurve(poles,knots,mults,1);
1851
1852             // compute reached tolerance.begin
1853             gp_Pnt PMid = C->Value((f + l) * 0.5);
1854             aProjector1.Perform(PMid);
1855
1856             if(aProjector1.IsDone()) {
1857               aProjector1.LowerDistanceParameters(U, V);
1858               gp_Pnt2d pmidproj(U, V);
1859               gp_Pnt2d pmidcurve2d = C2d->Value((f + l) * 0.5);
1860               Standard_Real adist = pmidcurve2d.Distance(pmidproj);
1861               Tol = (adist > Tol) ? adist : Tol;
1862             }
1863             // compute reached tolerance.end
1864           }
1865         }
1866       }
1867     }
1868     //
1869     S->Bounds(umin, umax, vmin, vmax);
1870
1871     if (S->IsUPeriodic() && !C2d.IsNull()) {
1872       // Recadre dans le domaine UV de la face
1873       Standard_Real period, U0, du, aEps; 
1874       
1875       du =0.0;
1876       aEps=Precision::PConfusion();
1877       period = S->UPeriod();
1878       gp_Pnt2d Pf = C2d->Value(f);
1879       U0=Pf.X();
1880       //
1881       gp_Pnt2d Pl = C2d->Value(l);
1882       
1883       U0 = Min(Pl.X(), U0);
1884 //       while(U0-umin<aEps) { 
1885       while(U0-umin<-aEps) { 
1886         U0+=period;
1887         du+=period;
1888       }
1889       //
1890       while(U0-umax>aEps) { 
1891         U0-=period;
1892         du-=period;
1893       }
1894       if (du != 0) {
1895         gp_Vec2d T1(du,0.);
1896         C2d->Translate(T1);
1897       }
1898     }
1899   }
1900   if (C2d.IsNull()) {
1901     BOPTColStd_Dump::PrintMessage("BuildPCurves()=> Echec ProjLib\n");
1902   }
1903 }
1904
1905 //=======================================================================
1906 //function : Parameters
1907 //purpose  : 
1908 //=======================================================================
1909  void Parameters(const Handle(GeomAdaptor_HSurface)& HS1,
1910                  const Handle(GeomAdaptor_HSurface)& HS2,
1911                  const gp_Pnt& Ptref,
1912                  Standard_Real& U1,
1913                  Standard_Real& V1,
1914                  Standard_Real& U2,
1915                  Standard_Real& V2)
1916 {
1917
1918   IntSurf_Quadric quad1,quad2;
1919   GeomAbs_SurfaceType typs = HS1->Surface().GetType();
1920
1921   switch (typs) {
1922   case GeomAbs_Plane:
1923     quad1.SetValue(HS1->Surface().Plane());
1924     break;
1925   case GeomAbs_Cylinder:
1926     quad1.SetValue(HS1->Surface().Cylinder());
1927     break;
1928   case GeomAbs_Cone:
1929     quad1.SetValue(HS1->Surface().Cone());
1930     break;
1931   case GeomAbs_Sphere:
1932     quad1.SetValue(HS1->Surface().Sphere());
1933     break;
1934   default:
1935     Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve");
1936   }
1937   
1938   typs = HS2->Surface().GetType();
1939   switch (typs) {
1940   case GeomAbs_Plane:
1941     quad2.SetValue(HS2->Surface().Plane());
1942     break;
1943   case GeomAbs_Cylinder:
1944     quad2.SetValue(HS2->Surface().Cylinder());
1945     break;
1946   case GeomAbs_Cone:
1947     quad2.SetValue(HS2->Surface().Cone());
1948     break;
1949   case GeomAbs_Sphere:
1950     quad2.SetValue(HS2->Surface().Sphere());
1951     break;
1952   default:
1953     Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve");
1954   }
1955
1956   quad1.Parameters(Ptref,U1,V1);
1957   quad2.Parameters(Ptref,U2,V2);
1958 }
1959
1960 //=======================================================================
1961 //function : MakeBSpline
1962 //purpose  : 
1963 //=======================================================================
1964 Handle(Geom_Curve) MakeBSpline  (const Handle(IntPatch_WLine)& WL,
1965                                  const Standard_Integer ideb,
1966                                  const Standard_Integer ifin)
1967 {
1968   Standard_Integer i,nbpnt = ifin-ideb+1;
1969   TColgp_Array1OfPnt poles(1,nbpnt);
1970   TColStd_Array1OfReal knots(1,nbpnt);
1971   TColStd_Array1OfInteger mults(1,nbpnt);
1972   Standard_Integer ipidebm1;
1973   for(i=1,ipidebm1=i+ideb-1; i<=nbpnt;ipidebm1++, i++) {
1974     poles(i) = WL->Point(ipidebm1).Value();
1975     mults(i) = 1;
1976     knots(i) = i-1;
1977   }
1978   mults(1) = mults(nbpnt) = 2;
1979   return
1980     new Geom_BSplineCurve(poles,knots,mults,1);
1981 }
1982 //
1983
1984 //=======================================================================
1985 //function : MakeBSpline2d
1986 //purpose  : 
1987 //=======================================================================
1988 Handle(Geom2d_BSplineCurve) MakeBSpline2d(const Handle(IntPatch_WLine)& theWLine,
1989                                           const Standard_Integer ideb,
1990                                           const Standard_Integer ifin,
1991                                           const Standard_Boolean onFirst)
1992 {
1993   Standard_Integer i, nbpnt = ifin-ideb+1;
1994   TColgp_Array1OfPnt2d poles(1,nbpnt);
1995   TColStd_Array1OfReal knots(1,nbpnt);
1996   TColStd_Array1OfInteger mults(1,nbpnt);
1997   Standard_Integer ipidebm1;
1998
1999   for(i = 1, ipidebm1 = i+ideb-1; i <= nbpnt; ipidebm1++, i++) {
2000       Standard_Real U, V;
2001       if(onFirst)
2002         theWLine->Point(ipidebm1).ParametersOnS1(U, V);
2003       else
2004         theWLine->Point(ipidebm1).ParametersOnS2(U, V);
2005       poles(i).SetCoord(U, V);
2006       mults(i) = 1;
2007       knots(i) = i-1;
2008     }
2009     mults(1) = mults(nbpnt) = 2;
2010
2011   return new Geom2d_BSplineCurve(poles,knots,mults,1);
2012 }
2013 //=======================================================================
2014 //function : PrepareLines3D
2015 //purpose  : 
2016 //=======================================================================
2017   void IntTools_FaceFace::PrepareLines3D()
2018 {
2019   Standard_Integer i, aNbCurves, j, aNbNewCurves;
2020   IntTools_SequenceOfCurves aNewCvs;
2021
2022   //
2023   // 1. Treatment of periodic and closed  curves
2024   aNbCurves=mySeqOfCurve.Length();
2025   for (i=1; i<=aNbCurves; i++) {
2026     const IntTools_Curve& aIC=mySeqOfCurve(i);
2027     // DEBUG
2028     // const Handle(Geom_Curve)&   aC3D =aIC.Curve();
2029     // const Handle(Geom2d_Curve)& aC2D1=aIC.FirstCurve2d();
2030     // const Handle(Geom2d_Curve)& aC2D2=aIC.SecondCurve2d();
2031     //
2032     IntTools_SequenceOfCurves aSeqCvs;
2033     aNbNewCurves=IntTools_Tools::SplitCurve(aIC, aSeqCvs);
2034     
2035     if (aNbNewCurves) {
2036       for (j=1; j<=aNbNewCurves; j++) {
2037         const IntTools_Curve& aICNew=aSeqCvs(j);
2038         aNewCvs.Append(aICNew);
2039       }
2040     }
2041     //
2042     else {
2043       aNewCvs.Append(aIC);
2044     }
2045   }
2046   //
2047   // 2. Plane\Cone intersection when we had 4 curves
2048   GeomAbs_SurfaceType aType1, aType2;
2049   BRepAdaptor_Surface aBS1, aBS2;
2050   
2051   aBS1.Initialize(myFace1);
2052   aType1=aBS1.GetType();
2053   
2054   aBS2.Initialize(myFace2);
2055   aType2=aBS2.GetType();
2056   
2057   if ((aType1==GeomAbs_Plane && aType2==GeomAbs_Cone) ||
2058       (aType2==GeomAbs_Plane && aType1==GeomAbs_Cone)) {
2059     aNbCurves=aNewCvs.Length();
2060     if (aNbCurves==4) {
2061       GeomAbs_CurveType aCType1=aNewCvs(1).Type();
2062       if (aCType1==GeomAbs_Line) {
2063         IntTools_SequenceOfCurves aSeqIn, aSeqOut;
2064         //
2065         for (i=1; i<=aNbCurves; i++) {
2066           const IntTools_Curve& aIC=aNewCvs(i);
2067           aSeqIn.Append(aIC);
2068         }
2069         //
2070         IntTools_Tools::RejectLines(aSeqIn, aSeqOut);
2071         //
2072         aNewCvs.Clear();
2073         aNbCurves=aSeqOut.Length(); 
2074         for (i=1; i<=aNbCurves; i++) {
2075           const IntTools_Curve& aIC=aSeqOut(i);
2076           aNewCvs.Append(aIC);
2077         }
2078         //
2079       }
2080     }
2081   }// end of if ((aType1==GeomAbs_Plane && ...
2082   //
2083   // 3. Fill  mySeqOfCurve
2084   mySeqOfCurve.Clear();
2085   aNbCurves=aNewCvs.Length();
2086   for (i=1; i<=aNbCurves; i++) {
2087     const IntTools_Curve& aIC=aNewCvs(i);
2088     mySeqOfCurve.Append(aIC);
2089   }
2090
2091 }
2092
2093
2094 //=======================================================================
2095 //function : CorrectSurfaceBoundaries
2096 //purpose  : 
2097 //=======================================================================
2098  void CorrectSurfaceBoundaries(const TopoDS_Face&  theFace,
2099                                const Standard_Real theTolerance,
2100                                Standard_Real&      theumin,
2101                                Standard_Real&      theumax, 
2102                                Standard_Real&      thevmin, 
2103                                Standard_Real&      thevmax) 
2104 {
2105   Standard_Boolean enlarge, isuperiodic, isvperiodic;
2106   Standard_Real uinf, usup, vinf, vsup, delta;
2107   GeomAbs_SurfaceType aType;
2108   Handle(Geom_Surface) aSurface;
2109   //
2110   aSurface = BRep_Tool::Surface(theFace);
2111   aSurface->Bounds(uinf, usup, vinf, vsup);
2112   delta = theTolerance;
2113   enlarge = Standard_False;
2114   //
2115   GeomAdaptor_Surface anAdaptorSurface(aSurface);
2116   //
2117   if(aSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
2118     Handle(Geom_Surface) aBasisSurface = 
2119       (Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface))->BasisSurface();
2120     
2121     if(aBasisSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)) ||
2122        aBasisSurface->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
2123       return;
2124     }
2125   }
2126   //
2127   if(aSurface->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
2128     Handle(Geom_Surface) aBasisSurface = 
2129       (Handle(Geom_OffsetSurface)::DownCast(aSurface))->BasisSurface();
2130     
2131     if(aBasisSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)) ||
2132        aBasisSurface->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
2133       return;
2134     }
2135   }
2136   //
2137   isuperiodic = anAdaptorSurface.IsUPeriodic();
2138   isvperiodic = anAdaptorSurface.IsVPeriodic();
2139   //
2140   aType=anAdaptorSurface.GetType();
2141   if((aType==GeomAbs_BezierSurface) ||
2142      (aType==GeomAbs_BSplineSurface) ||
2143      (aType==GeomAbs_SurfaceOfExtrusion) ||
2144      (aType==GeomAbs_SurfaceOfRevolution)) {
2145     enlarge=Standard_True;
2146   }
2147   //
2148   if(!isuperiodic && enlarge) {
2149
2150     if((theumin - uinf) > delta )
2151       theumin -= delta;
2152     else {
2153       theumin = uinf;
2154     }
2155
2156     if((usup - theumax) > delta )
2157       theumax += delta;
2158     else
2159       theumax = usup;
2160   }
2161   //
2162   if(!isvperiodic && enlarge) {
2163     if((thevmin - vinf) > delta ) {
2164       thevmin -= delta;
2165     }
2166     else { 
2167       thevmin = vinf;
2168     }
2169     if((vsup - thevmax) > delta ) {
2170       thevmax += delta;
2171     }
2172     else {
2173       thevmax = vsup;
2174     }
2175   }
2176   //
2177   {
2178     Standard_Integer aNbP;
2179     Standard_Real aXP, dXfact, aXmid, aX1, aX2, aTolPA;
2180     //
2181     aTolPA=Precision::Angular();
2182     // U
2183     if (isuperiodic) {
2184       aXP=anAdaptorSurface.UPeriod();
2185       dXfact=theumax-theumin;
2186       if (dXfact-aTolPA>aXP) {
2187         aXmid=0.5*(theumax+theumin);
2188         aNbP=RealToInt(aXmid/aXP);
2189         if (aXmid<0.) {
2190           aNbP=aNbP-1;
2191         }
2192         aX1=aNbP*aXP;
2193         aX2=aX1+aXP;
2194         if (theumin<aX1) {
2195           theumin=aX1;
2196         }
2197         if (theumax>aX2) {
2198           theumax=aX2;
2199         }
2200       }
2201     }
2202     // V
2203     if (isvperiodic) {
2204       aXP=anAdaptorSurface.VPeriod();
2205       dXfact=thevmax-thevmin;
2206       if (dXfact-aTolPA>aXP) {
2207         aXmid=0.5*(thevmax+thevmin);
2208         aNbP=RealToInt(aXmid/aXP);
2209         if (aXmid<0.) {
2210           aNbP=aNbP-1;
2211         }
2212         aX1=aNbP*aXP;
2213         aX2=aX1+aXP;
2214         if (thevmin<aX1) {
2215           thevmin=aX1;
2216         }
2217         if (thevmax>aX2) {
2218           thevmax=aX2;
2219         }
2220       }
2221     }
2222   }
2223   //
2224   if(isuperiodic || isvperiodic) {
2225     Standard_Boolean correct = Standard_False;
2226     Standard_Boolean correctU = Standard_False;
2227     Standard_Boolean correctV = Standard_False;
2228     Bnd_Box2d aBox;
2229     TopExp_Explorer anExp;
2230
2231     for(anExp.Init(theFace, TopAbs_EDGE); anExp.More(); anExp.Next()) {
2232       if(BRep_Tool::IsClosed(TopoDS::Edge(anExp.Current()), theFace)) {
2233         correct = Standard_True;
2234         Standard_Real f, l;
2235         TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
2236         
2237         for(Standard_Integer i = 0; i < 2; i++) {
2238           if(i==0) {
2239             anEdge.Orientation(TopAbs_FORWARD);
2240           }
2241           else {
2242             anEdge.Orientation(TopAbs_REVERSED);
2243           }
2244           Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, f, l);
2245           
2246           if(aCurve.IsNull()) {
2247             correct = Standard_False;
2248             break;
2249           }
2250           Handle(Geom2d_Line) aLine = Handle(Geom2d_Line)::DownCast(aCurve);
2251
2252           if(aLine.IsNull()) {
2253             correct = Standard_False;
2254             break;
2255           }
2256           gp_Dir2d anUDir(1., 0.);
2257           gp_Dir2d aVDir(0., 1.);
2258           Standard_Real anAngularTolerance = Precision::Angular();
2259
2260           correctU = correctU || aLine->Position().Direction().IsParallel(aVDir, anAngularTolerance);
2261           correctV = correctV || aLine->Position().Direction().IsParallel(anUDir, anAngularTolerance);
2262           
2263           gp_Pnt2d pp1 = aCurve->Value(f);
2264           aBox.Add(pp1);
2265           gp_Pnt2d pp2 = aCurve->Value(l);
2266           aBox.Add(pp2);
2267         }
2268         if(!correct)
2269           break;
2270       }
2271     }
2272
2273     if(correct) {
2274       Standard_Real umin, vmin, umax, vmax;
2275       aBox.Get(umin, vmin, umax, vmax);
2276
2277       if(isuperiodic && correctU) {
2278         
2279         if(theumin < umin)
2280           theumin = umin;
2281         
2282         if(theumax > umax) {
2283           theumax = umax;
2284         }
2285       }
2286       if(isvperiodic && correctV) {
2287         
2288         if(thevmin < vmin)
2289           thevmin = vmin;
2290         if(thevmax > vmax)
2291           thevmax = vmax;
2292       }
2293     }
2294   }
2295 }
2296 //
2297 //
2298 // The block is dedicated to determine whether WLine [ifprm, ilprm]
2299 // crosses the degenerated zone on each given surface or not.
2300 // If Yes -> We will not use info about surfaces during approximation
2301 // because inside degenerated zone of the surface the approx. alogo.
2302 // uses wrong values of normal, etc., and resulting curve will have
2303 // oscillations that we would not like to have. 
2304 //                                               PKV Tue Feb 12 2002  
2305  
2306
2307 static
2308   Standard_Boolean IsDegeneratedZone(const gp_Pnt2d& aP2d,
2309                                      const Handle(Geom_Surface)& aS,
2310                                      const Standard_Integer iDir);
2311 static
2312   Standard_Boolean IsPointInDegeneratedZone(const IntSurf_PntOn2S& aP2S,
2313                                             const TopoDS_Face& aF1,
2314                                             const TopoDS_Face& aF2);
2315 //=======================================================================
2316 //function :  NotUseSurfacesForApprox
2317 //purpose  : 
2318 //=======================================================================
2319 Standard_Boolean NotUseSurfacesForApprox(const TopoDS_Face& aF1,
2320                                          const TopoDS_Face& aF2,
2321                                          const Handle(IntPatch_WLine)& WL,
2322                                          const Standard_Integer ifprm,
2323                                          const Standard_Integer ilprm)
2324 {
2325   Standard_Boolean bPInDZ;
2326
2327   Handle(IntSurf_LineOn2S) aLineOn2S=WL->Curve();
2328   
2329   const IntSurf_PntOn2S& aP2Sfprm=aLineOn2S->Value(ifprm);
2330   bPInDZ=IsPointInDegeneratedZone(aP2Sfprm, aF1, aF2);
2331   if (bPInDZ) {
2332     return bPInDZ;
2333   }
2334
2335   const IntSurf_PntOn2S& aP2Slprm=aLineOn2S->Value(ilprm);
2336   bPInDZ=IsPointInDegeneratedZone(aP2Slprm, aF1, aF2);
2337   
2338   return bPInDZ;
2339 }
2340 //=======================================================================
2341 //function : IsPointInDegeneratedZone
2342 //purpose  : 
2343 //=======================================================================
2344 Standard_Boolean IsPointInDegeneratedZone(const IntSurf_PntOn2S& aP2S,
2345                                           const TopoDS_Face& aF1,
2346                                           const TopoDS_Face& aF2)
2347                                           
2348 {
2349   Standard_Boolean bFlag=Standard_True;
2350   Standard_Real US11, US12, VS11, VS12, US21, US22, VS21, VS22;
2351   Standard_Real U1, V1, U2, V2, aDelta, aD;
2352   gp_Pnt2d aP2d;
2353
2354   Handle(Geom_Surface)aS1 = BRep_Tool::Surface(aF1);
2355   aS1->Bounds(US11, US12, VS11, VS12);
2356   GeomAdaptor_Surface aGAS1(aS1);
2357
2358   Handle(Geom_Surface)aS2 = BRep_Tool::Surface(aF2);
2359   aS1->Bounds(US21, US22, VS21, VS22);
2360   GeomAdaptor_Surface aGAS2(aS2);
2361   //
2362   //const gp_Pnt& aP=aP2S.Value();
2363   aP2S.Parameters(U1, V1, U2, V2);
2364   //
2365   aDelta=1.e-7;
2366   // Check on Surf 1
2367   aD=aGAS1.UResolution(aDelta);
2368   aP2d.SetCoord(U1, V1);
2369   if (fabs(U1-US11) < aD) {
2370     bFlag=IsDegeneratedZone(aP2d, aS1, 1);
2371     if (bFlag) {
2372       return bFlag;
2373     }
2374   }
2375   if (fabs(U1-US12) < aD) {
2376     bFlag=IsDegeneratedZone(aP2d, aS1, 1);
2377     if (bFlag) {
2378       return bFlag;
2379     }
2380   }
2381   aD=aGAS1.VResolution(aDelta);
2382   if (fabs(V1-VS11) < aDelta) {
2383     bFlag=IsDegeneratedZone(aP2d, aS1, 2);
2384     if (bFlag) {
2385       return bFlag;
2386     }
2387   }
2388   if (fabs(V1-VS12) < aDelta) {
2389     bFlag=IsDegeneratedZone(aP2d, aS1, 2);
2390     if (bFlag) {
2391       return bFlag;
2392     }
2393   }
2394   // Check on Surf 2
2395   aD=aGAS2.UResolution(aDelta);
2396   aP2d.SetCoord(U2, V2);
2397   if (fabs(U2-US21) < aDelta) {
2398     bFlag=IsDegeneratedZone(aP2d, aS2, 1);
2399     if (bFlag) {
2400       return bFlag;
2401     }
2402   }
2403   if (fabs(U2-US22) < aDelta) {
2404     bFlag=IsDegeneratedZone(aP2d, aS2, 1);
2405     if (bFlag) {
2406       return bFlag;
2407     }
2408   }
2409   aD=aGAS2.VResolution(aDelta);
2410   if (fabs(V2-VS21) < aDelta) {
2411     bFlag=IsDegeneratedZone(aP2d, aS2, 2);
2412     if (bFlag) {  
2413       return bFlag;
2414     }
2415   }
2416   if (fabs(V2-VS22) < aDelta) {
2417     bFlag=IsDegeneratedZone(aP2d, aS2, 2);
2418     if (bFlag) {
2419       return bFlag;
2420     }
2421   }
2422   return !bFlag;
2423 }
2424
2425 //=======================================================================
2426 //function : IsDegeneratedZone
2427 //purpose  : 
2428 //=======================================================================
2429 Standard_Boolean IsDegeneratedZone(const gp_Pnt2d& aP2d,
2430                                    const Handle(Geom_Surface)& aS,
2431                                    const Standard_Integer iDir)
2432 {
2433   Standard_Boolean bFlag=Standard_True;
2434   Standard_Real US1, US2, VS1, VS2, dY, dX, d1, d2, dD;
2435   Standard_Real aXm, aYm, aXb, aYb, aXe, aYe;
2436   aS->Bounds(US1, US2, VS1, VS2); 
2437
2438   gp_Pnt aPm, aPb, aPe;
2439   
2440   aXm=aP2d.X();
2441   aYm=aP2d.Y();
2442   
2443   aS->D0(aXm, aYm, aPm); 
2444   
2445   dX=1.e-5;
2446   dY=1.e-5;
2447   dD=1.e-12;
2448
2449   if (iDir==1) {
2450     aXb=aXm;
2451     aXe=aXm;
2452     aYb=aYm-dY;
2453     if (aYb < VS1) {
2454       aYb=VS1;
2455     }
2456     aYe=aYm+dY;
2457     if (aYe > VS2) {
2458       aYe=VS2;
2459     }
2460     aS->D0(aXb, aYb, aPb);
2461     aS->D0(aXe, aYe, aPe);
2462     
2463     d1=aPm.Distance(aPb);
2464     d2=aPm.Distance(aPe);
2465     if (d1 < dD && d2 < dD) {
2466       return bFlag;
2467     }
2468     return !bFlag;
2469   }
2470   //
2471   else if (iDir==2) {
2472     aYb=aYm;
2473     aYe=aYm;
2474     aXb=aXm-dX;
2475     if (aXb < US1) {
2476       aXb=US1;
2477     }
2478     aXe=aXm+dX;
2479     if (aXe > US2) {
2480       aXe=US2;
2481     }
2482     aS->D0(aXb, aYb, aPb);
2483     aS->D0(aXe, aYe, aPe);
2484     
2485     d1=aPm.Distance(aPb);
2486     d2=aPm.Distance(aPe);
2487     if (d1 < dD && d2 < dD) {
2488       return bFlag;
2489     }
2490     return !bFlag;
2491   }
2492   return !bFlag;
2493 }
2494
2495 //=========================================================================
2496 // static function : ComputePurgedWLine
2497 // purpose : Removes equal points (leave one of equal points) from theWLine
2498 //           and recompute vertex parameters.
2499 //           Returns new WLine or null WLine if the number
2500 //           of the points is less than 2.
2501 //=========================================================================
2502 Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine)& theWLine) {
2503   Handle(IntPatch_WLine) aResult;
2504   Handle(IntPatch_WLine) aLocalWLine;
2505   Handle(IntPatch_WLine) aTmpWLine = theWLine;
2506
2507   Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
2508   aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
2509   Standard_Integer i, k, v, nb, nbvtx;
2510   nbvtx = theWLine->NbVertex();
2511   nb = theWLine->NbPnts();
2512
2513   for(i = 1; i <= nb; i++) {
2514     aLineOn2S->Add(theWLine->Point(i));
2515   }
2516
2517   for(v = 1; v <= nbvtx; v++) {
2518     aLocalWLine->AddVertex(theWLine->Vertex(v));
2519   }
2520   
2521   for(i = 1; i <= aLineOn2S->NbPoints(); i++) {
2522     Standard_Integer aStartIndex = i + 1;
2523     Standard_Integer anEndIndex = i + 5;
2524     nb = aLineOn2S->NbPoints();
2525     anEndIndex = (anEndIndex > nb) ? nb : anEndIndex;
2526
2527     if((aStartIndex >= nb) || (anEndIndex <= 1)) {
2528       continue;
2529     }
2530     k = aStartIndex;
2531
2532     while(k <= anEndIndex) {
2533       
2534       if(i != k) {
2535         IntSurf_PntOn2S p1 = aLineOn2S->Value(i);
2536         IntSurf_PntOn2S p2 = aLineOn2S->Value(k);
2537         
2538         if(p1.Value().IsEqual(p2.Value(), gp::Resolution())) {
2539           aTmpWLine = aLocalWLine;
2540           aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
2541
2542           for(v = 1; v <= aTmpWLine->NbVertex(); v++) {
2543             IntPatch_Point aVertex = aTmpWLine->Vertex(v);
2544             Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
2545
2546             if(avertexindex >= k) {
2547               aVertex.SetParameter(aVertex.ParameterOnLine() - 1.);
2548             }
2549             aLocalWLine->AddVertex(aVertex);
2550           }
2551           aLineOn2S->RemovePoint(k);
2552           anEndIndex--;
2553           continue;
2554         }
2555       }
2556       k++;
2557     }
2558   }
2559
2560   if(aLineOn2S->NbPoints() > 1) {
2561     aResult = aLocalWLine;
2562   }
2563   return aResult;
2564 }
2565
2566 //=======================================================================
2567 //function : TolR3d
2568 //purpose  : 
2569 //=======================================================================
2570 void TolR3d(const TopoDS_Face& aF1,
2571             const TopoDS_Face& aF2,
2572             Standard_Real& myTolReached3d)
2573 {
2574   Standard_Real aTolF1, aTolF2, aTolFMax, aTolTresh;
2575       
2576   aTolTresh=2.999999e-3;
2577   aTolF1 = BRep_Tool::Tolerance(aF1);
2578   aTolF2 = BRep_Tool::Tolerance(aF2);
2579   aTolFMax=Max(aTolF1, aTolF2);
2580   
2581   if (aTolFMax>aTolTresh) {
2582     myTolReached3d=aTolFMax;
2583   }
2584 }
2585 //=======================================================================
2586 //function : AdjustPeriodic
2587 //purpose  : 
2588 //=======================================================================
2589 Standard_Real AdjustPeriodic(const Standard_Real theParameter,
2590                              const Standard_Real parmin,
2591                              const Standard_Real parmax,
2592                              const Standard_Real thePeriod,
2593                              Standard_Real&      theOffset) 
2594 {
2595   Standard_Real aresult;
2596   //
2597   theOffset = 0.;
2598   aresult = theParameter;
2599   while(aresult < parmin) {
2600     aresult += thePeriod;
2601     theOffset += thePeriod;
2602   }
2603
2604   while(aresult > parmax) {
2605     aresult -= thePeriod;
2606     theOffset -= thePeriod;
2607   }
2608   return aresult;
2609 }
2610 //=======================================================================
2611 //function : IsPointOnBoundary
2612 //purpose  : 
2613 //=======================================================================
2614 Standard_Boolean IsPointOnBoundary(const Standard_Real theParameter,
2615                                    const Standard_Real theFirstBoundary,
2616                                    const Standard_Real theSecondBoundary,
2617                                    const Standard_Real theResolution,
2618                                    Standard_Boolean&   IsOnFirstBoundary) 
2619 {
2620   Standard_Boolean bRet;
2621   Standard_Integer i;
2622   Standard_Real adist;
2623   //
2624   bRet=Standard_False;
2625   for(i = 0; i < 2; ++i) {
2626     IsOnFirstBoundary = (i == 0);
2627     if (IsOnFirstBoundary) {
2628       adist = fabs(theParameter - theFirstBoundary);
2629     }
2630     else {
2631       adist = fabs(theParameter - theSecondBoundary);
2632     }
2633     if(adist < theResolution) {
2634       return !bRet;
2635     }
2636   }
2637   return bRet;
2638 }
2639 // ------------------------------------------------------------------------------------------------
2640 // static function: FindPoint
2641 // purpose:
2642 // ------------------------------------------------------------------------------------------------
2643 Standard_Boolean FindPoint(const gp_Pnt2d&     theFirstPoint,
2644                            const gp_Pnt2d&     theLastPoint,
2645                            const Standard_Real theUmin, 
2646                            const Standard_Real theUmax,
2647                            const Standard_Real theVmin,
2648                            const Standard_Real theVmax,
2649                            gp_Pnt2d&           theNewPoint) {
2650   
2651   gp_Vec2d aVec(theFirstPoint, theLastPoint);
2652   Standard_Integer i = 0, j = 0;
2653
2654   for(i = 0; i < 4; i++) {
2655     gp_Vec2d anOtherVec;
2656     gp_Vec2d anOtherVecNormal;
2657     gp_Pnt2d aprojpoint = theLastPoint;    
2658
2659     if((i % 2) == 0) {
2660       anOtherVec.SetX(0.);
2661       anOtherVec.SetY(1.);
2662       anOtherVecNormal.SetX(1.);
2663       anOtherVecNormal.SetY(0.);
2664
2665       if(i < 2)
2666         aprojpoint.SetX(theUmin);
2667       else
2668         aprojpoint.SetX(theUmax);
2669     }
2670     else {
2671       anOtherVec.SetX(1.);
2672       anOtherVec.SetY(0.);
2673       anOtherVecNormal.SetX(0.);
2674       anOtherVecNormal.SetY(1.);
2675
2676       if(i < 2)
2677         aprojpoint.SetY(theVmin);
2678       else
2679         aprojpoint.SetY(theVmax);
2680     }
2681     gp_Vec2d anormvec = aVec;
2682     anormvec.Normalize();
2683     Standard_Real adot1 = anormvec.Dot(anOtherVecNormal);
2684
2685     if(fabs(adot1) < Precision::Angular())
2686       continue;
2687     Standard_Real adist = 0.;
2688     Standard_Boolean bIsOut = Standard_False;
2689
2690     if((i % 2) == 0) {
2691       adist = (i < 2) ? fabs(theLastPoint.X() - theUmin) : fabs(theLastPoint.X() - theUmax);
2692       bIsOut = (i < 2) ? (theLastPoint.X() < theUmin) : (theLastPoint.X() > theUmax);
2693     }
2694     else {
2695       adist = (i < 2) ? fabs(theLastPoint.Y() - theVmin) : fabs(theLastPoint.Y() - theVmax);
2696       bIsOut = (i < 2) ? (theLastPoint.Y() < theVmin) : (theLastPoint.Y() > theVmax);
2697     }
2698     Standard_Real anoffset = adist * anOtherVec.Dot(anormvec) / adot1;
2699
2700     for(j = 0; j < 2; j++) {
2701       anoffset = (j == 0) ? anoffset : -anoffset;
2702       gp_Pnt2d acurpoint(aprojpoint.XY() + (anOtherVec.XY()*anoffset));
2703       gp_Vec2d acurvec(theLastPoint, acurpoint);
2704       if ( bIsOut )
2705         acurvec.Reverse();
2706
2707       if((aVec.Dot(acurvec) > 0.) &&
2708          (aVec.Angle(acurvec) < Precision::PConfusion())) {
2709         if((i % 2) == 0) {
2710           if((acurpoint.Y() >= theVmin) &&
2711              (acurpoint.Y() <= theVmax)) {
2712             theNewPoint = acurpoint;
2713             return Standard_True;
2714           }
2715         }
2716         else {
2717           if((acurpoint.X() >= theUmin) &&
2718              (acurpoint.X() <= theUmax)) {
2719             theNewPoint = acurpoint;
2720             return Standard_True;
2721           }
2722         }
2723       }
2724     }
2725   }
2726   return Standard_False;
2727 }
2728
2729
2730 // ------------------------------------------------------------------------------------------------
2731 // static function: FindPoint
2732 // purpose: Find point on the boundary of radial tangent zone
2733 // ------------------------------------------------------------------------------------------------
2734 Standard_Boolean FindPoint(const gp_Pnt2d&     theFirstPoint,
2735                            const gp_Pnt2d&     theLastPoint,
2736                            const Standard_Real theUmin, 
2737                            const Standard_Real theUmax,
2738                            const Standard_Real theVmin,
2739                            const Standard_Real theVmax,
2740                            const gp_Pnt2d&     theTanZoneCenter,
2741                            const Standard_Real theZoneRadius,
2742                            Handle(GeomAdaptor_HSurface) theGASurface,
2743                            gp_Pnt2d&           theNewPoint) {
2744   theNewPoint = theLastPoint;
2745
2746   if ( !IsInsideTanZone( theLastPoint, theTanZoneCenter, theZoneRadius, theGASurface) )
2747     return Standard_False;
2748
2749   Standard_Real aUResolution = theGASurface->UResolution( theZoneRadius );
2750   Standard_Real aVResolution = theGASurface->VResolution( theZoneRadius );
2751
2752   Standard_Real aRadius = ( aUResolution < aVResolution ) ? aUResolution : aVResolution;
2753   gp_Ax22d anAxis( theTanZoneCenter, gp_Dir2d(1, 0), gp_Dir2d(0, 1) );
2754   gp_Circ2d aCircle( anAxis, aRadius );
2755   
2756   //
2757   gp_Vec2d aDir( theLastPoint.XY() - theFirstPoint.XY() );
2758   Standard_Real aLength = aDir.Magnitude();
2759   if ( aLength <= gp::Resolution() )
2760     return Standard_False;
2761   gp_Lin2d aLine( theFirstPoint, aDir );
2762
2763   //
2764   Handle(Geom2d_Line) aCLine = new Geom2d_Line( aLine );
2765   Handle(Geom2d_TrimmedCurve) aC1 = new Geom2d_TrimmedCurve( aCLine, 0, aLength );
2766   Handle(Geom2d_Circle) aC2 = new Geom2d_Circle( aCircle );
2767
2768   Standard_Real aTol = aRadius * 0.001;
2769   aTol = ( aTol < Precision::PConfusion() ) ? Precision::PConfusion() : aTol;
2770
2771   Geom2dAPI_InterCurveCurve anIntersector;
2772   anIntersector.Init( aC1, aC2, aTol );
2773
2774   if ( anIntersector.NbPoints() == 0 )
2775     return Standard_False;
2776
2777   Standard_Boolean aFound = Standard_False;
2778   Standard_Real aMinDist = aLength * aLength;
2779   Standard_Integer i = 0;
2780   for ( i = 1; i <= anIntersector.NbPoints(); i++ ) {
2781     gp_Pnt2d aPInt = anIntersector.Point( i );
2782     if ( aPInt.SquareDistance( theFirstPoint ) < aMinDist ) {
2783       if ( ( aPInt.X() >= theUmin ) && ( aPInt.X() <= theUmax ) &&
2784            ( aPInt.Y() >= theVmin ) && ( aPInt.Y() <= theVmax ) ) {
2785         theNewPoint = aPInt;
2786         aFound = Standard_True;
2787       }
2788     }
2789   }
2790
2791   return aFound;
2792 }
2793
2794 // ------------------------------------------------------------------------------------------------
2795 // static function: IsInsideTanZone
2796 // purpose: Check if point is inside a radial tangent zone
2797 // ------------------------------------------------------------------------------------------------
2798 Standard_Boolean IsInsideTanZone(const gp_Pnt2d&     thePoint,
2799                                  const gp_Pnt2d&     theTanZoneCenter,
2800                                  const Standard_Real theZoneRadius,
2801                                  Handle(GeomAdaptor_HSurface) theGASurface) {
2802
2803   Standard_Real aUResolution = theGASurface->UResolution( theZoneRadius );
2804   Standard_Real aVResolution = theGASurface->VResolution( theZoneRadius );
2805   Standard_Real aRadiusSQR = ( aUResolution < aVResolution ) ? aUResolution : aVResolution;
2806   aRadiusSQR *= aRadiusSQR;
2807   if ( thePoint.SquareDistance( theTanZoneCenter ) <= aRadiusSQR )
2808     return Standard_True;
2809   return Standard_False;
2810 }
2811
2812 // ------------------------------------------------------------------------------------------------
2813 // static function: CheckTangentZonesExist
2814 // purpose: Check if tangent zone exists
2815 // ------------------------------------------------------------------------------------------------
2816 Standard_Boolean CheckTangentZonesExist( const Handle(GeomAdaptor_HSurface)& theSurface1,
2817                                         const Handle(GeomAdaptor_HSurface)&  theSurface2 ) 
2818 {
2819   if ( ( theSurface1->GetType() != GeomAbs_Torus ) ||
2820       ( theSurface2->GetType() != GeomAbs_Torus ) )
2821     return Standard_False;
2822
2823   IntTools_Context aContext;
2824
2825   gp_Torus aTor1 = theSurface1->Torus();
2826   gp_Torus aTor2 = theSurface2->Torus();
2827
2828   if ( aTor1.Location().Distance( aTor2.Location() ) > Precision::Confusion() )
2829     return Standard_False;
2830
2831   if ( ( fabs( aTor1.MajorRadius() - aTor2.MajorRadius() ) > Precision::Confusion() ) ||
2832        ( fabs( aTor1.MinorRadius() - aTor2.MinorRadius() ) > Precision::Confusion() ) )
2833     return Standard_False;
2834
2835   if ( ( aTor1.MajorRadius() < aTor1.MinorRadius() ) ||
2836        ( aTor2.MajorRadius() < aTor2.MinorRadius() ) )
2837     return Standard_False;
2838   return Standard_True;
2839 }
2840
2841 // ------------------------------------------------------------------------------------------------
2842 // static function: ComputeTangentZones
2843 // purpose: 
2844 // ------------------------------------------------------------------------------------------------
2845 Standard_Integer ComputeTangentZones( const Handle(GeomAdaptor_HSurface)& theSurface1,
2846                                      const Handle(GeomAdaptor_HSurface)&  theSurface2,
2847                                      const TopoDS_Face&                   theFace1,
2848                                      const TopoDS_Face&                   theFace2,
2849                                      Handle(TColgp_HArray1OfPnt2d)&       theResultOnS1,
2850                                      Handle(TColgp_HArray1OfPnt2d)&       theResultOnS2,
2851                                      Handle(TColStd_HArray1OfReal)&       theResultRadius) {
2852   Standard_Integer aResult = 0;
2853   if ( !CheckTangentZonesExist( theSurface1, theSurface2 ) )
2854     return aResult;
2855
2856   IntTools_Context aContext;
2857
2858   TColgp_SequenceOfPnt2d aSeqResultS1, aSeqResultS2;
2859   TColStd_SequenceOfReal aSeqResultRad;
2860
2861   gp_Torus aTor1 = theSurface1->Torus();
2862   gp_Torus aTor2 = theSurface2->Torus();
2863
2864   gp_Ax2 anax1( aTor1.Location(), aTor1.Axis().Direction() );
2865   gp_Ax2 anax2( aTor2.Location(), aTor2.Axis().Direction() );
2866   Standard_Integer j = 0;
2867
2868   for ( j = 0; j < 2; j++ ) {
2869     Standard_Real aCoef = ( j == 0 ) ? -1 : 1;
2870     Standard_Real aRadius1 = fabs(aTor1.MajorRadius() + aCoef * aTor1.MinorRadius());
2871     Standard_Real aRadius2 = fabs(aTor2.MajorRadius() + aCoef * aTor2.MinorRadius());
2872
2873     gp_Circ aCircle1( anax1, aRadius1 );
2874     gp_Circ aCircle2( anax2, aRadius2 );
2875
2876     // roughly compute radius of tangent zone for perpendicular case
2877     Standard_Real aCriteria = Precision::Confusion() * 0.5;
2878
2879     Standard_Real aT1 = aCriteria;
2880     Standard_Real aT2 = aCriteria;
2881     if ( j == 0 ) {
2882       // internal tangency
2883       Standard_Real aR = ( aRadius1 > aTor2.MinorRadius() ) ? aRadius1 : aTor2.MinorRadius();
2884       //aT1 = aCriteria * aCriteria + aR * aR - ( aR - aCriteria ) * ( aR - aCriteria );
2885       aT1 = 2. * aR * aCriteria;
2886       aT2 = aT1;
2887     }
2888     else {
2889       // external tangency
2890       Standard_Real aRb = ( aRadius1 > aTor2.MinorRadius() ) ? aRadius1 : aTor2.MinorRadius();
2891       Standard_Real aRm = ( aRadius1 < aTor2.MinorRadius() ) ? aRadius1 : aTor2.MinorRadius();
2892       Standard_Real aDelta = aRb - aCriteria;
2893       aDelta *= aDelta;
2894       aDelta -= aRm * aRm;
2895       aDelta /= 2. * (aRb - aRm);
2896       aDelta -= 0.5 * (aRb - aRm);
2897       
2898       aT1 = 2. * aRm * (aRm - aDelta);
2899       aT2 = aT1;
2900     }
2901     aCriteria = ( aT1 > aT2) ? aT1 : aT2;
2902     if ( aCriteria > 0 )
2903       aCriteria = sqrt( aCriteria );
2904
2905     if ( aCriteria > 0.5 * aTor1.MinorRadius() ) {
2906       // too big zone -> drop to minimum
2907       aCriteria = Precision::Confusion();
2908     }
2909
2910     GeomAdaptor_Curve aC1( new Geom_Circle(aCircle1) );
2911     GeomAdaptor_Curve aC2( new Geom_Circle(aCircle2) );
2912     Extrema_ExtCC anExtrema(aC1, aC2, 0, 2.*Standard_PI, 0, 2.*Standard_PI, 
2913                             Precision::PConfusion(), Precision::PConfusion());
2914         
2915     if ( anExtrema.IsDone() ) {
2916
2917       Standard_Integer i = 0;
2918       for ( i = 1; i <= anExtrema.NbExt(); i++ ) {
2919         if ( anExtrema.SquareDistance(i) > aCriteria * aCriteria )
2920           continue;
2921
2922         Extrema_POnCurv P1, P2;
2923         anExtrema.Points( i, P1, P2 );
2924
2925         Standard_Boolean bFoundResult = Standard_True;
2926         gp_Pnt2d pr1, pr2;
2927
2928         Standard_Integer surfit = 0;
2929         for ( surfit = 0; surfit < 2; surfit++ ) {
2930           GeomAPI_ProjectPointOnSurf& aProjector = (surfit == 0) ? aContext.ProjPS(theFace1) : aContext.ProjPS(theFace2);
2931
2932           gp_Pnt aP3d = (surfit == 0) ? P1.Value() : P2.Value();
2933           aProjector.Perform(aP3d);
2934
2935           if(!aProjector.IsDone())
2936             bFoundResult = Standard_False;
2937           else {
2938             if(aProjector.LowerDistance() > aCriteria) {
2939               bFoundResult = Standard_False;
2940             }
2941             else {
2942               Standard_Real foundU = 0, foundV = 0;
2943               aProjector.LowerDistanceParameters(foundU, foundV);
2944               if ( surfit == 0 )
2945                 pr1 = gp_Pnt2d( foundU, foundV );
2946               else
2947                 pr2 = gp_Pnt2d( foundU, foundV );
2948             }
2949           }
2950         }
2951         if ( bFoundResult ) {
2952           aSeqResultS1.Append( pr1 );
2953           aSeqResultS2.Append( pr2 );
2954           aSeqResultRad.Append( aCriteria );
2955
2956           // torus is u and v periodic
2957           const Standard_Real twoPI = Standard_PI + Standard_PI;
2958           Standard_Real arr1tmp[2] = {pr1.X(), pr1.Y()};
2959           Standard_Real arr2tmp[2] = {pr2.X(), pr2.Y()};
2960
2961           // iteration on period bounds
2962           for ( Standard_Integer k1 = 0; k1 < 2; k1++ ) {
2963             Standard_Real aBound = ( k1 == 0 ) ? 0 : twoPI;
2964             Standard_Real aShift = ( k1 == 0 ) ? twoPI : -twoPI;
2965
2966             // iteration on surfaces
2967             for ( Standard_Integer k2 = 0; k2 < 2; k2++ ) {
2968               Standard_Real* arr1 = ( k2 == 0 ) ? arr1tmp : arr2tmp;
2969               Standard_Real* arr2 = ( k2 != 0 ) ? arr1tmp : arr2tmp;
2970               TColgp_SequenceOfPnt2d& aSeqS1 = ( k2 == 0 ) ? aSeqResultS1 : aSeqResultS2; 
2971               TColgp_SequenceOfPnt2d& aSeqS2 = ( k2 != 0 ) ? aSeqResultS1 : aSeqResultS2; 
2972
2973               if (fabs(arr1[0] - aBound) < Precision::PConfusion()) {
2974                 aSeqS1.Append( gp_Pnt2d( arr1[0] + aShift, arr1[1] ) );
2975                 aSeqS2.Append( gp_Pnt2d( arr2[0], arr2[1] ) );
2976                 aSeqResultRad.Append( aCriteria );
2977               }
2978               if (fabs(arr1[1] - aBound) < Precision::PConfusion()) {
2979                 aSeqS1.Append( gp_Pnt2d( arr1[0], arr1[1] + aShift) );
2980                 aSeqS2.Append( gp_Pnt2d( arr2[0], arr2[1] ) );
2981                 aSeqResultRad.Append( aCriteria );
2982               }
2983             }
2984           } //
2985         }
2986       }
2987     }
2988   }
2989   aResult = aSeqResultRad.Length();
2990
2991   if ( aResult > 0 ) {
2992     theResultOnS1 = new TColgp_HArray1OfPnt2d( 1, aResult );
2993     theResultOnS2 = new TColgp_HArray1OfPnt2d( 1, aResult );
2994     theResultRadius = new TColStd_HArray1OfReal( 1, aResult );
2995
2996     for ( Standard_Integer i = 1 ; i <= aResult; i++ ) {
2997       theResultOnS1->SetValue( i, aSeqResultS1.Value(i) );
2998       theResultOnS2->SetValue( i, aSeqResultS2.Value(i) );
2999       theResultRadius->SetValue( i, aSeqResultRad.Value(i) );
3000     }
3001   }
3002   return aResult;
3003 }
3004
3005 // ------------------------------------------------------------------------------------------------
3006 // static function: AdjustByNeighbour
3007 // purpose:
3008 // ------------------------------------------------------------------------------------------------
3009 gp_Pnt2d AdjustByNeighbour(const gp_Pnt2d&     theaNeighbourPoint,
3010                            const gp_Pnt2d&     theOriginalPoint,
3011                            Handle(GeomAdaptor_HSurface) theGASurface) {
3012   
3013   gp_Pnt2d ap1 = theaNeighbourPoint;
3014   gp_Pnt2d ap2 = theOriginalPoint;
3015
3016   if ( theGASurface->IsUPeriodic() ) {
3017     Standard_Real aPeriod     = theGASurface->UPeriod();
3018     gp_Pnt2d aPTest = ap2;
3019     Standard_Real aSqDistMin = 1.e+100;
3020
3021     for ( Standard_Integer pIt = -1; pIt <= 1; pIt++) {
3022       aPTest.SetX( theOriginalPoint.X() + aPeriod * pIt );
3023       Standard_Real dd = ap1.SquareDistance( aPTest );
3024
3025       if ( dd < aSqDistMin ) {
3026         ap2 = aPTest;
3027         aSqDistMin = dd;
3028       }
3029     }
3030   }
3031   if ( theGASurface->IsVPeriodic() ) {
3032     Standard_Real aPeriod     = theGASurface->VPeriod();
3033     gp_Pnt2d aPTest = ap2;
3034     Standard_Real aSqDistMin = 1.e+100;
3035
3036     for ( Standard_Integer pIt = -1; pIt <= 1; pIt++) {
3037       aPTest.SetY( theOriginalPoint.Y() + aPeriod * pIt );
3038       Standard_Real dd = ap1.SquareDistance( aPTest );
3039
3040       if ( dd < aSqDistMin ) {
3041         ap2 = aPTest;
3042         aSqDistMin = dd;
3043       }
3044     }
3045   }
3046   return ap2;
3047 }
3048
3049 // ------------------------------------------------------------------------------------------------
3050 //function: DecompositionOfWLine
3051 // purpose:
3052 // ------------------------------------------------------------------------------------------------
3053 Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
3054                                       const Handle(GeomAdaptor_HSurface)&            theSurface1, 
3055                                       const Handle(GeomAdaptor_HSurface)&            theSurface2,
3056                                       const TopoDS_Face&                             theFace1,
3057                                       const TopoDS_Face&                             theFace2,
3058                                       const IntTools_LineConstructor&                theLConstructor,
3059                                       const Standard_Boolean                         theAvoidLConstructor,
3060                                       IntPatch_SequenceOfLine&                       theNewLines,
3061                                       Standard_Real&                                 theReachedTol3d) {
3062
3063   Standard_Boolean bRet, bAvoidLineConstructor;
3064   Standard_Integer aNbPnts, aNbParts;
3065   //
3066   bRet=Standard_False;
3067   aNbPnts=theWLine->NbPnts();
3068   bAvoidLineConstructor=theAvoidLConstructor;
3069   //
3070   if(!aNbPnts){
3071     return bRet;
3072   }
3073   if (!bAvoidLineConstructor) {
3074     aNbParts=theLConstructor.NbParts();
3075     if (!aNbParts) {
3076       return bRet;
3077     }
3078   }
3079   //
3080   Standard_Boolean bIsPrevPointOnBoundary, bIsPointOnBoundary, bIsCurrentPointOnBoundary;
3081   Standard_Integer nblines, pit, i, j;
3082   Standard_Real aTol;
3083   TColStd_Array1OfListOfInteger anArrayOfLines(1, aNbPnts); 
3084   TColStd_Array1OfInteger       anArrayOfLineType(1, aNbPnts);
3085   TColStd_ListOfInteger aListOfPointIndex;
3086   IntTools_Context aContext;
3087   
3088   Handle(TColgp_HArray1OfPnt2d) aTanZoneS1;
3089   Handle(TColgp_HArray1OfPnt2d) aTanZoneS2;
3090   Handle(TColStd_HArray1OfReal) aTanZoneRadius;
3091   Standard_Integer aNbZone = ComputeTangentZones( theSurface1, theSurface2, theFace1, theFace2,
3092                                                  aTanZoneS1, aTanZoneS2, aTanZoneRadius );
3093   
3094   //
3095   nblines=0;
3096   aTol=Precision::Confusion();
3097   aTol=0.5*aTol;
3098   bIsPrevPointOnBoundary=Standard_False;
3099   bIsPointOnBoundary=Standard_False;
3100   //
3101   // 1. ...
3102   //
3103   // Points
3104   for(pit = 1; pit <= aNbPnts; ++pit) {
3105     Standard_Boolean bIsOnFirstBoundary, isperiodic;
3106     Standard_Real aResolution, aPeriod, alowerboundary, aupperboundary, U, V;
3107     Standard_Real aParameter, anoffset, anAdjustPar;
3108     Standard_Real umin, umax, vmin, vmax;
3109     //
3110     bIsCurrentPointOnBoundary = Standard_False;
3111     const IntSurf_PntOn2S& aPoint = theWLine->Point(pit);
3112     //
3113     // Surface
3114     for(i = 0; i < 2; ++i) {
3115       Handle(GeomAdaptor_HSurface) aGASurface = (!i) ? theSurface1 : theSurface2;
3116       aGASurface->ChangeSurface().Surface()->Bounds(umin, umax, vmin, vmax);
3117       if(!i) {
3118         aPoint.ParametersOnS1(U, V);
3119       }
3120       else {
3121         aPoint.ParametersOnS2(U, V);
3122       }
3123       // U, V
3124       for(j = 0; j < 2; j++) {
3125         isperiodic = (!j) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
3126         if(!isperiodic){
3127           continue;
3128         }
3129         //
3130         if (!j) {
3131           aResolution=aGASurface->UResolution(aTol);
3132           aPeriod=aGASurface->UPeriod();
3133           alowerboundary=umin;
3134           aupperboundary=umax;
3135           aParameter=U;
3136         }
3137         else {
3138           aResolution=aGASurface->VResolution(aTol);
3139           aPeriod=aGASurface->VPeriod();
3140           alowerboundary=vmin;
3141           aupperboundary=vmax;
3142           aParameter=V;
3143         }
3144         
3145         anoffset = 0.;
3146         anAdjustPar = AdjustPeriodic(aParameter, 
3147                                      alowerboundary, 
3148                                      aupperboundary, 
3149                                      aPeriod, 
3150                                      anoffset);
3151         //
3152         bIsOnFirstBoundary = Standard_True;// ?
3153         bIsPointOnBoundary=
3154           IsPointOnBoundary(anAdjustPar, 
3155                             alowerboundary, 
3156                             aupperboundary,
3157                             aResolution, 
3158                             bIsOnFirstBoundary);
3159         //
3160         if(bIsPointOnBoundary) {
3161           bIsCurrentPointOnBoundary = Standard_True;
3162           break;
3163         }
3164         else {
3165           // check if a point belong to a tangent zone. Begin
3166           Standard_Integer zIt = 0;
3167           for ( zIt = 1; zIt <= aNbZone; zIt++ ) {
3168             gp_Pnt2d aPZone = (i == 0) ? aTanZoneS1->Value(zIt) : aTanZoneS2->Value(zIt);
3169             Standard_Real aZoneRadius = aTanZoneRadius->Value(zIt);
3170
3171             if ( IsInsideTanZone(gp_Pnt2d( U, V ), aPZone, aZoneRadius, aGASurface ) ) {
3172               // set boundary flag to split the curve by a tangent zone
3173               bIsPointOnBoundary = Standard_True;
3174               bIsCurrentPointOnBoundary = Standard_True;
3175               if ( theReachedTol3d < aZoneRadius ) {
3176                 theReachedTol3d = aZoneRadius;
3177               }
3178               break;
3179             }
3180           }
3181         }
3182       }//for(j = 0; j < 2; j++) {
3183
3184       if(bIsCurrentPointOnBoundary){
3185         break;
3186       }
3187     }//for(i = 0; i < 2; ++i) {
3188     //
3189     if((bIsCurrentPointOnBoundary != bIsPrevPointOnBoundary)) {
3190       if(!aListOfPointIndex.IsEmpty()) {
3191         nblines++;
3192         anArrayOfLines.SetValue(nblines, aListOfPointIndex);
3193         anArrayOfLineType.SetValue(nblines, bIsPrevPointOnBoundary);
3194         aListOfPointIndex.Clear();
3195       }
3196       bIsPrevPointOnBoundary = bIsCurrentPointOnBoundary;
3197     }
3198     aListOfPointIndex.Append(pit);
3199   } //for(pit = 1; pit <= aNbPnts; ++pit) {
3200   //
3201   if(!aListOfPointIndex.IsEmpty()) {
3202     nblines++;
3203     anArrayOfLines.SetValue(nblines, aListOfPointIndex);
3204     anArrayOfLineType.SetValue(nblines, bIsPrevPointOnBoundary);
3205     aListOfPointIndex.Clear();
3206   }
3207   //
3208   if(nblines<=1) {
3209     return bRet; //Standard_False;
3210   }
3211   //
3212   // 
3213   // 2. Correct wlines.begin
3214   TColStd_Array1OfListOfInteger anArrayOfLineEnds(1, nblines);
3215   Handle(IntSurf_LineOn2S) aSeqOfPntOn2S = new IntSurf_LineOn2S();
3216   //
3217   for(i = 1; i <= nblines; i++) {
3218     if(anArrayOfLineType.Value(i) != 0) {
3219       continue;
3220     }
3221     const TColStd_ListOfInteger& aListOfIndex = anArrayOfLines.Value(i);
3222     if(aListOfIndex.Extent() < 2) {
3223       continue;
3224     }
3225     TColStd_ListOfInteger aListOfFLIndex;
3226
3227     for(j = 0; j < 2; j++) {
3228       Standard_Integer aneighbourindex = (j == 0) ? (i - 1) : (i + 1);
3229
3230       if((aneighbourindex < 1) || (aneighbourindex > nblines))
3231         continue;
3232
3233       if(anArrayOfLineType.Value(aneighbourindex) == 0)
3234         continue;
3235       const TColStd_ListOfInteger& aNeighbour = anArrayOfLines.Value(aneighbourindex);
3236       Standard_Integer anIndex = (j == 0) ? aNeighbour.Last() : aNeighbour.First();
3237       const IntSurf_PntOn2S& aPoint = theWLine->Point(anIndex);
3238
3239       IntSurf_PntOn2S aNewP = aPoint;
3240       
3241       for(Standard_Integer surfit = 0; surfit < 2; surfit++) {
3242
3243         Handle(GeomAdaptor_HSurface) aGASurface = (surfit == 0) ? theSurface1 : theSurface2;
3244         Standard_Real umin=0., umax=0., vmin=0., vmax=0.;
3245         aGASurface->ChangeSurface().Surface()->Bounds(umin, umax, vmin, vmax);
3246         Standard_Real U=0., V=0.;
3247
3248         if(surfit == 0)
3249           aNewP.ParametersOnS1(U, V);
3250         else
3251           aNewP.ParametersOnS2(U, V);
3252         Standard_Integer nbboundaries = 0;
3253
3254         Standard_Boolean bIsNearBoundary = Standard_False;
3255         Standard_Integer aZoneIndex = 0;
3256         Standard_Integer bIsUBoundary = Standard_False; // use if nbboundaries == 1
3257         Standard_Integer bIsFirstBoundary = Standard_False; // use if nbboundaries == 1
3258         
3259
3260         for(Standard_Integer parit = 0; parit < 2; parit++) {
3261           Standard_Boolean isperiodic = (parit == 0) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
3262
3263           Standard_Real aResolution = (parit == 0) ? aGASurface->UResolution(aTol) : aGASurface->VResolution(aTol);
3264           Standard_Real alowerboundary = (parit == 0) ? umin : vmin;
3265           Standard_Real aupperboundary = (parit == 0) ? umax : vmax;
3266
3267           Standard_Real aParameter = (parit == 0) ? U : V;
3268           Standard_Boolean bIsOnFirstBoundary = Standard_True;
3269   
3270           if(!isperiodic) {
3271             bIsPointOnBoundary=
3272               IsPointOnBoundary(aParameter, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary);
3273             if(bIsPointOnBoundary) {
3274               bIsUBoundary = (parit == 0);
3275               bIsFirstBoundary = bIsOnFirstBoundary;
3276               nbboundaries++;
3277             }
3278           }
3279           else {
3280             Standard_Real aPeriod     = (parit == 0) ? aGASurface->UPeriod() : aGASurface->VPeriod();
3281             Standard_Real anoffset = 0.;
3282             Standard_Real anAdjustPar = AdjustPeriodic(aParameter, alowerboundary, aupperboundary, aPeriod, anoffset);
3283
3284             bIsPointOnBoundary=
3285               IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary);
3286             if(bIsPointOnBoundary) {
3287               bIsUBoundary = (parit == 0);
3288               bIsFirstBoundary = bIsOnFirstBoundary;
3289               nbboundaries++;
3290             }
3291             else {
3292               //check neighbourhood of boundary
3293               Standard_Real anEpsilon = aResolution * 100.;
3294               Standard_Real aPart = ( aupperboundary - alowerboundary ) * 0.1;
3295               anEpsilon = ( anEpsilon > aPart ) ? aPart : anEpsilon;
3296                 
3297               bIsNearBoundary = IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary, 
3298                                                   anEpsilon, bIsOnFirstBoundary);
3299
3300             }
3301           }
3302         }
3303
3304         // check if a point belong to a tangent zone. Begin
3305         for ( Standard_Integer zIt = 1; zIt <= aNbZone; zIt++ ) {
3306           gp_Pnt2d aPZone = (surfit == 0) ? aTanZoneS1->Value(zIt) : aTanZoneS2->Value(zIt);
3307           Standard_Real aZoneRadius = aTanZoneRadius->Value(zIt);
3308
3309           Standard_Integer aneighbourpointindex1 = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
3310           const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
3311           Standard_Real nU1, nV1;
3312             
3313           if(surfit == 0)
3314             aNeighbourPoint.ParametersOnS1(nU1, nV1);
3315           else
3316             aNeighbourPoint.ParametersOnS2(nU1, nV1);
3317           gp_Pnt2d ap1(nU1, nV1);
3318           gp_Pnt2d ap2 = AdjustByNeighbour( ap1, gp_Pnt2d( U, V ), aGASurface );
3319
3320
3321           if ( IsInsideTanZone( ap2, aPZone, aZoneRadius, aGASurface ) ) {
3322             aZoneIndex = zIt;
3323             bIsNearBoundary = Standard_True;
3324             if ( theReachedTol3d < aZoneRadius ) {
3325               theReachedTol3d = aZoneRadius;
3326             }
3327           }
3328         }
3329         // check if a point belong to a tangent zone. End
3330         Standard_Boolean bComputeLineEnd = Standard_False;
3331
3332         if(nbboundaries == 2) {
3333           //xf
3334           //bComputeLineEnd = Standard_True;
3335           //xt
3336         }
3337         else if(nbboundaries == 1) {
3338           Standard_Boolean isperiodic = (bIsUBoundary) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
3339
3340           if(isperiodic) {
3341             Standard_Real alowerboundary = (bIsUBoundary) ? umin : vmin;
3342             Standard_Real aupperboundary = (bIsUBoundary) ? umax : vmax;
3343             Standard_Real aPeriod     = (bIsUBoundary) ? aGASurface->UPeriod() : aGASurface->VPeriod();
3344             Standard_Real aParameter = (bIsUBoundary) ? U : V;
3345             Standard_Real anoffset = 0.;
3346             Standard_Real anAdjustPar = AdjustPeriodic(aParameter, alowerboundary, aupperboundary, aPeriod, anoffset);
3347
3348             Standard_Real adist = (bIsFirstBoundary) ? fabs(anAdjustPar - alowerboundary) : fabs(anAdjustPar - aupperboundary);
3349             Standard_Real anotherPar = (bIsFirstBoundary) ? (aupperboundary - adist) : (alowerboundary + adist);
3350             anotherPar += anoffset;
3351             Standard_Integer aneighbourpointindex = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
3352             const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex);
3353             Standard_Real nU1, nV1;
3354
3355             if(surfit == 0)
3356               aNeighbourPoint.ParametersOnS1(nU1, nV1);
3357             else
3358               aNeighbourPoint.ParametersOnS2(nU1, nV1);
3359             
3360             Standard_Real adist1 = (bIsUBoundary) ? fabs(nU1 - U) : fabs(nV1 - V);
3361             Standard_Real adist2 = (bIsUBoundary) ? fabs(nU1 - anotherPar) : fabs(nV1 - anotherPar);
3362             bComputeLineEnd = Standard_True;
3363             Standard_Boolean bCheckAngle1 = Standard_False;
3364             Standard_Boolean bCheckAngle2 = Standard_False;
3365             gp_Vec2d aNewVec;
3366             Standard_Real anewU = (bIsUBoundary) ? anotherPar : U;
3367             Standard_Real anewV = (bIsUBoundary) ? V : anotherPar;
3368
3369             if(((adist1 - adist2) > Precision::PConfusion()) && 
3370                (adist2 < (aPeriod / 4.))) {
3371               bCheckAngle1 = Standard_True;
3372               aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(anewU, anewV));
3373
3374               if(aNewVec.SquareMagnitude() < (gp::Resolution() * gp::Resolution())) {
3375                 aNewP.SetValue((surfit == 0), anewU, anewV);
3376                 bCheckAngle1 = Standard_False;
3377               }
3378             }
3379             else if(adist1 < (aPeriod / 4.)) {
3380               bCheckAngle2 = Standard_True;
3381               aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(U, V));
3382
3383               if(aNewVec.SquareMagnitude() < (gp::Resolution() * gp::Resolution())) {
3384                 bCheckAngle2 = Standard_False;
3385               }
3386             }
3387
3388             if(bCheckAngle1 || bCheckAngle2) {
3389               // assume there are at least two points in line (see "if" above)
3390               Standard_Integer anindexother = aneighbourpointindex;
3391
3392               while((anindexother <= aListOfIndex.Last()) && (anindexother >= aListOfIndex.First())) {
3393                 anindexother = (j == 0) ? (anindexother + 1) : (anindexother - 1);
3394                 const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(anindexother);
3395                 Standard_Real nU2, nV2;
3396                 
3397                 if(surfit == 0)
3398                   aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
3399                 else
3400                   aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
3401                 gp_Vec2d aVecOld(gp_Pnt2d(nU2, nV2), gp_Pnt2d(nU1, nV1));
3402
3403                 if(aVecOld.SquareMagnitude() <= (gp::Resolution() * gp::Resolution())) {
3404                   continue;
3405                 }
3406                 else {
3407                   Standard_Real anAngle = aNewVec.Angle(aVecOld);
3408
3409                   if((fabs(anAngle) < (Standard_PI * 0.25)) && (aNewVec.Dot(aVecOld) > 0.)) {
3410
3411                     if(bCheckAngle1) {
3412                       Standard_Real U1, U2, V1, V2;
3413                       IntSurf_PntOn2S atmppoint = aNewP;
3414                       atmppoint.SetValue((surfit == 0), anewU, anewV);
3415                       atmppoint.Parameters(U1, V1, U2, V2);
3416                       gp_Pnt P1 = theSurface1->Value(U1, V1);
3417                       gp_Pnt P2 = theSurface2->Value(U2, V2);
3418                       gp_Pnt P0 = aPoint.Value();
3419
3420                       if(P0.IsEqual(P1, aTol) &&
3421                          P0.IsEqual(P2, aTol) &&
3422                          P1.IsEqual(P2, aTol)) {
3423                         bComputeLineEnd = Standard_False;
3424                         aNewP.SetValue((surfit == 0), anewU, anewV);
3425                       }
3426                     }
3427
3428                     if(bCheckAngle2) {
3429                       bComputeLineEnd = Standard_False;
3430                     }
3431                   }
3432                   break;
3433                 }
3434               } // end while(anindexother...)
3435             }
3436           }
3437         }
3438         else if ( bIsNearBoundary ) {
3439           bComputeLineEnd = Standard_True;
3440         }
3441
3442         if(bComputeLineEnd) {
3443
3444           gp_Pnt2d anewpoint;
3445           Standard_Boolean found = Standard_False;
3446
3447           if ( bIsNearBoundary ) {
3448             // re-compute point near natural boundary or near tangent zone
3449             Standard_Real u1, v1, u2, v2;
3450             aNewP.Parameters( u1, v1, u2, v2 );
3451             if(surfit == 0)
3452               anewpoint = gp_Pnt2d( u1, v1 );
3453             else
3454               anewpoint = gp_Pnt2d( u2, v2 );
3455             
3456             Standard_Integer aneighbourpointindex1 = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
3457             const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
3458             Standard_Real nU1, nV1;
3459             
3460             if(surfit == 0)
3461               aNeighbourPoint.ParametersOnS1(nU1, nV1);
3462             else
3463               aNeighbourPoint.ParametersOnS2(nU1, nV1);
3464             gp_Pnt2d ap1(nU1, nV1);
3465             gp_Pnt2d ap2;
3466
3467
3468             if ( aZoneIndex ) {
3469               // exclude point from a tangent zone
3470               anewpoint = AdjustByNeighbour( ap1, anewpoint, aGASurface );
3471               gp_Pnt2d aPZone = (surfit == 0) ? aTanZoneS1->Value(aZoneIndex) : aTanZoneS2->Value(aZoneIndex);
3472               Standard_Real aZoneRadius = aTanZoneRadius->Value(aZoneIndex);
3473
3474               if ( FindPoint(ap1, anewpoint, umin, umax, vmin, vmax, 
3475                              aPZone, aZoneRadius, aGASurface, ap2) ) {
3476                 anewpoint = ap2;
3477                 found = Standard_True;
3478               }
3479             }
3480             else if ( aGASurface->IsUPeriodic() || aGASurface->IsVPeriodic() ) {
3481               // re-compute point near boundary if shifted on a period
3482               ap2 = AdjustByNeighbour( ap1, anewpoint, aGASurface );
3483
3484               if ( ( ap2.X() < umin ) || ( ap2.X() > umax ) ||
3485                   ( ap2.Y() < vmin ) || ( ap2.Y() > vmax ) ) {
3486                 found = FindPoint(ap1, ap2, umin, umax, vmin, vmax, anewpoint);
3487               }
3488               else {
3489                 anewpoint = ap2;
3490                 aNewP.SetValue( (surfit == 0), anewpoint.X(), anewpoint.Y() );
3491               }
3492             }
3493           }
3494           else {
3495
3496             Standard_Integer aneighbourpointindex1 = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
3497             const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
3498             Standard_Real nU1, nV1;
3499
3500             if(surfit == 0)
3501               aNeighbourPoint.ParametersOnS1(nU1, nV1);
3502             else
3503               aNeighbourPoint.ParametersOnS2(nU1, nV1);
3504             gp_Pnt2d ap1(nU1, nV1);
3505             gp_Pnt2d ap2(nU1, nV1);
3506             Standard_Integer aneighbourpointindex2 = aneighbourpointindex1;
3507
3508             while((aneighbourpointindex2 <= aListOfIndex.Last()) && (aneighbourpointindex2 >= aListOfIndex.First())) {
3509               aneighbourpointindex2 = (j == 0) ? (aneighbourpointindex2 + 1) : (aneighbourpointindex2 - 1);
3510               const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(aneighbourpointindex2);
3511               Standard_Real nU2, nV2;
3512
3513               if(surfit == 0)
3514                 aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
3515               else
3516                 aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
3517               ap2.SetX(nU2);
3518               ap2.SetY(nV2);
3519
3520               if(ap1.SquareDistance(ap2) > (gp::Resolution() * gp::Resolution())) {
3521                 break;
3522               }
3523             }  
3524             found = FindPoint(ap2, ap1, umin, umax, vmin, vmax, anewpoint);
3525           }
3526
3527           if(found) {
3528             // check point
3529             Standard_Real aCriteria = BRep_Tool::Tolerance(theFace1) + BRep_Tool::Tolerance(theFace2);
3530             GeomAPI_ProjectPointOnSurf& aProjector = (surfit == 0) ? aContext.ProjPS(theFace2) : aContext.ProjPS(theFace1);
3531             Handle(GeomAdaptor_HSurface) aSurface = (surfit == 0) ? theSurface1 : theSurface2;
3532
3533             Handle(GeomAdaptor_HSurface) aSurfaceOther = (surfit == 0) ? theSurface2 : theSurface1;
3534
3535             gp_Pnt aP3d = aSurface->Value(anewpoint.X(), anewpoint.Y());
3536             aProjector.Perform(aP3d);
3537
3538             if(aProjector.IsDone()) {
3539               if(aProjector.LowerDistance() < aCriteria) {
3540                 Standard_Real foundU = U, foundV = V;
3541                 aProjector.LowerDistanceParameters(foundU, foundV);
3542
3543                 //Correction of projected coordinates. Begin
3544                 //Note, it may be shifted on a period
3545                 Standard_Integer aneindex1 = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
3546                 const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneindex1);
3547                 Standard_Real nUn, nVn;
3548                 
3549                 if(surfit == 0)
3550                   aNeighbourPoint.ParametersOnS2(nUn, nVn);
3551                 else
3552                   aNeighbourPoint.ParametersOnS1(nUn, nVn);
3553                 gp_Pnt2d aNeighbour2d(nUn, nVn);
3554                 gp_Pnt2d anAdjustedPoint = AdjustByNeighbour( aNeighbour2d, gp_Pnt2d(foundU, foundV), aSurfaceOther );
3555                 foundU = anAdjustedPoint.X();
3556                 foundV = anAdjustedPoint.Y();
3557
3558                 if ( ( anAdjustedPoint.X() < umin ) && ( anAdjustedPoint.X() > umax ) &&
3559                     ( anAdjustedPoint.Y() < vmin ) && ( anAdjustedPoint.Y() > vmax ) ) {
3560                   // attempt to roughly re-compute point
3561                   foundU = ( foundU < umin ) ? umin : foundU;
3562                   foundU = ( foundU > umax ) ? umax : foundU;
3563                   foundV = ( foundV < vmin ) ? vmin : foundV;
3564                   foundV = ( foundV > vmax ) ? vmax : foundV;
3565
3566                   GeomAPI_ProjectPointOnSurf& aProjector2 = (surfit == 0) ? aContext.ProjPS(theFace1) : aContext.ProjPS(theFace2);
3567
3568                   aP3d = aSurfaceOther->Value(foundU, foundV);
3569                   aProjector2.Perform(aP3d);
3570                   
3571                   if(aProjector2.IsDone()) {
3572                     if(aProjector2.LowerDistance() < aCriteria) {
3573                       Standard_Real foundU2 = anewpoint.X(), foundV2 = anewpoint.Y();
3574                       aProjector2.LowerDistanceParameters(foundU2, foundV2);
3575                       anewpoint.SetX(foundU2);
3576                       anewpoint.SetY(foundV2);
3577                     }
3578                   }
3579                 }
3580                 //Correction of projected coordinates. End
3581
3582                 if(surfit == 0)
3583                   aNewP.SetValue(aP3d, anewpoint.X(), anewpoint.Y(), foundU, foundV);
3584                 else
3585                   aNewP.SetValue(aP3d, foundU, foundV, anewpoint.X(), anewpoint.Y());
3586               }
3587             }
3588           }
3589         }
3590       }
3591       aSeqOfPntOn2S->Add(aNewP);
3592       aListOfFLIndex.Append(aSeqOfPntOn2S->NbPoints());
3593     }
3594     anArrayOfLineEnds.SetValue(i, aListOfFLIndex);
3595   }
3596   // Correct wlines.end
3597
3598   // Split wlines.begin
3599   Standard_Integer nbiter;
3600   //
3601   nbiter=1;
3602   if (!bAvoidLineConstructor) {
3603     nbiter=theLConstructor.NbParts();
3604   }
3605   //
3606   for(j = 1; j <= nbiter; ++j) {
3607     Standard_Real fprm, lprm;
3608     Standard_Integer ifprm, ilprm;
3609     //
3610     if(bAvoidLineConstructor) {
3611       ifprm = 1;
3612       ilprm = theWLine->NbPnts();
3613     }
3614     else {
3615       theLConstructor.Part(j, fprm, lprm);
3616       ifprm = (Standard_Integer)fprm;
3617       ilprm = (Standard_Integer)lprm;
3618     }
3619
3620     Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
3621     //
3622     for(i = 1; i <= nblines; i++) {
3623       if(anArrayOfLineType.Value(i) != 0) {
3624         continue;
3625       }
3626       const TColStd_ListOfInteger& aListOfIndex = anArrayOfLines.Value(i);
3627
3628       if(aListOfIndex.Extent() < 2) {
3629         continue;
3630       }
3631       const TColStd_ListOfInteger& aListOfFLIndex = anArrayOfLineEnds.Value(i);
3632       Standard_Boolean bhasfirstpoint = (aListOfFLIndex.Extent() == 2);
3633       Standard_Boolean bhaslastpoint = (aListOfFLIndex.Extent() == 2);
3634
3635       if(!bhasfirstpoint && !aListOfFLIndex.IsEmpty()) {
3636         bhasfirstpoint = (i != 1);
3637       }
3638
3639       if(!bhaslastpoint && !aListOfFLIndex.IsEmpty()) {
3640         bhaslastpoint = (i != nblines);
3641       }
3642       Standard_Boolean bIsFirstInside = ((ifprm >= aListOfIndex.First()) && (ifprm <= aListOfIndex.Last()));
3643       Standard_Boolean bIsLastInside =  ((ilprm >= aListOfIndex.First()) && (ilprm <= aListOfIndex.Last()));
3644
3645       if(!bIsFirstInside && !bIsLastInside) {
3646         if((ifprm < aListOfIndex.First()) && (ilprm > aListOfIndex.Last())) {
3647           // append whole line, and boundaries if neccesary
3648           if(bhasfirstpoint) {
3649             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.First());
3650             aLineOn2S->Add(aP);
3651           }
3652           TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
3653
3654           for(; anIt.More(); anIt.Next()) {
3655             const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
3656             aLineOn2S->Add(aP);
3657           }
3658
3659           if(bhaslastpoint) {
3660             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.Last());
3661             aLineOn2S->Add(aP);
3662           }
3663
3664           // check end of split line (end is almost always)
3665           Standard_Integer aneighbour = i + 1;
3666           Standard_Boolean bIsEndOfLine = Standard_True;
3667
3668           if(aneighbour <= nblines) {
3669             const TColStd_ListOfInteger& aListOfNeighbourIndex = anArrayOfLines.Value(aneighbour);
3670
3671             if((anArrayOfLineType.Value(aneighbour) != 0) &&
3672                (aListOfNeighbourIndex.IsEmpty())) {
3673               bIsEndOfLine = Standard_False;
3674             }
3675           }
3676
3677           if(bIsEndOfLine) {
3678             if(aLineOn2S->NbPoints() > 1) {
3679               Handle(IntPatch_WLine) aNewWLine = 
3680                 new IntPatch_WLine(aLineOn2S, Standard_False);
3681               theNewLines.Append(aNewWLine);
3682             }
3683             aLineOn2S = new IntSurf_LineOn2S();
3684           }
3685         }
3686         continue;
3687       }
3688       // end if(!bIsFirstInside && !bIsLastInside)
3689
3690       if(bIsFirstInside && bIsLastInside) {
3691         // append inside points between ifprm and ilprm
3692         TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
3693
3694         for(; anIt.More(); anIt.Next()) {
3695           if((anIt.Value() < ifprm) || (anIt.Value() > ilprm))
3696             continue;
3697           const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
3698           aLineOn2S->Add(aP);
3699         }
3700       }
3701       else {
3702
3703         if(bIsFirstInside) {
3704           // append points from ifprm to last point + boundary point
3705           TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
3706
3707           for(; anIt.More(); anIt.Next()) {
3708             if(anIt.Value() < ifprm)
3709               continue;
3710             const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
3711             aLineOn2S->Add(aP);
3712           }
3713
3714           if(bhaslastpoint) {
3715             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.Last());
3716             aLineOn2S->Add(aP);
3717           }
3718           // check end of split line (end is almost always)
3719           Standard_Integer aneighbour = i + 1;
3720           Standard_Boolean bIsEndOfLine = Standard_True;
3721
3722           if(aneighbour <= nblines) {
3723             const TColStd_ListOfInteger& aListOfNeighbourIndex = anArrayOfLines.Value(aneighbour);
3724
3725             if((anArrayOfLineType.Value(aneighbour) != 0) &&
3726                (aListOfNeighbourIndex.IsEmpty())) {
3727               bIsEndOfLine = Standard_False;
3728             }
3729           }
3730
3731           if(bIsEndOfLine) {
3732             if(aLineOn2S->NbPoints() > 1) {
3733               Handle(IntPatch_WLine) aNewWLine = 
3734                 new IntPatch_WLine(aLineOn2S, Standard_False);
3735               theNewLines.Append(aNewWLine);
3736             }
3737             aLineOn2S = new IntSurf_LineOn2S();
3738           }
3739         }
3740         // end if(bIsFirstInside)
3741
3742         if(bIsLastInside) {
3743           // append points from first boundary point to ilprm
3744           if(bhasfirstpoint) {
3745             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.First());
3746             aLineOn2S->Add(aP);
3747           }
3748           TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
3749
3750           for(; anIt.More(); anIt.Next()) {
3751             if(anIt.Value() > ilprm)
3752               continue;
3753             const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
3754             aLineOn2S->Add(aP);
3755           }
3756         }
3757         //end if(bIsLastInside)
3758       }
3759     }
3760
3761     if(aLineOn2S->NbPoints() > 1) {
3762       Handle(IntPatch_WLine) aNewWLine = 
3763         new IntPatch_WLine(aLineOn2S, Standard_False);
3764       theNewLines.Append(aNewWLine);
3765     }
3766   }
3767   // Split wlines.end
3768
3769   return Standard_True;
3770 }
3771
3772 // ------------------------------------------------------------------------------------------------
3773 // static function: ParameterOutOfBoundary
3774 // purpose:         Computes a new parameter for given curve. The corresponding 2d points 
3775 //                  does not lay on any boundary of given faces
3776 // ------------------------------------------------------------------------------------------------
3777 Standard_Boolean ParameterOutOfBoundary(const Standard_Real       theParameter, 
3778                                         const Handle(Geom_Curve)& theCurve, 
3779                                         const TopoDS_Face&        theFace1, 
3780                                         const TopoDS_Face&        theFace2,
3781                                         const Standard_Real       theOtherParameter,
3782                                         const Standard_Boolean    bIncreasePar,
3783                                         Standard_Real&            theNewParameter) {
3784   Standard_Boolean bIsComputed = Standard_False;
3785   theNewParameter = theParameter;
3786
3787   IntTools_Context aContext;
3788   Standard_Real acurpar = theParameter;
3789   TopAbs_State aState = TopAbs_ON;
3790   Standard_Integer iter = 0;
3791   Standard_Real asumtol = BRep_Tool::Tolerance(theFace1) + BRep_Tool::Tolerance(theFace2);
3792   Standard_Real adelta = asumtol * 0.1;
3793   adelta = (adelta < Precision::Confusion()) ? Precision::Confusion() : adelta;
3794   Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(theFace1);
3795   Handle(Geom_Surface) aSurf2 = BRep_Tool::Surface(theFace2);
3796
3797   Standard_Real u1, u2, v1, v2;
3798
3799   GeomAPI_ProjectPointOnSurf aPrj1;
3800   aSurf1->Bounds(u1, u2, v1, v2);
3801   aPrj1.Init(aSurf1, u1, u2, v1, v2);
3802
3803   GeomAPI_ProjectPointOnSurf aPrj2;
3804   aSurf2->Bounds(u1, u2, v1, v2);
3805   aPrj2.Init(aSurf2, u1, u2, v1, v2);
3806
3807   while(aState == TopAbs_ON) {
3808     if(bIncreasePar)
3809       acurpar += adelta;
3810     else
3811       acurpar -= adelta;
3812     gp_Pnt aPCurrent = theCurve->Value(acurpar);
3813     aPrj1.Perform(aPCurrent);
3814     Standard_Real U=0., V=0.;
3815
3816     if(aPrj1.IsDone()) {
3817       aPrj1.LowerDistanceParameters(U, V);
3818       aState = aContext.StatePointFace(theFace1, gp_Pnt2d(U, V));
3819     }
3820
3821     if(aState != TopAbs_ON) {
3822       aPrj2.Perform(aPCurrent);
3823                 
3824       if(aPrj2.IsDone()) {
3825         aPrj2.LowerDistanceParameters(U, V);
3826         aState = aContext.StatePointFace(theFace2, gp_Pnt2d(U, V));
3827       }
3828     }
3829
3830     if(iter > 11) {
3831       break;
3832     }
3833     iter++;
3834   }
3835
3836   if(iter <= 11) {
3837     theNewParameter = acurpar;
3838     bIsComputed = Standard_True;
3839
3840     if(bIncreasePar) {
3841       if(acurpar >= theOtherParameter)
3842         theNewParameter = theOtherParameter;
3843     }
3844     else {
3845       if(acurpar <= theOtherParameter)
3846         theNewParameter = theOtherParameter;
3847     }
3848   }
3849   return bIsComputed;
3850 }
3851
3852 Standard_Boolean IsCurveValid(Handle(Geom2d_Curve)& thePCurve)
3853 {
3854   if(thePCurve.IsNull())
3855     return Standard_False;
3856
3857   Standard_Real tolint = 1.e-10;
3858   Geom2dAdaptor_Curve PCA;
3859   IntRes2d_Domain PCD;
3860   Geom2dInt_GInter PCI;
3861
3862   Standard_Real pf = 0., pl = 0.;
3863   gp_Pnt2d pntf, pntl;
3864
3865   if(!thePCurve->IsClosed() && !thePCurve->IsPeriodic()) {
3866     pf = thePCurve->FirstParameter();
3867     pl = thePCurve->LastParameter();
3868     pntf = thePCurve->Value(pf);
3869     pntl = thePCurve->Value(pl);
3870     PCA.Load(thePCurve);
3871     if(!PCA.IsPeriodic()) {
3872       if(PCA.FirstParameter() > pf) pf = PCA.FirstParameter();
3873       if(PCA.LastParameter()  < pl) pl = PCA.LastParameter();
3874     }
3875     PCD.SetValues(pntf,pf,tolint,pntl,pl,tolint);
3876     PCI.Perform(PCA,PCD,tolint,tolint);
3877     if(PCI.IsDone())
3878       if(PCI.NbPoints() > 0) {
3879         return Standard_False;
3880       }
3881   }
3882
3883   return Standard_True;
3884 }
3885
3886 //=======================================================================
3887 //static function : ApproxWithPCurves
3888 //purpose  : for bug 20964 only
3889 //=======================================================================
3890
3891 Standard_Boolean ApproxWithPCurves(const gp_Cylinder& theCyl, 
3892                                    const gp_Sphere& theSph)
3893 {
3894   Standard_Boolean bRes = Standard_True;
3895   Standard_Real R1 = theCyl.Radius(), R2 = theSph.Radius();
3896
3897   if(R1 < 2.*R2) return bRes;
3898
3899   gp_Lin anCylAx(theCyl.Axis());
3900
3901   Standard_Real aDist = anCylAx.Distance(theSph.Location());
3902   Standard_Real aDRel = Abs(aDist - R1)/R2;
3903
3904   if(aDRel > .2) return bRes;
3905
3906   Standard_Real par = ElCLib::Parameter(anCylAx, theSph.Location());
3907   gp_Pnt aP = ElCLib::Value(par, anCylAx);
3908   gp_Vec aV(aP, theSph.Location());
3909
3910   Standard_Real dd = aV.Dot(theSph.Position().XDirection());
3911
3912   if(aDist < R1 && dd > 0.) return Standard_False;
3913   if(aDist > R1 && dd < 0.) return Standard_False;
3914
3915   
3916   return bRes;
3917 }
3918
3919 //=======================================================================
3920 //function : PerformPlanes
3921 //purpose  : 
3922 //=======================================================================
3923
3924 void  PerformPlanes(const Handle(GeomAdaptor_HSurface)& theS1, 
3925                     const Handle(GeomAdaptor_HSurface)& theS2, 
3926                     const Standard_Real TolAng, 
3927                     const Standard_Real TolTang, 
3928                     const Standard_Boolean theApprox1,
3929                     const Standard_Boolean theApprox2,
3930                     IntTools_SequenceOfCurves& theSeqOfCurve, 
3931                     Standard_Boolean& theTangentFaces)
3932 {
3933
3934   gp_Pln aPln1 = theS1->Surface().Plane();
3935   gp_Pln aPln2 = theS2->Surface().Plane();
3936
3937   IntAna_QuadQuadGeo aPlnInter(aPln1, aPln2, TolAng, TolTang);
3938
3939   if(!aPlnInter.IsDone()) {
3940     theTangentFaces = Standard_False;
3941     return;
3942   }
3943
3944   IntAna_ResultType aResType = aPlnInter.TypeInter();
3945
3946   if(aResType == IntAna_Same) {
3947     theTangentFaces = Standard_True;
3948     return;
3949   }
3950
3951   theTangentFaces = Standard_False;
3952
3953   if(aResType == IntAna_Empty) {
3954     return;
3955   }
3956
3957   gp_Lin aLin = aPlnInter.Line(1);
3958
3959   ProjLib_Plane aProj;
3960
3961   aProj.Init(aPln1);
3962   aProj.Project(aLin);
3963   gp_Lin2d aLin2d1 = aProj.Line();
3964   //
3965   aProj.Init(aPln2);
3966   aProj.Project(aLin);
3967   gp_Lin2d aLin2d2 = aProj.Line();
3968   //
3969   //classify line2d1 relatively first plane
3970   Standard_Real P11, P12;
3971   Standard_Boolean IsCrossed = ClassifyLin2d(theS1, aLin2d1, TolTang, P11, P12);
3972   if(!IsCrossed) return;
3973   //classify line2d2 relatively second plane
3974   Standard_Real P21, P22;
3975   IsCrossed = ClassifyLin2d(theS2, aLin2d2, TolTang, P21, P22);
3976   if(!IsCrossed) return;
3977
3978   //Analysis of parametric intervals: must have common part
3979
3980   if(P21 >= P12) return;
3981   if(P22 <= P11) return;
3982
3983   Standard_Real pmin, pmax;
3984   pmin = Max(P11, P21);
3985   pmax = Min(P12, P22);
3986
3987   if(pmax - pmin <= TolTang) return;
3988
3989   Handle(Geom_Line) aGLin = new Geom_Line(aLin);
3990
3991   IntTools_Curve aCurve;
3992   Handle(Geom_TrimmedCurve) aGTLin = new Geom_TrimmedCurve(aGLin, pmin, pmax);
3993
3994   aCurve.SetCurve(aGTLin);
3995
3996   if(theApprox1) { 
3997     Handle(Geom2d_Line) C2d = new Geom2d_Line(aLin2d1);
3998     aCurve.SetFirstCurve2d(new Geom2d_TrimmedCurve(C2d, pmin, pmax));
3999   }
4000   else { 
4001     Handle(Geom2d_Curve) H1;
4002     aCurve.SetFirstCurve2d(H1);
4003   }
4004   if(theApprox2) { 
4005     Handle(Geom2d_Line) C2d = new Geom2d_Line(aLin2d2);
4006     aCurve.SetSecondCurve2d(new Geom2d_TrimmedCurve(C2d, pmin, pmax));
4007   }
4008   else { 
4009     Handle(Geom2d_Curve) H1;
4010     aCurve.SetFirstCurve2d(H1);
4011   }
4012
4013   theSeqOfCurve.Append(aCurve);
4014  
4015 }
4016
4017 //=======================================================================
4018 //function : ClassifyLin2d
4019 //purpose  : 
4020 //=======================================================================
4021 static inline Standard_Boolean INTER(const Standard_Real d1, 
4022                                      const Standard_Real d2, 
4023                                      const Standard_Real tol) 
4024 {
4025   return (d1 > tol && d2 < -tol) || 
4026          (d1 < -tol && d2 > tol) ||
4027          ((d1 <= tol && d1 >= -tol) && (d2 > tol || d2 < -tol)) || 
4028          ((d2 <= tol && d2 >= -tol) && (d1 > tol || d1 < -tol));
4029 }
4030 static inline Standard_Boolean COINC(const Standard_Real d1, 
4031                                      const Standard_Real d2, 
4032                                      const Standard_Real tol) 
4033 {
4034   return (d1 <= tol && d1 >= -tol) && (d2 <= tol && d2 >= -tol);
4035 }
4036 Standard_Boolean ClassifyLin2d(const Handle(GeomAdaptor_HSurface)& theS, 
4037                                const gp_Lin2d& theLin2d, 
4038                                const Standard_Real theTol,
4039                                Standard_Real& theP1, 
4040                                Standard_Real& theP2)
4041
4042 {
4043   Standard_Real xmin, xmax, ymin, ymax, d1, d2, A, B, C;
4044   Standard_Real par[2];
4045   Standard_Integer nbi = 0;
4046
4047   xmin = theS->Surface().FirstUParameter();
4048   xmax = theS->Surface().LastUParameter();
4049   ymin = theS->Surface().FirstVParameter();
4050   ymax = theS->Surface().LastVParameter();
4051
4052   theLin2d.Coefficients(A, B, C);
4053
4054   //xmin, ymin <-> xmin, ymax
4055   d1 = A*xmin + B*ymin + C;
4056   d2 = A*xmin + B*ymax + C;
4057
4058   if(INTER(d1, d2, theTol)) {
4059     //Intersection with boundary
4060     Standard_Real y = -(C + A*xmin)/B;
4061     par[nbi] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, y));
4062     nbi++;
4063   }
4064   else if (COINC(d1, d2, theTol)) {
4065     //Coincidence with boundary
4066     par[0] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, ymin));
4067     par[1] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, ymax));
4068     nbi = 2;
4069   }
4070
4071   if(nbi == 2) {
4072
4073     if(fabs(par[0]-par[1]) > theTol) {
4074       theP1 = Min(par[0], par[1]);
4075       theP2 = Max(par[0], par[1]);
4076       return Standard_True;
4077     }
4078     else return Standard_False;
4079
4080   }
4081
4082   //xmin, ymax <-> xmax, ymax
4083   d1 = d2;
4084   d2 = A*xmax + B*ymax + C;
4085
4086   if(d1 > theTol || d1 < -theTol) {//to avoid checking of
4087                                    //coincidence with the same point
4088     if(INTER(d1, d2, theTol)) {
4089       Standard_Real x = -(C + B*ymax)/A;
4090       par[nbi] = ElCLib::Parameter(theLin2d, gp_Pnt2d(x, ymax));
4091       nbi++;
4092     }
4093     else if (COINC(d1, d2, theTol)) {
4094       par[0] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, ymax));
4095       par[1] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, ymax));
4096       nbi = 2;
4097     }
4098   }
4099
4100   if(nbi == 2) {
4101
4102     if(fabs(par[0]-par[1]) > theTol) {
4103       theP1 = Min(par[0], par[1]);
4104       theP2 = Max(par[0], par[1]);
4105       return Standard_True;
4106     }
4107     else return Standard_False;
4108
4109   }
4110
4111   //xmax, ymax <-> xmax, ymin
4112   d1 = d2;
4113   d2 = A*xmax + B*ymin + C;
4114
4115   if(d1 > theTol || d1 < -theTol) {
4116     if(INTER(d1, d2, theTol)) {
4117       Standard_Real y = -(C + A*xmax)/B;
4118       par[nbi] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, y));
4119       nbi++;
4120     }
4121     else if (COINC(d1, d2, theTol)) {
4122       par[0] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, ymax));
4123       par[1] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, ymin));
4124       nbi = 2;
4125     }
4126   }
4127
4128   if(nbi == 2) {
4129     if(fabs(par[0]-par[1]) > theTol) {
4130       theP1 = Min(par[0], par[1]);
4131       theP2 = Max(par[0], par[1]);
4132       return Standard_True;
4133     }
4134     else return Standard_False;
4135   }
4136
4137   //xmax, ymin <-> xmin, ymin 
4138   d1 = d2;
4139   d2 = A*xmin + B*ymin + C;
4140
4141   if(d1 > theTol || d1 < -theTol) {
4142     if(INTER(d1, d2, theTol)) {
4143       Standard_Real x = -(C + B*ymin)/A;
4144       par[nbi] = ElCLib::Parameter(theLin2d, gp_Pnt2d(x, ymin));
4145       nbi++;
4146     }
4147     else if (COINC(d1, d2, theTol)) {
4148       par[0] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmax, ymin));
4149       par[1] = ElCLib::Parameter(theLin2d, gp_Pnt2d(xmin, ymin));
4150       nbi = 2;
4151     }
4152   }
4153
4154   if(nbi == 2) {
4155     if(fabs(par[0]-par[1]) > theTol) {
4156       theP1 = Min(par[0], par[1]);
4157       theP2 = Max(par[0], par[1]);
4158       return Standard_True;
4159     }
4160     else return Standard_False;
4161   }
4162
4163   return Standard_False;
4164
4165 }
4166 //
4167 //modified by NIZNHY-PKV Thu Sep 23 08:37:32 2010f
4168 //=======================================================================
4169 //function : ApproxParameters
4170 //purpose  : 
4171 //=======================================================================
4172 void ApproxParameters(const Handle(GeomAdaptor_HSurface)& aHS1,
4173                       const Handle(GeomAdaptor_HSurface)& aHS2,
4174                       Standard_Integer& iDegMin,
4175                       Standard_Integer& iDegMax,
4176                       Standard_Integer& iNbIterMax,
4177                       Standard_Boolean& anWithPC
4178                       )
4179 {
4180   GeomAbs_SurfaceType aTS1, aTS2;
4181   //
4182   iDegMin=4;
4183   iDegMax=8;
4184   iNbIterMax=0;
4185   //
4186   aTS1=aHS1->Surface().GetType();
4187   aTS2=aHS2->Surface().GetType();
4188   //
4189   // Cylinder/Torus
4190   if ((aTS1==GeomAbs_Cylinder && aTS2==GeomAbs_Torus) ||
4191       (aTS2==GeomAbs_Cylinder && aTS1==GeomAbs_Torus)) {
4192     Standard_Real aRC, aRT, dR, aPC, aDPC, aScPr;
4193     gp_Cylinder aCylinder;
4194     gp_Torus aTorus;
4195     //
4196     aPC=Precision::Confusion();
4197     //
4198     aCylinder=(aTS1==GeomAbs_Cylinder)? 
4199       aHS1->Surface().Cylinder() : 
4200       aHS2->Surface().Cylinder();
4201     aTorus=(aTS1==GeomAbs_Torus)? 
4202       aHS1->Surface().Torus() : 
4203       aHS2->Surface().Torus();
4204     //
4205     aRC=aCylinder.Radius();
4206     aRT=aTorus.MinorRadius();
4207     dR=aRC-aRT;
4208     if (dR<0.) {
4209       dR=-dR;
4210     }
4211     //
4212     if (dR<aPC) {
4213       const gp_Ax3& aPosT=aTorus.Position();
4214       const gp_Dir& aDirT=aPosT.Direction();
4215       //      
4216       const gp_Ax1& aAxisC=aCylinder.Axis();
4217       const gp_Dir& aDirC=aAxisC.Direction();
4218       //
4219       aScPr=aDirT*aDirC;
4220       if (aScPr<0.){
4221         aScPr=-aScPr;
4222       }
4223       //
4224       if (aScPr<aPC) {
4225         gp_Pln aPlnT(aPosT);
4226         const gp_Pnt& aLocC=aCylinder.Location();
4227         
4228         aDPC=aPlnT.SquareDistance(aLocC);
4229         if (aDPC<2.5e-9) {
4230           iDegMax=6;
4231           anWithPC=Standard_False;
4232           iNbIterMax=10;
4233         }
4234       }
4235     }
4236   }
4237 }
4238 //modified by NIZNHY-PKV Thu Sep 23 08:37:39 2010t