0025416: Wrong section curve
[occt.git] / src / IntPatch / IntPatch_ImpPrmIntersection.cxx
1 // Created on: 1992-05-07
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <IntPatch_ImpPrmIntersection.ixx>
18
19 #include <Standard_ConstructionError.hxx>
20 #include <IntPatch_SequenceOfLine.hxx>
21 #include <TColStd_Array1OfInteger.hxx>
22 #include <IntSurf_PntOn2S.hxx>
23 #include <IntSurf_LineOn2S.hxx>
24 #include <IntSurf.hxx>
25 #include <IntSurf_InteriorPoint.hxx>
26
27 #include <Adaptor2d_HCurve2d.hxx>
28 #include <IntSurf_PathPoint.hxx>
29 #include <IntSurf_SequenceOfPathPoint.hxx>
30 #include <IntPatch_TheIWalking.hxx>
31 #include <IntPatch_TheIWLineOfTheIWalking.hxx>
32 #include <IntPatch_ThePathPointOfTheSOnBounds.hxx>
33 #include <IntPatch_TheSegmentOfTheSOnBounds.hxx>
34 #include <IntPatch_TheSurfFunction.hxx>
35 #include <IntPatch_RLine.hxx>
36 #include <IntPatch_WLine.hxx>
37 #include <IntPatch_ArcFunction.hxx>
38 #include <IntPatch_RstInt.hxx>
39 #ifndef OCCT_DEBUG
40 #define No_Standard_RangeError
41 #define No_Standard_OutOfRange
42 #endif
43
44 #include <math_Vector.hxx>
45 #include <math_Matrix.hxx>
46 #include <TopTrans_CurveTransition.hxx>
47 #include <TopAbs_State.hxx>
48 #include <TopAbs_Orientation.hxx>
49 #include <TColStd_Array1OfInteger.hxx>
50 #include <TColStd_Array1OfReal.hxx>
51
52 #include <IntSurf_SequenceOfInteriorPoint.hxx>
53 #include <IntSurf_QuadricTool.hxx>
54 #include <GeomAbs_SurfaceType.hxx>
55 #include <IntAna2d_AnaIntersection.hxx>
56 #include <gp_Lin2d.hxx>
57 #include <ElCLib.hxx>
58
59 #include <Bnd_Box2d.hxx>
60
61 static Standard_Boolean DecomposeResult(const Handle(IntPatch_Line)&   Line,
62   const Standard_Boolean         IsReversed,
63   const IntSurf_Quadric&         Quad,
64   const Handle(Adaptor3d_TopolTool)&    PDomain,
65   const Handle(Adaptor3d_HSurface)&              QSurf,
66   const Standard_Real            ArcTol,
67   IntPatch_SequenceOfLine& Lines);
68 static 
69   void ComputeTangency (const IntPatch_TheSOnBounds& solrst,
70   IntSurf_SequenceOfPathPoint& seqpdep,
71   const Handle(Adaptor3d_TopolTool)& Domain,
72   IntPatch_TheSurfFunction& Func,
73   const Handle(Adaptor3d_HSurface)& PSurf,
74   TColStd_Array1OfInteger& Destination);
75 static 
76   void Recadre(const Standard_Boolean ,
77   GeomAbs_SurfaceType typeS1,
78   GeomAbs_SurfaceType typeS2,
79   IntPatch_Point&  pt,
80   const Handle(IntPatch_TheIWLineOfTheIWalking)& iwline,
81   Standard_Integer Param,
82   Standard_Real U1,
83   Standard_Real V1,
84   Standard_Real U2,
85   Standard_Real V2);
86
87 static Standard_Boolean IsIn2DBox(const Bnd_Box2d& theBox,
88                                   const Handle(IntPatch_PointLine)& theLine,
89                                   const Standard_Real theUPeriod,
90                                   const Standard_Real theVPeriod,
91                                   const Standard_Boolean isTheSurface1Using);
92
93 //=======================================================================
94 //function : IntPatch_ImpPrmIntersection
95 //purpose  : 
96 //=======================================================================
97 IntPatch_ImpPrmIntersection::IntPatch_ImpPrmIntersection ()
98   : done(Standard_False),
99   empt(Standard_False),
100   myIsStartPnt(Standard_False),
101   myUStart(0.0),
102   myVStart(0.0)
103 { }
104
105
106 //=======================================================================
107 //function : IntPatch_ImpPrmIntersection
108 //purpose  : 
109 //=======================================================================
110
111 IntPatch_ImpPrmIntersection::IntPatch_ImpPrmIntersection
112   (const Handle(Adaptor3d_HSurface)&    Surf1,
113   const Handle(Adaptor3d_TopolTool)&   D1,
114   const Handle(Adaptor3d_HSurface)&    Surf2,
115   const Handle(Adaptor3d_TopolTool)&   D2,
116   const Standard_Real    TolArc,
117   const Standard_Real    TolTang,
118   const Standard_Real    Fleche,
119   const Standard_Real    Pas)
120   : done(Standard_False),
121   empt(Standard_False),
122   myIsStartPnt(Standard_False),
123   myUStart(0.0),
124   myVStart(0.0)
125 {
126   Perform(Surf1,D1,Surf2,D2,TolArc,TolTang,Fleche,Pas);
127 }
128
129
130 //=======================================================================
131 //function : SetStartPoint
132 //purpose  : 
133 //=======================================================================
134
135 void IntPatch_ImpPrmIntersection::SetStartPoint(const Standard_Real U,
136   const Standard_Real V)
137 {
138   myIsStartPnt = Standard_True;
139   myUStart = U; myVStart = V;
140 }
141
142 //=======================================================================
143 //function : ComputeTangency
144 //purpose  : 
145 //=======================================================================
146 void ComputeTangency (const IntPatch_TheSOnBounds& solrst,
147   IntSurf_SequenceOfPathPoint& seqpdep,
148   const Handle(Adaptor3d_TopolTool)& Domain,
149   IntPatch_TheSurfFunction& Func,
150   const Handle(Adaptor3d_HSurface)& PSurf,
151   TColStd_Array1OfInteger& Destination)
152 {
153   Standard_Integer i,k, NbPoints, seqlength;
154   Standard_Real theparam,test;
155   Standard_Boolean fairpt, ispassing;
156   TopAbs_Orientation arcorien,vtxorien;
157   Handle(Adaptor2d_HCurve2d) thearc;
158   Handle(Adaptor3d_HVertex) vtx,vtxbis;
159   //Standard_Boolean ispassing;
160   IntPatch_ThePathPointOfTheSOnBounds PStart;
161   IntSurf_PathPoint PPoint;
162   gp_Vec vectg;
163   gp_Dir2d dirtg;
164   gp_Pnt ptbid;
165   gp_Vec d1u,d1v,v1,v2;
166   gp_Pnt2d p2d;
167   gp_Vec2d d2d;
168   //
169   double aX[2], aF[1], aD[1][2];
170   math_Vector X(aX, 1, 2);
171   math_Vector F(aF, 1, 1);
172   math_Matrix D(aD, 1, 1, 1, 2); 
173   //
174   seqlength = 0;
175   NbPoints = solrst.NbPoints();
176   for (i=1; i<= NbPoints; i++) {
177     if (Destination(i) == 0) {
178       PStart = solrst.Point(i);
179       thearc   = PStart.Arc();
180       theparam = PStart.Parameter();
181       arcorien = Domain->Orientation(thearc);
182       ispassing = (arcorien == TopAbs_INTERNAL || 
183         arcorien == TopAbs_EXTERNAL);
184
185       thearc->D0(theparam,p2d);
186       X(1) = p2d.X(); 
187       X(2) = p2d.Y();
188       PPoint.SetValue(PStart.Value(),X(1),X(2));
189
190       Func.Values(X,F,D);
191       if (Func.IsTangent()) {
192         PPoint.SetTangency(Standard_True);
193         Destination(i) = seqlength+1;
194         if (!PStart.IsNew()) {
195           vtx = PStart.Vertex();
196           for (k=i+1; k<=NbPoints; k++) {
197             if (Destination(k) ==0) {
198               PStart = solrst.Point(k);
199               if (!PStart.IsNew()) {
200                 vtxbis = PStart.Vertex();
201                 if (Domain->Identical(vtx,vtxbis)) {
202                   thearc   = PStart.Arc();
203                   theparam = PStart.Parameter();
204                   arcorien = Domain->Orientation(thearc);
205                   ispassing = ispassing && (arcorien == TopAbs_INTERNAL ||
206                     arcorien == TopAbs_EXTERNAL);
207
208                   thearc->D0(theparam,p2d);
209                   PPoint.AddUV(p2d.X(),p2d.Y());
210                   Destination(k) = seqlength+1;
211                 }
212               }
213             }
214           }
215         }
216         PPoint.SetPassing(ispassing);
217         seqpdep.Append(PPoint);
218         seqlength++;
219       }
220       else { // on a un point de depart potentiel
221
222         vectg = Func.Direction3d();
223         dirtg = Func.Direction2d();
224
225         PSurf->D1(X(1),X(2),ptbid,d1u,d1v);
226         thearc->D1(theparam,p2d,d2d);
227         v2.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
228         v1 = d1u.Crossed(d1v);
229
230         test = vectg.Dot(v1.Crossed(v2));
231         if (PStart.IsNew()) {
232           if ((test < 0. && arcorien == TopAbs_FORWARD) ||
233             (test > 0. && arcorien == TopAbs_REVERSED)) {
234               vectg.Reverse();
235               dirtg.Reverse();
236           }
237           PPoint.SetDirections(vectg,dirtg);
238           PPoint.SetPassing(ispassing);
239           Destination(i) = seqlength+1;
240           seqpdep.Append(PPoint);
241           seqlength++;
242         }
243         else { // traiter la transition complexe
244           gp_Dir bidnorm(1.,1.,1.);
245           Standard_Real tole = 1.e-8;
246           TopAbs_Orientation LocTrans;
247           TopTrans_CurveTransition comptrans;
248           comptrans.Reset(vectg,bidnorm,0.);
249           if (arcorien == TopAbs_FORWARD || 
250             arcorien == TopAbs_REVERSED) {
251               // pour essai
252
253               vtx = PStart.Vertex();
254               vtxorien = Domain->Orientation(vtx);
255               if (Abs(test) <= tole) {
256                 LocTrans = TopAbs_EXTERNAL; // et pourquoi pas INTERNAL
257               }
258               else {
259                 if (((test > 0.)&& arcorien == TopAbs_FORWARD) ||
260                   ((test < 0.)&& arcorien == TopAbs_REVERSED)){
261                     LocTrans = TopAbs_FORWARD;
262                 }
263                 else {
264                   LocTrans = TopAbs_REVERSED;
265                 }
266                 if (arcorien == TopAbs_REVERSED) {v2.Reverse();}
267               }
268
269               comptrans.Compare(tole,v2,bidnorm,0.,LocTrans,vtxorien);
270           }
271           Destination(i) = seqlength+1;
272           for (k= i+1; k<=NbPoints; k++) {
273             if (Destination(k) == 0) {
274               PStart = solrst.Point(k);
275               if (!PStart.IsNew()) {
276                 vtxbis = PStart.Vertex();
277                 if (Domain->Identical(vtx,vtxbis)) {
278                   thearc   = PStart.Arc();
279                   theparam = PStart.Parameter();
280                   arcorien = Domain->Orientation(thearc);
281
282                   PPoint.AddUV(X(1),X(2));
283
284                   thearc->D1(theparam,p2d,d2d);
285                   PPoint.AddUV(p2d.X(),p2d.Y());
286
287                   if (arcorien == TopAbs_FORWARD || 
288                     arcorien == TopAbs_REVERSED) {
289                       ispassing = Standard_False;
290                       v2.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
291
292                       test = vectg.Dot(v1.Crossed(v2));
293                       vtxorien = Domain->Orientation(PStart.Vertex());
294                       if (Abs(test) <= tole) {
295                         LocTrans = TopAbs_EXTERNAL; // et pourquoi pas INTERNAL
296                       }
297                       else {
298                         if (((test > 0.)&& arcorien == TopAbs_FORWARD) ||
299                           ((test < 0.)&& arcorien == TopAbs_REVERSED)){
300                             LocTrans = TopAbs_FORWARD;
301                         }
302                         else {
303                           LocTrans = TopAbs_REVERSED;
304                         }
305                         if (arcorien == TopAbs_REVERSED) {v2.Reverse();}
306                       }
307
308                       comptrans.Compare(tole,v2,bidnorm,0.,LocTrans,vtxorien);
309                   }
310                   Destination(k) = seqlength+1;
311                 }
312               }
313             }
314           }
315           fairpt = Standard_True;
316           if (!ispassing) {
317             TopAbs_State Before = comptrans.StateBefore();
318             TopAbs_State After  = comptrans.StateAfter();
319             if ((Before == TopAbs_UNKNOWN)||(After == TopAbs_UNKNOWN)) {
320               fairpt = Standard_False;
321             }
322             else if (Before == TopAbs_IN) {
323               if (After == TopAbs_IN) {
324                 ispassing = Standard_True;
325               }
326               else {
327                 vectg.Reverse();
328                 dirtg.Reverse();
329               }
330             }
331             else {
332               if (After !=TopAbs_IN) {
333                 fairpt = Standard_False;
334               }
335             }
336           }
337           if (fairpt) {
338             PPoint.SetDirections(vectg,dirtg);
339             PPoint.SetPassing(ispassing);
340             seqpdep.Append(PPoint);
341             seqlength++;
342           }
343           else { // il faut remettre en "ordre" si on ne garde pas le point.
344             for (k=i; k <=NbPoints ; k++) {
345               if (Destination(k)==seqlength + 1) {
346                 Destination(k) = -Destination(k);
347               }
348             }
349           }
350         }
351       }
352     }
353   }
354 }
355 //=======================================================================
356 //function : Recadre
357 //purpose  : 
358 //=======================================================================
359 void Recadre(const Standard_Boolean ,
360   GeomAbs_SurfaceType typeS1,
361   GeomAbs_SurfaceType typeS2,
362   IntPatch_Point&  pt,
363   const Handle(IntPatch_TheIWLineOfTheIWalking)& iwline,
364   Standard_Integer Param,
365   Standard_Real U1,
366   Standard_Real V1,
367   Standard_Real U2,
368   Standard_Real V2)
369 {
370   Standard_Real U1p,V1p,U2p,V2p;
371   iwline->Line()->Value(Param).Parameters(U1p,V1p,U2p,V2p);
372   switch(typeS1)
373   {
374   case GeomAbs_Torus:
375     while(V1<(V1p-1.5*M_PI)) V1+=M_PI+M_PI;
376     while(V1>(V1p+1.5*M_PI)) V1-=M_PI+M_PI;
377   case GeomAbs_Cylinder:
378   case GeomAbs_Cone:
379   case GeomAbs_Sphere:
380     while(U1<(U1p-1.5*M_PI)) U1+=M_PI+M_PI;
381     while(U1>(U1p+1.5*M_PI)) U1-=M_PI+M_PI;
382   default:
383     break;
384   }
385   switch(typeS2)
386   { 
387   case GeomAbs_Torus:
388     while(V2<(V2p-1.5*M_PI)) V2+=M_PI+M_PI;
389     while(V2>(V2p+1.5*M_PI)) V2-=M_PI+M_PI;
390   case GeomAbs_Cylinder:
391   case GeomAbs_Cone:
392   case GeomAbs_Sphere:
393     while(U2<(U2p-1.5*M_PI)) U2+=M_PI+M_PI;
394     while(U2>(U2p+1.5*M_PI)) U2-=M_PI+M_PI;
395   default:
396     break;
397   }
398   pt.SetParameters(U1,V1,U2,V2);
399 }
400
401 //=======================================================================
402 //function : Perform
403 //purpose  : 
404 //=======================================================================
405 void IntPatch_ImpPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)& Surf1,
406   const Handle(Adaptor3d_TopolTool)& D1,
407   const Handle(Adaptor3d_HSurface)& Surf2,
408   const Handle(Adaptor3d_TopolTool)& D2,
409   const Standard_Real TolArc,
410   const Standard_Real TolTang,
411   const Standard_Real Fleche,
412   const Standard_Real Pas)
413 {
414   Standard_Boolean reversed, procf, procl, dofirst, dolast;
415   Standard_Integer indfirst = 0, indlast = 0, ind2, NbSegm;
416   Standard_Integer NbPointIns, NbPointRst, Nblines, Nbpts, NbPointDep;
417   Standard_Real U1,V1,U2,V2,paramf,paraml,currentparam;
418
419   IntPatch_TheSegmentOfTheSOnBounds thesegm;
420   IntSurf_PathPoint PPoint;
421
422   Handle(IntPatch_RLine) rline;
423   Handle(IntPatch_WLine) wline;
424   IntPatch_ThePathPointOfTheSOnBounds PStart,PStartf,PStartl;
425   IntPatch_Point ptdeb,ptfin,ptbis;
426
427   IntPatch_IType typ;
428   IntSurf_Transition TLine,TArc;
429   IntSurf_TypeTrans trans1,trans2;
430   gp_Pnt valpt,ptbid;
431   gp_Vec tgline,tgrst,norm1,norm2,d1u,d1v;
432   gp_Dir DirNormale;
433   gp_Vec VecNormale;
434
435   gp_Pnt2d p2d;
436   gp_Vec2d d2d;
437
438   Handle(Adaptor2d_HCurve2d) currentarc;
439   GeomAbs_SurfaceType typeS1, typeS2;
440   IntSurf_Quadric Quad;
441   IntPatch_TheSurfFunction Func;
442   IntPatch_ArcFunction AFunc;
443   //
444   typeS1 = Surf1->GetType();
445   typeS2 = Surf2->GetType();
446
447   paramf =0.;
448   paraml =0.;
449   trans1 = IntSurf_Undecided;
450   trans2 = IntSurf_Undecided;
451   //
452   done = Standard_False;
453   empt = Standard_True;
454   slin.Clear();
455   spnt.Clear();
456   //
457   reversed = Standard_False;
458   switch (typeS1)
459   {
460   case GeomAbs_Plane:
461     Quad.SetValue(Surf1->Plane());
462     break;
463
464   case GeomAbs_Cylinder:
465     Quad.SetValue(Surf1->Cylinder());
466     break;
467
468   case GeomAbs_Sphere:
469     Quad.SetValue(Surf1->Sphere());
470     break;
471
472   case GeomAbs_Cone:
473     Quad.SetValue(Surf1->Cone());
474     break;
475
476   default:
477     {
478       reversed = Standard_True;
479       switch (typeS2)
480       {
481       case GeomAbs_Plane:
482         Quad.SetValue(Surf2->Plane());
483         break;
484
485       case GeomAbs_Cylinder:
486         Quad.SetValue(Surf2->Cylinder());
487         break;
488
489       case GeomAbs_Sphere:
490         Quad.SetValue(Surf2->Sphere());
491         break;
492
493       case GeomAbs_Cone:
494         Quad.SetValue(Surf2->Cone());
495         break;
496       default:
497         {
498           Standard_ConstructionError::Raise();
499           break;
500         }
501       } 
502     }
503     break;
504   }
505   //
506   Func.SetImplicitSurface(Quad);
507   Func.Set(IntSurf_QuadricTool::Tolerance(Quad));
508   AFunc.SetQuadric(Quad);
509   //
510   if (!reversed) {
511     Func.Set(Surf2);
512     AFunc.Set(Surf2);
513   }
514   else {
515     Func.Set(Surf1);
516     AFunc.Set(Surf1);
517   }
518   //
519   if (!reversed) {
520     solrst.Perform(AFunc,D2,TolArc,TolTang);
521   }
522   else {
523     solrst.Perform(AFunc,D1,TolArc,TolTang);
524   }
525   if (!solrst.IsDone()) {
526     return;
527   }
528   //
529   IntSurf_SequenceOfPathPoint seqpdep;
530   IntSurf_SequenceOfInteriorPoint seqpins;
531   //
532   NbPointRst = solrst.NbPoints();
533   TColStd_Array1OfInteger Destination(1,NbPointRst+1); Destination.Init(0);
534   if (NbPointRst) {
535     if (!reversed) {
536       ComputeTangency(solrst,seqpdep,D2,Func,Surf2,Destination);
537     }
538     else {
539       ComputeTangency(solrst,seqpdep,D1,Func,Surf1,Destination);
540     }
541   }
542   //
543   Standard_Boolean SearchIns = Standard_True;
544   if(Quad.TypeQuadric() == GeomAbs_Plane && solrst.NbSegments() > 0)
545   {
546     //For such kind of cases it is possible that whole surface is on one side of plane,
547     //plane only touches surface and does not cross it,
548     //so no inner points exist.
549     SearchIns = Standard_False;
550     Handle(Adaptor3d_TopolTool) T;
551     if(reversed)
552     {
553       T = D1;
554     }
555     else
556     {
557       T = D2;
558     }
559     Standard_Integer aNbSamples = 0;
560     aNbSamples = T->NbSamples();
561     gp_Pnt2d s2d;
562     gp_Pnt s3d;
563     Standard_Real aValf[1], aUVap[2];
564     math_Vector Valf(aValf,1,1), UVap(aUVap,1,2);
565     T->SamplePoint(1,s2d, s3d);
566     UVap(1)=s2d.X(); 
567     UVap(2)=s2d.Y();
568     Func.Value(UVap,Valf);
569     Standard_Real rvalf = Sign(1.,Valf(1));
570     for(Standard_Integer i = 2; i <= aNbSamples; ++i)
571     {
572       D1->SamplePoint(i,s2d, s3d);
573       UVap(1)=s2d.X(); 
574       UVap(2)=s2d.Y();
575       Func.Value(UVap,Valf);
576       if(rvalf * Valf(1) < 0.)
577       {
578         SearchIns = Standard_True;
579         break;
580       }   
581     }
582   }
583   // Recherche des points interieurs
584   NbPointIns = 0;
585   if(SearchIns) {
586     if (!reversed) {
587       if (myIsStartPnt)
588         solins.Perform(Func,Surf2,myUStart,myVStart);
589       else
590         solins.Perform(Func,Surf2,D2,TolTang);
591     }
592     else {
593       if (myIsStartPnt)
594         solins.Perform(Func,Surf1,myUStart,myVStart);
595       else
596         solins.Perform(Func,Surf1,D1,TolTang);
597     }
598     NbPointIns = solins.NbPoints();
599     for (Standard_Integer i=1; i <= NbPointIns; i++) {
600       seqpins.Append(solins.Value(i));
601     }
602   }
603   //
604   NbPointDep=seqpdep.Length();
605   //
606   if (NbPointDep || NbPointIns) {
607     IntPatch_TheIWalking iwalk(TolTang,Fleche,Pas);
608     if (!reversed) {
609       iwalk.Perform(seqpdep,seqpins,Func,Surf2);
610     }
611     else {
612       iwalk.Perform(seqpdep,seqpins,Func,Surf1,Standard_True);
613     }
614     if(!iwalk.IsDone()) {
615       return;
616     }
617
618     Standard_Real Vmin, Vmax, TolV = 1.e-14;
619     if (!reversed) { //Surf1 is quadric
620       Vmin = Surf1->FirstVParameter();
621       Vmax = Surf1->LastVParameter();
622     }
623     else { //Surf2 is quadric
624       Vmin = Surf2->FirstVParameter();
625       Vmax = Surf2->LastVParameter();
626     }
627     //
628     Nblines = iwalk.NbLines();
629     for (Standard_Integer j=1; j<=Nblines; j++) {
630       const Handle(IntPatch_TheIWLineOfTheIWalking)&  iwline  = iwalk.Value(j);
631       const Handle(IntSurf_LineOn2S)&                 thelin  = iwline->Line();
632
633       Nbpts = thelin->NbPoints();
634       if(Nbpts>=2) { 
635         Standard_Integer k = 0;
636         tgline = iwline->TangentVector(k);      
637         if(k>=1 && k<=Nbpts) { } else { k=Nbpts>>1; } 
638         valpt = thelin->Value(k).Value();       
639
640         if (!reversed) {
641           thelin->Value(k).ParametersOnS2(U2,V2);
642           norm1 = Quad.Normale(valpt);
643           Surf2->D1(U2,V2,ptbid,d1u,d1v);
644           norm2 = d1u.Crossed(d1v);
645         }
646         else {
647           thelin->Value(k).ParametersOnS1(U2,V2);
648           norm2 = Quad.Normale(valpt);
649           Surf1->D1(U2,V2,ptbid,d1u,d1v);
650           norm1 = d1u.Crossed(d1v);
651         }
652         if (tgline.DotCross(norm2,norm1) > 0.) {
653           trans1 = IntSurf_Out;
654           trans2 = IntSurf_In;
655         }
656         else {
657           trans1 = IntSurf_In;
658           trans2 = IntSurf_Out;
659         }
660
661         //
662         Standard_Real AnU1,AnU2,AnV2;
663
664         GeomAbs_SurfaceType typQuad = Quad.TypeQuadric();
665         Standard_Boolean arecadr=Standard_False;
666         valpt = thelin->Value(1).Value();
667         Quad.Parameters(valpt,AnU1,V1);
668
669         if((V1 < Vmin) && (Vmin-V1 < TolV)) V1 = Vmin;
670         if((V1 > Vmax) && (V1-Vmax < TolV)) V1 = Vmax;
671
672         if(reversed) { 
673           thelin->SetUV(1,Standard_False,AnU1,V1); //-- on va lire u2,v2
674           thelin->Value(1).ParametersOnS1(AnU2,AnV2);
675         }
676         else { 
677           thelin->SetUV(1,Standard_True,AnU1,V1);  //-- on va lire u1,v1 
678           thelin->Value(1).ParametersOnS2(AnU2,AnV2);
679         }
680
681         if(typQuad==GeomAbs_Cylinder || 
682           typQuad==GeomAbs_Cone || 
683           typQuad==GeomAbs_Sphere) { 
684             arecadr=Standard_True; 
685         } 
686         //
687         for (k=2; k<=Nbpts; ++k) {
688           valpt = thelin->Value(k).Value();
689           Quad.Parameters(valpt,U1,V1);
690           //
691           if((V1 < Vmin) && (Vmin-V1 < TolV)) {
692             V1 = Vmin;
693           }
694           if((V1 > Vmax) && (V1-Vmax < TolV)) {
695             V1 = Vmax;
696           }
697           //
698           if(arecadr) {
699             //modified by NIZNHY-PKV Fri Mar 28 15:06:01 2008f
700             Standard_Real aCf, aTwoPI;
701             //
702             aCf=0.;
703             aTwoPI=M_PI+M_PI;
704             if ((U1-AnU1) >  1.5*M_PI) { 
705               while ((U1-AnU1) > (1.5*M_PI+aCf*aTwoPI)) {
706                 aCf=aCf+1.;
707               }
708               U1=U1-aCf*aTwoPI;
709             } 
710             //
711             else {
712               while ((U1-AnU1) < (-1.5*M_PI-aCf*aTwoPI)) {
713                 aCf=aCf+1.;
714               }
715               U1=U1+aCf*aTwoPI;
716             }
717             // was:
718             //if ((U1-AnU1) >  1.5*M_PI) { 
719             //  U1-=M_PI+M_PI;
720             //}
721             //else if ((U1-AnU1) < -1.5*M_PI) { 
722             //  U1+=M_PI+M_PI; 
723             //}
724             //modified by NIZNHY-PKV Fri Mar 28 15:06:11 2008t
725           }
726           //
727           if(reversed) { 
728             thelin->SetUV(k,Standard_False,U1,V1);
729
730             thelin->Value(k).ParametersOnS1(U2,V2);
731             switch(typeS1) { 
732             case GeomAbs_Cylinder:
733             case GeomAbs_Cone:
734             case GeomAbs_Sphere:
735             case GeomAbs_Torus:
736               while(U2<(AnU2-1.5*M_PI)) U2+=M_PI+M_PI;
737               while(U2>(AnU2+1.5*M_PI)) U2-=M_PI+M_PI;
738               break;
739             default: 
740               break;
741             }
742             if(typeS2==GeomAbs_Torus) { 
743               while(V2<(AnV2-1.5*M_PI)) V2+=M_PI+M_PI;
744               while(V2>(AnV2+1.5*M_PI)) V2-=M_PI+M_PI;
745             }
746             thelin->SetUV(k,Standard_True,U2,V2);
747           }
748           else { 
749             thelin->SetUV(k,Standard_True,U1,V1);
750
751             thelin->Value(k).ParametersOnS2(U2,V2);
752             switch(typeS2) { 
753             case GeomAbs_Cylinder:
754             case GeomAbs_Cone:
755             case GeomAbs_Sphere:
756             case GeomAbs_Torus:
757               while(U2<(AnU2-1.5*M_PI)) U2+=M_PI+M_PI;
758               while(U2>(AnU2+1.5*M_PI)) U2-=M_PI+M_PI;
759               break;
760             default: 
761               break;
762             }
763             if(typeS2==GeomAbs_Torus) { 
764               while(V2<(AnV2-1.5*M_PI)) V2+=M_PI+M_PI;
765               while(V2>(AnV2+1.5*M_PI)) V2-=M_PI+M_PI;
766             }
767             thelin->SetUV(k,Standard_False,U2,V2);
768
769           }
770
771           AnU1=U1;
772           AnU2=U2;
773           AnV2=V2;
774         }
775         // <-A
776         wline = new IntPatch_WLine(thelin,Standard_False,trans1,trans2);
777
778         if (   iwline->HasFirstPoint() 
779           && iwline->IsTangentAtBegining() == Standard_False) 
780         {
781           indfirst = iwline->FirstPointIndex();
782           PPoint = seqpdep(indfirst);
783           tgline = PPoint.Direction3d();
784           Standard_Integer themult = PPoint.Multiplicity();
785           for (Standard_Integer i=NbPointRst; i>=1; i--) {
786             if (Destination(i) == indfirst) {
787               if (!reversed) { //-- typeS1 = Pln || Cyl || Sph || Cone
788                 Quad.Parameters(PPoint.Value(),U1,V1);
789
790                 if((V1 < Vmin) && (Vmin-V1 < TolV)) V1 = Vmin;
791                 if((V1 > Vmax) && (V1-Vmax < TolV)) V1 = Vmax;
792
793                 PPoint.Parameters(themult,U2,V2);
794                 Surf2->D1(U2,V2,ptbid,d1u,d1v); //-- @@@@
795               }
796               else {  //-- typeS1 != Pln && Cyl && Sph && Cone
797                 Quad.Parameters(PPoint.Value(),U2,V2);
798
799                 if((V2 < Vmin) && (Vmin-V2 < TolV)) V2 = Vmin;
800                 if((V2 > Vmax) && (V2-Vmax < TolV)) V2 = Vmax;
801
802                 PPoint.Parameters(themult,U1,V1);
803                 Surf1->D1(U1,V1,ptbid,d1u,d1v); //-- @@@@
804               }
805
806               VecNormale = d1u.Crossed(d1v);                      
807               //-- Modif du 27 Septembre 94 (Recadrage des pts U,V) 
808               ptdeb.SetValue(PPoint.Value(),TolArc,Standard_False);
809               ptdeb.SetParameters(U1,V1,U2,V2);
810               ptdeb.SetParameter(1.);
811
812               Recadre(reversed,typeS1,typeS2,ptdeb,iwline,1,U1,V1,U2,V2);
813
814               currentarc = solrst.Point(i).Arc();
815               currentparam = solrst.Point(i).Parameter();
816               currentarc->D1(currentparam,p2d,d2d);
817               tgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
818
819               Standard_Real squaremagnitudeVecNormale = VecNormale.SquareMagnitude();
820               if(squaremagnitudeVecNormale > 1e-13) { 
821                 DirNormale=VecNormale;
822                 IntSurf::MakeTransition(tgline,tgrst,DirNormale,TLine,TArc);
823               }
824               else { 
825                 TLine.SetValue(Standard_True,IntSurf_Undecided);
826                 TArc.SetValue(Standard_True,IntSurf_Undecided);
827               }
828
829               ptdeb.SetArc(reversed,currentarc,currentparam,TLine,TArc);
830               if (!solrst.Point(i).IsNew()) {
831                 ptdeb.SetVertex(reversed,solrst.Point(i).Vertex());
832               }
833               wline->AddVertex(ptdeb);
834               if (themult == 0) {
835                 wline->SetFirstPoint(wline->NbVertex());
836               }
837
838               themult--;
839             }
840           }
841         }
842         else if (iwline->IsTangentAtBegining()) 
843         {
844           gp_Pnt psol = thelin->Value(1).Value();
845           thelin->Value(1).ParametersOnS1(U1,V1);
846           thelin->Value(1).ParametersOnS2(U2,V2);
847           ptdeb.SetValue(psol,TolArc,Standard_True);
848           ptdeb.SetParameters(U1,V1,U2,V2);
849           ptdeb.SetParameter(1.);
850           wline->AddVertex(ptdeb);
851           wline->SetFirstPoint(wline->NbVertex());
852         }
853         else 
854         { 
855           gp_Pnt psol = thelin->Value(1).Value();
856           thelin->Value(1).ParametersOnS1(U1,V1);
857           thelin->Value(1).ParametersOnS2(U2,V2);
858           ptdeb.SetValue(psol,TolArc,Standard_False);
859           ptdeb.SetParameters(U1,V1,U2,V2);
860           ptdeb.SetParameter(1.);
861           wline->AddVertex(ptdeb);
862           wline->SetFirstPoint(wline->NbVertex());
863         }
864
865
866         if (   iwline->HasLastPoint() 
867           && iwline->IsTangentAtEnd() == Standard_False) 
868         {
869           indlast = iwline->LastPointIndex();
870           PPoint = seqpdep(indlast);
871           tgline = PPoint.Direction3d().Reversed();
872           Standard_Integer themult = PPoint.Multiplicity();
873           for (Standard_Integer i=NbPointRst; i >=1; i--) {
874             if (Destination(i) == indlast) {
875               if (!reversed) {
876                 Quad.Parameters(PPoint.Value(),U1,V1);
877
878                 if((V1 < Vmin) && (Vmin-V1 < TolV)) V1 = Vmin;
879                 if((V1 > Vmax) && (V1-Vmax < TolV)) V1 = Vmax;
880
881                 PPoint.Parameters(themult,U2,V2);
882                 Surf2->D1(U2,V2,ptbid,d1u,d1v); //-- @@@@
883                 VecNormale = d1u.Crossed(d1v);                    //-- @@@@
884               }
885               else {
886                 Quad.Parameters(PPoint.Value(),U2,V2);
887
888                 if((V2 < Vmin) && (Vmin-V2 < TolV)) V2 = Vmin;
889                 if((V2 > Vmax) && (V2-Vmax < TolV)) V2 = Vmax;
890
891                 PPoint.Parameters(themult,U1,V1);
892                 Surf1->D1(U1,V1,ptbid,d1u,d1v); //-- @@@@
893                 VecNormale = d1u.Crossed(d1v);                    //-- @@@@
894               }
895
896               ptfin.SetValue(PPoint.Value(),TolArc,Standard_False);
897               ptfin.SetParameters(U1,V1,U2,V2);
898               ptfin.SetParameter(Nbpts);
899
900               Recadre(reversed,typeS1,typeS2,ptfin,iwline,Nbpts-1,U1,V1,U2,V2);
901
902               currentarc = solrst.Point(i).Arc();
903               currentparam = solrst.Point(i).Parameter();
904               currentarc->D1(currentparam,p2d,d2d);
905               tgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
906
907
908               Standard_Real squaremagnitudeVecNormale = VecNormale.SquareMagnitude();
909               if(squaremagnitudeVecNormale > 1e-13) { 
910                 DirNormale=VecNormale;
911                 IntSurf::MakeTransition(tgline,tgrst,DirNormale,TLine,TArc);
912               }
913               else { 
914                 TLine.SetValue(Standard_True,IntSurf_Undecided);
915                 TArc.SetValue(Standard_True,IntSurf_Undecided);
916               }
917
918
919               ptfin.SetArc(reversed,currentarc,currentparam,TLine,TArc);
920               if (!solrst.Point(i).IsNew()) {
921                 ptfin.SetVertex(reversed,solrst.Point(i).Vertex());
922               }
923               wline->AddVertex(ptfin);
924               if (themult == 0) {
925                 wline->SetLastPoint(wline->NbVertex());
926               }
927
928               themult--;
929             }
930           }
931         }
932         else if (iwline->IsTangentAtEnd()) 
933         {
934           gp_Pnt psol = thelin->Value(Nbpts).Value();
935           thelin->Value(Nbpts).ParametersOnS1(U1,V1);
936           thelin->Value(Nbpts).ParametersOnS2(U2,V2);
937           ptfin.SetValue(psol,TolArc,Standard_True);
938           ptfin.SetParameters(U1,V1,U2,V2);
939           ptfin.SetParameter(Nbpts);
940           wline->AddVertex(ptfin);
941           wline->SetLastPoint(wline->NbVertex());
942         }
943         else 
944         { 
945           gp_Pnt psol = thelin->Value(Nbpts).Value();
946           thelin->Value(Nbpts).ParametersOnS1(U1,V1);
947           thelin->Value(Nbpts).ParametersOnS2(U2,V2);
948           ptfin.SetValue(psol,TolArc,Standard_False);
949           ptfin.SetParameters(U1,V1,U2,V2);
950           ptfin.SetParameter(Nbpts);
951           wline->AddVertex(ptfin);
952           wline->SetLastPoint(wline->NbVertex());
953         }
954         //
955         // Il faut traiter les points de passage.
956         slin.Append(wline);
957       }// if(Nbpts>=2) {
958     }// for (j=1; j<=Nblines; j++) {
959
960     // ON GERE LES RACCORDS ENTRE LIGNES. ELLE NE PEUVENT SE RACCORDER
961     // QUE SUR DES POINTS DE TANGENCE
962
963
964     Nblines = slin.Length();
965     for (Standard_Integer j=1; j<=Nblines-1; j++) {
966       dofirst = dolast = Standard_False;
967       const  Handle(IntPatch_Line)& slinj = slin(j);
968       const Handle(IntPatch_WLine)& wlin1 = *((Handle(IntPatch_WLine)*)&slinj);
969       if (wlin1->HasFirstPoint()) {
970         ptdeb = wlin1->FirstPoint(indfirst);
971         if (ptdeb.IsTangencyPoint()) {
972           dofirst = Standard_True;
973         }
974       }
975       if (wlin1->HasLastPoint()) {
976         ptfin = wlin1->LastPoint(indlast);
977         if (ptfin.IsTangencyPoint()) {
978           dolast = Standard_True;
979         }
980       }
981
982       if (dofirst || dolast) {
983         for (Standard_Integer k=j+1; k<=Nblines;k++) {
984           const  Handle(IntPatch_Line)& slink = slin(k);
985           const  Handle(IntPatch_WLine)& wlin2 = *((Handle(IntPatch_WLine)*)&slink);
986           if (wlin2->HasFirstPoint()) {
987             ptbis = wlin2->FirstPoint(ind2);
988             if (ptbis.IsTangencyPoint()) {
989               if (dofirst ) {
990                 if (ptdeb.Value().Distance(ptbis.Value()) <= TolArc) {
991                   ptdeb.SetMultiple(Standard_True);
992                   if (!ptbis.IsMultiple()) {
993                     ptbis.SetMultiple(Standard_True);
994                     wlin2->Replace(ind2,ptbis);
995                   }
996                 }
997               }
998               if (dolast ) {
999                 if (ptfin.Value().Distance(ptbis.Value()) <= TolArc) {
1000                   ptfin.SetMultiple(Standard_True);
1001                   if (!ptbis.IsMultiple()) {
1002                     ptbis.SetMultiple(Standard_True);
1003                     wlin2->Replace(ind2,ptbis);
1004                   }
1005                 }
1006               }
1007             }
1008           }
1009           if (wlin2->HasLastPoint()) {
1010             ptbis = wlin2->LastPoint(ind2);
1011             if (ptbis.IsTangencyPoint()) {
1012               if (dofirst ) {
1013                 if (ptdeb.Value().Distance(ptbis.Value()) <= TolArc) {
1014                   ptdeb.SetMultiple(Standard_True);
1015                   if (!ptbis.IsMultiple()) {
1016                     ptbis.SetMultiple(Standard_True);
1017                     wlin2->Replace(ind2,ptbis);
1018                   }
1019                 }
1020               }
1021               if (dolast ) {
1022                 if (ptfin.Value().Distance(ptbis.Value()) <= TolArc) {
1023                   ptfin.SetMultiple(Standard_True);
1024                   if (!ptbis.IsMultiple()) {
1025                     ptbis.SetMultiple(Standard_True);
1026                     wlin2->Replace(ind2,ptbis);
1027                   }
1028                 }
1029               }
1030             }
1031           }
1032         }
1033         if(dofirst) 
1034           wlin1->Replace(indfirst,ptdeb);
1035         if(dolast) 
1036           wlin1->Replace(indlast,ptfin);
1037       }
1038     }
1039   }// if (seqpdep.Length() != 0 || seqpins.Length() != 0) {
1040   //
1041   // Treatment the segments
1042   NbSegm = solrst.NbSegments();
1043   if (NbSegm) {
1044     for(Standard_Integer i=1; i<=NbSegm; i++) {
1045       thesegm = solrst.Segment(i);  
1046       //Check if segment is degenerated
1047       if(thesegm.HasFirstPoint() && thesegm.HasLastPoint())
1048       {
1049         Standard_Real tol2 = Precision::Confusion();
1050         tol2 *= tol2;
1051         const gp_Pnt& aPf = thesegm.FirstPoint().Value();
1052         const gp_Pnt& aPl = thesegm.LastPoint().Value();
1053         if(aPf.SquareDistance(aPl) <= tol2)
1054         {
1055           //segment can be degenerated - check inner point
1056           paramf = thesegm.FirstPoint().Parameter();
1057           paraml = thesegm.LastPoint().Parameter();
1058           gp_Pnt2d _p2d = 
1059             thesegm.Curve()->Value(.57735 * paramf + 0.42265 * paraml);
1060           gp_Pnt aPm;
1061           if(reversed)
1062           {
1063             Surf1->D0(_p2d.X(), _p2d.Y(), aPm);
1064           }
1065           else
1066           {
1067             Surf2->D0(_p2d.X(), _p2d.Y(), aPm);
1068           }
1069           if(aPm.SquareDistance(aPf) <= tol2)
1070           {
1071             //Degenerated
1072             continue;
1073           }
1074         }
1075       }
1076
1077
1078       //----------------------------------------------------------------------      
1079       // on cree une ligne d intersection contenant uniquement le segment.
1080       // VOIR POUR LA TRANSITION DE LA LIGNE
1081       // On ajoute aussi un polygone pour le traitement des intersections
1082       // entre ligne et restrictions de la surface implicite (PutVertexOnLine)
1083       //----------------------------------------------------------------------
1084       //-- Calcul de la transition sur la rline (12 fev 97)
1085       //-- reversed a le sens de OnFirst
1086       //--
1087       dofirst = dolast  = Standard_False;
1088       procf = Standard_False;
1089       procl = Standard_False;
1090       IntSurf_Transition TLineUnk,TArcUnk;
1091
1092       IntPatch_Point _thepointAtBeg;
1093       IntPatch_Point _thepointAtEnd;
1094
1095       Standard_Boolean TransitionOK=Standard_False;
1096
1097       if(thesegm.HasFirstPoint()) { 
1098         Standard_Real _u1,_v1,_u2,_v2;
1099
1100         dofirst = Standard_True;
1101         PStartf = thesegm.FirstPoint();
1102         paramf = PStartf.Parameter();
1103
1104         gp_Pnt2d _p2d     = thesegm.Curve()->Value(paramf);
1105         Handle(Adaptor3d_HVertex) _vtx;
1106         if(PStartf.IsNew()==Standard_False) 
1107           _vtx= PStartf.Vertex();
1108         const gp_Pnt& _Pp = PStartf.Value();
1109         _thepointAtBeg.SetValue(_Pp,PStartf.Tolerance(),Standard_False);
1110         if (!reversed) { //-- typeS1 = Pln || Cyl || Sph || Cone
1111           Quad.Parameters(_Pp,_u1,_v1);
1112           _u2=_p2d.X(); _v2=_p2d.Y();
1113         }
1114         else {  //-- typeS1 != Pln && Cyl && Sph && Cone
1115           Quad.Parameters(_Pp,_u2,_v2);
1116           _u1=_p2d.X(); _v1=_p2d.Y();
1117         }
1118         _thepointAtBeg.SetParameters(_u1,_v1,_u2,_v2);
1119         _thepointAtBeg.SetParameter(paramf);
1120         if(PStartf.IsNew()==Standard_False) 
1121           _thepointAtBeg.SetVertex(reversed,_vtx);
1122         _thepointAtBeg.SetArc(reversed,thesegm.Curve(),paramf,TLineUnk,TArcUnk);
1123
1124
1125         gp_Vec d1u1,d1v1,d1u2,d1v2; gp_Vec2d _d2d;
1126         Surf1->D1(_u1,_v1,ptbid,d1u1,d1v1);
1127         norm1 = d1u1.Crossed(d1v1);
1128         Surf2->D1(_u2,_v2,ptbid,d1u2,d1v2);
1129         norm2 = d1u2.Crossed(d1v2);
1130
1131         thesegm.Curve()->D1(paramf,_p2d,_d2d);
1132         if(reversed) { 
1133           tgline.SetLinearForm(_d2d.X(),d1u1,_d2d.Y(),d1v1);
1134         }
1135         else { 
1136           tgline.SetLinearForm(_d2d.X(),d1u2,_d2d.Y(),d1v2);
1137         }
1138         _u1=tgline.DotCross(norm2,norm1);
1139         TransitionOK=Standard_True;
1140         if (_u1 > 0.00000001) {
1141           trans1 = IntSurf_Out;
1142           trans2 = IntSurf_In;
1143         }
1144         else if(_u1 < -0.00000001) { 
1145           trans1 = IntSurf_In;
1146           trans2 = IntSurf_Out;
1147         }
1148         else { 
1149           TransitionOK=Standard_False;
1150         }
1151       }
1152       if(thesegm.HasLastPoint()) {  
1153         Standard_Real _u1,_v1,_u2,_v2;
1154
1155         dolast = Standard_True;
1156         PStartl = thesegm.LastPoint();
1157         paraml = PStartl.Parameter();
1158
1159         gp_Pnt2d _p2d = thesegm.Curve()->Value(paraml);
1160         Handle(Adaptor3d_HVertex) _vtx;
1161         if(PStartl.IsNew()==Standard_False) 
1162           _vtx = PStartl.Vertex();
1163         const gp_Pnt& _Pp = PStartl.Value();
1164         IntPatch_Point _thepoint;
1165         _thepointAtEnd.SetValue(_Pp,PStartl.Tolerance(),Standard_False);
1166         if (!reversed) { //-- typeS1 = Pln || Cyl || Sph || Cone
1167           Quad.Parameters(_Pp,_u1,_v1);
1168           _u2=_p2d.X(); _v2=_p2d.Y();
1169         }
1170         else {  //-- typeS1 != Pln && Cyl && Sph && Cone
1171           Quad.Parameters(_Pp,_u2,_v2);
1172           _u1=_p2d.X(); _v1=_p2d.Y();
1173         }
1174         _thepointAtEnd.SetParameters(_u1,_v1,_u2,_v2);
1175         _thepointAtEnd.SetParameter(paraml);
1176         if(PStartl.IsNew()==Standard_False)
1177           _thepointAtEnd.SetVertex(reversed,_vtx);
1178         _thepointAtEnd.SetArc(reversed,thesegm.Curve(),paraml,TLineUnk,TArcUnk);
1179
1180
1181
1182         gp_Vec d1u1,d1v1,d1u2,d1v2; gp_Vec2d _d2d;
1183         Surf1->D1(_u1,_v1,ptbid,d1u1,d1v1);
1184         norm1 = d1u1.Crossed(d1v1);
1185         Surf2->D1(_u2,_v2,ptbid,d1u2,d1v2);
1186         norm2 = d1u2.Crossed(d1v2);
1187
1188         thesegm.Curve()->D1(paraml,_p2d,_d2d);
1189         if(reversed) { 
1190           tgline.SetLinearForm(_d2d.X(),d1u1,_d2d.Y(),d1v1);
1191         }
1192         else { 
1193           tgline.SetLinearForm(_d2d.X(),d1u2,_d2d.Y(),d1v2);
1194         }
1195         _u1=tgline.DotCross(norm2,norm1);
1196         TransitionOK=Standard_True;
1197         if (_u1 > 0.00000001) {
1198           trans1 = IntSurf_Out;
1199           trans2 = IntSurf_In;
1200         }
1201         else if(_u1 < -0.00000001) { 
1202           trans1 = IntSurf_In;
1203           trans2 = IntSurf_Out;
1204         }
1205         else { 
1206           TransitionOK=Standard_False;
1207         }       
1208       }
1209       if(TransitionOK==Standard_False) { 
1210         //-- rline = new IntPatch_RLine (thesegm.Curve(),reversed,Standard_False);
1211         rline =  new IntPatch_RLine (Standard_False);
1212         if(reversed) { 
1213           rline->SetArcOnS1(thesegm.Curve());
1214         }
1215         else { 
1216           rline->SetArcOnS2(thesegm.Curve());
1217         }
1218       }
1219       else { 
1220         //-- rline = new IntPatch_RLine (thesegm.Curve(),reversed,Standard_False,trans1,trans2);
1221         rline =  new IntPatch_RLine (Standard_False,trans1,trans2);
1222         if(reversed) { 
1223           rline->SetArcOnS1(thesegm.Curve());
1224         }
1225         else { 
1226           rline->SetArcOnS2(thesegm.Curve());
1227         }
1228       }
1229
1230       //------------------------------
1231       //-- Ajout des points 
1232       //--
1233       if (thesegm.HasFirstPoint()) {
1234         rline->AddVertex(_thepointAtBeg);
1235         rline->SetFirstPoint(rline->NbVertex());
1236       }
1237
1238       if (thesegm.HasLastPoint()) {
1239         rline->AddVertex(_thepointAtEnd);
1240         rline->SetLastPoint(rline->NbVertex());
1241       }
1242
1243       // Polygone sur restriction solution
1244       if (dofirst && dolast) {
1245         Standard_Real prm;
1246         gp_Pnt ptpoly;
1247         IntSurf_PntOn2S p2s;
1248         Handle(IntSurf_LineOn2S) Thelin = new IntSurf_LineOn2S ();
1249         Handle(Adaptor2d_HCurve2d) arcsegm = thesegm.Curve();
1250         Standard_Integer nbsample = 100;
1251
1252         if (!reversed) {
1253           for (Standard_Integer j=1; j<=nbsample; j++) {
1254             prm = paramf + (j-1)*(paraml-paramf)/(nbsample-1);
1255             arcsegm->D0(prm,p2d);
1256             Surf2->D0(p2d.X(),p2d.Y(),ptpoly);
1257
1258             Quad.Parameters(ptpoly,U1,V1);
1259             p2s.SetValue(ptpoly,U1,V1,p2d.X(),p2d.Y());
1260             Thelin->Add(p2s);
1261           }
1262         }
1263         else {
1264           for (Standard_Integer j=1; j<=nbsample; j++) {
1265             prm = paramf + (j-1)*(paraml-paramf)/(nbsample-1);
1266             arcsegm->D0(prm,p2d);
1267             Surf1->D0(p2d.X(),p2d.Y(),ptpoly);
1268
1269             Quad.Parameters(ptpoly,U2,V2);
1270             p2s.SetValue(ptpoly,p2d.X(),p2d.Y(),U2,V2);
1271             Thelin->Add(p2s);
1272           }
1273         }
1274         rline->Add(Thelin);
1275       }
1276
1277       if (dofirst || dolast) {
1278         Nblines = slin.Length();
1279         for (Standard_Integer j=1; j<=Nblines; j++) {
1280           const Handle(IntPatch_Line)& slinj = slin(j);
1281           typ = slinj->ArcType();
1282           if (typ == IntPatch_Walking) {
1283             Nbpts = (*((Handle(IntPatch_WLine)*)&slinj))->NbVertex();
1284           }
1285           else {
1286             Nbpts = (*((Handle(IntPatch_RLine)*)&slinj))->NbVertex();
1287           }
1288           for (Standard_Integer k=1; k<=Nbpts;k++) {
1289             if (typ == IntPatch_Walking) {
1290               ptdeb = (*((Handle(IntPatch_WLine)*)&slinj))->Vertex(k);
1291             }
1292             else {
1293               ptdeb = (*((Handle(IntPatch_RLine)*)&slinj))->Vertex(k);
1294             }
1295             if (dofirst) {
1296
1297               if (ptdeb.Value().Distance(PStartf.Value()) <=TolArc) {
1298                 ptdeb.SetMultiple(Standard_True);
1299                 if (typ == IntPatch_Walking) {
1300                   (*((Handle(IntPatch_WLine)*)&slinj))->Replace(k,ptdeb);
1301                 }
1302                 else {
1303                   (*((Handle(IntPatch_RLine)*)&slinj))->Replace(k,ptdeb);
1304                 }
1305                 ptdeb.SetParameter(paramf);
1306                 rline->AddVertex(ptdeb);
1307                 if (!procf){
1308                   procf=Standard_True;
1309                   rline->SetFirstPoint(rline->NbVertex());
1310                 }
1311               }
1312             }
1313             if (dolast) {
1314               if(dofirst) { //-- on recharge le ptdeb
1315                 if (typ == IntPatch_Walking) {
1316                   ptdeb = (*((Handle(IntPatch_WLine)*)&slinj))->Vertex(k);
1317                 }
1318                 else {
1319                   ptdeb = (*((Handle(IntPatch_RLine)*)&slinj))->Vertex(k);
1320                 }
1321               }
1322               if (ptdeb.Value().Distance(PStartl.Value()) <=TolArc) {
1323                 ptdeb.SetMultiple(Standard_True);
1324                 if (typ == IntPatch_Walking) {
1325                   (*((Handle(IntPatch_WLine)*)&slinj))->Replace(k,ptdeb);
1326                 }
1327                 else {
1328                   (*((Handle(IntPatch_RLine)*)&slinj))->Replace(k,ptdeb);
1329                 }
1330                 ptdeb.SetParameter(paraml);
1331                 rline->AddVertex(ptdeb);
1332                 if (!procl){
1333                   procl=Standard_True;
1334                   rline->SetLastPoint(rline->NbVertex());
1335                 }
1336               }
1337             }
1338           }
1339         }
1340       }
1341       slin.Append(rline);
1342     }
1343   }// if (NbSegm) 
1344   //
1345   // on traite les restrictions de la surface implicite
1346   for (Standard_Integer i=1; i<=slin.Length(); i++)
1347   {
1348     Handle(IntPatch_Line)& aL = slin(i);
1349     
1350     if (!reversed)
1351       IntPatch_RstInt::PutVertexOnLine(aL,Surf1,D1,Surf2,Standard_True,TolTang);
1352     else
1353       IntPatch_RstInt::PutVertexOnLine(aL,Surf2,D2,Surf1,Standard_False,TolTang);
1354   }
1355
1356   const Standard_Real aUPeriodOfSurf1 = Surf1->IsUPeriodic() ? Surf1->UPeriod() : 0.0,
1357                       aUPeriodOfSurf2 = Surf2->IsUPeriodic() ? Surf2->UPeriod() : 0.0,
1358                       aVPeriodOfSurf1 = Surf1->IsVPeriodic() ? Surf1->VPeriod() : 0.0,
1359                       aVPeriodOfSurf2 = Surf2->IsVPeriodic() ? Surf2->VPeriod() : 0.0;
1360
1361   for (Standard_Integer i = 1; i <= slin.Length(); i++)
1362   {
1363     //BndBox of the points in Restriction line
1364     Bnd_Box2d aBRL;
1365     for(Standard_Integer j = i + 1; j <= slin.Length(); j++)
1366     {
1367       Handle(IntPatch_PointLine) aL1 = Handle(IntPatch_PointLine)::DownCast(slin(i));
1368       Handle(IntPatch_PointLine) aL2 = Handle(IntPatch_PointLine)::DownCast(slin(j));
1369
1370       Handle(IntPatch_RLine) aRL1 = Handle(IntPatch_RLine)::DownCast(aL1);
1371       Handle(IntPatch_RLine) aRL2 = Handle(IntPatch_RLine)::DownCast(aL2);
1372
1373       if(aRL1.IsNull() && aRL2.IsNull())
1374       {//If Walking-Walking
1375         continue;
1376       }
1377       else if(aRL1.IsNull())
1378       {// i-th line is not restriction,
1379        // but j-th is restriction
1380         slin.Append(aL1);
1381         slin.SetValue(i, aL2);
1382         slin.Remove(j);
1383         j--;
1384         continue;
1385       }
1386
1387       //Here aL1 (i-th line) is Restriction-line and aL2 (j-th line) is not Restriction
1388
1389       if(aBRL.IsVoid())
1390       {//Fill aBRL
1391         for(Standard_Integer aPRID = 1; aPRID <= aRL1->NbPnts(); aPRID++)
1392         {
1393           Standard_Real u = 0.0, v = 0.0;
1394           if(reversed)
1395             aRL1->Point(aPRID).ParametersOnS1(u, v);
1396           else
1397             aRL1->Point(aPRID).ParametersOnS2(u, v);
1398
1399           aBRL.Add(gp_Pnt2d(u, v));
1400         }
1401
1402         Standard_Real aXmin = 0.0, aYmin = 0.0, aXMax = 0.0, aYMax = 0.0;
1403         aBRL.Get(aXmin, aYmin, aXMax, aYMax);
1404         const Standard_Real aDX = aXMax - aXmin,
1405                             aDY = aYMax - aYmin;
1406
1407         const Standard_Real aTolU = reversed? Surf1->UResolution(TolArc) : Surf2->UResolution(TolArc);
1408         const Standard_Real aTolV = reversed? Surf1->VResolution(TolArc) : Surf2->VResolution(TolArc);
1409
1410         if((aDX > aTolU) && (aDY > aTolV))
1411         {//Delete restriction line because it is not isoline.
1412           slin.Remove(i);
1413           i--;
1414           break;
1415         }
1416
1417         aXmin -= aTolU;
1418         aXMax += aTolU;
1419         aYmin -= aTolV;
1420         aYMax += aTolV;
1421         aBRL.SetVoid();
1422         aBRL.Update(aXmin, aYmin, aXMax, aYMax);
1423       }
1424
1425       const Standard_Boolean isCoincide = IsIn2DBox(aBRL, aL2,
1426                         (reversed? aUPeriodOfSurf1 : aUPeriodOfSurf2),
1427                         (reversed? aVPeriodOfSurf1 : aVPeriodOfSurf2), reversed);
1428
1429       if(isCoincide)
1430       {//Delete Walking-line
1431         slin.Remove(j);
1432         j--;
1433       }
1434     }
1435   }
1436
1437   empt = (slin.Length() == 0 && spnt.Length() == 0);
1438   done = Standard_True;
1439
1440
1441   if(slin.Length() == 0)
1442     return;
1443
1444   Standard_Boolean isDecomposeRequired =  (Quad.TypeQuadric() == GeomAbs_Cone) || 
1445                                           (Quad.TypeQuadric() == GeomAbs_Sphere);
1446
1447   if(!isDecomposeRequired)
1448     return;
1449
1450   // post processing for cones and spheres
1451
1452   const Handle(Adaptor3d_TopolTool)& PDomain = (reversed) ? D1 : D2;
1453   const Handle(Adaptor3d_HSurface)& aQSurf = (reversed) ? Surf2 : Surf1;
1454
1455   IntPatch_SequenceOfLine dslin;
1456   Standard_Boolean isDecompose = Standard_False;
1457   for(Standard_Integer i = 1; i <= slin.Length(); i++ )
1458   {
1459     if(DecomposeResult(slin(i),reversed,Quad,PDomain,aQSurf,TolArc,dslin))
1460     {
1461       isDecompose = Standard_True;
1462     }
1463   }
1464
1465   if(!isDecompose)
1466     return;
1467
1468   slin.Clear();
1469   for(Standard_Integer i = 1; i <= dslin.Length(); i++ )
1470     slin.Append(dslin(i));
1471 }
1472
1473 // correct U parameter of the start point of line on Quadric
1474 // (change 0->2PI or vs, if necessary)
1475 static Standard_Real AdjustUFirst(Standard_Real U1,Standard_Real U2)
1476 {
1477   Standard_Real u = U1;
1478
1479   // case: no adjustment
1480   if( U1 > 0. && U1 < (2.*M_PI) )
1481     return u;
1482
1483   // case: near '0'
1484   if( U1 == 0. || fabs(U1) <= 1.e-9 ) {
1485     if( U2 > 0. && U2 < (2.*M_PI) )
1486       u = ( U2 < ((2.*M_PI)-U2) ) ? 0. : (2.*M_PI);
1487     else {
1488       Standard_Real uu = U2;
1489       if( U2 > (2.*M_PI) )
1490         while( uu > (2.*M_PI) )
1491           uu -= (2.*M_PI);
1492       else 
1493         while( uu < 0.)
1494           uu += (2.*M_PI);
1495
1496       u = ( uu < ((2.*M_PI)-uu) ) ? 0. : (2.*M_PI);
1497     }
1498   }
1499   // case: near '2PI'
1500   else if( U1 == (2.*M_PI) || fabs((2.*M_PI)-fabs(U1)) <= 1.e-9 ) {
1501     if( U2 > 0. && U2 < (2.*M_PI) )
1502       u = ( U2 < ((2.*M_PI)-U2) ) ? 0. : (2.*M_PI);
1503     else {
1504       Standard_Real uu = U2;
1505       if( U2 > (2.*M_PI) )
1506         while( uu > (2.*M_PI) )
1507           uu -= (2.*M_PI);
1508       else 
1509         while( uu < 0.)
1510           uu += (2.*M_PI);
1511
1512       u = ( uu < ((2.*M_PI)-uu) ) ? 0. : (2.*M_PI);
1513     }
1514   }
1515   // case: '<0. || >2PI'
1516   else {
1517     if(U1 < 0.)
1518       while(u < 0.)
1519         u += 2.*M_PI;
1520     if(U1 > (2.*M_PI))
1521       while(u > (2.*M_PI))
1522         u -= (2.*M_PI);
1523   }
1524
1525   return u;
1526 }
1527
1528 // collect vertices, reject equals
1529 static Handle(IntSurf_LineOn2S) GetVertices(const Handle(IntPatch_WLine)& WLine,
1530                                             const Standard_Real           TOL3D,
1531                                             const Standard_Real           TOL2D)
1532 {
1533   //  Standard_Real TOL3D = 1.e-12, TOL2D = 1.e-8;
1534
1535   Handle(IntSurf_LineOn2S) vertices = new IntSurf_LineOn2S();
1536
1537   Standard_Real U1 = 0., U2 = 0., V1 = 0., V2 = 0.;
1538   Standard_Integer i = 0, k = 0;
1539   Standard_Integer NbVrt = WLine->NbVertex();
1540
1541   TColStd_Array1OfInteger anVrts(1,NbVrt);
1542   anVrts.Init(0);
1543
1544   // check equal vertices
1545   for(i = 1; i <= NbVrt; i++) {
1546
1547     if( anVrts(i) == -1 ) continue;
1548
1549     const IntPatch_Point& Pi = WLine->Vertex(i);
1550
1551     for(k = (i+1); k <= NbVrt; k++) {
1552
1553       if( anVrts(k) == -1 ) continue;
1554
1555       const IntPatch_Point& Pk = WLine->Vertex(k);
1556
1557       if(Pi.Value().Distance(Pk.Value()) <= TOL3D) {
1558         // suggest the points are equal;
1559         // test 2d parameters on surface
1560         Standard_Boolean sameU1 = Standard_False;
1561         Standard_Boolean sameV1 = Standard_False;
1562         Standard_Boolean sameU2 = Standard_False;
1563         Standard_Boolean sameV2 = Standard_False;
1564
1565         Pi.ParametersOnS1(U1,V1);
1566         Pk.ParametersOnS1(U2,V2);
1567         if(fabs(U1-U2) <= TOL2D) sameU1 = Standard_True;
1568         if(fabs(V1-V2) <= TOL2D) sameV1 = Standard_True;
1569
1570         Pi.ParametersOnS2(U1,V1);
1571         Pk.ParametersOnS2(U2,V2);
1572         if(fabs(U1-U2) <= TOL2D) sameU2 = Standard_True;
1573         if(fabs(V1-V2) <= TOL2D) sameV2 = Standard_True;
1574
1575         if((sameU1 && sameV1) && (sameU2 && sameV2))
1576           anVrts(k) = -1;
1577       }
1578     }
1579   }
1580
1581   // copy further processed vertices
1582   for(i = 1; i <= NbVrt; i++) {
1583     if( anVrts(i) == -1 ) continue;
1584     vertices->Add(WLine->Vertex(i).PntOn2S());
1585   }
1586   return vertices;
1587 }
1588
1589 static Standard_Boolean AreSamePoints(const IntSurf_PntOn2S& P1,
1590   const IntSurf_PntOn2S& P2)
1591 {
1592   Standard_Boolean result = Standard_False;
1593   Standard_Real T2D = 1.e-9, T3D = 1.e-8;
1594   const gp_Pnt& P3D1 = P1.Value();
1595   const gp_Pnt& P3D2 = P2.Value();
1596   if(P3D1.Distance(P3D2) <= T3D) {
1597     Standard_Real U1 = 0., V1 = 0., U2 = 0., V2 = 0., U3 = 0., V3 = 0., U4 = 0., V4 = 0.;
1598     P1.ParametersOnS1(U1,V1);
1599     P1.ParametersOnS2(U2,V2);
1600     P2.ParametersOnS1(U3,V3);
1601     P2.ParametersOnS2(U4,V4);
1602     gp_Pnt2d P2D11(U1,V1);
1603     gp_Pnt2d P2D12(U2,V2);
1604     gp_Pnt2d P2D21(U3,V3);
1605     gp_Pnt2d P2D22(U4,V4);
1606     Standard_Boolean sameS1 = (P2D11.Distance(P2D21) <= T2D) ? Standard_True : Standard_False;
1607     Standard_Boolean sameS2 = (P2D12.Distance(P2D22) <= T2D) ? Standard_True : Standard_False;
1608     if(sameS1 && sameS2)
1609       result = Standard_True;
1610   }
1611   return result;
1612 }
1613
1614 static void ForcedPurgePoints(const Handle(IntSurf_LineOn2S)& Result,
1615                               const Standard_Boolean          IsReversed,
1616                               const IntSurf_Quadric&          Quad)
1617 {
1618   if(Result->NbPoints() <= 30) return;
1619   Standard_Integer Index = 0, IndexLimF = 8, IndexLimL = 8;
1620
1621   Standard_Real U1 = 0., V1 = 0., U2 = 0., V2 = 0.;
1622   if(IsReversed) {
1623     Result->Value(1).ParametersOnS2(U1,V1);
1624     Result->Value(Result->NbPoints()).ParametersOnS2(U2,V2);
1625   }
1626   else {
1627     Result->Value(1).ParametersOnS1(U1,V1);   
1628     Result->Value(Result->NbPoints()).ParametersOnS1(U2,V2);
1629   }
1630
1631   if(Quad.TypeQuadric() == GeomAbs_Cone) {
1632     Standard_Real Uapx = 0., Vapx = 0.;
1633     Quad.Parameters(Quad.Cone().Apex(),Uapx,Vapx);
1634
1635     if(fabs(V1-Vapx) <= 1.e-3)
1636       IndexLimF = 12;
1637     if(fabs(V2-Vapx) <= 1.e-3)
1638       IndexLimL = 12;
1639   }
1640
1641   if(Quad.TypeQuadric() == GeomAbs_Sphere) {
1642     Standard_Real Vapx1 = M_PI/2., Vapx2 = -M_PI/2.;
1643
1644     if(fabs(V1-Vapx1) <= 1.e-3 || fabs(V1-Vapx2) <= 1.e-3)
1645       IndexLimF = 12;
1646     if(fabs(V2-Vapx1) <= 1.e-3 || fabs(V2-Vapx2) <= 1.e-3)
1647       IndexLimL = 12;
1648   }
1649
1650   while(Result->NbPoints() > 2 && Index < IndexLimF) {
1651     Result->RemovePoint(2);
1652     Index++;
1653   }
1654   Index = 0;
1655   while(Result->NbPoints() > 2 && Index < IndexLimL) {
1656     Result->RemovePoint(Result->NbPoints()-1);
1657     Index++;
1658   }
1659 }
1660
1661 // DEBUG FUNCTION !!!
1662 #if 0
1663 static void DumpLine(Handle(IntSurf_LineOn2S)& Line,
1664   Standard_Boolean          IsReversed,
1665   Standard_Integer          Number)
1666 {
1667   cout << "DUMP LINE" << endl;
1668   Standard_Integer i;
1669   Standard_Real U,V;
1670   for(i = 1; i <= Line->NbPoints(); i++) {
1671     if(i <= Number || i >= (Line->NbPoints()-Number)) {
1672       if(IsReversed)
1673         Line->Value(i).ParametersOnS2(U,V); // S2 - quadric
1674       else
1675         Line->Value(i).ParametersOnS1(U,V); // S1 - quadric
1676       cout << "point p" << i << " " << U << " " << V << endl;
1677     }
1678   }
1679   cout << endl;
1680 }
1681 #endif
1682 // DEBUG FUNCTION !!!
1683
1684 static void SearchVertices(const Handle(IntSurf_LineOn2S)& Line,
1685   const Handle(IntSurf_LineOn2S)& Vertices,
1686   TColStd_Array1OfInteger&        PTypes)
1687 {
1688   Standard_Integer nbp = Line->NbPoints(), nbv = Vertices->NbPoints();
1689   Standard_Integer ip = 0, iv = 0;
1690   for(ip = 1; ip <= nbp; ip++) {
1691     const IntSurf_PntOn2S& aP = Line->Value(ip);
1692     Standard_Integer type = 0;
1693     for(iv = 1; iv <= nbv; iv++) {
1694       const IntSurf_PntOn2S& aV = Vertices->Value(iv);
1695       if(AreSamePoints(aP,aV)) {
1696         type = iv; 
1697         break;
1698       }
1699     }
1700     PTypes(ip) = type;
1701   }
1702 }
1703
1704 static inline Standard_Boolean IsSeamParameter(const Standard_Real U,
1705   const Standard_Real TOL2D)
1706 {
1707   return (fabs(U) <= TOL2D || fabs(2.*M_PI - U) <= TOL2D);
1708 }
1709
1710 static inline Standard_Real AdjustU(const Standard_Real U)
1711 {
1712   Standard_Real u = U, DBLPI = 2.*M_PI;
1713   if(u < 0. || u > DBLPI) {
1714     if(u < 0.)
1715       while(u < 0.)
1716         u += DBLPI;
1717     else
1718       while(u > DBLPI)
1719         u -= DBLPI;
1720   }
1721   return u;
1722 }
1723
1724 static inline void Correct2DBounds(const Standard_Real UF,
1725   const Standard_Real UL,
1726   const Standard_Real VF,
1727   const Standard_Real VL,
1728   const Standard_Real TOL2D,
1729   Standard_Real&      U,
1730   Standard_Real&      V)
1731 {
1732   Standard_Real Eps = 1.e-16;
1733   Standard_Real dUF = fabs(U - UF);
1734   Standard_Real dUL = fabs(U - UL);
1735   Standard_Real dVF = fabs(V - VF);
1736   Standard_Real dVL = fabs(V - VL);
1737   if(dUF <= TOL2D && dUF > Eps) U = UF;
1738   if(dUL <= TOL2D && dUL > Eps) U = UL;
1739   if(dVF <= TOL2D && dVF > Eps) V = VF;
1740   if(dVL <= TOL2D && dVL > Eps) V = VL;
1741 }
1742
1743 static void AdjustLine(Handle(IntSurf_LineOn2S)& Line,
1744   const Standard_Boolean    IsReversed,
1745   const Handle(Adaptor3d_HSurface)&         QSurf,
1746   const Standard_Real       TOL2D)
1747 {
1748   Standard_Real VF = QSurf->FirstVParameter();
1749   Standard_Real VL = QSurf->LastVParameter();
1750   Standard_Real UF = QSurf->FirstUParameter();
1751   Standard_Real UL = QSurf->LastUParameter();
1752
1753   Standard_Integer nbp = Line->NbPoints(), ip = 0;
1754   Standard_Real U = 0., V = 0.;
1755   for(ip = 1; ip <= nbp; ip++) {
1756     if(IsReversed) {
1757       Line->Value(ip).ParametersOnS2(U,V);
1758       U = AdjustU(U);
1759       Correct2DBounds(UF,UL,VF,VL,TOL2D,U,V);
1760       Line->SetUV(ip,Standard_False,U,V);
1761     }
1762     else {
1763       Line->Value(ip).ParametersOnS1(U,V);
1764       U = AdjustU(U);
1765       Correct2DBounds(UF,UL,VF,VL,TOL2D,U,V);
1766       Line->SetUV(ip,Standard_True,U,V);
1767     }
1768   }
1769 }
1770
1771 static Standard_Boolean InsertSeamVertices(Handle(IntSurf_LineOn2S)&       Line,
1772   const Standard_Boolean          IsReversed,
1773   Handle(IntSurf_LineOn2S)&       Vertices,
1774   const TColStd_Array1OfInteger&  PTypes,
1775   const Standard_Real             TOL2D)
1776 {
1777   Standard_Boolean result = Standard_False;
1778   Standard_Integer ip = 0, nbp = Line->NbPoints();
1779   Standard_Real U = 0., V = 0.;
1780   for(ip = 1; ip <= nbp; ip++) {
1781     Standard_Integer ipt = PTypes(ip);
1782     if(ipt != 0) {
1783       const IntSurf_PntOn2S& aP = Line->Value(ip);
1784       if(IsReversed)
1785         aP.ParametersOnS2(U,V); // S2 - quadric
1786       else
1787         aP.ParametersOnS1(U,V); // S1 - quadric
1788       U = AdjustU(U);
1789       if(IsSeamParameter(U,TOL2D)) {
1790         if(ip == 1 || ip == nbp) {
1791           Standard_Real U1 = 0., V1 = 0.;
1792           Standard_Integer ipp = (ip == 1) ? (ip+1) : (ip-1);
1793           if(IsReversed)
1794             Line->Value(ipp).ParametersOnS2(U1,V1); // S2 - quadric
1795           else
1796             Line->Value(ipp).ParametersOnS1(U1,V1); // S1 - quadric
1797           Standard_Real u = AdjustUFirst(U,U1);
1798           if(fabs(u-U) >= 1.5*M_PI) {
1799             Standard_Real U2 = 0., V2 = 0.;
1800             if(IsReversed) {
1801               Line->Value(ip).ParametersOnS1(U2,V2); // prm
1802               Line->SetUV(ip,Standard_False,u,V);
1803               Line->SetUV(ip,Standard_True,U2,V2);
1804             }
1805             else {
1806               Line->Value(ip).ParametersOnS2(U2,V2); // prm
1807               Line->SetUV(ip,Standard_True,u,V);
1808               Line->SetUV(ip,Standard_False,U2,V2);
1809             }
1810           }
1811         }
1812         else {
1813           Standard_Integer ipp = ip - 1;
1814           Standard_Integer ipn = ip + 1;
1815           Standard_Real U1 = 0., V1 = 0., U2 = 0., V2 = 0.;
1816           if(IsReversed) {
1817             Line->Value(ipp).ParametersOnS2(U1,V1); // quad
1818             Line->Value(ipn).ParametersOnS2(U2,V2); // quad
1819           }
1820           else {
1821             Line->Value(ipp).ParametersOnS1(U1,V1); // quad
1822             Line->Value(ipn).ParametersOnS1(U2,V2); // quad
1823           }
1824           U1 = AdjustU(U1);
1825           U2 = AdjustU(U2);
1826           Standard_Boolean pnearZero = (fabs(U1) < fabs(2.*M_PI-U1)) ? Standard_True : Standard_False;
1827           Standard_Boolean cnearZero = (fabs(U) < fabs(2.*M_PI-U)) ? Standard_True : Standard_False;
1828           if(pnearZero == cnearZero) {
1829             if(!IsSeamParameter(U2,TOL2D) && !IsSeamParameter(U1,TOL2D)) {
1830               Standard_Real nU = (cnearZero) ? (2.*M_PI) : 0.;
1831               IntSurf_PntOn2S nP;
1832               nP.SetValue(aP.Value());
1833               Standard_Real U3 = 0., V3 = 0.;
1834               if(IsReversed) {
1835                 Line->Value(ip).ParametersOnS1(U3,V3); // prm
1836                 nP.SetValue(Standard_False,nU,V);
1837                 nP.SetValue(Standard_True,U3,V3);
1838               }
1839               else {
1840                 Line->Value(ip).ParametersOnS2(U3,V3); // prm
1841                 nP.SetValue(Standard_True,nU,V);
1842                 nP.SetValue(Standard_False,U3,V3);
1843               }
1844               Line->InsertBefore(ipn,nP);
1845               Vertices->Add(nP);
1846               result = Standard_True;
1847               break;
1848             }
1849           }
1850           else {
1851             if(!IsSeamParameter(U2,TOL2D) && !IsSeamParameter(U1,TOL2D)) {
1852               Standard_Real nU = (cnearZero) ? (2.*M_PI) : 0.;
1853               IntSurf_PntOn2S nP;
1854               nP.SetValue(aP.Value());
1855               Standard_Real U3 = 0., V3 = 0.;
1856               if(IsReversed) {
1857                 Line->Value(ip).ParametersOnS1(U3,V3); // prm
1858                 nP.SetValue(Standard_False,nU,V);
1859                 nP.SetValue(Standard_True,U3,V3);
1860               }
1861               else {
1862                 Line->Value(ip).ParametersOnS2(U3,V3); // prm
1863                 nP.SetValue(Standard_True,nU,V);
1864                 nP.SetValue(Standard_False,U3,V3);
1865               }
1866               Line->InsertBefore(ip,nP);
1867               Vertices->Add(nP);
1868               result = Standard_True;
1869               break;
1870             }
1871             else {
1872               // Line->InsertBefore(ip,Line->Value(ipn));
1873               // Line->RemovePoint(ip+2);
1874               // result = Standard_True;
1875               // cout << "swap vertex " << endl;
1876               // break;
1877             }
1878           }
1879         }
1880       }
1881     }
1882   }
1883   return result;
1884 }
1885
1886 static void ToSmooth( const Handle(IntSurf_LineOn2S)& Line,
1887                       const Standard_Boolean          IsReversed,
1888                       const IntSurf_Quadric&          Quad,
1889                       const Standard_Boolean          IsFirst,
1890                       Standard_Real&                  D3D)
1891 {
1892   if(Line->NbPoints() <= 10)
1893     return;
1894
1895   D3D = 0.;
1896   Standard_Integer NbTestPnts = Line->NbPoints() / 5;
1897   if(NbTestPnts < 5) NbTestPnts = 5;
1898
1899   Standard_Integer startp = (IsFirst) ? 2 : (Line->NbPoints() - NbTestPnts - 2);
1900   Standard_Integer ip = 0;
1901   Standard_Real Uc = 0., Vc = 0., Un = 0., Vn = 0., DDU = 0., DDV = 0.;
1902
1903   for(ip = startp; ip <= NbTestPnts; ip++) {
1904     if(IsReversed) {
1905       Line->Value(ip).ParametersOnS2(Uc,Vc); // S2 - quadric
1906       Line->Value(ip+1).ParametersOnS2(Un,Vn);
1907     }
1908     else {
1909       Line->Value(ip).ParametersOnS1(Uc,Vc); // S1 - quadric
1910       Line->Value(ip+1).ParametersOnS1(Un,Vn);
1911     }
1912     DDU += fabs(fabs(Uc)-fabs(Un));
1913     DDV += fabs(fabs(Vc)-fabs(Vn));
1914
1915     if(ip > startp) {
1916       Standard_Real DP = Line->Value(ip).Value().Distance(Line->Value(ip-1).Value());
1917       D3D += DP;
1918     }
1919   }
1920
1921   DDU /= (Standard_Real) NbTestPnts + 1;
1922   DDV /= (Standard_Real) NbTestPnts + 1;
1923
1924   D3D /= (Standard_Real) NbTestPnts + 1;
1925
1926
1927   Standard_Integer Index1 = (IsFirst) ? 1 : (Line->NbPoints());
1928   Standard_Integer Index2 = (IsFirst) ? 2 : (Line->NbPoints()-1);
1929   Standard_Integer Index3 = (IsFirst) ? 3 : (Line->NbPoints()-2);
1930
1931   Standard_Boolean doU = Standard_False;
1932
1933   Standard_Real U1 = 0., U2 = 0., V1 = 0., V2 = 0., U3 = 0., V3 = 0.;
1934
1935   if(IsReversed) {
1936     Line->Value(Index1).ParametersOnS2(U1,V1); // S2 - quadric
1937     Line->Value(Index2).ParametersOnS2(U2,V2);
1938     Line->Value(Index3).ParametersOnS2(U3,V3);
1939   }
1940   else {
1941     Line->Value(Index1).ParametersOnS1(U1,V1); // S1 - quadric
1942     Line->Value(Index2).ParametersOnS1(U2,V2);
1943     Line->Value(Index3).ParametersOnS1(U3,V3);
1944   }
1945
1946   if(!doU && Quad.TypeQuadric() == GeomAbs_Sphere) {
1947     if(fabs(fabs(U1)-fabs(U2)) > (M_PI/16.)) doU = Standard_True;
1948
1949     if(doU && (fabs(U1) <= 1.e-9 || fabs(U1-2.*M_PI) <= 1.e-9)) {
1950       if(fabs(V1-M_PI/2.) <= 1.e-9 || fabs(V1+M_PI/2.) <= 1.e-9) {}
1951       else {
1952         doU = Standard_False;
1953       }
1954     }
1955   }
1956
1957   if(Quad.TypeQuadric() == GeomAbs_Cone) {
1958     Standard_Real Uapx = 0., Vapx = 0.;
1959     Quad.Parameters(Quad.Cone().Apex(),Uapx,Vapx);
1960
1961     if(fabs(fabs(U1)-fabs(U2)) > M_PI/32.) doU = Standard_True;
1962
1963     if(doU && (fabs(U1) <= 1.e-9 || fabs(U1-2.*M_PI) <= 1.e-9)) {
1964       if(fabs(V1-Vapx) <= 1.e-9) {}
1965       else {
1966         doU = Standard_False;
1967       }
1968     }
1969   }
1970
1971   if(doU) {
1972     Standard_Real dU = Min((DDU/10.),5.e-8);
1973     Standard_Real U = (U2 > U3) ? (U2 + dU) : (U2 - dU);
1974     if(IsReversed)
1975       Line->SetUV(Index1,Standard_False,U,V1);
1976     else
1977       Line->SetUV(Index1,Standard_True,U,V1);
1978     U1 = U;
1979   }
1980
1981
1982 static Standard_Boolean TestMiddleOnPrm(const IntSurf_PntOn2S& aP,
1983                                         const IntSurf_PntOn2S& aV,
1984                                         const Standard_Boolean IsReversed,
1985                                         const Standard_Real    ArcTol,
1986                                         const Handle(Adaptor3d_TopolTool)&  PDomain)
1987
1988 {
1989   Standard_Boolean result = Standard_False;
1990   Standard_Real Up = 0., Vp = 0., Uv = 0., Vv = 0.;
1991   if(IsReversed) {
1992     aP.ParametersOnS1(Up,Vp); //S1 - parametric
1993     aV.ParametersOnS1(Uv,Vv);
1994   }
1995   else {
1996     aP.ParametersOnS2(Up,Vp); // S2 - parametric
1997     aV.ParametersOnS2(Uv,Vv);
1998   }
1999   Standard_Real Um = (Up + Uv)*0.5, Vm = (Vp + Vv)*0.5;
2000   gp_Pnt2d a2DPntM(Um,Vm);
2001   TopAbs_State PosM = PDomain->Classify(a2DPntM,ArcTol);
2002   if(PosM == TopAbs_ON || PosM == TopAbs_IN )
2003     result = Standard_True;
2004   return result;
2005 }
2006
2007 static void VerifyVertices( const Handle(IntSurf_LineOn2S)&    Line,
2008                             const Standard_Boolean             IsReversed,
2009                             const Handle(IntSurf_LineOn2S)&    Vertices,
2010                             const Standard_Real                TOL2D,
2011                             const Standard_Real       ArcTol,
2012                             const Handle(Adaptor3d_TopolTool)& PDomain,
2013                             IntSurf_PntOn2S&          VrtF,
2014                             Standard_Boolean&         AddFirst,
2015                             IntSurf_PntOn2S&          VrtL,
2016                             Standard_Boolean&         AddLast)
2017 {
2018   Standard_Integer nbp = Line->NbPoints(), nbv = Vertices->NbPoints();
2019   Standard_Integer FIndexSame = 0, FIndexNear = 0, LIndexSame = 0, LIndexNear = 0;
2020   const IntSurf_PntOn2S& aPF = Line->Value(1);
2021   const IntSurf_PntOn2S& aPL = Line->Value(nbp);
2022   Standard_Real UF = 0., VF = 0., UL = 0., VL = 0.;
2023   if(IsReversed) {
2024     aPF.ParametersOnS2(UF,VF);
2025     aPL.ParametersOnS2(UL,VL);
2026   }
2027   else {
2028     aPF.ParametersOnS1(UF,VF);
2029     aPL.ParametersOnS1(UL,VL);
2030   }
2031   gp_Pnt2d a2DPF(UF,VF);
2032   gp_Pnt2d a2DPL(UL,VL);
2033   Standard_Real DistMinF = 1.e+100, DistMinL = 1.e+100;
2034   Standard_Integer FConjugated = 0, LConjugated = 0;
2035
2036   Standard_Integer iv = 0;
2037
2038   for(iv = 1; iv <= nbv; iv++) {
2039     Standard_Real Uv = 0., Vv = 0.;
2040     if(IsReversed) {
2041       Vertices->Value(iv).ParametersOnS2(Uv,Vv);
2042       Uv = AdjustU(Uv);
2043       Vertices->SetUV(iv,Standard_False,Uv,Vv);
2044     }
2045     else {
2046       Vertices->Value(iv).ParametersOnS1(Uv,Vv);
2047       Uv = AdjustU(Uv);
2048       Vertices->SetUV(iv,Standard_True,Uv,Vv);
2049     }
2050   }
2051
2052   for(iv = 1; iv <= nbv; iv++) {
2053     const IntSurf_PntOn2S& aV = Vertices->Value(iv);
2054     if(AreSamePoints(aPF,aV)) {
2055       FIndexSame = iv;
2056       break;
2057     }
2058     else {
2059       Standard_Real Uv = 0., Vv = 0.;
2060       if(IsReversed)
2061         aV.ParametersOnS2(Uv,Vv);
2062       else
2063         aV.ParametersOnS1(Uv,Vv);
2064       gp_Pnt2d a2DV(Uv,Vv);
2065       Standard_Real Dist = a2DV.Distance(a2DPF);
2066       if(Dist < DistMinF) {
2067         DistMinF = Dist;
2068         FIndexNear = iv;
2069         if(FConjugated != 0)
2070           FConjugated = 0;
2071       }
2072       if(IsSeamParameter(Uv,TOL2D)) {
2073         Standard_Real Ucv = (fabs(Uv) < fabs(2.*M_PI-Uv)) ? (2.*M_PI) : 0.;
2074         gp_Pnt2d a2DCV(Ucv,Vv);
2075         Standard_Real CDist = a2DCV.Distance(a2DPF);
2076         if(CDist < DistMinF) {
2077           DistMinF = CDist;
2078           FConjugated = iv;
2079           FIndexNear = iv;
2080         }
2081       }
2082     }
2083   }
2084
2085   for(iv = 1; iv <= nbv; iv++) {
2086     const IntSurf_PntOn2S& aV = Vertices->Value(iv);
2087     if(AreSamePoints(aPL,aV)) {
2088       LIndexSame = iv;
2089       break;
2090     }
2091     else {
2092       Standard_Real Uv = 0., Vv = 0.;
2093       if(IsReversed)
2094         aV.ParametersOnS2(Uv,Vv);
2095       else
2096         aV.ParametersOnS1(Uv,Vv);
2097       gp_Pnt2d a2DV(Uv,Vv);
2098       Standard_Real Dist = a2DV.Distance(a2DPL);
2099       if(Dist < DistMinL) {
2100         DistMinL = Dist;
2101         LIndexNear = iv;
2102         if(LConjugated != 0)
2103           LConjugated = 0;
2104       }
2105       if(IsSeamParameter(Uv,TOL2D)) {
2106         Standard_Real Ucv = (fabs(Uv) < fabs(2.*M_PI-Uv)) ? (2.*M_PI) : 0.;
2107         gp_Pnt2d a2DCV(Ucv,Vv);
2108         Standard_Real CDist = a2DCV.Distance(a2DPL);
2109         if(CDist < DistMinL) {
2110           DistMinL = CDist;
2111           LConjugated = iv;
2112           LIndexNear = iv;
2113         }
2114       }
2115     }
2116   }
2117
2118   AddFirst = Standard_False;
2119   AddLast  = Standard_False;
2120
2121   if(FIndexSame == 0) {
2122     if(FIndexNear != 0) {
2123       const IntSurf_PntOn2S& aV = Vertices->Value(FIndexNear);
2124       Standard_Real Uv = 0., Vv = 0.;
2125       if(IsReversed)
2126         aV.ParametersOnS2(Uv,Vv);
2127       else
2128         aV.ParametersOnS1(Uv,Vv);
2129       if(IsSeamParameter(Uv,TOL2D)) {
2130         Standard_Real Ucv = (fabs(Uv) < fabs(2.*M_PI-Uv)) ? (2.*M_PI) : 0.;
2131         Standard_Boolean test = TestMiddleOnPrm(aPF,aV,IsReversed,ArcTol,PDomain);
2132         if(test) {
2133           VrtF.SetValue(aV.Value());
2134           if(IsReversed) {
2135             Standard_Real U2 = 0., V2 = 0.;
2136             aV.ParametersOnS1(U2,V2); // S1 - prm
2137             VrtF.SetValue(Standard_True,U2,V2);
2138             if(FConjugated == 0)
2139               VrtF.SetValue(Standard_False,Uv,Vv);
2140             else
2141               VrtF.SetValue(Standard_False,Ucv,Vv);
2142           }
2143           else {
2144             Standard_Real U2 = 0., V2 = 0.;
2145             aV.ParametersOnS2(U2,V2); // S2 - prm
2146             VrtF.SetValue(Standard_False,U2,V2);
2147             if(FConjugated == 0)
2148               VrtF.SetValue(Standard_True,Uv,Vv);
2149             else
2150               VrtF.SetValue(Standard_True,Ucv,Vv);
2151           }
2152           Standard_Real Dist3D = VrtF.Value().Distance(aPF.Value());
2153           if(Dist3D > 1.5e-7 && DistMinF > TOL2D) {
2154             AddFirst = Standard_True;
2155           }
2156         }
2157       }
2158       else {
2159         // to do: analyze internal vertex
2160       }
2161     }
2162   }
2163
2164   if(LIndexSame == 0) {
2165     if(LIndexNear != 0) {
2166       const IntSurf_PntOn2S& aV = Vertices->Value(LIndexNear);
2167       Standard_Real Uv = 0., Vv = 0.;
2168       if(IsReversed)
2169         aV.ParametersOnS2(Uv,Vv);
2170       else
2171         aV.ParametersOnS1(Uv,Vv);
2172       if(IsSeamParameter(Uv,TOL2D)) {
2173         Standard_Real Ucv = (fabs(Uv) < fabs(2.*M_PI-Uv)) ? (2.*M_PI) : 0.;
2174         Standard_Boolean test = TestMiddleOnPrm(aPL,aV,IsReversed,ArcTol,PDomain);
2175         if(test) {
2176           VrtL.SetValue(aV.Value());
2177           if(IsReversed) {
2178             Standard_Real U2 = 0., V2 = 0.;
2179             aV.ParametersOnS1(U2,V2); // S1 - prm
2180             VrtL.SetValue(Standard_True,U2,V2);
2181             if(LConjugated == 0)
2182               VrtL.SetValue(Standard_False,Uv,Vv);
2183             else
2184               VrtL.SetValue(Standard_False,Ucv,Vv);
2185           }
2186           else {
2187             Standard_Real U2 = 0., V2 = 0.;
2188             aV.ParametersOnS2(U2,V2); // S2 - prm
2189             VrtL.SetValue(Standard_False,U2,V2);
2190             if(LConjugated == 0)
2191               VrtL.SetValue(Standard_True,Uv,Vv);
2192             else
2193               VrtL.SetValue(Standard_True,Ucv,Vv);
2194           }
2195           Standard_Real Dist3D = VrtL.Value().Distance(aPL.Value());
2196           if(Dist3D > 1.5e-7 && DistMinL > TOL2D) {
2197             AddLast = Standard_True;
2198           }
2199         }
2200       }
2201       else {
2202         // to do: analyze internal vertex
2203       }
2204     }
2205   }
2206 }
2207
2208 static Standard_Boolean AddVertices(Handle(IntSurf_LineOn2S)& Line,
2209   const IntSurf_PntOn2S&    VrtF,
2210   const Standard_Boolean    AddFirst,
2211   const IntSurf_PntOn2S&    VrtL,
2212   const Standard_Boolean    AddLast,
2213   const Standard_Real       D3DF,
2214   const Standard_Real       D3DL)
2215 {
2216   Standard_Boolean result = Standard_False;
2217   if(AddFirst) {
2218     Standard_Real DF = Line->Value(1).Value().Distance(VrtF.Value());
2219     if((D3DF*2.) > DF && DF > 1.5e-7) {
2220       Line->InsertBefore(1,VrtF);
2221       result = Standard_True;
2222     }
2223   }
2224   if(AddLast) {
2225     Standard_Real DL = Line->Value(Line->NbPoints()).Value().Distance(VrtL.Value());
2226     if((D3DL*2.) > DL && DL > 1.5e-7) {
2227       Line->Add(VrtL);
2228       result = Standard_True;
2229     }
2230   }
2231   return result;
2232 }
2233
2234
2235 static void PutIntVertices(Handle(IntPatch_Line)&    Line,
2236   Handle(IntSurf_LineOn2S)& Result,
2237   Standard_Boolean          ,//IsReversed,
2238   Handle(IntSurf_LineOn2S)& Vertices,
2239   const Standard_Real       ArcTol)
2240 {
2241   Standard_Integer nbp = Result->NbPoints(), nbv = Vertices->NbPoints();
2242
2243   if(nbp < 3)
2244     return;
2245
2246   Handle(IntPatch_WLine)& WLine = (*((Handle(IntPatch_WLine)*)&Line));
2247   Standard_Integer ip = 0, iv = 0;
2248   gp_Pnt aPnt;
2249   IntPatch_Point thePnt;
2250   Standard_Real U1 = 0., V1 = 0., U2 = 0., V2 = 0.;
2251
2252   for(ip = 2; ip <= (nbp-1); ip++) {
2253     const IntSurf_PntOn2S& aP = Result->Value(ip);
2254     for(iv = 1; iv <= nbv; iv++) {
2255       const IntSurf_PntOn2S& aV = Vertices->Value(iv);
2256       if(AreSamePoints(aP,aV)) {
2257         aPnt = Result->Value(ip).Value();
2258         Result->Value(ip).ParametersOnS1(U1,V1);
2259         Result->Value(ip).ParametersOnS2(U2,V2);
2260         thePnt.SetValue(aPnt,ArcTol,Standard_False);
2261         thePnt.SetParameters(U1,V1,U2,V2);
2262         thePnt.SetParameter((Standard_Real)ip);
2263         WLine->AddVertex(thePnt);
2264       }
2265     }
2266   }
2267 }
2268
2269 static Standard_Boolean HasInternals(Handle(IntSurf_LineOn2S)& Line,
2270   Handle(IntSurf_LineOn2S)& Vertices)
2271 {
2272   Standard_Integer nbp = Line->NbPoints(), nbv = Vertices->NbPoints();
2273   Standard_Integer ip = 0, iv = 0;
2274   Standard_Boolean result = Standard_False;
2275
2276   if(nbp < 3)
2277     return result;
2278
2279   for(ip = 2; ip <= (nbp-1); ip++) {
2280     const IntSurf_PntOn2S& aP = Line->Value(ip);
2281     for(iv = 1; iv <= nbv; iv++) {
2282       const IntSurf_PntOn2S& aV = Vertices->Value(iv);
2283       if(AreSamePoints(aP,aV)) {
2284         result = Standard_True;
2285         break;
2286       }
2287     }
2288     if(result)
2289       break;
2290   }
2291
2292   return result;
2293 }
2294 static Handle(IntPatch_WLine) MakeSplitWLine (Handle(IntPatch_WLine)&        WLine,
2295   Standard_Boolean         Tang,
2296   IntSurf_TypeTrans        Trans1,
2297   IntSurf_TypeTrans        Trans2,
2298   Standard_Real            ArcTol,
2299   Standard_Integer         ParFirst,
2300   Standard_Integer         ParLast)
2301 {
2302   Handle(IntSurf_LineOn2S) SLine = WLine->Curve();
2303   Handle(IntSurf_LineOn2S) sline = new IntSurf_LineOn2S();
2304
2305   Standard_Integer ip = 0;
2306   for(ip = ParFirst; ip <= ParLast; ip++)
2307     sline->Add(SLine->Value(ip));
2308
2309   Handle(IntPatch_WLine) wline = new IntPatch_WLine(sline,Tang,Trans1,Trans2);
2310
2311   gp_Pnt aSPnt;
2312   IntPatch_Point TPntF,TPntL;
2313   Standard_Real uu1 = 0., vv1 = 0., uu2 = 0., vv2 = 0.;
2314
2315   aSPnt = sline->Value(1).Value();
2316   sline->Value(1).ParametersOnS1(uu1,vv1);
2317   sline->Value(1).ParametersOnS2(uu2,vv2);
2318   TPntF.SetValue(aSPnt,ArcTol,Standard_False);
2319   TPntF.SetParameters(uu1,vv1,uu2,vv2);
2320   TPntF.SetParameter(1.);
2321   wline->AddVertex(TPntF);
2322   wline->SetFirstPoint(1);
2323
2324   aSPnt =  sline->Value(sline->NbPoints()).Value();
2325   sline->Value(sline->NbPoints()).ParametersOnS1(uu1,vv1);
2326   sline->Value(sline->NbPoints()).ParametersOnS2(uu2,vv2);
2327   TPntL.SetValue(aSPnt,ArcTol,Standard_False);
2328   TPntL.SetParameters(uu1,vv1,uu2,vv2);
2329   TPntL.SetParameter((Standard_Real)sline->NbPoints());
2330   wline->AddVertex(TPntL);
2331   wline->SetLastPoint(sline->NbPoints());
2332
2333   return wline;
2334 }
2335
2336 static Standard_Boolean SplitOnSegments(Handle(IntPatch_WLine)&        WLine,
2337   Standard_Boolean         Tang,
2338   IntSurf_TypeTrans        Trans1,
2339   IntSurf_TypeTrans        Trans2,
2340   Standard_Real            ArcTol,
2341   IntPatch_SequenceOfLine& Segments)
2342 {
2343   Standard_Boolean result = Standard_False;
2344   Segments.Clear();
2345
2346   Standard_Integer nbv = WLine->NbVertex();
2347   if(nbv > 3) {
2348     Standard_Integer iv = 0;
2349     for(iv = 1; iv < nbv; iv++) {
2350       Standard_Integer firstPar = 
2351                     (Standard_Integer) WLine->Vertex(iv).ParameterOnLine();
2352       Standard_Integer lastPar  = 
2353                     (Standard_Integer) WLine->Vertex(iv+1).ParameterOnLine();
2354       if((lastPar - firstPar) <= 1)
2355         continue;
2356       else {
2357         Handle(IntPatch_WLine) splitwline = MakeSplitWLine(WLine,Tang,Trans1,Trans2,
2358                                                                 ArcTol,firstPar,lastPar);
2359         Segments.Append(splitwline);
2360         if(!result)
2361           result = Standard_True;
2362       }
2363     }
2364   }
2365   return result;
2366 }
2367
2368 static Standard_Boolean DecomposeResult(const Handle(IntPatch_Line)& theLine,
2369                                         const Standard_Boolean       IsReversed,
2370                                         const IntSurf_Quadric&       theQuad,
2371                                         const Handle(Adaptor3d_TopolTool)& thePDomain,
2372                                         const Handle(Adaptor3d_HSurface)&  theQSurf,
2373                                         const Standard_Real                theArcTol,
2374                                         IntPatch_SequenceOfLine&           theLines)
2375 {
2376   // Split <theLine> in the places where it passes through seam edge or singularity
2377   // (apex of cone or pole of sphere). This passage is detected by jump of U-parameter
2378   // from point to point.
2379   
2380   const Standard_Real aDeltaUmax = 0.5*M_PI;
2381   const Standard_Real aTOL3D = 1.e-10, 
2382                       aTOL2D = Precision::PConfusion(),
2383                       aTOL2DS = Precision::PConfusion();
2384
2385   if( theLine->ArcType() != IntPatch_Walking )
2386   {
2387     return Standard_False;
2388   }
2389
2390   const Handle(IntPatch_WLine)& aWLine = (*((Handle(IntPatch_WLine)*)&theLine));
2391   const Handle(IntSurf_LineOn2S)& aSLine = aWLine->Curve();
2392
2393   if(aSLine->NbPoints() <= 2)
2394   {
2395     return Standard_False;
2396   }
2397   
2398   //Deletes repeated vertices
2399   Handle(IntSurf_LineOn2S) aVLine = GetVertices(aWLine,aTOL3D,aTOL2D);
2400   
2401   Handle(IntSurf_LineOn2S) aSSLine(aSLine);
2402
2403   if(aSSLine->NbPoints() <= 1)
2404     return Standard_False;
2405
2406   AdjustLine(aSSLine,IsReversed,theQSurf,aTOL2D);
2407
2408   {
2409     Standard_Boolean isInserted = Standard_True;
2410     while(isInserted)
2411     {
2412       const Standard_Integer aNbPnts = aSSLine->NbPoints();
2413       TColStd_Array1OfInteger aPTypes(1,aNbPnts);
2414       SearchVertices(aSSLine,aVLine,aPTypes);
2415       isInserted = InsertSeamVertices(aSSLine,IsReversed,aVLine,aPTypes,aTOL2D);
2416     }
2417   }
2418
2419   const Standard_Integer aLindex = aSSLine->NbPoints();
2420   Standard_Integer aFindex = 1, aBindex = 0;
2421
2422   IntPatch_Point aTPntF, aTPntL;
2423
2424   // build WLine parts (if any)
2425   Standard_Boolean flNextLine = Standard_True;
2426   Standard_Boolean hasBeenDecomposed = Standard_False;
2427   Standard_Boolean PrePointExist = Standard_False;
2428   IntSurf_PntOn2S PrePoint;
2429   while(flNextLine)
2430   {
2431     // reset variables
2432     flNextLine = Standard_False;
2433     Standard_Boolean isDecomposited = Standard_False;
2434     Standard_Real U1 = 0., U2 = 0., V1 = 0., V2 = 0., AnU1 = 0.;
2435
2436     Handle(IntSurf_LineOn2S) sline = new IntSurf_LineOn2S();
2437
2438     //if((Lindex-Findex+1) <= 2 )
2439     if(aLindex <= aFindex)
2440       return hasBeenDecomposed;
2441
2442     if (PrePointExist)
2443     {
2444       sline->Add(PrePoint);
2445       PrePointExist = Standard_False;
2446     }
2447     
2448     // analyze other points
2449     for(Standard_Integer k = aFindex; k <= aLindex; k++)
2450     {
2451       if( k == aFindex )
2452       {
2453         if(IsReversed)
2454         {
2455           aSSLine->Value(k).ParametersOnS2(AnU1,V1);   // S2 - quadric, set U,V by Pnt3D
2456         }
2457         else
2458         {
2459           aSSLine->Value(k).ParametersOnS1(AnU1,V1);    // S1 - quadric, set U,V by Pnt3D
2460         }
2461
2462         sline->Add(aSSLine->Value(k));
2463         PrePoint = aSSLine->Value(k);
2464         continue;
2465       }
2466
2467       if(IsReversed)
2468       {
2469         aSSLine->Value(k).ParametersOnS2(U1,V1);   // S2 - quadric, set U,V by Pnt3D
2470       }
2471       else
2472       {
2473         aSSLine->Value(k).ParametersOnS1(U1,V1);    // S1 - quadric, set U,V by Pnt3D
2474       }
2475
2476       if(Abs(U1-AnU1) > aDeltaUmax)
2477       {
2478         aBindex = k;
2479         isDecomposited = Standard_True;
2480         ////
2481         if (Abs(U1) <= Precision::PConfusion() ||
2482             Abs(U1 - 2*M_PI) <= Precision::PConfusion())
2483         {
2484           IntSurf_PntOn2S NewPoint;
2485           IntSurf_PntOn2S CurPoint = aSSLine->Value(k);
2486           gp_Pnt thePnt = CurPoint.Value();
2487           Standard_Real theU1, theV1, theU2, theV2;
2488           theU1 = (Abs(U1) <= Precision::PConfusion())? 2*M_PI : 0.;
2489           theV1 = V1;
2490           NewPoint.SetValue(thePnt);
2491           if (!IsReversed)
2492           {
2493             CurPoint.ParametersOnS2(theU2, theV2);
2494             NewPoint.SetValue(theU1, theV1, theU2, theV2);
2495           }
2496           else
2497           {
2498             CurPoint.ParametersOnS1(theU2, theV2);
2499             NewPoint.SetValue(theU2, theV2, theU1, theV1);
2500           }
2501           sline->Add(NewPoint);
2502         }
2503         else if (Abs(AnU1) <= Precision::PConfusion() ||
2504                  Abs(AnU1 - 2*M_PI) <= Precision::PConfusion())
2505         {
2506           //Modify <PrePoint>
2507           PrePointExist = Standard_True;
2508           Standard_Real theU1, theV1;
2509           if (!IsReversed)
2510           {
2511             PrePoint.ParametersOnS1(theU1, theV1);
2512             theU1 = (Abs(AnU1) <= Precision::PConfusion())? 2*M_PI : 0.;
2513             PrePoint.SetValue(Standard_True, //on first
2514                               theU1, theV1);
2515           }
2516           else
2517           {
2518             PrePoint.ParametersOnS2(theU1, theV1);
2519             theU1 = (Abs(AnU1) <= Precision::PConfusion())? 2*M_PI : 0.;
2520             PrePoint.SetValue(Standard_False, //on second
2521                               theU1, theV1);
2522           }
2523         }
2524         ////
2525         break;
2526       }
2527
2528       sline->Add(aSSLine->Value(k));
2529       PrePoint = aSSLine->Value(k);
2530       AnU1=U1;
2531     }
2532
2533     IntSurf_PntOn2S aVF, aVL;
2534     Standard_Boolean addVF = Standard_False, addVL = Standard_False;
2535     VerifyVertices(sline,IsReversed,aVLine,aTOL2DS,theArcTol,
2536                                     thePDomain,aVF,addVF,aVL,addVL);
2537
2538     Standard_Boolean hasInternals = HasInternals(sline,aVLine);
2539
2540     Standard_Real D3F = 0., D3L = 0.;
2541     ToSmooth(sline,IsReversed,theQuad,Standard_True,D3F);
2542     ToSmooth(sline,IsReversed,theQuad,Standard_False,D3L);
2543
2544     //if(D3F <= 1.5e-7 && sline->NbPoints() >=3) {
2545     //  D3F = sline->Value(2).Value().Distance(sline->Value(3).Value());
2546     //}
2547     //if(D3L <= 1.5e-7 && sline->NbPoints() >=3) {
2548     //  D3L = sline->Value(sline->NbPoints()-1).Value().Distance(sline->
2549     //                                  Value(sline->NbPoints()-2).Value());
2550     //}
2551
2552     if(addVF || addVL)
2553     {
2554       Standard_Boolean isAdded = AddVertices(sline,aVF,addVF,aVL,addVL,D3F,D3L);
2555       if(isAdded)
2556       {
2557         ToSmooth(sline,IsReversed,theQuad,Standard_True,D3F);
2558         ToSmooth(sline,IsReversed,theQuad,Standard_False,D3L);
2559       }
2560     }
2561
2562     if(!hasInternals)
2563     {
2564       ForcedPurgePoints(sline,IsReversed,theQuad);
2565     }
2566
2567     Handle(IntPatch_WLine) wline = 
2568                         new IntPatch_WLine(sline,Standard_False,
2569                         theLine->TransitionOnS1(),theLine->TransitionOnS2());
2570
2571     gp_Pnt aSPnt(sline->Value(1).Value());
2572     sline->Value(1).ParametersOnS1(U1,V1);
2573     sline->Value(1).ParametersOnS2(U2,V2);
2574     aTPntF.SetValue(aSPnt,theArcTol,Standard_False);
2575     aTPntF.SetParameters(U1,V1,U2,V2);
2576     aTPntF.SetParameter(1.);
2577     wline->AddVertex(aTPntF);
2578     wline->SetFirstPoint(1);
2579
2580     if(hasInternals)
2581     {
2582       PutIntVertices(wline,sline,IsReversed,aVLine,theArcTol);
2583     }
2584
2585     aSPnt =  sline->Value(sline->NbPoints()).Value();
2586     sline->Value(sline->NbPoints()).ParametersOnS1(U1,V1);
2587     sline->Value(sline->NbPoints()).ParametersOnS2(U2,V2);
2588     aTPntL.SetValue(aSPnt,theArcTol,Standard_False);
2589     aTPntL.SetParameters(U1,V1,U2,V2);
2590     aTPntL.SetParameter(sline->NbPoints());
2591     wline->AddVertex(aTPntL);
2592     wline->SetLastPoint(sline->NbPoints());
2593
2594     IntPatch_SequenceOfLine segm;
2595     Standard_Boolean isSplited = SplitOnSegments(wline,Standard_False,
2596                     theLine->TransitionOnS1(),theLine->TransitionOnS2(),theArcTol,segm);
2597
2598     if(!isSplited)
2599     {
2600       theLines.Append(wline);
2601     }
2602     else
2603     {
2604       Standard_Integer nbsegms = segm.Length();
2605       Standard_Integer iseg = 0;
2606       for(iseg = 1; iseg <= nbsegms; iseg++)
2607         theLines.Append(segm(iseg));
2608     }
2609
2610     if(isDecomposited)
2611     {
2612       aFindex = aBindex;
2613       flNextLine = hasBeenDecomposed = Standard_True;
2614     }
2615   }
2616
2617   return hasBeenDecomposed;
2618 }
2619
2620 static Standard_Boolean IsIn2DBox(const Bnd_Box2d& theBox,
2621                                   const Handle(IntPatch_PointLine)& theLine,
2622                                   const Standard_Real theUPeriod,
2623                                   const Standard_Real theVPeriod,
2624                                   const Standard_Boolean isTheSurface1Using)
2625 {
2626   const Standard_Integer aNbPnts = theLine->NbPnts();
2627
2628   const Standard_Real aDeltaUPeriod[] = {0.0, -theUPeriod, 2.0*theUPeriod};
2629   const Standard_Real aDeltaVPeriod[] = {0.0, -theVPeriod, 2.0*theVPeriod};
2630
2631   const Standard_Integer aSzOfUPArr = sizeof(aDeltaUPeriod)/sizeof(aDeltaUPeriod[0]);
2632   const Standard_Integer aSzOfVPArr = sizeof(aDeltaVPeriod)/sizeof(aDeltaVPeriod[0]);
2633
2634   for(Standard_Integer aPtID = 1; aPtID <= aNbPnts; aPtID++)
2635   {
2636     Standard_Real aU = 0.0, aV = 0.0;
2637     if(isTheSurface1Using)
2638       theLine->Point(aPtID).ParametersOnS1(aU, aV);
2639     else
2640       theLine->Point(aPtID).ParametersOnS2(aU, aV);
2641
2642     if(!theBox.IsOut(gp_Pnt2d(aU, aV)))
2643       continue;
2644
2645     Standard_Boolean isInscribe = Standard_False;
2646
2647     for(Standard_Integer aUind = 0; !isInscribe && (aUind < aSzOfUPArr); aUind++)
2648     {
2649       if((aUind > 0) && (aDeltaUPeriod[aUind] == 0.0))
2650       {
2651         break;
2652       }
2653
2654       aU += aDeltaUPeriod[aUind];
2655
2656       for(Standard_Integer aVind = 0; !isInscribe && (aVind < aSzOfVPArr); aVind++)
2657       {
2658         if((aVind > 0) && (aDeltaVPeriod[aVind] == 0.0))
2659         {
2660           break;
2661         }
2662
2663         aV += aDeltaVPeriod[aVind];
2664
2665         isInscribe = !theBox.IsOut(gp_Pnt2d(aU, aV));
2666       }
2667     }
2668
2669     if(!isInscribe)
2670       return Standard_False;
2671   }
2672   return Standard_True;
2673 }