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