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