0028966: Coding Rules - remove Adaptor2d_HCurve2d, Adaptor3d_HCurve and Adaptor3d_HSu...
[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 <algorithm>
18
19 #include <Adaptor2d_Curve2d.hxx>
20 #include <Adaptor3d_TopolTool.hxx>
21 #include <ElCLib.hxx>
22 #include <GeomAbs_SurfaceType.hxx>
23 #include <GeomAdaptor_Surface.hxx>
24 #include <GeomInt.hxx>
25 #include <GeomInt_LineConstructor.hxx>
26 #include <GeomInt_LineTool.hxx>
27 #include <GeomInt_ParameterAndOrientation.hxx>
28 #include <GeomInt_SequenceOfParameterAndOrientation.hxx>
29 #include <gp_Pnt2d.hxx>
30 #include <IntPatch_ALine.hxx>
31 #include <IntPatch_GLine.hxx>
32 #include <IntPatch_Line.hxx>
33 #include <IntPatch_Point.hxx>
34 #include <IntPatch_WLine.hxx>
35 #include <IntSurf_PntOn2S.hxx>
36 #include <IntSurf_Quadric.hxx>
37 #include <IntSurf_Transition.hxx>
38 #include <Precision.hxx>
39 #include <Standard_ConstructionError.hxx>
40 #include <Standard_OutOfRange.hxx>
41 #include <StdFail_NotDone.hxx>
42 #include <TColStd_IndexedMapOfInteger.hxx>
43 #include <TopAbs_Orientation.hxx>
44
45 static const Standard_Real TwoPI = M_PI + M_PI;
46
47 //=======================================================================
48 //class    : GeomInt_Vertex
49 //purpose  : This class has been created in order to provide possibility
50 //            to sort IntPatch_Points by their parameter on line.
51 //=======================================================================
52 class GeomInt_Vertex
53 {
54 public:
55   GeomInt_Vertex()
56   {
57   };
58
59   //! Initializes this class by IntPatch_Point
60   void SetVertex(const IntPatch_Point& theOther)
61   {
62     myVertex = theOther;
63     const Standard_Real aNewParam = ElCLib::InPeriod(theOther.ParameterOnLine(), 0.0, TwoPI);
64     SetParameter(aNewParam);
65   }
66
67   //! Sets Parameter on Line
68   void SetParameter(const Standard_Real theParam)
69   {
70     myVertex.SetParameter(theParam);
71   }
72
73   //! Returns IntPatch_Point
74   const IntPatch_Point& Getvertex() const
75   {
76     return myVertex;
77   }
78
79   //! To provide sort
80   Standard_Boolean operator < (const GeomInt_Vertex& theOther) const
81   {
82     return myVertex.ParameterOnLine() < theOther.myVertex.ParameterOnLine();
83   }
84
85 private:
86   IntPatch_Point myVertex;
87 };
88
89 //------------
90 static void Parameters(const Handle(GeomAdaptor_Surface)& myHS1,
91                        const gp_Pnt& Ptref,
92                        Standard_Real& U1,
93                        Standard_Real& V1);
94
95 static void Parameters(const Handle(GeomAdaptor_Surface)& myHS1,
96                        const Handle(GeomAdaptor_Surface)& myHS2,
97                        const gp_Pnt& Ptref,
98                        Standard_Real& U1,
99                        Standard_Real& V1,
100                        Standard_Real& U2,
101                        Standard_Real& V2);
102
103 static void GLinePoint(const IntPatch_IType typl,
104                        const Handle(IntPatch_GLine)& GLine,
105                        const Standard_Real aT,
106                        gp_Pnt& aP);
107
108 static void AdjustPeriodic(const Handle(GeomAdaptor_Surface)& myHS1,
109                            const Handle(GeomAdaptor_Surface)& myHS2,
110                            Standard_Real& u1,
111                            Standard_Real& v1,
112                            Standard_Real& u2,
113                            Standard_Real& v2);
114
115 static
116   Standard_Boolean RejectMicroCircle(const Handle(IntPatch_GLine)& aGLine,
117                                      const IntPatch_IType aType,
118                                      const Standard_Real aTol3D);
119
120 static void RejectDuplicates(NCollection_Array1<GeomInt_Vertex>& theVtxArr);
121
122 //=======================================================================
123 //function : Perform
124 //purpose  : 
125 //=======================================================================
126 void GeomInt_LineConstructor::Perform(const Handle(IntPatch_Line)& L)
127 {
128   Standard_Integer i,nbvtx;
129   Standard_Real firstp,lastp;
130   const Standard_Real Tol = Precision::PConfusion() * 35.0;
131   
132   const IntPatch_IType typl = L->ArcType();
133   if(typl == IntPatch_Analytic)  {
134     Standard_Real u1,v1,u2,v2;
135     Handle(IntPatch_ALine) ALine (Handle(IntPatch_ALine)::DownCast (L));
136     seqp.Clear();
137     nbvtx = GeomInt_LineTool::NbVertex(L);
138     for(i=1;i<nbvtx;i++)   {
139       firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine();
140       lastp =  GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine();
141       if(firstp!=lastp)      {
142         const Standard_Real pmid = (firstp+lastp)*0.5;
143         const gp_Pnt Pmid = ALine->Value(pmid);
144         Parameters(myHS1,myHS2,Pmid,u1,v1,u2,v2);
145         AdjustPeriodic(myHS1, myHS2, u1, v1, u2, v2);
146         const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
147         if(in1 !=  TopAbs_OUT) {
148           const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
149           if(in2 != TopAbs_OUT) { 
150             seqp.Append(firstp);
151             seqp.Append(lastp);
152           }
153         }
154       }
155     }
156     done = Standard_True;
157     return;
158   } // if(typl == IntPatch_Analytic)  {
159   else if(typl == IntPatch_Walking)  {
160     Standard_Real u1,v1,u2,v2;
161     Handle(IntPatch_WLine) WLine (Handle(IntPatch_WLine)::DownCast (L));
162     seqp.Clear();
163     nbvtx = GeomInt_LineTool::NbVertex(L);
164     for(i=1;i<nbvtx;i++)    { 
165       firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine();
166       lastp =  GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine();
167       if(firstp!=lastp)
168       { 
169         if (lastp != firstp + 1)
170         {
171           const Standard_Integer pmid = (Standard_Integer) ((firstp + lastp) / 2);
172           const IntSurf_PntOn2S& Pmid = WLine->Point(pmid);
173           Pmid.Parameters(u1,v1,u2,v2);
174           AdjustPeriodic(myHS1, myHS2, u1, v1, u2, v2);
175           const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1, v1), Tol);
176           if (in1 != TopAbs_OUT)
177           {
178             const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2, v2), Tol);
179             if (in2 != TopAbs_OUT)
180             {
181               seqp.Append(firstp);
182               seqp.Append(lastp);
183             }
184           }
185         }
186         else
187         {
188           if (WLine->GetCreatingWay() == IntPatch_WLine::IntPatch_WLImpPrm)
189           {
190             //The fix #29972.
191             //Implicit-Parametric intersector does not respect domain of 
192             //the quadric surface (it takes into account the domain of the
193             //parametric surface only). It means that we cannot warrant that
194             //we have a point exactly in the quadric boundary.
195             //E.g. in the test cases "bugs modalg_5 bug25697_2", 
196             //"bugs modalg_5 bug23948", "boolean bopfuse_complex G9",
197             //"boolean bopcommon_complex H7", "boolean bopcut_complex I7" etc.
198             //the WLine contains 2 points and one is out of the quadric's domain.
199             //In order to process these cases correctly, we classify a middle
200             //(between these two) point (obtained by interpolation).
201
202             //Other types of intersector take into account the domains of both surfaces.
203             //So, they require to reject all "outboundaried" parts of WLine. As result,
204             //more strict check (all two points of WLine are checksed) is
205             //applied in this case.
206
207             Standard_Real aU21, aV21, aU22, aV22;
208             const IntSurf_PntOn2S& aPfirst = WLine->Point((Standard_Integer) (firstp));
209             const IntSurf_PntOn2S& aPlast = WLine->Point((Standard_Integer) (lastp));
210             aPfirst.Parameters(u1, v1, u2, v2);
211             AdjustPeriodic(myHS1, myHS2, u1, v1, u2, v2);
212             aPlast.Parameters(aU21, aV21, aU22, aV22);
213             AdjustPeriodic(myHS1, myHS2, aU21, aV21, aU22, aV22);
214
215             u1 = 0.5*(u1 + aU21);
216             v1 = 0.5*(v1 + aV21);
217             u2 = 0.5*(u2 + aU22);
218             v2 = 0.5*(v2 + aV22);
219
220             const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1, v1), Tol);
221             if (in1 != TopAbs_OUT)
222             {
223               const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2, v2), Tol);
224               if (in2 != TopAbs_OUT)
225               {
226                 seqp.Append(firstp);
227                 seqp.Append(lastp);
228               }
229             }
230           }
231           else
232           {
233             const IntSurf_PntOn2S& Pfirst = WLine->Point((Standard_Integer) (firstp));
234             Pfirst.Parameters(u1, v1, u2, v2);
235             AdjustPeriodic(myHS1, myHS2, u1, v1, u2, v2);
236             TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1, v1), Tol);
237             if (in1 != TopAbs_OUT)
238             {
239               TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2, v2), Tol);
240               if (in2 != TopAbs_OUT)
241               {
242                 const IntSurf_PntOn2S& Plast = WLine->Point((Standard_Integer) (lastp));
243                 Plast.Parameters(u1, v1, u2, v2);
244                 AdjustPeriodic(myHS1, myHS2, u1, v1, u2, v2);
245                 in1 = myDom1->Classify(gp_Pnt2d(u1, v1), Tol);
246                 if (in1 != TopAbs_OUT)
247                 {
248                   in2 = myDom2->Classify(gp_Pnt2d(u2, v2), Tol);
249                   if (in2 != TopAbs_OUT)
250                   {
251                     seqp.Append(firstp);
252                     seqp.Append(lastp);
253                   }
254                 }
255               }
256             }
257           }
258         }
259       }
260     }
261     //
262     // The One resulting curve consists of 7 segments that are 
263     // connected between each other.
264     // The aim of the block is to reject these segments and have
265     // one segment instead of 7. 
266     //     The other reason to do that is value of TolReached3D=49.
267     //     Why -? It is not known yet. 
268     //                                             PKV 22.Apr.2002
269     //
270     Standard_Integer aNbParts;
271     //
272     aNbParts = seqp.Length()/2;
273     if (aNbParts > 1) {  
274       Standard_Boolean bCond;
275       GeomAbs_SurfaceType aST1, aST2;
276       aST1 = myHS1->GetType();
277       aST2 = myHS2->GetType();
278       //
279       bCond=Standard_False;
280       if (aST1==GeomAbs_Plane) {
281         if (aST2==GeomAbs_SurfaceOfExtrusion || 
282             aST2==GeomAbs_SurfaceOfRevolution) {//+zft
283           bCond=!bCond;
284         }
285       }
286       else if (aST2==GeomAbs_Plane) {
287         if (aST1==GeomAbs_SurfaceOfExtrusion || 
288             aST1==GeomAbs_SurfaceOfRevolution) {//+zft
289           bCond=!bCond;
290         }
291       }
292       //
293       if (bCond) {
294         Standard_Integer aNb, anIndex, aNbTmp, jx;
295         TColStd_IndexedMapOfInteger aMap;
296         TColStd_SequenceOfReal aSeqTmp;
297         //
298         aNb=seqp.Length();
299         for(i=1; i<=aNb; ++i) {
300           lastp =seqp(i);
301           anIndex=(Standard_Integer)lastp;
302           if (!aMap.Contains(anIndex)){
303             aMap.Add(anIndex);
304             aSeqTmp.Append(lastp);
305           }
306           else {
307             aNbTmp=aSeqTmp.Length();
308             aSeqTmp.Remove(aNbTmp);
309           }
310         }
311         //
312         seqp.Clear();
313         //
314         aNb=aSeqTmp.Length()/2;
315         for(i=1; i<=aNb;++i) {
316           jx=2*i;
317           firstp=aSeqTmp(jx-1);
318           lastp =aSeqTmp(jx);
319           seqp.Append(firstp);
320           seqp.Append(lastp);
321         }
322       }//if (bCond) {
323     }
324     done = Standard_True;
325     return;
326   }// else if(typl == IntPatch_Walking)  {
327   //
328   //-----------------------------------------------------------
329   else if (typl != IntPatch_Restriction)  {
330     seqp.Clear();
331     //
332     Handle(IntPatch_GLine) GLine (Handle(IntPatch_GLine)::DownCast (L));
333     //
334     if(typl == IntPatch_Circle || typl == IntPatch_Ellipse) { 
335       TreatCircle(L, Tol);
336       done=Standard_True;
337       return;
338     }
339     //----------------------------
340     Standard_Boolean intrvtested;
341     Standard_Real u1,v1,u2,v2;
342     //
343     nbvtx = GeomInt_LineTool::NbVertex(L);
344     intrvtested = Standard_False;
345     for(i=1; i<nbvtx; ++i) { 
346       firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine();
347       lastp =  GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine();
348       if(Abs(firstp-lastp)>Precision::PConfusion()) {
349         intrvtested = Standard_True;
350         const Standard_Real pmid = (firstp+lastp)*0.5;
351         gp_Pnt Pmid;
352         GLinePoint(typl, GLine, pmid, Pmid);
353         //
354         Parameters(myHS1,myHS2,Pmid,u1,v1,u2,v2);
355         AdjustPeriodic(myHS1, myHS2, u1, v1, u2, v2);
356         const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
357         if(in1 !=  TopAbs_OUT) { 
358           const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
359           if(in2 != TopAbs_OUT) { 
360             seqp.Append(firstp);
361             seqp.Append(lastp);
362           }
363         }
364       }
365     }
366     //
367     if (!intrvtested) {
368       // Keep a priori. A point 2d on each
369       // surface is required to make the decision. Will be done in the caller
370       seqp.Append(GeomInt_LineTool::FirstParameter(L));
371       seqp.Append(GeomInt_LineTool::LastParameter(L));
372     }
373     //
374     done =Standard_True;
375     return;
376   } // else if (typl != IntPatch_Restriction)  { 
377
378   done = Standard_False;
379   seqp.Clear();
380   nbvtx = GeomInt_LineTool::NbVertex(L);
381   if (nbvtx == 0) { // Keep a priori. Point 2d is required on each
382                     // surface to make the decision. Will be done in the caller
383     seqp.Append(GeomInt_LineTool::FirstParameter(L));
384     seqp.Append(GeomInt_LineTool::LastParameter(L));
385     done = Standard_True;
386     return;
387   }
388
389   GeomInt_SequenceOfParameterAndOrientation seqpss;
390   TopAbs_Orientation or1=TopAbs_FORWARD,or2=TopAbs_FORWARD;
391
392   for (i=1; i<=nbvtx; i++)  {
393     const IntPatch_Point& thevtx = GeomInt_LineTool::Vertex(L,i);
394     const Standard_Real prm = thevtx.ParameterOnLine();
395     if (thevtx.IsOnDomS1())    {
396       switch (thevtx.TransitionLineArc1().TransitionType())      {
397         case IntSurf_In:        or1 = TopAbs_FORWARD; break;  
398         case IntSurf_Out:       or1 = TopAbs_REVERSED; break;  
399         case IntSurf_Touch:     or1 = TopAbs_INTERNAL; break;  
400         case IntSurf_Undecided: or1 = TopAbs_INTERNAL; break;  
401       }
402     }
403     else {
404       or1 = TopAbs_INTERNAL;
405     }
406     
407     if (thevtx.IsOnDomS2())    {
408       switch (thevtx.TransitionLineArc2().TransitionType())      {
409         case IntSurf_In:        or2 = TopAbs_FORWARD; break;
410         case IntSurf_Out:       or2 = TopAbs_REVERSED; break;
411         case IntSurf_Touch:     or2 = TopAbs_INTERNAL; break;
412         case IntSurf_Undecided: or2 = TopAbs_INTERNAL; break;
413       }
414     }
415     else {
416       or2 = TopAbs_INTERNAL;
417     }
418     //
419     const Standard_Integer nbinserted = seqpss.Length();
420     Standard_Boolean inserted = Standard_False;
421     for (Standard_Integer j=1; j<=nbinserted;j++)    {
422       if (Abs(prm-seqpss(j).Parameter()) <= Tol)      {
423         // accumulate
424         GeomInt_ParameterAndOrientation& valj = seqpss.ChangeValue(j);
425         if (or1 != TopAbs_INTERNAL) {
426           if (valj.Orientation1() != TopAbs_INTERNAL) {
427             if (or1 != valj.Orientation1()) {
428               valj.SetOrientation1(TopAbs_INTERNAL);
429             }
430           }
431           else {
432             valj.SetOrientation1(or1);
433           }
434         }
435         
436         if (or2 != TopAbs_INTERNAL) {
437           if (valj.Orientation2() != TopAbs_INTERNAL) {
438             if (or2 != valj.Orientation2()) {
439               valj.SetOrientation2(TopAbs_INTERNAL);
440             }
441           }
442           else {
443             valj.SetOrientation2(or2);
444           }
445         }          
446         inserted = Standard_True;
447         break;
448       }
449       
450       if (prm < seqpss(j).Parameter()-Tol ) {
451         // insert before position j
452         seqpss.InsertBefore(j,GeomInt_ParameterAndOrientation(prm,or1,or2));
453         inserted = Standard_True;
454         break;
455       }
456       
457     }
458     if (!inserted) {
459       seqpss.Append(GeomInt_ParameterAndOrientation(prm,or1,or2));
460     }
461   }
462
463   // determine the state at the beginning of line
464   Standard_Boolean trim = Standard_False;
465   Standard_Boolean dansS1 = Standard_False;
466   Standard_Boolean dansS2 = Standard_False;
467
468   nbvtx = seqpss.Length();
469   for (i=1; i<= nbvtx; i++)  {
470     or1 = seqpss(i).Orientation1();
471     if (or1 != TopAbs_INTERNAL)    {
472       trim = Standard_True;
473       dansS1 = (or1 != TopAbs_FORWARD);
474       break;
475     }
476   }
477   
478   if (i > nbvtx)  {
479     Standard_Real U,V;
480     for (i=1; i<=GeomInt_LineTool::NbVertex(L); i++ )    {
481       if (!GeomInt_LineTool::Vertex(L,i).IsOnDomS1() )      {
482         GeomInt_LineTool::Vertex(L,i).ParametersOnS1(U,V);
483         gp_Pnt2d PPCC(U,V);
484         if (myDom1->Classify(PPCC,Tol) == TopAbs_OUT) {
485           done = Standard_True;
486           return;
487         }
488         break;
489       }
490     }
491     dansS1 = Standard_True; // Keep in doubt
492   }
493   //
494   for (i=1; i<= nbvtx; i++)  {
495     or2 = seqpss(i).Orientation2();
496     if (or2 != TopAbs_INTERNAL)    {
497       trim = Standard_True;
498       dansS2 = (or2 != TopAbs_FORWARD);
499       break;
500     }
501   }
502   
503   if (i > nbvtx)  {
504     Standard_Real U,V;
505     for (i=1; i<=GeomInt_LineTool::NbVertex(L); i++ )    {
506       if (!GeomInt_LineTool::Vertex(L,i).IsOnDomS2() )      {
507         GeomInt_LineTool::Vertex(L,i).ParametersOnS2(U,V);
508         if (myDom2->Classify(gp_Pnt2d(U,V),Tol) == TopAbs_OUT) {
509           done = Standard_True;
510           return;
511         }
512         break;
513       }
514     }
515     dansS2 = Standard_True; //  Keep in doubt
516   }
517
518   if (!trim) { // necessarily dansS1 == dansS2 == Standard_True
519     seqp.Append(GeomInt_LineTool::FirstParameter(L));
520     seqp.Append(GeomInt_LineTool::LastParameter(L));
521     done = Standard_True;
522     return;
523   }
524
525   // sequence seqpss is peeled to create valid ends 
526   // and store them in seqp(2*i+1) and seqp(2*i+2)
527   Standard_Real thefirst = GeomInt_LineTool::FirstParameter(L);
528   Standard_Real thelast = GeomInt_LineTool::LastParameter(L);
529   firstp = thefirst;
530
531   for (i=1; i<=nbvtx; i++)  {
532     or1 = seqpss(i).Orientation1(); 
533     or2 = seqpss(i).Orientation2(); 
534     if (dansS1 && dansS2)    {
535       if (or1 == TopAbs_REVERSED){
536         dansS1 = Standard_False;
537       }
538       
539       if (or2 == TopAbs_REVERSED){
540         dansS2 = Standard_False;
541       }
542       if (!dansS1 || !dansS2)      {
543         lastp = seqpss(i).Parameter();
544         Standard_Real stofirst = Max(firstp, thefirst);
545         Standard_Real stolast  = Min(lastp,  thelast) ;
546
547         if (stolast > stofirst) {
548           seqp.Append(stofirst);
549           seqp.Append(stolast);
550         }
551         if (lastp > thelast) {
552           break;
553         }
554       }
555     }
556     else    {
557       if (dansS1)      {
558         if (or1 == TopAbs_REVERSED) {
559           dansS1 = Standard_False;
560         }
561       }
562       else      {
563         if (or1 == TopAbs_FORWARD){
564           dansS1 = Standard_True;
565         }
566       }
567       if (dansS2) {
568         if (or2 == TopAbs_REVERSED) {
569           dansS2 = Standard_False;
570         }
571       }
572       else {
573         if (or2 == TopAbs_FORWARD){
574           dansS2 = Standard_True;
575         }
576       }
577       if (dansS1 && dansS2){
578         firstp = seqpss(i).Parameter();
579       }
580     }
581   }
582   //
583   // finally to add
584   if (dansS1 && dansS2)  {
585     lastp  = thelast;
586     firstp = Max(firstp,thefirst);
587     if (lastp > firstp) {
588       seqp.Append(firstp);
589       seqp.Append(lastp);
590     }
591   }
592   done = Standard_True;
593 }
594
595 //=======================================================================
596 //function : TreatCircle
597 //purpose  : 
598 //=======================================================================
599 void GeomInt_LineConstructor::TreatCircle(const Handle(IntPatch_Line)& theLine,
600                                            const Standard_Real theTol)
601 {  
602   const IntPatch_IType aType = theLine->ArcType();
603   const Handle(IntPatch_GLine) aGLine(Handle(IntPatch_GLine)::DownCast(theLine));
604   if (RejectMicroCircle(aGLine, aType, theTol))
605   {
606     return;
607   }
608   //----------------------------------------
609   const Standard_Integer aNbVtx = aGLine->NbVertex();
610   NCollection_Array1<GeomInt_Vertex> aVtxArr(1, aNbVtx + 1);
611   for (Standard_Integer i = 1; i <= aNbVtx; i++)
612   {
613     aVtxArr(i).SetVertex(aGLine->Vertex(i));
614   }
615
616   std::sort(aVtxArr.begin(), aVtxArr.begin() + aNbVtx);
617   
618   //Create last vertex
619   const Standard_Real aMinPrm = aVtxArr.First().Getvertex().ParameterOnLine() + TwoPI;
620   aVtxArr.ChangeLast().SetParameter(aMinPrm);
621
622   RejectDuplicates(aVtxArr);
623
624   std::sort(aVtxArr.begin(), aVtxArr.end());
625
626   Standard_Real aU1, aV1, aU2, aV2;
627   gp_Pnt aPmid;
628   gp_Pnt2d aP2D;
629   for (Standard_Integer i = aVtxArr.Lower(); i <= aVtxArr.Upper() - 1; i++)
630   {
631     const Standard_Real aT1 = aVtxArr(i).Getvertex().ParameterOnLine();
632     const Standard_Real aT2 = aVtxArr(i + 1).Getvertex().ParameterOnLine();
633
634     if (aT2 == RealLast())
635       break;
636
637     const Standard_Real aTmid = (aT1 + aT2)*0.5;
638     GLinePoint(aType, aGLine, aTmid, aPmid);
639     //
640     Parameters(myHS1, myHS2, aPmid, aU1, aV1, aU2, aV2);
641     AdjustPeriodic(myHS1, myHS2, aU1, aV1, aU2, aV2);
642     //
643     aP2D.SetCoord(aU1, aV1);
644     TopAbs_State aState = myDom1->Classify(aP2D, theTol);
645     if (aState != TopAbs_OUT)
646     {
647       aP2D.SetCoord(aU2, aV2);
648       aState = myDom2->Classify(aP2D, theTol);
649       if (aState != TopAbs_OUT)
650       {
651         seqp.Append(aT1);
652         seqp.Append(aT2);
653       }
654     }
655   }
656 }
657
658 //=======================================================================
659 //function : AdjustPeriodic
660 //purpose  : 
661 //=======================================================================
662 void AdjustPeriodic(const Handle(GeomAdaptor_Surface)& myHS1,
663                     const Handle(GeomAdaptor_Surface)& myHS2,
664                     Standard_Real& u1,
665                     Standard_Real& v1,
666                     Standard_Real& u2,
667                     Standard_Real& v2)
668 {
669   Standard_Boolean myHS1IsUPeriodic, myHS1IsVPeriodic;
670   const GeomAbs_SurfaceType typs1 = myHS1->GetType();
671   switch (typs1)
672   {
673     case GeomAbs_Cylinder:
674     case GeomAbs_Cone:
675     case GeomAbs_Sphere:
676     {
677       myHS1IsUPeriodic = Standard_True;
678       myHS1IsVPeriodic = Standard_False;
679       break;
680     }
681     case GeomAbs_Torus:
682     {
683       myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_True;
684       break;
685     }
686     default:
687     {
688       //-- Case of periodic biparameters is processed upstream
689       myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_False;
690       break;
691     }
692   }
693   Standard_Boolean myHS2IsUPeriodic, myHS2IsVPeriodic;
694   const GeomAbs_SurfaceType typs2 = myHS2->GetType();
695   switch (typs2)
696   {
697     case GeomAbs_Cylinder:
698     case GeomAbs_Cone:
699     case GeomAbs_Sphere:
700     {
701       myHS2IsUPeriodic = Standard_True;
702       myHS2IsVPeriodic = Standard_False;
703       break;
704     }
705     case GeomAbs_Torus:
706     {
707       myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_True;
708       break;
709     }
710     default:
711     {
712       //-- Case of periodic biparameters is processed upstream
713       myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_False;
714       break;
715     }
716   }
717   Standard_Real du, dv;
718   //
719   if (myHS1IsUPeriodic)
720   {
721     const Standard_Real lmf = M_PI + M_PI; //-- myHS1->UPeriod();
722     const Standard_Real f = myHS1->FirstUParameter();
723     const Standard_Real l = myHS1->LastUParameter();
724     GeomInt::AdjustPeriodic(u1, f, l, lmf, u1, du);
725   }
726   if (myHS1IsVPeriodic)
727   {
728     const Standard_Real lmf = M_PI + M_PI; //-- myHS1->VPeriod(); 
729     const Standard_Real f = myHS1->FirstVParameter();
730     const Standard_Real l = myHS1->LastVParameter();
731     GeomInt::AdjustPeriodic(v1, f, l, lmf, v1, dv);
732   }
733   if (myHS2IsUPeriodic)
734   {
735     const Standard_Real lmf = M_PI + M_PI; //-- myHS2->UPeriod();
736     const Standard_Real f = myHS2->FirstUParameter();
737     const Standard_Real l = myHS2->LastUParameter();
738     GeomInt::AdjustPeriodic(u2, f, l, lmf, u2, du);
739   }
740   if (myHS2IsVPeriodic)
741   {
742     const Standard_Real lmf = M_PI + M_PI; //-- myHS2->VPeriod();
743     const Standard_Real f = myHS2->FirstVParameter();
744     const Standard_Real l = myHS2->LastVParameter();
745     GeomInt::AdjustPeriodic(v2, f, l, lmf, v2, dv);
746   }
747 }
748
749 //=======================================================================
750 //function : Parameters
751 //purpose  : 
752 //=======================================================================
753 void Parameters(const Handle(GeomAdaptor_Surface)& myHS1,
754                 const Handle(GeomAdaptor_Surface)& myHS2,
755                 const gp_Pnt& Ptref,
756                 Standard_Real& U1,
757                 Standard_Real& V1,
758                 Standard_Real& U2,
759                 Standard_Real& V2)
760 {
761   Parameters(myHS1, Ptref, U1, V1);
762   Parameters(myHS2, Ptref, U2, V2);
763 }
764
765 //=======================================================================
766 //function : Parameter
767 //purpose  : 
768 //=======================================================================
769 void Parameters(const Handle(GeomAdaptor_Surface)& myHS1,
770                 const gp_Pnt& Ptref,
771                 Standard_Real& U1,
772                 Standard_Real& V1)
773 {
774   IntSurf_Quadric quad1;
775   //
776   switch (myHS1->GetType())
777   {
778     case GeomAbs_Plane:
779       quad1.SetValue(myHS1->Plane());
780       break;
781     case GeomAbs_Cylinder:
782       quad1.SetValue(myHS1->Cylinder());
783       break;
784     case GeomAbs_Cone:
785       quad1.SetValue(myHS1->Cone());
786       break;
787     case GeomAbs_Sphere:
788       quad1.SetValue(myHS1->Sphere());
789       break;
790     case GeomAbs_Torus:
791       quad1.SetValue(myHS1->Torus());
792       break;
793     default:
794       throw Standard_ConstructionError("GeomInt_LineConstructor::Parameters");
795   }
796   quad1.Parameters(Ptref, U1, V1);
797 }
798
799 //=======================================================================
800 //function : GLinePoint
801 //purpose  : 
802 //=======================================================================
803 void GLinePoint(const IntPatch_IType typl,
804                 const Handle(IntPatch_GLine)& GLine,
805                 const Standard_Real aT,
806                 gp_Pnt& aP)
807 {
808   switch (typl)
809   {
810     case IntPatch_Lin:
811       aP = ElCLib::Value(aT, GLine->Line());
812       break;
813     case IntPatch_Circle:
814       aP = ElCLib::Value(aT, GLine->Circle());
815       break;
816     case IntPatch_Ellipse:
817       aP = ElCLib::Value(aT, GLine->Ellipse());
818       break;
819     case IntPatch_Hyperbola:
820       aP = ElCLib::Value(aT, GLine->Hyperbola());
821       break;
822     case IntPatch_Parabola:
823       aP = ElCLib::Value(aT, GLine->Parabola());
824       break;
825     default:
826       throw Standard_ConstructionError("GeomInt_LineConstructor::Parameters");
827   }
828 }
829
830 //=======================================================================
831 //function : RejectMicroCrcles
832 //purpose  : 
833 //=======================================================================
834 Standard_Boolean RejectMicroCircle(const Handle(IntPatch_GLine)& aGLine,
835                                    const IntPatch_IType aType,
836                                    const Standard_Real aTol3D)
837 {
838   Standard_Boolean bRet;
839   Standard_Real aR;
840   //
841   bRet=Standard_False;
842   //
843   if (aType==IntPatch_Circle) {
844     aR=aGLine->Circle().Radius();
845     bRet=(aR<aTol3D);
846   }
847   else if (aType==IntPatch_Ellipse) {
848     aR=aGLine->Ellipse().MajorRadius();
849     bRet=(aR<aTol3D);
850   }
851   return bRet;
852 }
853
854 //=======================================================================
855 //function : RejectDuplicates
856 //purpose  : Finds two coincident IntPatch_Points (if they exist) and 
857 //            sets Parameter-On-Line fore one such point to DBL_MAX
858 //            (i.e. its use in the future is forbidden).
859 //
860 //ATTENTION!!!
861 //           The source array must be sorted in ascending order.
862 //=======================================================================
863 void RejectDuplicates(NCollection_Array1<GeomInt_Vertex>& theVtxArr)
864 {
865   // About the value aTolPC=1000.*Precision::PConfusion(),
866   // see IntPatch_GLine::ComputeVertexParameters(...)
867   // for more details;
868   const Standard_Real aTolPC = 1000.*Precision::PConfusion();
869
870   //Find duplicates in a slice of the array [LowerBound, UpperBound-1].
871   //If a duplicate has been found, the element with greater index will be rejected.
872   for (Standard_Integer i = theVtxArr.Lower(); i <= theVtxArr.Upper() - 2; i++)
873   {
874     const IntPatch_Point &aVi = theVtxArr(i).Getvertex();
875     const Standard_Real aPrmi = aVi.ParameterOnLine();
876
877     if (aPrmi == RealLast())
878       continue;
879
880     for (Standard_Integer j = i + 1; j <= theVtxArr.Upper() - 1; j++)
881     {
882       const IntPatch_Point &aVj = theVtxArr(j).Getvertex();
883       const Standard_Real aPrmj = aVj.ParameterOnLine();
884
885       if (aPrmj - aPrmi < aTolPC)
886       {
887         theVtxArr(j).SetParameter(RealLast());
888       }
889       else
890       {
891         break;
892       }
893     }
894   }
895
896   //Find duplicates with the last element of the array.
897   //If a duplicate has been found, the found element will be rejected.
898   const Standard_Real aMaxPrm = theVtxArr.Last().Getvertex().ParameterOnLine();
899   for (Standard_Integer i = theVtxArr.Upper() - 1; i > theVtxArr.Lower(); i--)
900   {
901     const IntPatch_Point &aVi = theVtxArr(i).Getvertex();
902     const Standard_Real aPrmi = aVi.ParameterOnLine();
903
904     if (aPrmi == RealLast())
905       continue;
906
907     if ((aMaxPrm - aPrmi) < aTolPC)
908     {
909       theVtxArr(i).SetParameter(RealLast());
910     }
911     else
912     {
913       break;
914     }
915   }
916 }