d61733cfa120a06e25239e5bb86a1277da5d1121
[occt.git] / src / IntTools / IntTools_LineConstructor.cxx
1 // File:      IntTools_LineConstructor.cxx
2 // Created:   Tue Feb  7 10:12:45 1995
3 // Author:    Jacques GOUSSARD
4 // Copyright: OPEN CASCADE 1995
5
6 #include <IntTools_LineConstructor.ixx>
7
8 #include <GeomInt_LineTool.hxx>
9 #include <GeomInt_SequenceOfParameterAndOrientation.hxx>
10 #include <GeomInt_ParameterAndOrientation.hxx>
11
12 #include <IntPatch_Point.hxx>
13 #include <IntPatch_GLine.hxx>
14 #include <IntPatch_WLine.hxx>
15 #include <IntPatch_ALine.hxx>
16 #include <IntSurf_Transition.hxx>
17 #include <TopAbs_Orientation.hxx>
18
19
20 #include <Precision.hxx>
21
22 #include <gp_Pnt2d.hxx>
23
24 #include <Adaptor2d_HCurve2d.hxx>
25
26 #include <GeomAdaptor_HSurface.hxx>
27 #include <Standard_ConstructionError.hxx>
28 #include <IntSurf_Quadric.hxx>
29 #include <IntSurf_PntOn2S.hxx>
30 #include <ElCLib.hxx>
31 #include <GeomAbs_SurfaceType.hxx>
32 //
33 #include <TColStd_IndexedMapOfInteger.hxx>
34
35
36 //=======================================================================
37 //function : Recadre
38 //purpose  : 
39 //=======================================================================
40 static void Recadre(const Handle(GeomAdaptor_HSurface)& myHS1,
41                     const Handle(GeomAdaptor_HSurface)& myHS2,
42                     Standard_Real& u1,
43                     Standard_Real& v1,
44                     Standard_Real& u2,
45                     Standard_Real& v2)
46
47   Standard_Boolean myHS1IsUPeriodic,myHS1IsVPeriodic;
48   const GeomAbs_SurfaceType typs1 = myHS1->GetType();
49   switch (typs1)
50   { 
51     case GeomAbs_Cylinder:
52     case GeomAbs_Cone:
53     case GeomAbs_Sphere: 
54     { 
55       myHS1IsUPeriodic = Standard_True;
56       myHS1IsVPeriodic = Standard_False;
57       break;
58     }
59     case GeomAbs_Torus:
60     {
61       myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_True;
62       break;
63     }
64     default:
65     {
66       //-- Case of periodic biparameters is processed upstream
67       myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_False;
68       break;
69     }
70   }
71   Standard_Boolean myHS2IsUPeriodic,myHS2IsVPeriodic;
72   const GeomAbs_SurfaceType typs2 = myHS2->GetType();
73   switch (typs2)
74   { 
75     case GeomAbs_Cylinder:
76     case GeomAbs_Cone:
77     case GeomAbs_Sphere: 
78     { 
79       myHS2IsUPeriodic = Standard_True;
80       myHS2IsVPeriodic = Standard_False;
81       break;
82     }
83     case GeomAbs_Torus:
84     {
85       myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_True;
86       break;
87     }
88     default:
89     {
90       //-- Case of periodic biparameters is processed upstream
91       myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_False;
92       break;
93     }
94   }
95   if(myHS1IsUPeriodic) {
96     const Standard_Real lmf = M_PI+M_PI; //-- myHS1->UPeriod();
97     const Standard_Real f = myHS1->FirstUParameter();
98     const Standard_Real l = myHS1->LastUParameter();
99     while(u1 < f) { u1+=lmf; } 
100     while(u1 > l) { u1-=lmf; }
101   }
102   if(myHS1IsVPeriodic) {
103     const Standard_Real lmf = M_PI+M_PI; //-- myHS1->VPeriod(); 
104     const Standard_Real f = myHS1->FirstVParameter();
105     const Standard_Real l = myHS1->LastVParameter();
106     while(v1 < f) { v1+=lmf; } 
107     while(v1 > l) { v1-=lmf; }
108   }
109   if(myHS2IsUPeriodic) { 
110     const Standard_Real lmf = M_PI+M_PI; //-- myHS2->UPeriod();
111     const Standard_Real f = myHS2->FirstUParameter();
112     const Standard_Real l = myHS2->LastUParameter();
113     while(u2 < f) { u2+=lmf; } 
114     while(u2 > l) { u2-=lmf; }
115   }
116   if(myHS2IsVPeriodic) { 
117     const Standard_Real lmf = M_PI+M_PI; //-- myHS2->VPeriod();
118     const Standard_Real f = myHS2->FirstVParameter();
119     const Standard_Real l = myHS2->LastVParameter();
120     while(v2 < f) { v2+=lmf; } 
121     while(v2 > l) { v2-=lmf; }
122   }
123 }
124
125
126 //=======================================================================
127 //function : Parameters
128 //purpose  : 
129 //=======================================================================
130 static void Parameters(const Handle(GeomAdaptor_HSurface)& myHS1,
131                        const Handle(GeomAdaptor_HSurface)& myHS2,
132                        const gp_Pnt& Ptref,
133                        Standard_Real& U1,
134                        Standard_Real& V1,
135                        Standard_Real& U2,
136                        Standard_Real& V2)
137 {
138   IntSurf_Quadric quad1,quad2;
139   switch (myHS1->Surface().GetType())
140   {
141     case GeomAbs_Plane:    quad1.SetValue(myHS1->Surface().Plane()); break;
142     case GeomAbs_Cylinder: quad1.SetValue(myHS1->Surface().Cylinder()); break;
143     case GeomAbs_Cone:     quad1.SetValue(myHS1->Surface().Cone()); break;
144     case GeomAbs_Sphere:   quad1.SetValue(myHS1->Surface().Sphere()); break;
145     default: Standard_ConstructionError::Raise("IntTools_LineConstructor::Parameters");
146   }
147   switch (myHS2->Surface().GetType())
148   {
149     case GeomAbs_Plane:    quad2.SetValue(myHS2->Surface().Plane()); break;
150     case GeomAbs_Cylinder: quad2.SetValue(myHS2->Surface().Cylinder()); break;
151     case GeomAbs_Cone:     quad2.SetValue(myHS2->Surface().Cone()); break;
152     case GeomAbs_Sphere:   quad2.SetValue(myHS2->Surface().Sphere()); break;
153     default: Standard_ConstructionError::Raise("IntTools_LineConstructor::Parameters");
154   }
155   quad1.Parameters(Ptref,U1,V1);
156   quad2.Parameters(Ptref,U2,V2);
157 }
158
159
160 //=======================================================================
161 //function : Perform
162 //purpose  : 
163 //=======================================================================
164 void IntTools_LineConstructor::Perform(const Handle(IntPatch_Line)& L)
165 {
166   Standard_Integer i,nbvtx;
167   Standard_Real firstp,lastp;
168   const Standard_Real Tol = Precision::PConfusion() * 35.0;
169   
170   const IntPatch_IType typl = L->ArcType();
171   if(typl == IntPatch_Analytic)
172   {
173     Standard_Real u1,v1,u2,v2;
174     Handle(IntPatch_ALine)& ALine =  *((Handle(IntPatch_ALine) *)&L);
175     seqp.Clear();
176     nbvtx = GeomInt_LineTool::NbVertex(L);
177     for(i=1;i<nbvtx;i++)
178     {
179       firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine();
180       lastp =  GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine();
181       if(firstp!=lastp)
182       {
183         const Standard_Real pmid = (firstp+lastp)*0.5;
184         const gp_Pnt Pmid = ALine->Value(pmid);
185         Parameters(myHS1,myHS2,Pmid,u1,v1,u2,v2);
186         Recadre(myHS1,myHS2,u1,v1,u2,v2);
187         const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
188         if(in1 !=  TopAbs_OUT) {
189           const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
190           if(in2 != TopAbs_OUT) { 
191             seqp.Append(firstp);
192             seqp.Append(lastp);
193           }
194         }
195       }
196     }
197     done = Standard_True;
198     return;
199   }
200   else if(typl == IntPatch_Walking)
201   {
202     Standard_Real u1,v1,u2,v2;
203     Handle(IntPatch_WLine)& WLine =  *((Handle(IntPatch_WLine) *)&L);
204     seqp.Clear();
205     nbvtx = GeomInt_LineTool::NbVertex(L);
206     for(i=1;i<nbvtx;i++)
207     { 
208       firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine();
209       lastp =  GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine();
210       if(firstp!=lastp)
211       { 
212         if(lastp != firstp+1)
213         {
214           const Standard_Integer pmid = (Standard_Integer )( (firstp+lastp)/2);
215           const IntSurf_PntOn2S& Pmid = WLine->Point(pmid);
216           Pmid.Parameters(u1,v1,u2,v2);
217           Recadre(myHS1,myHS2,u1,v1,u2,v2);
218           const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
219           if(in1 !=  TopAbs_OUT) {   
220             const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
221             if(in2 != TopAbs_OUT) {   
222               seqp.Append(firstp);
223               seqp.Append(lastp);
224             }
225           }
226         }
227         else
228         {
229           const IntSurf_PntOn2S& Pfirst = WLine->Point((Standard_Integer)(firstp));
230           Pfirst.Parameters(u1,v1,u2,v2);
231           Recadre(myHS1,myHS2,u1,v1,u2,v2);
232           TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
233           if(in1 !=  TopAbs_OUT) {  //-- !=ON donne Pb 
234             TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
235             if(in2 != TopAbs_OUT) { //-- !=ON  
236               const IntSurf_PntOn2S& Plast = WLine->Point((Standard_Integer)(lastp));
237               Plast.Parameters(u1,v1,u2,v2);
238               Recadre(myHS1,myHS2,u1,v1,u2,v2);
239               in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
240               if(in1 !=  TopAbs_OUT) {  //-- !=ON donne Pb 
241                 in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
242                 if(in2 != TopAbs_OUT) {
243                   seqp.Append(firstp);
244                   seqp.Append(lastp);
245                 }
246               }
247             }
248           }
249           
250         }
251       }
252     }
253     //XX
254     //                                             904/L7 
255     //
256     //     The One resulting curve consists of 7 segments that are 
257     // connected between each other.
258     //     The aim of the block is to reject these segments and have
259     // one segment instead of 7. 
260     //     The other reason to do that is value of TolReached3D=49.
261     //     Why -? It is not known yet. 
262     //                                             PKV 22.Apr.2002
263     //
264     const GeomAbs_SurfaceType aST1 = myHS1->Surface().GetType();
265     const GeomAbs_SurfaceType aST2 = myHS2->Surface().GetType();
266     if ((aST1==GeomAbs_Plane && aST2==GeomAbs_SurfaceOfExtrusion) || 
267         (aST2==GeomAbs_Plane && aST1==GeomAbs_SurfaceOfExtrusion))
268     {
269       TColStd_IndexedMapOfInteger aMap;
270       TColStd_SequenceOfReal aSeqTmp;
271       
272       Standard_Integer aNb, anIndex, aNbTmp, jx;
273       
274       aNb=seqp.Length();
275       for(i=1; i<=aNb;++i) {
276         lastp =seqp(i);
277         anIndex=(Standard_Integer)lastp;
278         if (!aMap.Contains(anIndex)){
279           aMap.Add(anIndex);
280           aSeqTmp.Append(lastp);
281         }
282         else {
283           aNbTmp=aSeqTmp.Length();
284           aSeqTmp.Remove(aNbTmp);
285         }
286       }
287       //
288       seqp.Clear();
289       //
290       aNb=aSeqTmp.Length()/2;
291       for(i=1; i<=aNb;++i) {
292         jx=2*i;
293         firstp=aSeqTmp(jx-1);
294         lastp =aSeqTmp(jx);
295         seqp.Append(firstp);
296         seqp.Append(lastp);
297       }
298     }
299     ////XX
300     done = Standard_True;
301     return;
302   }
303   else if (typl != IntPatch_Restriction)
304   { 
305     Standard_Real u1,v1,u2,v2;
306     Handle(IntPatch_GLine)& GLine =  *((Handle(IntPatch_GLine) *)&L);
307     seqp.Clear();
308     nbvtx = GeomInt_LineTool::NbVertex(L);
309     Standard_Boolean intrvtested = Standard_False;
310     for(i=1;i<nbvtx;i++)
311     { 
312       firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine();
313       lastp =  GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine();
314       if(Abs(firstp-lastp)>Precision::PConfusion())
315       {
316         intrvtested = Standard_True;
317         const Standard_Real pmid = (firstp+lastp)*0.5;
318         gp_Pnt Pmid;
319         switch (typl)
320         {
321           case IntPatch_Lin:       Pmid = ElCLib::Value(pmid,GLine->Line()); break;
322           case IntPatch_Circle:    Pmid = ElCLib::Value(pmid,GLine->Circle()); break;
323           case IntPatch_Ellipse:   Pmid = ElCLib::Value(pmid,GLine->Ellipse()); break;
324           case IntPatch_Hyperbola: Pmid = ElCLib::Value(pmid,GLine->Hyperbola()); break;
325           case IntPatch_Parabola:  Pmid = ElCLib::Value(pmid,GLine->Parabola()); break;
326         }
327         Parameters(myHS1,myHS2,Pmid,u1,v1,u2,v2);
328         Recadre(myHS1,myHS2,u1,v1,u2,v2);
329         const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
330         if(in1 !=  TopAbs_OUT) { 
331           const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
332           if(in2 != TopAbs_OUT) { 
333             seqp.Append(firstp);
334             seqp.Append(lastp);
335           }
336         }
337       }
338     }
339
340     if(typl == IntPatch_Circle || typl == IntPatch_Ellipse)
341     { 
342       firstp = GeomInt_LineTool::Vertex(L,nbvtx).ParameterOnLine();
343       lastp  = M_PI + M_PI + GeomInt_LineTool::Vertex(L,1).ParameterOnLine();
344       const Standard_Real cadrinf = GeomInt_LineTool::FirstParameter(L);
345       const Standard_Real cadrsup = GeomInt_LineTool::LastParameter(L);
346       Standard_Real acadr = (firstp+lastp)*0.5;
347       while(acadr < cadrinf) { acadr+=M_PI+M_PI; }
348       while(acadr > cadrsup) { acadr-=M_PI+M_PI; } 
349       if(acadr>=cadrinf && acadr<=cadrsup)
350       { 
351         if(Abs(firstp-lastp)>Precision::PConfusion())
352         {
353           intrvtested = Standard_True;
354           const Standard_Real pmid = (firstp+lastp)*0.5;
355           gp_Pnt Pmid;
356           if (typl == IntPatch_Circle)
357             Pmid = ElCLib::Value(pmid,GLine->Circle());
358           else
359             Pmid = ElCLib::Value(pmid,GLine->Ellipse());
360           Parameters(myHS1,myHS2,Pmid,u1,v1,u2,v2);
361           Recadre(myHS1,myHS2,u1,v1,u2,v2);
362           const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
363           if(in1 !=  TopAbs_OUT) { 
364             const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
365             if(in2 != TopAbs_OUT) { 
366               seqp.Append(firstp);
367               seqp.Append(lastp);
368             }
369           }
370         }
371       }
372     }      
373     if (!intrvtested) {
374       // Keep a priori. A point 2d on each
375       // surface is required to make the decision. Will be done in the caller
376       seqp.Append(GeomInt_LineTool::FirstParameter(L));
377       seqp.Append(GeomInt_LineTool::LastParameter(L));
378     }
379     //
380     //modified by NIZNHY-PKV Mon Jan 21 17:02:12 2002 f
381     //
382     // Unite neighbouring intervals if it's possible.
383     // It is valid when 3D intersection curve does not go through 
384     // the apex on surface. So for the moment we take into account
385     // Plane and Cylinder - surfaces that do not contain an apex.
386     //                      by NIZNHY-PKV Tue Jan 22 14:00:51 2002
387
388     const GeomAbs_SurfaceType aST1 = myHS1->Surface().GetType();
389     const GeomAbs_SurfaceType aST2 = myHS2->Surface().GetType();
390     if ((aST1==GeomAbs_Plane || aST1==GeomAbs_Cylinder) &&
391         (aST2==GeomAbs_Plane || aST2==GeomAbs_Cylinder))
392     {
393       if(typl == IntPatch_Circle || typl == IntPatch_Ellipse)
394       {
395         Standard_Integer aNbParts = seqp.Length()/2;
396         //
397         if (aNbParts > 1)
398         {
399           Standard_Integer j, i2, j2;
400           Standard_Real aFi = seqp(1), aLi, aFj, aLj, aF, aL;
401           TColStd_SequenceOfReal aSeq;
402           aSeq.Append(aFi);
403           for (i=1; i<aNbParts; ++i)
404           {
405             j=i+1;
406             i2=2*i;
407             j2=2*j;
408             
409             aFi=seqp(i2-1);
410             aLi=seqp(i2);
411
412             aFj=seqp(j2-1);
413             aLj=seqp(j2);
414             
415             if (fabs (aFj-aLi) < Tol)
416             {
417               aL=aLj;
418             }
419             else
420             {
421               aL=aLi;
422               aSeq.Append(aL);
423               aF=aFj;
424               aSeq.Append(aF);
425             }
426           }
427           aSeq.Append(aLj);
428           //
429           seqp.Clear();
430           aNbParts=aSeq.Length();
431           for (i=1; i<=aNbParts; ++i)
432           {
433             aF=aSeq(i);
434             seqp.Append(aF);
435           }
436         }
437       }
438     }
439     //modified by NIZNHY-PKV Mon Jan 21 17:02:17 2002 t
440     //
441     done =Standard_True;
442     return;
443   }
444
445   done = Standard_False;
446   seqp.Clear();
447   nbvtx = GeomInt_LineTool::NbVertex(L);
448   if (nbvtx == 0) { // Keep a priori. Point 2d is required on each
449                     // surface to make the decision. Will be done in the caller
450     seqp.Append(GeomInt_LineTool::FirstParameter(L));
451     seqp.Append(GeomInt_LineTool::LastParameter(L));
452     done = Standard_True;
453     return;
454   }
455
456   GeomInt_SequenceOfParameterAndOrientation seqpss;
457   TopAbs_Orientation or1=TopAbs_FORWARD,or2=TopAbs_FORWARD;
458
459   for (i=1; i<=nbvtx; i++)
460   {
461     const IntPatch_Point& thevtx = GeomInt_LineTool::Vertex(L,i);
462     const Standard_Real prm = thevtx.ParameterOnLine();
463     if (thevtx.IsOnDomS1())
464     {
465       switch (thevtx.TransitionLineArc1().TransitionType())
466       {
467         case IntSurf_In:        or1 = TopAbs_FORWARD; break;  
468         case IntSurf_Out:       or1 = TopAbs_REVERSED; break;  
469         case IntSurf_Touch:     or1 = TopAbs_INTERNAL; break;  
470         case IntSurf_Undecided: or1 = TopAbs_INTERNAL; break;  
471       }
472     }
473     else
474       or1 = TopAbs_INTERNAL;
475     
476     if (thevtx.IsOnDomS2())
477     {
478       switch (thevtx.TransitionLineArc2().TransitionType())
479       {
480         case IntSurf_In:        or2 = TopAbs_FORWARD; break;
481         case IntSurf_Out:       or2 = TopAbs_REVERSED; break;
482         case IntSurf_Touch:     or2 = TopAbs_INTERNAL; break;
483         case IntSurf_Undecided: or2 = TopAbs_INTERNAL; break;
484       }
485     }
486     else
487       or2 = TopAbs_INTERNAL;
488
489     const Standard_Integer nbinserted = seqpss.Length();
490     Standard_Boolean inserted = Standard_False;
491     for (Standard_Integer j=1; j<=nbinserted;j++)
492     {
493       if (Abs(prm-seqpss(j).Parameter()) <= Tol)
494       {
495         // accumulate
496         GeomInt_ParameterAndOrientation& valj = seqpss.ChangeValue(j);
497         if (or1 != TopAbs_INTERNAL) {
498           if (valj.Orientation1() != TopAbs_INTERNAL) {
499             if (or1 != valj.Orientation1()) {
500               valj.SetOrientation1(TopAbs_INTERNAL);
501             }
502           }
503           else {
504             valj.SetOrientation1(or1);
505           }
506         }
507         
508         if (or2 != TopAbs_INTERNAL) {
509           if (valj.Orientation2() != TopAbs_INTERNAL) {
510             if (or2 != valj.Orientation2()) {
511               valj.SetOrientation2(TopAbs_INTERNAL);
512             }
513           }
514           else {
515             valj.SetOrientation2(or2);
516           }
517         }         
518         inserted = Standard_True;
519         break;
520       }
521       
522       if (prm < seqpss(j).Parameter()-Tol ) {
523         // insert before position j
524         seqpss.InsertBefore(j,GeomInt_ParameterAndOrientation(prm,or1,or2));
525         inserted = Standard_True;
526         break;
527       }
528       
529     }
530     if (!inserted) {
531       seqpss.Append(GeomInt_ParameterAndOrientation(prm,or1,or2));
532     }
533   }
534
535   // determine the state at the beginning of line
536   Standard_Boolean trim = Standard_False;
537   Standard_Boolean dansS1 = Standard_False;
538   Standard_Boolean dansS2 = Standard_False;
539
540   nbvtx = seqpss.Length();
541   for (i=1; i<= nbvtx; i++)
542   {
543     or1 = seqpss(i).Orientation1();
544     if (or1 != TopAbs_INTERNAL)
545     {
546       trim = Standard_True;
547       dansS1 = (or1 != TopAbs_FORWARD);
548       break;
549     }
550   }
551   
552   if (i > nbvtx)
553   {
554     Standard_Real U,V;
555     for (i=1; i<=GeomInt_LineTool::NbVertex(L); i++ )
556     {
557       if (!GeomInt_LineTool::Vertex(L,i).IsOnDomS1() )
558       {
559         GeomInt_LineTool::Vertex(L,i).ParametersOnS1(U,V);
560         gp_Pnt2d PPCC(U,V);
561         if (myDom1->Classify(PPCC,Tol) == TopAbs_OUT) {
562           done = Standard_True;
563           return;
564         }
565         break;
566       }
567     }
568     dansS1 = Standard_True; // Keep in doubt
569   }
570
571   for (i=1; i<= nbvtx; i++)
572   {
573     or2 = seqpss(i).Orientation2();
574     if (or2 != TopAbs_INTERNAL)
575     {
576       trim = Standard_True;
577       dansS2 = (or2 != TopAbs_FORWARD);
578       break;
579     }
580   }
581   
582   if (i > nbvtx)
583   {
584     Standard_Real U,V;
585     for (i=1; i<=GeomInt_LineTool::NbVertex(L); i++ )
586     {
587       if (!GeomInt_LineTool::Vertex(L,i).IsOnDomS2() )
588       {
589         GeomInt_LineTool::Vertex(L,i).ParametersOnS2(U,V);
590         if (myDom2->Classify(gp_Pnt2d(U,V),Tol) == TopAbs_OUT) {
591           done = Standard_True;
592           return;
593         }
594         break;
595       }
596     }
597     dansS2 = Standard_True; //  Keep in doubt
598   }
599
600   if (!trim) { // necessarily dansS1 == dansS2 == Standard_True
601     seqp.Append(GeomInt_LineTool::FirstParameter(L));
602     seqp.Append(GeomInt_LineTool::LastParameter(L));
603     done = Standard_True;
604     return;
605   }
606
607   // sequence seqpss is peeled to create valid ends 
608   // and store them in seqp(2*i+1) and seqp(2*i+2)
609
610   Standard_Real thefirst = GeomInt_LineTool::FirstParameter(L);
611   Standard_Real thelast = GeomInt_LineTool::LastParameter(L);
612   firstp = thefirst;
613
614   for (i=1; i<=nbvtx; i++)
615   {
616     or1 = seqpss(i).Orientation1(); 
617     or2 = seqpss(i).Orientation2(); 
618     if (dansS1 && dansS2)
619     {
620       if (or1 == TopAbs_REVERSED)
621         dansS1 = Standard_False;
622       /*else if (or1 == TopAbs_FORWARD) {
623       }*/
624       if (or2 == TopAbs_REVERSED)
625         dansS2 = Standard_False;
626       /*else if (or2 == TopAbs_FORWARD) {
627       }*/
628       if (!dansS1 || !dansS2)
629       {
630         lastp = seqpss(i).Parameter();
631         Standard_Real stofirst = Max(firstp, thefirst);
632         Standard_Real stolast  = Min(lastp,  thelast) ;
633
634         if (stolast > stofirst) {
635           seqp.Append(stofirst);
636           seqp.Append(stolast);
637         }
638         if (lastp > thelast)
639           break;
640       }
641     }
642     else
643     {
644       if (dansS1)
645       {
646         if (or1 == TopAbs_REVERSED)
647           dansS1 = Standard_False;
648         /*else if (or1 == TopAbs_FORWARD) {
649         }*/
650       }
651       else
652       {
653         if (or1 == TopAbs_FORWARD)
654           dansS1 = Standard_True;
655         /*else if (or1 == TopAbs_REVERSED) {
656         }*/
657       }
658       if (dansS2)
659       {
660         if (or2 == TopAbs_REVERSED)
661           dansS2 = Standard_False;
662         /*else if (or2 == TopAbs_FORWARD) {
663         }*/
664       }
665       else
666       {
667         if (or2 == TopAbs_FORWARD)
668           dansS2 = Standard_True;
669         /*else if (or2 == TopAbs_REVERSED) {
670         }*/
671       }
672       if (dansS1 && dansS2)
673         firstp = seqpss(i).Parameter();
674     }
675   }
676
677   // finally to add
678   if (dansS1 && dansS2)
679   {
680     lastp  = thelast;
681     firstp = Max(firstp,thefirst);
682     if (lastp > firstp) {
683       seqp.Append(firstp);
684       seqp.Append(lastp);
685     }
686   }
687   done = Standard_True;
688 }
689
690
691 //=======================================================================
692 //function : PeriodicLine
693 //purpose  : 
694 //=======================================================================
695 void IntTools_LineConstructor::PeriodicLine (const Handle(IntPatch_Line)& L) const
696 {
697   const IntPatch_IType typl = L->ArcType();
698   if (typl != IntPatch_Circle && typl != IntPatch_Ellipse)
699     return;
700
701   const Standard_Real Tol = Precision::PConfusion();
702   Handle(IntPatch_GLine) glin = Handle(IntPatch_GLine)::DownCast(L);
703   Standard_Integer i,j,nbvtx = glin->NbVertex();
704   for (i=1; i<=nbvtx; i++)
705   {
706     IntPatch_Point thevtx = glin->Vertex(i);
707     const Standard_Real prm = thevtx.ParameterOnLine();
708     Standard_Boolean changevtx = Standard_False;
709     if (thevtx.IsOnDomS1() || thevtx.IsOnDomS2())
710     {
711       for (j=1; j<=nbvtx; j++)
712       {
713         if (j!=i)
714         {
715           const IntPatch_Point& thevtxbis = glin->Vertex(j);
716           const Standard_Real prmbis = thevtxbis.ParameterOnLine();
717           if (Abs(prm-prmbis) <= Tol)
718           {
719             Standard_Real u,v;
720             gp_Pnt2d p2d;
721             if (thevtx.IsOnDomS1() && thevtxbis.IsOnDomS1() &&
722                 thevtxbis.TransitionLineArc1().TransitionType()==IntSurf_In)
723             {
724               p2d = thevtx.ArcOnS1()->Value(thevtx.ParameterOnArc1());
725               u = p2d.X(); v = p2d.Y();
726               p2d = thevtxbis.ArcOnS1()->Value(thevtxbis.ParameterOnArc1());
727               if (Abs(u-p2d.X()) > Tol || Abs(v-p2d.Y()) > Tol)
728               {
729                 changevtx = Standard_True;
730                 break;
731               }
732             }
733             if (thevtx.IsOnDomS2() && thevtxbis.IsOnDomS2() &&
734                 thevtxbis.TransitionLineArc2().TransitionType()==IntSurf_In)
735             {
736               p2d = thevtx.ArcOnS2()->Value(thevtx.ParameterOnArc2());
737               u = p2d.X(); v = p2d.Y();
738               p2d = thevtxbis.ArcOnS2()->Value(thevtxbis.ParameterOnArc2());
739               if (Abs(u-p2d.X()) > Tol || Abs(v-p2d.Y()) > Tol)
740               {
741                 changevtx = Standard_True;
742                 break;
743               }
744             }
745           }
746         }
747       }
748     }
749     if (changevtx) {
750       thevtx.SetParameter(prm + 2.*M_PI);
751       glin->Replace(i,thevtx);
752     }
753   }
754 }