0024612: Wrong pcurve of the section curve
[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(isMicro)
265       {//3D-dimension is small. Checking 2D-dimension
266         aSQDist = 0.0;
267         Standard_Real u1f, v1f, u2f, v2f;
268         Standard_Real u1l, v1l, u2l, v2l;
269         Standard_Real u1m, v1m, u2m, v2m;
270
271         WLine->Point(RealToInt(firstp)).Parameters(u1f, v1f, u2f, v2f);
272         WLine->Point(RealToInt(lastp)).Parameters(u1l, v1l, u2l, v2l);
273         WLine->Point(pmid).Parameters(u1m, v1m, u2m, v2m);
274
275         Standard_Real aDelta = u1m - u1f;
276         aSQDist += aDelta*aDelta;
277         aDelta = v1m - v1f;
278         aSQDist += aDelta*aDelta;
279         aDelta = u2m - u2f;
280         aSQDist += aDelta*aDelta;
281         aDelta = v2m - v2f;
282         aSQDist += aDelta*aDelta;
283
284         aDelta = u1m - u1l;
285         aSQDist += aDelta*aDelta;
286         aDelta = v1m - v1l;
287         aSQDist += aDelta*aDelta;
288         aDelta = u2m - u2l;
289         aSQDist += aDelta*aDelta;
290         aDelta = v2m - v2l;
291         aSQDist += aDelta*aDelta;
292
293         isMicro = aSQDist*100.0 < Tol;
294       }
295
296       if((Abs(firstp-lastp)>Precision::PConfusion()) && !isMicro)
297       {
298         Pmid.Parameters(u1,v1,u2,v2);
299 //Inscribe parameters into main period for periodic surfaces
300         Recadre(myHS1,myHS2,u1,v1,u2,v2);
301
302         const TopAbs_State in1m = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
303         if(in1m ==  TopAbs_OUT)
304         {
305           continue;
306         }
307
308         const TopAbs_State in2m = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
309         if(in2m == TopAbs_OUT)
310         {
311           continue;
312         }
313
314         const IntSurf_PntOn2S& Plast = WLine->Point(RealToInt(lastp));
315         Plast.Parameters(u1,v1,u2,v2);
316 //Inscribe parameters into main period for periodic surfaces
317         Recadre(myHS1,myHS2,u1,v1,u2,v2);
318
319         const TopAbs_State in1l = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
320         if(in1l ==  TopAbs_OUT)
321         {
322           continue;
323         }
324
325         const TopAbs_State in2l = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
326         if(in2l == TopAbs_OUT)
327         {
328           continue;
329         }
330
331         seqp.Append(firstp);
332         seqp.Append(lastp);
333       }
334     }
335     done = Standard_True;
336     return;
337   }
338   else if (typl != IntPatch_Restriction)
339   {
340     Standard_Real u1,v1,u2,v2;
341     Handle(IntPatch_GLine)& GLine =  *((Handle(IntPatch_GLine) *)&L);
342     seqp.Clear();
343     nbvtx = GeomInt_LineTool::NbVertex(L);
344     Standard_Boolean intrvtested = Standard_False;
345     for(i=1;i<nbvtx;i++)
346     {
347       firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine();
348       lastp =  GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine();
349
350       if((Abs(firstp-lastp)>Precision::PConfusion()))
351       {
352         intrvtested = Standard_True;
353         const Standard_Real pmid = (firstp+lastp)*0.5;
354         gp_Pnt Pmid, aP1, aP2;
355         switch (typl)
356         {
357           case IntPatch_Lin:
358             Pmid = ElCLib::Value(pmid,GLine->Line());
359             aP1 = ElCLib::Value(firstp,GLine->Line());
360             aP2 = ElCLib::Value(lastp,GLine->Line());
361             break;
362           case IntPatch_Circle:
363             Pmid = ElCLib::Value(pmid,GLine->Circle());
364             aP1 = ElCLib::Value(firstp,GLine->Circle());
365             aP2 = ElCLib::Value(lastp,GLine->Circle());
366             break;
367           case IntPatch_Ellipse:
368             Pmid = ElCLib::Value(pmid,GLine->Ellipse());
369             aP1 = ElCLib::Value(firstp,GLine->Ellipse());
370             aP2 = ElCLib::Value(lastp,GLine->Ellipse());
371             break;
372           case IntPatch_Hyperbola:
373             Pmid = ElCLib::Value(pmid,GLine->Hyperbola());
374             aP1 = ElCLib::Value(firstp,GLine->Hyperbola());
375             aP2 = ElCLib::Value(lastp,GLine->Hyperbola());
376             break;
377           case IntPatch_Parabola:
378             Pmid = ElCLib::Value(pmid,GLine->Parabola());
379             aP1 = ElCLib::Value(firstp,GLine->Parabola());
380             aP2 = ElCLib::Value(lastp,GLine->Parabola());
381             break;
382           case IntPatch_Analytic:
383           case IntPatch_Walking:
384           case IntPatch_Restriction: break; // cases Analytic, Walking and Restriction are handled above
385         }
386
387         Standard_Real aSQDist = aP1.SquareDistance(aP2);
388         aSQDist = Max(aSQDist, aP1.SquareDistance(Pmid));
389         aSQDist = Max(aSQDist, aP2.SquareDistance(Pmid));
390
391         if(aSQDist*100.0 > Tol)
392         {       //if it is not an "micro-curve" (can it be collapsed in one point?).
393                 //If "yes" then first-, last- and midpoints are same point.
394           Parameters(myHS1,myHS2,Pmid,u1,v1,u2,v2);
395           Recadre(myHS1,myHS2,u1,v1,u2,v2);
396           const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
397           if(in1 !=  TopAbs_OUT) { 
398             const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
399             if(in2 != TopAbs_OUT) { 
400               seqp.Append(firstp);
401               seqp.Append(lastp);
402             }
403           }
404         }
405       }
406     }
407     if(typl == IntPatch_Circle || typl == IntPatch_Ellipse)
408     {
409       const Standard_Real aT = M_PI + M_PI;
410       firstp = GeomInt_LineTool::Vertex(L,nbvtx).ParameterOnLine();
411       lastp  = aT + GeomInt_LineTool::Vertex(L,1).ParameterOnLine();
412       const Standard_Real cadrinf = GeomInt_LineTool::FirstParameter(L);
413       const Standard_Real cadrsup = GeomInt_LineTool::LastParameter(L);
414       Standard_Real acadr = (firstp+lastp)*0.5;
415       while(acadr < cadrinf)
416       {
417         acadr+=aT;
418       }
419       
420       while(acadr > cadrsup)
421       {
422         acadr-=aT;
423       } 
424       
425       if(acadr>=cadrinf && acadr<=cadrsup)
426       { 
427         if(Abs(firstp-lastp) > Precision::PConfusion())
428         {
429           intrvtested = Standard_True;
430           const Standard_Real pmid = (firstp+lastp)*0.5;
431           gp_Pnt Pmid;
432           if (typl == IntPatch_Circle)
433             Pmid = ElCLib::Value(pmid,GLine->Circle());
434           else
435             Pmid = ElCLib::Value(pmid,GLine->Ellipse());
436           Parameters(myHS1,myHS2,Pmid,u1,v1,u2,v2);
437           Recadre(myHS1,myHS2,u1,v1,u2,v2);
438           const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
439           if(in1 !=  TopAbs_OUT)
440           {
441             const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
442             if(in2 != TopAbs_OUT)
443             { 
444               seqp.Append(firstp);
445               seqp.Append(lastp);
446             }
447           }
448         }
449       }
450     }
451
452     if (!intrvtested) {
453       // on garde a priori. Il faudrait un point 2d sur chaque
454       // surface pour prendre la decision. Sera fait dans 
455       // l`appelant
456       seqp.Append(GeomInt_LineTool::FirstParameter(L));
457       seqp.Append(GeomInt_LineTool::LastParameter(L));
458     }
459     done = Standard_True;
460     return;
461   }
462
463   done = Standard_False;
464   seqp.Clear();
465   nbvtx = GeomInt_LineTool::NbVertex(L);
466   if (nbvtx == 0) { // on garde a priori. Il faudrait un point 2d sur chaque
467                     // surface pour prendre la decision. Sera fait dans 
468                     // l`appelant
469     seqp.Append(GeomInt_LineTool::FirstParameter(L));
470     seqp.Append(GeomInt_LineTool::LastParameter(L));
471     done = Standard_True;
472     return;
473   }
474
475   GeomInt_SequenceOfParameterAndOrientation seqpss;
476   TopAbs_Orientation or1=TopAbs_FORWARD,or2=TopAbs_FORWARD;
477
478   for (i=1; i<=nbvtx; i++)
479   {
480     const IntPatch_Point& thevtx = GeomInt_LineTool::Vertex(L,i);
481     const Standard_Real prm = thevtx.ParameterOnLine();
482     if (thevtx.IsOnDomS1())
483     {
484       switch (thevtx.TransitionLineArc1().TransitionType())
485       {
486         case IntSurf_In: or1 = TopAbs_FORWARD; break;  
487         case IntSurf_Out: or1 = TopAbs_REVERSED; break;  
488         case IntSurf_Touch: or1 = TopAbs_INTERNAL; break;  
489         case IntSurf_Undecided: or1 = TopAbs_INTERNAL; break;  
490       }
491     }
492     else
493       or1 = TopAbs_INTERNAL;
494
495     if (thevtx.IsOnDomS2())
496     {
497       switch (thevtx.TransitionLineArc2().TransitionType())
498       {
499         case IntSurf_In: or2 = TopAbs_FORWARD; break;  
500         case IntSurf_Out: or2 = TopAbs_REVERSED; break;  
501         case IntSurf_Touch: or2 = TopAbs_INTERNAL; break;  
502         case IntSurf_Undecided: or2 = TopAbs_INTERNAL; break;  
503       }
504     }
505     else
506       or2 = TopAbs_INTERNAL;
507
508     const Standard_Integer nbinserted = seqpss.Length();
509     Standard_Boolean inserted = Standard_False;
510     for (Standard_Integer j=1; j<=nbinserted;j++)
511     {
512       if (Abs(prm-seqpss(j).Parameter()) <= Tol)
513       {
514         // on cumule
515         GeomInt_ParameterAndOrientation& valj = seqpss.ChangeValue(j);
516         if (or1 != TopAbs_INTERNAL)
517         {
518           if (valj.Orientation1() != TopAbs_INTERNAL)
519           {
520             if (or1 != valj.Orientation1())
521             {
522               valj.SetOrientation1(TopAbs_INTERNAL);
523             }
524           }
525           else
526           {
527             valj.SetOrientation1(or1);
528           }
529         }
530         
531         if (or2 != TopAbs_INTERNAL)
532         {
533           if (valj.Orientation2() != TopAbs_INTERNAL)
534           {
535             if (or2 != valj.Orientation2())
536             {
537               valj.SetOrientation2(TopAbs_INTERNAL);
538             }
539           }
540           else
541           {
542             valj.SetOrientation2(or2);
543           }
544         }
545         
546         inserted = Standard_True;
547         break;
548       }
549       
550       if (prm < seqpss(j).Parameter()-Tol ) {
551         // on insere avant la position j
552         seqpss.InsertBefore(j,GeomInt_ParameterAndOrientation(prm,or1,or2));
553         inserted = Standard_True;
554         break;
555       }
556     }
557
558     if (!inserted)
559     {
560       seqpss.Append(GeomInt_ParameterAndOrientation(prm,or1,or2));
561     }
562   }
563
564   // on determine l`etat en debut de ligne
565   Standard_Boolean trim = Standard_False;
566   Standard_Boolean dansS1 = Standard_False;
567   Standard_Boolean dansS2 = Standard_False;
568
569   nbvtx = seqpss.Length();
570   for (i=1; i<= nbvtx; i++)
571   {
572     or1 = seqpss(i).Orientation1();
573     if (or1 != TopAbs_INTERNAL)
574     {
575       trim = Standard_True;
576       dansS1 = (or1 != TopAbs_FORWARD);
577       break;
578     }
579   }
580
581   if (i > nbvtx)
582   {
583     Standard_Real U,V;
584     for (i=1; i<=GeomInt_LineTool::NbVertex(L); i++ )
585     {
586       if (!GeomInt_LineTool::Vertex(L,i).IsOnDomS1() )
587       {
588         GeomInt_LineTool::Vertex(L,i).ParametersOnS1(U,V);
589         gp_Pnt2d PPCC(U,V);
590         if (myDom1->Classify(PPCC,Tol) == TopAbs_OUT) {
591           done = Standard_True;
592           return;
593         }
594         break;
595       }
596     }
597     dansS1 = Standard_True; // on garde dans le doute
598   }
599
600   for (i=1; i<= nbvtx; i++)
601   {
602     or2 = seqpss(i).Orientation2();
603     if (or2 != TopAbs_INTERNAL)
604     {
605       trim = Standard_True;
606       dansS2 = (or2 != TopAbs_FORWARD);
607       break;
608     }
609   }
610   
611   if (i > nbvtx)
612   {
613     Standard_Real U,V;
614     for (i=1; i<=GeomInt_LineTool::NbVertex(L); i++ )
615     {
616       if (!GeomInt_LineTool::Vertex(L,i).IsOnDomS2() )
617       {
618         GeomInt_LineTool::Vertex(L,i).ParametersOnS2(U,V);
619         if (myDom2->Classify(gp_Pnt2d(U,V),Tol) == TopAbs_OUT) {
620           done = Standard_True;
621           return;
622         }
623         break;
624       }
625     }
626     dansS2 = Standard_True; // on garde dans le doute
627   }
628
629   if (!trim) { // on a necessairement dansS1 == dansS2 == Standard_True
630     seqp.Append(GeomInt_LineTool::FirstParameter(L));
631     seqp.Append(GeomInt_LineTool::LastParameter(L));
632     done = Standard_True;
633     return;
634   }
635
636   // On epluche la sequence seqpss pour constituer les bouts valides
637   // et les stocker dans seqp(2*i+1) et seqp(2*i+2)
638   Standard_Real thefirst = GeomInt_LineTool::FirstParameter(L);
639   Standard_Real thelast = GeomInt_LineTool::LastParameter(L);
640   firstp = thefirst;
641
642   for (i=1; i<=nbvtx; i++)
643   {
644     or1 = seqpss(i).Orientation1(); 
645     or2 = seqpss(i).Orientation2(); 
646     if (dansS1 && dansS2)
647     {
648       if (or1 == TopAbs_REVERSED)
649         dansS1 = Standard_False;
650       /*else if (or1 == TopAbs_FORWARD) {
651       }*/
652       if (or2 == TopAbs_REVERSED)
653         dansS2 = Standard_False;
654       /*else if (or2 == TopAbs_FORWARD) {
655       }*/
656       if (!dansS1 || !dansS2)
657       {
658         lastp = seqpss(i).Parameter();
659         Standard_Real stofirst = Max(firstp, thefirst);
660         Standard_Real stolast  = Min(lastp,  thelast) ;
661         if (stolast > stofirst)
662         {
663           seqp.Append(stofirst);
664           seqp.Append(stolast);
665         }
666         
667         if (lastp > thelast)
668           break;
669       }
670     }
671     else
672     {
673       if (dansS1)
674       {
675         if (or1 == TopAbs_REVERSED)
676           dansS1 = Standard_False;
677         /*else if (or1 == TopAbs_FORWARD) {
678         }*/
679       }
680       else
681       {
682         if (or1 == TopAbs_FORWARD)
683           dansS1 = Standard_True;
684         /*else if (or1 == TopAbs_REVERSED) {
685         }*/
686       }
687       if (dansS2)
688       {
689         if (or2 == TopAbs_REVERSED)
690           dansS2 = Standard_False;
691         /*else if (or2 == TopAbs_FORWARD) {
692         }*/
693       }
694       else
695       {
696         if (or2 == TopAbs_FORWARD)
697           dansS2 = Standard_True;
698         /*else if (or2 == TopAbs_REVERSED) {
699         }*/
700       }
701       if (dansS1 && dansS2)
702         firstp = seqpss(i).Parameter();
703     }
704   }
705
706   // le petit dernier a rajouter
707   if (dansS1 && dansS2)
708   {
709     lastp  = thelast;
710     firstp = Max(firstp,thefirst);
711     if (lastp > firstp) {
712       seqp.Append(firstp);
713       seqp.Append(lastp);
714     }
715   }
716   done = Standard_True;
717 }
718
719
720 //=======================================================================
721 //function : PeriodicLine
722 //purpose  : 
723 //=======================================================================
724 void GeomInt_LineConstructor::PeriodicLine (const Handle(IntPatch_Line)& L) const
725 {
726   const IntPatch_IType typl = L->ArcType();
727   if (typl != IntPatch_Circle && typl != IntPatch_Ellipse)
728     return;
729
730   const Standard_Real Tol = Precision::PConfusion();
731   Handle(IntPatch_GLine) glin = Handle(IntPatch_GLine)::DownCast(L);
732   Standard_Integer i,j,nbvtx = glin->NbVertex();
733   for (i=1; i<=nbvtx; i++)
734   {
735     IntPatch_Point thevtx = glin->Vertex(i);
736     const Standard_Real prm = thevtx.ParameterOnLine();
737     Standard_Boolean changevtx = Standard_False;
738     if (thevtx.IsOnDomS1() || thevtx.IsOnDomS2())
739     {
740       for (j=1; j<=nbvtx; j++)
741       {
742         if (j!=i)
743         {
744           const IntPatch_Point& thevtxbis = glin->Vertex(j);
745           const Standard_Real prmbis = thevtxbis.ParameterOnLine();
746           if (Abs(prm-prmbis) <= Tol)
747           {
748             Standard_Real u,v;
749             gp_Pnt2d p2d;
750             if (thevtx.IsOnDomS1() && thevtxbis.IsOnDomS1() &&
751                 thevtxbis.TransitionLineArc1().TransitionType()==IntSurf_In)
752             {
753               p2d = thevtx.ArcOnS1()->Value(thevtx.ParameterOnArc1());
754               u = p2d.X(); v = p2d.Y();
755               p2d = thevtxbis.ArcOnS1()->Value(thevtxbis.ParameterOnArc1());
756               if (Abs(u-p2d.X()) > Tol || Abs(v-p2d.Y()) > Tol)
757               {
758                 changevtx = Standard_True;
759                 break;
760               }
761             }
762             if (thevtx.IsOnDomS2() && thevtxbis.IsOnDomS2() &&
763                 thevtxbis.TransitionLineArc2().TransitionType()==IntSurf_In)
764             {
765               p2d = thevtx.ArcOnS2()->Value(thevtx.ParameterOnArc2());
766               u = p2d.X(); v = p2d.Y();
767               p2d = thevtxbis.ArcOnS2()->Value(thevtxbis.ParameterOnArc2());
768               if (Abs(u-p2d.X()) > Tol || Abs(v-p2d.Y()) > Tol)
769               {
770                 changevtx = Standard_True;
771                 break;
772               }
773             }
774           }
775         }
776       }
777     }
778     if (changevtx) {
779       thevtx.SetParameter(prm + 2.*M_PI);
780       glin->Replace(i,thevtx);
781     }
782   }
783 }