0023576: Intersection algorithm produces trimmed circle with illegal parametric range.
[occt.git] / src / IntPatch / IntPatch_ImpImpIntersection_4.gxx
1 // Created on: 1992-05-07
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22 #include <IntAna_ListOfCurve.hxx>
23 #include <IntAna_ListIteratorOfListOfCurve.hxx>
24 //
25 static 
26   Standard_Boolean ExploreCurve(const gp_Cylinder& aCy,
27                                 const gp_Cone& aCo,
28                                 IntAna_Curve& aC,
29                                 const Standard_Real aTol,
30                                 IntAna_ListOfCurve& aLC);
31 static
32   Standard_Boolean IsToReverse(const gp_Cylinder& Cy1,
33                                const gp_Cylinder& Cy2,
34                                const Standard_Real Tol);
35
36 //=======================================================================
37 //function : ProcessBounds
38 //purpose  : 
39 //=======================================================================
40 void ProcessBounds(const Handle(IntPatch_ALine)& alig,          //-- ligne courante
41                    const IntPatch_SequenceOfLine& slin,
42                    const IntSurf_Quadric& Quad1,
43                    const IntSurf_Quadric& Quad2,
44                    Standard_Boolean& procf,
45                    const gp_Pnt& ptf,                     //-- Debut Ligne Courante
46                    const Standard_Real first,             //-- Paramf
47                    Standard_Boolean& procl,
48                    const gp_Pnt& ptl,                     //-- Fin Ligne courante
49                    const Standard_Real last,              //-- Paraml
50                    Standard_Boolean& Multpoint,
51                    const Standard_Real Tol)
52 {  
53   Standard_Integer j,k;
54   Standard_Real U1,V1,U2,V2;
55   IntPatch_Point ptsol;
56   Standard_Real d;
57   
58   if (procf && procl) {
59     j = slin.Length() + 1;
60   }
61   else {
62     j = 1;
63   }
64
65
66   //-- On prend les lignes deja enregistrees
67
68   while (j <= slin.Length()) {  
69     if(slin.Value(j)->ArcType() == IntPatch_Analytic) { 
70       const Handle(IntPatch_ALine)& aligold = *((Handle(IntPatch_ALine)*)&slin.Value(j));
71       k = 1;
72
73       //-- On prend les vertex des lignes deja enregistrees
74
75       while (k <= aligold->NbVertex()) {
76         ptsol = aligold->Vertex(k);            
77         if (!procf) {
78           d=ptf.Distance(ptsol.Value());
79           if (d <= Tol) {
80             if (!ptsol.IsMultiple()) {
81               //-- le point ptsol (de aligold) est declare multiple sur aligold
82               Multpoint = Standard_True;
83               ptsol.SetMultiple(Standard_True);
84               aligold->Replace(k,ptsol);
85             }
86             ptsol.SetParameter(first);
87             alig->AddVertex(ptsol);
88             alig->SetFirstPoint(alig->NbVertex());
89             procf = Standard_True;
90
91             //-- On restore le point avec son parametre sur aligold
92             ptsol = aligold->Vertex(k); 
93                                         
94           }
95         }
96         if (!procl) {
97           if (ptl.Distance(ptsol.Value()) <= Tol) {
98             if (!ptsol.IsMultiple()) {
99               Multpoint = Standard_True;
100               ptsol.SetMultiple(Standard_True);
101               aligold->Replace(k,ptsol);
102             }
103             ptsol.SetParameter(last);
104             alig->AddVertex(ptsol);
105             alig->SetLastPoint(alig->NbVertex());
106             procl = Standard_True;
107
108             //-- On restore le point avec son parametre sur aligold
109             ptsol = aligold->Vertex(k); 
110              
111           }
112         }
113         if (procf && procl) {
114           k = aligold->NbVertex()+1;
115         }
116         else {
117           k = k+1;
118         }
119       }
120       if (procf && procl) {
121         j = slin.Length()+1;
122       }
123       else {
124         j = j+1;
125       }
126     }
127   }
128   if (!procf && !procl) {
129     Quad1.Parameters(ptf,U1,V1);
130     Quad2.Parameters(ptf,U2,V2);
131     ptsol.SetValue(ptf,Tol,Standard_False);
132     ptsol.SetParameters(U1,V1,U2,V2);
133     ptsol.SetParameter(first);
134     if (ptf.Distance(ptl) <= Tol) {
135       ptsol.SetMultiple(Standard_True); // a voir
136       Multpoint = Standard_True;        // a voir de meme
137       alig->AddVertex(ptsol);
138       alig->SetFirstPoint(alig->NbVertex());
139       
140       ptsol.SetParameter(last);
141       alig->AddVertex(ptsol);
142       alig->SetLastPoint(alig->NbVertex());
143     }
144     else { 
145       alig->AddVertex(ptsol);
146       alig->SetFirstPoint(alig->NbVertex());
147       Quad1.Parameters(ptl,U1,V1);
148       Quad2.Parameters(ptl,U2,V2);
149       ptsol.SetValue(ptl,Tol,Standard_False);
150       ptsol.SetParameters(U1,V1,U2,V2);
151       ptsol.SetParameter(last);
152       alig->AddVertex(ptsol);
153       alig->SetLastPoint(alig->NbVertex());
154     }
155   }
156   else if (!procf) {
157     Quad1.Parameters(ptf,U1,V1);
158     Quad2.Parameters(ptf,U2,V2);
159     ptsol.SetValue(ptf,Tol,Standard_False);
160     ptsol.SetParameters(U1,V1,U2,V2);
161     ptsol.SetParameter(first);
162     alig->AddVertex(ptsol);
163     alig->SetFirstPoint(alig->NbVertex());
164   }
165   else if (!procl) {
166     Quad1.Parameters(ptl,U1,V1);
167     Quad2.Parameters(ptl,U2,V2);
168     ptsol.SetValue(ptl,Tol,Standard_False);
169     ptsol.SetParameters(U1,V1,U2,V2);
170     ptsol.SetParameter(last);
171     alig->AddVertex(ptsol);
172     alig->SetLastPoint(alig->NbVertex());
173   }
174 }
175 //=======================================================================
176 //function : IntCyCy
177 //purpose  : 
178 //=======================================================================
179 Standard_Boolean IntCyCy(const IntSurf_Quadric& Quad1,
180                          const IntSurf_Quadric& Quad2,
181                          const Standard_Real Tol,
182                          Standard_Boolean& Empty,
183                          Standard_Boolean& Same,
184                          Standard_Boolean& Multpoint,
185                          IntPatch_SequenceOfLine& slin,
186                          IntPatch_SequenceOfPoint& spnt)
187
188 {
189   IntPatch_Point ptsol;
190
191   Standard_Integer i;
192
193   IntSurf_TypeTrans trans1,trans2;
194   IntAna_ResultType typint;
195
196   gp_Elips elipsol;
197   gp_Lin linsol;
198
199   gp_Cylinder Cy1(Quad1.Cylinder());
200   gp_Cylinder Cy2(Quad2.Cylinder());
201
202   IntAna_QuadQuadGeo inter(Cy1,Cy2,Tol);
203
204   if (!inter.IsDone()) {return Standard_False;}
205
206   typint = inter.TypeInter();
207   Standard_Integer NbSol = inter.NbSolutions();
208   Empty = Standard_False;
209   Same  = Standard_False;
210
211   switch (typint) {
212
213   case IntAna_Empty :
214     {
215       Empty = Standard_True;
216     }
217     break;
218
219   case IntAna_Same:
220     {
221       Same  = Standard_True;
222     }
223     break;
224
225
226   case IntAna_Point :
227     {
228       gp_Pnt psol(inter.Point(1));
229       Standard_Real U1,V1,U2,V2;
230       Quad1.Parameters(psol,U1,V1);
231       Quad2.Parameters(psol,U2,V2);
232       ptsol.SetValue(psol,Tol,Standard_True);
233       ptsol.SetParameters(U1,V1,U2,V2);
234       spnt.Append(ptsol);
235     }
236     break;
237
238   case IntAna_Line:
239     {
240       gp_Pnt ptref;
241       if (NbSol == 1) { // ligne de tangence
242         linsol = inter.Line(1);
243         ptref = linsol.Location();
244         gp_Dir crb1(gp_Vec(ptref,Cy1.Location()));
245         gp_Dir crb2(gp_Vec(ptref,Cy2.Location()));
246         gp_Vec norm1(Quad1.Normale(ptref));
247         gp_Vec norm2(Quad2.Normale(ptref));
248         IntSurf_Situation situcyl1;
249         IntSurf_Situation situcyl2;
250
251         if (crb1.Dot(crb2) < 0.) { // centre de courbures "opposes"
252           if (norm1.Dot(crb1) > 0.) {
253             situcyl2 = IntSurf_Inside;
254           }
255           else {
256             situcyl2 = IntSurf_Outside;
257           }
258           if (norm2.Dot(crb2) > 0.) {
259             situcyl1 = IntSurf_Inside;
260           }
261           else {
262             situcyl1 = IntSurf_Outside;
263           }
264         }
265         else {
266           if (Cy1.Radius() < Cy2.Radius()) {
267             if (norm1.Dot(crb1) > 0.) {
268               situcyl2 = IntSurf_Inside;
269             }
270             else {
271               situcyl2 = IntSurf_Outside;
272             }
273             if (norm2.Dot(crb2) > 0.) {
274               situcyl1 = IntSurf_Outside;
275             }
276             else {
277               situcyl1 = IntSurf_Inside;
278             }
279           }
280           else {
281             if (norm1.Dot(crb1) > 0.) {
282               situcyl2 = IntSurf_Outside;
283             }
284             else {
285               situcyl2 = IntSurf_Inside;
286             }
287             if (norm2.Dot(crb2) > 0.) {
288               situcyl1 = IntSurf_Inside;
289             }
290             else {
291               situcyl1 = IntSurf_Outside;
292             }
293           }
294         }
295         Handle(IntPatch_GLine) glig =  new IntPatch_GLine(linsol, Standard_True, situcyl1, situcyl2);
296         slin.Append(glig);
297       }
298       else {
299         for (i=1; i <= NbSol; i++) {
300           linsol = inter.Line(i);
301           ptref = linsol.Location();
302           gp_Vec lsd = linsol.Direction();
303           Standard_Real qwe = lsd.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
304           if (qwe >0.00000001) {
305             trans1 = IntSurf_Out;
306             trans2 = IntSurf_In;
307           }
308           else if (qwe <-0.00000001) {
309             trans1 = IntSurf_In;
310             trans2 = IntSurf_Out;
311           }
312           else {
313             trans1=trans2=IntSurf_Undecided; 
314           }
315           
316           Handle(IntPatch_GLine) glig = new IntPatch_GLine(linsol, Standard_False,trans1,trans2);
317           slin.Append(glig);
318         }
319       }
320     }
321     break;
322     
323   case IntAna_Ellipse:
324     {
325       gp_Vec Tgt;
326       gp_Pnt ptref;
327       IntPatch_Point pmult1, pmult2;
328       
329       elipsol = inter.Ellipse(1);
330       
331       gp_Pnt pttang1(ElCLib::Value(0.5*M_PI, elipsol));
332       gp_Pnt pttang2(ElCLib::Value(1.5*M_PI, elipsol));
333       
334       Multpoint = Standard_True;
335       pmult1.SetValue(pttang1,Tol,Standard_True);
336       pmult2.SetValue(pttang2,Tol,Standard_True);
337       pmult1.SetMultiple(Standard_True);
338       pmult2.SetMultiple(Standard_True);
339       
340       Standard_Real oU1,oV1,oU2,oV2;
341       Quad1.Parameters(pttang1,oU1,oV1); 
342       Quad2.Parameters(pttang1,oU2,oV2);
343       pmult1.SetParameters(oU1,oV1,oU2,oV2);
344
345       Quad1.Parameters(pttang2,oU1,oV1); 
346       Quad2.Parameters(pttang2,oU2,oV2);
347       pmult2.SetParameters(oU1,oV1,oU2,oV2);
348       
349       // on traite la premiere ellipse
350
351       //-- Calcul de la Transition de la ligne 
352       ElCLib::D1(0.,elipsol,ptref,Tgt);
353       Standard_Real qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
354       if (qwe>0.00000001) {
355         trans1 = IntSurf_Out;
356         trans2 = IntSurf_In;
357       }
358       else if (qwe<-0.00000001) {
359         trans1 = IntSurf_In;
360         trans2 = IntSurf_Out;
361       }
362       else { 
363         trans1=trans2=IntSurf_Undecided; 
364       }
365       //-- Transition calculee au point 0 -> Trans2 , Trans1 
366       //-- car ici, on devarit calculer en PI
367       Handle(IntPatch_GLine) glig = new IntPatch_GLine(elipsol,Standard_False,trans2,trans1);
368       //
369       {
370         Standard_Real aU1, aV1, aU2, aV2;
371         IntPatch_Point aIP;
372         gp_Pnt aP (ElCLib::Value(0., elipsol));
373         //
374         aIP.SetValue(aP,Tol,Standard_False);
375         aIP.SetMultiple(Standard_False);
376         //
377         Quad1.Parameters(aP, aU1, aV1); 
378         Quad2.Parameters(aP, aU2, aV2);
379         aIP.SetParameters(aU1, aV1, aU2, aV2);
380         //
381         aIP.SetParameter(0.);
382         glig->AddVertex(aIP);
383         glig->SetFirstPoint(1);
384         //
385         aIP.SetParameter(2.*M_PI);
386         glig->AddVertex(aIP);
387         glig->SetLastPoint(2);
388       }
389       //
390       pmult1.SetParameter(0.5*M_PI);
391       glig->AddVertex(pmult1);
392       //
393       pmult2.SetParameter(1.5*M_PI);
394       glig->AddVertex(pmult2);
395      
396       //
397       slin.Append(glig);
398       
399       //-- Transitions calculee au point 0    OK
400       //
401       // on traite la deuxieme ellipse
402       elipsol = inter.Ellipse(2);
403
404       Standard_Real param1 = ElCLib::Parameter(elipsol,pttang1);
405       Standard_Real param2 = ElCLib::Parameter(elipsol,pttang2);
406       Standard_Real parampourtransition;
407       if (param1 < param2) {
408         pmult1.SetParameter(0.5*M_PI);
409         pmult2.SetParameter(1.5*M_PI);
410         parampourtransition = M_PI;
411       }
412       else {
413         pmult1.SetParameter(1.5*M_PI);
414         pmult2.SetParameter(0.5*M_PI);
415         parampourtransition = 0.0;
416       }
417       
418       //-- Calcul des transitions de ligne pour la premiere ligne 
419       ElCLib::D1(parampourtransition,elipsol,ptref,Tgt);      
420       qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
421       if(qwe> 0.00000001) {
422         trans1 = IntSurf_Out;
423         trans2 = IntSurf_In;
424       }
425       else if(qwe< -0.00000001) {
426         trans1 = IntSurf_In;
427         trans2 = IntSurf_Out;
428       }
429       else { 
430         trans1=trans2=IntSurf_Undecided;
431       }
432       //-- La transition a ete calculee sur un point de cette ligne 
433       glig = new IntPatch_GLine(elipsol,Standard_False,trans1,trans2);
434       //
435       {
436         Standard_Real aU1, aV1, aU2, aV2;
437         IntPatch_Point aIP;
438         gp_Pnt aP (ElCLib::Value(0., elipsol));
439         //
440         aIP.SetValue(aP,Tol,Standard_False);
441         aIP.SetMultiple(Standard_False);
442         //
443         Quad1.Parameters(aP, aU1, aV1); 
444         Quad2.Parameters(aP, aU2, aV2);
445         aIP.SetParameters(aU1, aV1, aU2, aV2);
446         //
447         aIP.SetParameter(0.);
448         glig->AddVertex(aIP);
449         glig->SetFirstPoint(1);
450         //
451         aIP.SetParameter(2.*M_PI);
452         glig->AddVertex(aIP);
453         glig->SetLastPoint(2);
454       }
455       //
456       glig->AddVertex(pmult1);
457       glig->AddVertex(pmult2);
458       //
459       slin.Append(glig);
460     }
461     break;
462     
463
464   case IntAna_NoGeometricSolution:
465     {
466       Standard_Boolean bReverse;
467       Standard_Real U1,V1,U2,V2;
468       gp_Pnt psol;
469       //
470       bReverse=IsToReverse(Cy1, Cy2, Tol);
471       if (bReverse){
472         Cy2=Quad1.Cylinder();
473         Cy1=Quad2.Cylinder();
474       }
475       //
476       IntAna_IntQuadQuad anaint(Cy1,Cy2,Tol);
477       if (!anaint.IsDone()) {
478         return Standard_False;
479       }
480       
481       if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0) {
482         Empty = Standard_True;
483       }
484       else {
485         NbSol = anaint.NbPnt();
486         for (i = 1; i <= NbSol; i++) {
487           psol = anaint.Point(i);
488           Quad1.Parameters(psol,U1,V1);
489           Quad2.Parameters(psol,U2,V2);
490           ptsol.SetValue(psol,Tol,Standard_True);
491           ptsol.SetParameters(U1,V1,U2,V2);
492           spnt.Append(ptsol);
493         }
494         
495         gp_Pnt ptvalid, ptf, ptl;
496         gp_Vec tgvalid;
497         
498         Standard_Real first,last,para;
499         IntAna_Curve curvsol;
500         Standard_Boolean tgfound;
501         Standard_Integer kount;
502         
503         NbSol = anaint.NbCurve();
504         for (i = 1; i <= NbSol; i++) {
505           curvsol = anaint.Curve(i);
506           curvsol.Domain(first,last);
507           ptf = curvsol.Value(first);
508           ptl = curvsol.Value(last);
509           
510           para = last;
511           kount = 1;
512           tgfound = Standard_False;
513           
514           while (!tgfound) {
515             para = (1.123*first + para)/2.123;
516             tgfound = curvsol.D1u(para,ptvalid,tgvalid);
517             if (!tgfound) {
518               kount ++;
519               tgfound = kount > 5;
520             }
521           }
522           Handle(IntPatch_ALine) alig;
523           if (kount <= 5) {
524             Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid),
525                                                  Quad1.Normale(ptvalid));
526             if(qwe>0.00000001) { 
527               trans1 = IntSurf_Out;
528               trans2 = IntSurf_In;
529             }
530             else if(qwe<-0.00000001) {
531               trans1 = IntSurf_In;
532               trans2 = IntSurf_Out;
533             }
534             else { 
535               trans1=trans2=IntSurf_Undecided; 
536             }
537             alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
538           }
539           else {
540             alig = new IntPatch_ALine(curvsol,Standard_False);
541             //-- cout << "Transition indeterminee" << endl;
542           }
543           Standard_Boolean TempFalse1 = Standard_False;
544           Standard_Boolean TempFalse2 = Standard_False;
545           
546           ProcessBounds(alig,slin,Quad1,Quad2,TempFalse1,ptf,first,
547                         TempFalse2,ptl,last,Multpoint,Tol);
548           slin.Append(alig);
549         }
550       }
551     }
552     break;
553
554   default:
555     {
556       return Standard_False;
557     }
558   }
559   return Standard_True;
560 }
561
562
563 //=======================================================================
564 //function : IntCySp
565 //purpose  : 
566 //=======================================================================
567 Standard_Boolean IntCySp(const IntSurf_Quadric& Quad1,
568                          const IntSurf_Quadric& Quad2,
569                          const Standard_Real Tol,
570                          const Standard_Boolean Reversed,
571                          Standard_Boolean& Empty,
572                          Standard_Boolean& Multpoint,
573                          IntPatch_SequenceOfLine& slin,
574                          IntPatch_SequenceOfPoint& spnt)
575
576 {
577   Standard_Integer i;
578
579   IntSurf_TypeTrans trans1,trans2;
580   IntAna_ResultType typint;
581   IntPatch_Point ptsol;
582   gp_Circ cirsol;
583
584   gp_Cylinder Cy;
585   gp_Sphere Sp;
586
587   if (!Reversed) {
588     Cy = Quad1.Cylinder();
589     Sp = Quad2.Sphere();
590   }
591   else {
592     Cy = Quad2.Cylinder();
593     Sp = Quad1.Sphere();
594   }
595   IntAna_QuadQuadGeo inter(Cy,Sp,Tol);
596
597   if (!inter.IsDone()) {return Standard_False;}
598
599   typint = inter.TypeInter();
600   Standard_Integer NbSol = inter.NbSolutions();
601   Empty = Standard_False;
602
603   switch (typint) {
604
605   case IntAna_Empty :
606     {
607       Empty = Standard_True;
608     }
609     break;
610
611   case IntAna_Point :
612     {
613       gp_Pnt psol(inter.Point(1));
614       Standard_Real U1,V1,U2,V2;
615       Quad1.Parameters(psol,U1,V1);
616       Quad2.Parameters(psol,U2,V2);
617       ptsol.SetValue(psol,Tol,Standard_True);
618       ptsol.SetParameters(U1,V1,U2,V2);
619       spnt.Append(ptsol);
620     }
621     break;
622
623   case IntAna_Circle:
624     {
625       cirsol = inter.Circle(1);
626       gp_Vec Tgt;
627       gp_Pnt ptref;
628       ElCLib::D1(0.,cirsol,ptref,Tgt);
629
630       if (NbSol == 1) {
631         gp_Vec TestCurvature(ptref,Sp.Location());
632         gp_Vec Normsp,Normcyl;
633         if (!Reversed) {
634           Normcyl = Quad1.Normale(ptref);
635           Normsp  = Quad2.Normale(ptref);
636         }
637         else {
638           Normcyl = Quad2.Normale(ptref);
639           Normsp  = Quad1.Normale(ptref);
640         }
641         
642         IntSurf_Situation situcyl;
643         IntSurf_Situation situsp;
644         
645         if (Normcyl.Dot(TestCurvature) > 0.) {
646           situsp = IntSurf_Outside;
647           if (Normsp.Dot(Normcyl) > 0.) {
648             situcyl = IntSurf_Inside;
649           }
650           else {
651             situcyl = IntSurf_Outside;
652           }
653         }
654         else {
655           situsp = IntSurf_Inside;
656           if (Normsp.Dot(Normcyl) > 0.) {
657             situcyl = IntSurf_Outside;
658           }
659           else {
660             situcyl = IntSurf_Inside;
661           }
662         }
663         Handle(IntPatch_GLine) glig;
664         if (!Reversed) {
665           glig = new IntPatch_GLine(cirsol, Standard_True, situcyl, situsp);
666         }
667         else {
668           glig = new IntPatch_GLine(cirsol, Standard_True, situsp, situcyl);
669         }
670         slin.Append(glig);
671       }
672       else {
673         if (Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref)) > 0.0) {
674           trans1 = IntSurf_Out;
675           trans2 = IntSurf_In;
676         }
677         else {
678           trans1 = IntSurf_In;
679           trans2 = IntSurf_Out;
680         }
681         Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
682         slin.Append(glig);
683
684         cirsol = inter.Circle(2);
685         ElCLib::D1(0.,cirsol,ptref,Tgt);
686         Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
687         if(qwe> 0.0000001) {
688           trans1 = IntSurf_Out;
689           trans2 = IntSurf_In;
690         }
691         else if(qwe<-0.0000001) {
692           trans1 = IntSurf_In;
693           trans2 = IntSurf_Out;
694         }
695         else { 
696           trans1=trans2=IntSurf_Undecided; 
697         }
698         glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
699         slin.Append(glig);
700       }
701     }
702     break;
703     
704   case IntAna_NoGeometricSolution:
705     {
706       gp_Pnt psol;
707       Standard_Real U1,V1,U2,V2;
708       IntAna_IntQuadQuad anaint(Cy,Sp,Tol);
709       if (!anaint.IsDone()) {
710         return Standard_False;
711       }
712
713       if (anaint.NbPnt()==0 && anaint.NbCurve()==0) {
714         Empty = Standard_True;
715       }
716       else {
717
718         NbSol = anaint.NbPnt();
719         for (i = 1; i <= NbSol; i++) {
720           psol = anaint.Point(i);
721           Quad1.Parameters(psol,U1,V1);
722           Quad2.Parameters(psol,U2,V2);
723           ptsol.SetValue(psol,Tol,Standard_True);
724           ptsol.SetParameters(U1,V1,U2,V2);
725           spnt.Append(ptsol);
726         }
727         
728         gp_Pnt ptvalid,ptf,ptl;
729         gp_Vec tgvalid;
730         Standard_Real first,last,para;
731         IntAna_Curve curvsol;
732         Standard_Boolean tgfound;
733         Standard_Integer kount;
734         
735         NbSol = anaint.NbCurve();
736         for (i = 1; i <= NbSol; i++) {
737           curvsol = anaint.Curve(i);
738           curvsol.Domain(first,last);
739           ptf = curvsol.Value(first);
740           ptl = curvsol.Value(last);
741
742           para = last;
743           kount = 1;
744           tgfound = Standard_False;
745           
746           while (!tgfound) {
747             para = (1.123*first + para)/2.123;
748             tgfound = curvsol.D1u(para,ptvalid,tgvalid);
749             if (!tgfound) {
750               kount ++;
751               tgfound = kount > 5;
752             }
753           }
754           Handle(IntPatch_ALine) alig;
755           if (kount <= 5) {
756             Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid),
757                                                  Quad1.Normale(ptvalid));
758             if(qwe> 0.00000001) {
759               trans1 = IntSurf_Out;
760               trans2 = IntSurf_In;
761             }
762             else if(qwe<-0.00000001) {
763               trans1 = IntSurf_In;
764               trans2 = IntSurf_Out;
765             }
766             else { 
767               trans1=trans2=IntSurf_Undecided; 
768             }
769             alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
770           }
771           else {
772             alig = new IntPatch_ALine(curvsol,Standard_False);
773           }
774           Standard_Boolean TempFalse1a = Standard_False;
775           Standard_Boolean TempFalse2a = Standard_False;
776
777           //-- ptf et ptl : points debut et fin de alig 
778           
779           ProcessBounds(alig,slin,Quad1,Quad2,TempFalse1a,ptf,first,
780                         TempFalse2a,ptl,last,Multpoint,Tol);
781           slin.Append(alig);
782         } //-- boucle sur les lignes 
783       } //-- solution avec au moins une lihne 
784     }
785     break;
786
787   default:
788     {
789       return Standard_False;
790     }
791   }
792   return Standard_True;
793 }
794 //=======================================================================
795 //function : IntCyCo
796 //purpose  : 
797 //=======================================================================
798 Standard_Boolean IntCyCo(const IntSurf_Quadric& Quad1,
799                          const IntSurf_Quadric& Quad2,
800                          const Standard_Real Tol,
801                          const Standard_Boolean Reversed,
802                          Standard_Boolean& Empty,
803                          Standard_Boolean& Multpoint,
804                          IntPatch_SequenceOfLine& slin,
805                          IntPatch_SequenceOfPoint& spnt)
806
807 {
808   IntPatch_Point ptsol;
809
810   Standard_Integer i;
811
812   IntSurf_TypeTrans trans1,trans2;
813   IntAna_ResultType typint;
814   gp_Circ cirsol;
815
816   gp_Cylinder Cy;
817   gp_Cone     Co;
818
819   if (!Reversed) {
820     Cy = Quad1.Cylinder();
821     Co = Quad2.Cone();
822   }
823   else {
824     Cy = Quad2.Cylinder();
825     Co = Quad1.Cone();
826   }
827   IntAna_QuadQuadGeo inter(Cy,Co,Tol);
828
829   if (!inter.IsDone()) {return Standard_False;}
830
831   typint = inter.TypeInter();
832   Standard_Integer NbSol = inter.NbSolutions();
833   Empty = Standard_False;
834
835   switch (typint) {
836
837   case IntAna_Empty : {
838     Empty = Standard_True;
839   }
840     break;
841
842   case IntAna_Point :{
843     gp_Pnt psol(inter.Point(1));
844     Standard_Real U1,V1,U2,V2;
845     Quad1.Parameters(psol,U1,V1);
846     Quad1.Parameters(psol,U2,V2);
847     ptsol.SetValue(psol,Tol,Standard_True);
848     ptsol.SetParameters(U1,V1,U2,V2);
849     spnt.Append(ptsol);
850   }
851     break;
852     
853   case IntAna_Circle:  {
854     gp_Vec Tgt;
855     gp_Pnt ptref;
856     Standard_Integer j;
857     Standard_Real qwe;
858     //
859     for(j=1; j<=2; ++j) { 
860       cirsol = inter.Circle(j);
861       ElCLib::D1(0.,cirsol,ptref,Tgt);
862       qwe = Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
863       if(qwe> 0.00000001) {
864         trans1 = IntSurf_Out;
865         trans2 = IntSurf_In;
866       }
867       else if(qwe<-0.00000001) {
868         trans1 = IntSurf_In;
869         trans2 = IntSurf_Out;
870       }
871       else { 
872         trans1=trans2=IntSurf_Undecided; 
873       }
874       Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
875       slin.Append(glig);
876     }
877   }
878     break;
879     
880   case IntAna_NoGeometricSolution:    {
881     gp_Pnt psol;
882     Standard_Real U1,V1,U2,V2;
883     IntAna_IntQuadQuad anaint(Cy,Co,Tol);
884     if (!anaint.IsDone()) {
885       return Standard_False;
886     }
887     
888     if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0) {
889       Empty = Standard_True;
890     }
891     else {
892       NbSol = anaint.NbPnt();
893       for (i = 1; i <= NbSol; i++) {
894         psol = anaint.Point(i);
895         Quad1.Parameters(psol,U1,V1);
896         Quad2.Parameters(psol,U2,V2);
897         ptsol.SetValue(psol,Tol,Standard_True);
898         ptsol.SetParameters(U1,V1,U2,V2);
899         spnt.Append(ptsol);
900       }
901       
902       gp_Pnt ptvalid, ptf, ptl;
903       gp_Vec tgvalid;
904       //
905       Standard_Real first,last,para;
906       Standard_Boolean tgfound,firstp,lastp,kept;
907       Standard_Integer kount;
908       //
909       //
910       //IntAna_Curve curvsol;
911       IntAna_Curve aC;
912       IntAna_ListOfCurve aLC;
913       IntAna_ListIteratorOfListOfCurve aIt;
914       Standard_Boolean bToSplit;
915       
916       //
917       NbSol = anaint.NbCurve();
918       for (i = 1; i <= NbSol; ++i) {
919         kept = Standard_False;
920         //curvsol = anaint.Curve(i);
921         aC=anaint.Curve(i);
922         aLC.Clear();
923         bToSplit=ExploreCurve(Cy, Co, aC, 10.*Tol, aLC);
924         //
925         aIt.Initialize(aLC);
926         for (; aIt.More(); aIt.Next()) {
927           IntAna_Curve& curvsol=aIt.Value();
928           //
929           curvsol.Domain(first, last);
930           firstp = !curvsol.IsFirstOpen();
931           lastp  = !curvsol.IsLastOpen();
932           if (firstp) {
933             ptf = curvsol.Value(first);
934           }
935           if (lastp) {
936             ptl = curvsol.Value(last);
937           }
938           para = last;
939           kount = 1;
940           tgfound = Standard_False;
941           
942           while (!tgfound) {
943             para = (1.123*first + para)/2.123;
944             tgfound = curvsol.D1u(para,ptvalid,tgvalid);
945             if (!tgfound) {
946               kount ++;
947               tgfound = kount > 5;
948             }
949           }
950           Handle(IntPatch_ALine) alig;
951           if (kount <= 5) {
952             Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid),
953                                                  Quad1.Normale(ptvalid));
954             if(qwe> 0.00000001) {
955               trans1 = IntSurf_Out;
956               trans2 = IntSurf_In;
957             }
958             else if(qwe<-0.00000001) {
959               trans1 = IntSurf_In;
960               trans2 = IntSurf_Out;
961             }
962             else { 
963               trans1=trans2=IntSurf_Undecided; 
964             }
965             alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
966             kept = Standard_True;
967           }
968           else {
969             ptvalid = curvsol.Value(para);
970             alig = new IntPatch_ALine(curvsol,Standard_False);
971             kept = Standard_True;
972             //-- cout << "Transition indeterminee" << endl;
973           }
974           if (kept) {
975             Standard_Boolean Nfirstp = !firstp;
976             Standard_Boolean Nlastp  = !lastp;
977             ProcessBounds(alig,slin,Quad1,Quad2,Nfirstp,ptf,first,
978                           Nlastp,ptl,last,Multpoint,Tol);
979             slin.Append(alig);
980           }
981         } // for (; aIt.More(); aIt.Next())
982       } // for (i = 1; i <= NbSol; ++i) 
983     }
984   }
985     break;
986     
987   default:
988     return Standard_False;
989     
990   } // switch (typint)
991   
992   return Standard_True;
993 }
994 //=======================================================================
995 //function : ExploreCurve
996 //purpose  : 
997 //=======================================================================
998 Standard_Boolean ExploreCurve(const gp_Cylinder& ,//aCy,
999                               const gp_Cone& aCo,
1000                               IntAna_Curve& aC,
1001                               const Standard_Real aTol,
1002                               IntAna_ListOfCurve& aLC)
1003                               
1004 {
1005   Standard_Boolean bFind=Standard_False;
1006   Standard_Real aTheta, aT1, aT2, aDst;
1007   gp_Pnt aPapx, aPx;
1008   //
1009   //aC.Dump();
1010   //
1011   aLC.Clear();
1012   aLC.Append(aC);
1013   //
1014   aPapx=aCo.Apex();
1015   //
1016   aC.Domain(aT1, aT2);
1017   //
1018   aPx=aC.Value(aT1);
1019   aDst=aPx.Distance(aPapx);
1020   if (aDst<aTol) {
1021     return bFind;
1022   }
1023   aPx=aC.Value(aT2);
1024   aDst=aPx.Distance(aPapx);
1025   if (aDst<aTol) {
1026     return bFind;
1027   }
1028   //
1029   bFind=aC.FindParameter(aPapx, aTheta);
1030   if (!bFind){
1031     return bFind;
1032   }
1033   //
1034   aPx=aC.Value(aTheta);
1035   aDst=aPx.Distance(aPapx);
1036   if (aDst>aTol) {
1037     return !bFind;
1038   }
1039   //
1040   // need to be splitted at aTheta
1041   IntAna_Curve aC1, aC2;
1042   //
1043   aC1=aC;
1044   aC1.SetDomain(aT1, aTheta);
1045   aC2=aC;
1046   aC2.SetDomain(aTheta, aT2);
1047   //
1048   aLC.Clear();
1049   aLC.Append(aC1);
1050   aLC.Append(aC2);
1051   //
1052   return bFind;
1053 }
1054 //=======================================================================
1055 //function : IsToReverse
1056 //purpose  : 
1057 //=======================================================================
1058 Standard_Boolean IsToReverse(const gp_Cylinder& Cy1,
1059                              const gp_Cylinder& Cy2,
1060                              const Standard_Real Tol)
1061 {
1062   Standard_Boolean bRet;
1063   Standard_Real aR1,aR2, dR, aSc1, aSc2;
1064   //
1065   bRet=Standard_False;
1066   //
1067   aR1=Cy1.Radius();
1068   aR2=Cy2.Radius();
1069   dR=aR1-aR2;
1070   if (dR<0.) {
1071     dR=-dR;
1072   }
1073   if (dR>Tol) {
1074     bRet=aR1>aR2;
1075   }
1076   else {
1077     gp_Dir aDZ(0.,0.,1.);
1078     //
1079     const gp_Dir& aDir1=Cy1.Axis().Direction();
1080     aSc1=aDir1*aDZ;
1081     if (aSc1<0.) {
1082       aSc1=-aSc1;
1083     }
1084     //
1085     const gp_Dir& aDir2=Cy2.Axis().Direction();
1086     aSc2=aDir2*aDZ;
1087     if (aSc2<0.) {
1088       aSc2=-aSc2;
1089     }
1090     //
1091     if (aSc2<aSc1) {
1092       bRet=!bRet;
1093     }
1094   }//if (dR<Tol) {
1095   return bRet;
1096 }