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