0024915: Wrong intersection curves between two cylinders
[occt.git] / src / IntPatch / IntPatch_ImpImpIntersection_2.gxx
1 // Created on: 1992-05-07
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1992-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 static 
18   Standard_Integer SetQuad(const Handle(Adaptor3d_HSurface)& theS,
19                            GeomAbs_SurfaceType& theTS,
20                            IntSurf_Quadric& theQuad);
21
22 //=======================================================================
23 //function : IntPatch_ImpImpIntersection
24 //purpose  : 
25 //=======================================================================
26 IntPatch_ImpImpIntersection::IntPatch_ImpImpIntersection ():
27        done(Standard_False)
28 {
29 }
30 //=======================================================================
31 //function : IntPatch_ImpImpIntersection
32 //purpose  : 
33 //=======================================================================
34 IntPatch_ImpImpIntersection::IntPatch_ImpImpIntersection
35        (const Handle(Adaptor3d_HSurface)&  S1,
36         const Handle(Adaptor3d_TopolTool)& D1,
37         const Handle(Adaptor3d_HSurface)&  S2,
38         const Handle(Adaptor3d_TopolTool)& D2,
39         const Standard_Real TolArc,
40         const Standard_Real TolTang)
41 {
42   Perform(S1,D1,S2,D2,TolArc,TolTang);
43 }
44 //=======================================================================
45 //function : Perform
46 //purpose  : 
47 //=======================================================================
48 void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_HSurface)&  S1,
49                                           const Handle(Adaptor3d_TopolTool)& D1,
50                                           const Handle(Adaptor3d_HSurface)&  S2,
51                                           const Handle(Adaptor3d_TopolTool)& D2,
52                                           const Standard_Real TolArc,
53                                           const Standard_Real TolTang,
54                                           const Standard_Boolean isTheTrimmed) {
55   done = Standard_False;
56   Standard_Boolean isTrimmed = isTheTrimmed;
57   spnt.Clear();
58   slin.Clear();
59
60   empt = Standard_True;
61   tgte = Standard_False;
62   oppo = Standard_False;
63
64   Standard_Boolean all1 = Standard_False;
65   Standard_Boolean all2 = Standard_False;
66   Standard_Boolean SameSurf = Standard_False;
67   Standard_Boolean multpoint = Standard_False;
68
69   Standard_Boolean nosolonS1 = Standard_False;
70   // indique s il y a des points sur restriction du carreau 1
71   Standard_Boolean nosolonS2 = Standard_False;
72   // indique s il y a des points sur restriction du carreau 2
73   Standard_Integer i, nbpt, nbseg;
74   IntPatch_SequenceOfSegmentOfTheSOnBounds edg1,edg2;
75   IntPatch_SequenceOfPathPointOfTheSOnBounds pnt1,pnt2;
76   //
77   // On commence par intersecter les supports des surfaces
78   IntSurf_Quadric quad1, quad2;
79   IntPatch_ArcFunction AFunc;
80   const Standard_Real Tolang = 1.e-8;
81   GeomAbs_SurfaceType typs1, typs2;
82   Standard_Boolean bEmpty = Standard_False;
83   //
84   const Standard_Integer iT1 = SetQuad(S1, typs1, quad1);
85   const Standard_Integer iT2 = SetQuad(S2, typs2, quad2);
86   //
87   if (!iT1 || !iT2) {
88     Standard_ConstructionError::Raise();
89     return;
90   }
91   //
92   const Standard_Boolean bReverse = iT1 > iT2;
93   const Standard_Integer iTT = iT1*10 + iT2;
94   //
95   switch (iTT) {
96     case 11: { // Plane/Plane
97       if (!IntPP(quad1, quad2, Tolang, TolTang, SameSurf, slin)) {
98         return;
99       }
100       break;
101     }
102     //
103     case 12:
104     case 21: { // Plane/Cylinder
105       Standard_Real VMin, VMax, H;
106       //
107       const Handle(Adaptor3d_HSurface)& aSCyl = bReverse ? S2 : S1;
108       VMin = aSCyl->FirstVParameter();
109       VMax = aSCyl->LastVParameter();
110       H = (Precision::IsNegativeInfinite(VMin) || 
111            Precision::IsPositiveInfinite(VMax)) ? 0 : (VMax - VMin);
112       //
113       if (!IntPCy(quad1, quad2, Tolang, TolTang, bReverse, empt, slin, H)) {
114         return;
115       }
116       bEmpty = empt;
117       break;
118     }
119     //
120     case 13:
121     case 31: { // Plane/Cone
122       if (!IntPCo(quad1, quad2, Tolang, TolTang, bReverse, empt, multpoint, slin, spnt)) {
123         return;
124       }
125       bEmpty = empt;
126       break;
127     }
128     //
129     case 14:
130     case 41: { // Plane/Sphere
131       if (!IntPSp(quad1, quad2, Tolang, TolTang, bReverse, empt, slin, spnt)) {
132         return;
133       }
134       bEmpty = empt;
135       break;
136     }
137     //
138     case 15:
139     case 51: { // Plane/Torus
140       if (!IntPTo(quad1, quad2, TolTang, bReverse, empt, slin)) {
141         return;
142       }
143       bEmpty = empt;
144       break;
145     }
146     //
147     case 22:
148       { // Cylinder/Cylinder
149         Standard_Boolean isDONE = Standard_False;
150         
151         if(!isTrimmed)
152         {
153           isDONE = IntCyCy(quad1, quad2, TolTang, empt,
154                             SameSurf, multpoint, slin, spnt);
155         }
156         else
157         {
158           Bnd_Box2d aBox1, aBox2;
159
160           const Standard_Real aU1f = S1->FirstUParameter();
161           const Standard_Real aU1l = S1->LastUParameter();
162           const Standard_Real aU2f = S2->FirstUParameter();
163           const Standard_Real aU2l = S2->LastUParameter();
164
165           aBox1.Add(gp_Pnt2d(aU1f, S1->FirstVParameter()));
166           aBox1.Add(gp_Pnt2d(aU1l, S1->LastVParameter()));
167           aBox2.Add(gp_Pnt2d(aU2f, S2->FirstVParameter()));
168           aBox2.Add(gp_Pnt2d(aU2l, S2->LastVParameter()));
169
170           const Standard_Real a2DTol = Min( S1->UResolution(TolTang),
171                                               S2->UResolution(TolTang));
172
173           Standard_Boolean isReversed = ((aU2l - aU2f) < (aU1l - aU1f));
174
175           if(isReversed)
176           {
177             isDONE = IntCyCyTrim(quad2, quad1, TolTang, a2DTol, aBox2, aBox1,
178                                                   isReversed, empt, slin, spnt);
179           }
180           else
181           {
182             isDONE = IntCyCyTrim(quad1, quad2, TolTang, a2DTol, aBox1, aBox2,
183                                                   isReversed, empt, slin, spnt);
184           }
185
186           if(!isDONE)
187           {
188             isDONE = IntCyCy(quad1, quad2, TolTang, empt,
189                             SameSurf, multpoint, slin, spnt);
190             isTrimmed = Standard_False;
191           }
192         }
193
194         if (!isDONE)
195         {
196           return;
197         }
198
199         bEmpty = empt;
200         break;
201       }
202     //
203     case 23:
204     case 32: { // Cylinder/Cone
205       if (!IntCyCo(quad1, quad2, TolTang, bReverse, empt, multpoint, slin, spnt)) {
206         return;
207       }
208       bEmpty = empt;
209       break;
210     }
211     //
212     case 24:
213     case 42: { // Cylinder/Sphere
214       if (!IntCySp(quad1, quad2, TolTang, bReverse, empt, multpoint, slin, spnt)) {
215         return;
216       }
217       bEmpty = empt;
218       break;
219     }
220     //
221     case 25:
222     case 52: { // Cylinder/Torus
223       if (!IntCyTo(quad1, quad2, TolTang, bReverse, empt, slin)) {
224         return;
225       }
226       bEmpty = empt;
227       break;
228     }
229     //
230     case 33: { // Cone/Cone
231       if (!IntCoCo(quad1, quad2, TolTang, empt, SameSurf, multpoint, slin, spnt)) {
232         return;
233       }
234       bEmpty = empt;
235       break;
236     }
237     //
238     case 34:
239     case 43: { // Cone/Sphere
240       if (!IntCoSp(quad1, quad2, TolTang, bReverse, empt, multpoint, slin, spnt)) {
241         return;
242       }
243       bEmpty = empt;
244       break;
245     }
246     //
247     case 35:
248     case 53: { // Cone/Torus
249       if (!IntCoTo(quad1, quad2, TolTang, bReverse, empt, slin)) {
250         return;
251       }
252       break;
253     }
254     //
255     case 44: { // Sphere/Sphere
256       if (!IntSpSp(quad1, quad2, TolTang, empt, SameSurf, slin, spnt)) {
257         return;
258       }
259       bEmpty = empt;
260       break;
261     }
262     //
263     case 45:
264     case 54: { // Sphere/Torus
265       if (!IntSpTo(quad1, quad2, TolTang, bReverse, empt, slin)) {
266         return;
267       }
268       bEmpty = empt;
269       break;
270     }
271     //
272     case 55: { // Torus/Torus
273       if (!IntToTo(quad1, quad2, TolTang, SameSurf, empt, slin)) {
274         return;
275       }
276       bEmpty = empt;
277       break;
278     }
279     //
280     default: {
281       Standard_ConstructionError::Raise();
282       break;
283     }
284   }
285   //
286   if (bEmpty) {
287     done = Standard_True;
288     return;
289   }
290   //
291
292   if(!isTrimmed)
293   {
294     if (!SameSurf) {
295       AFunc.SetQuadric(quad2);
296       AFunc.Set(S1);
297     
298       solrst.Perform(AFunc, D1, TolArc, TolTang);
299       if (!solrst.IsDone()) {
300         return;
301       }
302
303       if (solrst.AllArcSolution() && typs1 == typs2) {
304         all1 = Standard_True;
305       }
306       nbpt = solrst.NbPoints();
307       nbseg= solrst.NbSegments();
308       for (i=1; i<= nbpt; i++) {
309         pnt1.Append(solrst.Point(i));
310       }
311       for (i=1; i<= nbseg; i++) {
312         edg1.Append(solrst.Segment(i));
313       }
314       nosolonS1 = (nbpt == 0) && (nbseg == 0);
315
316       if (nosolonS1 && all1) {  // cas de face sans restrictions
317         all1 = Standard_False;
318       }
319     }//if (!SameSurf) {
320     else {
321       nosolonS1 = Standard_True;
322     }
323
324     if (!SameSurf) {
325       AFunc.SetQuadric(quad1);
326       AFunc.Set(S2);
327
328       solrst.Perform(AFunc, D2, TolArc, TolTang);
329       if (!solrst.IsDone()) {
330         return;
331       }
332     
333       if (solrst.AllArcSolution() && typs1 == typs2) {
334         all2 = Standard_True;
335       }
336       nbpt = solrst.NbPoints();
337       nbseg= solrst.NbSegments();
338       for (i=1; i<= nbpt; i++) {
339         pnt2.Append(solrst.Point(i));
340       }
341     
342       for (i=1; i<= nbseg; i++) {
343         edg2.Append(solrst.Segment(i));
344       }
345       nosolonS2 = (nbpt == 0) && (nbseg == 0);
346
347       if (nosolonS2 && all2) {  // cas de face sans restrictions
348         all2 = Standard_False;
349       }
350     }// if (!SameSurf) {
351     else {
352       nosolonS2 = Standard_True;
353     }
354     //
355     if (SameSurf || (all1 && all2)) {
356       // faces "paralleles" parfaites
357       empt = Standard_False;
358       tgte = Standard_True;
359       slin.Clear();
360       spnt.Clear();
361
362       gp_Pnt Ptreference;
363
364       switch (typs1) {
365       case GeomAbs_Plane:      {
366         Ptreference = (S1->Plane()).Location();
367       }
368         break;
369       case GeomAbs_Cylinder: {
370         Ptreference = ElSLib::Value(0.,0.,S1->Cylinder());
371       }
372         break;
373       case GeomAbs_Sphere:      {
374         Ptreference = ElSLib::Value(M_PI/4.,M_PI/4.,S1->Sphere());
375       }
376         break;
377       case GeomAbs_Cone:      {
378         Ptreference = ElSLib::Value(0.,10.,S1->Cone());
379       }
380         break;
381       case GeomAbs_Torus:      {
382         Ptreference = ElSLib::Value(0.,0.,S1->Torus());
383       }
384         break;
385       default: 
386         break;
387       }
388       //
389       oppo = quad1.Normale(Ptreference).Dot(quad2.Normale(Ptreference)) < 0.0;
390       done = Standard_True;
391       return;
392     }// if (SameSurf || (all1 && all2)) {
393
394     if (!nosolonS1 || !nosolonS2) {
395       empt = Standard_False;
396       // C est la qu il faut commencer a bosser...
397       PutPointsOnLine(S1,S2,pnt1, slin, Standard_True, D1, quad1,quad2,
398                       multpoint,TolArc);
399     
400       PutPointsOnLine(S1,S2,pnt2, slin, Standard_False,D2, quad2,quad1,
401                       multpoint,TolArc);
402
403       if (edg1.Length() != 0) {
404         ProcessSegments(edg1,slin,quad1,quad2,Standard_True,TolArc);
405       }
406
407       if (edg2.Length() != 0) {
408         ProcessSegments(edg2,slin,quad1,quad2,Standard_False,TolArc);
409       }
410
411       if (edg1.Length() !=0 || edg2.Length() !=0) {
412         //      ProcessRLine(slin,S1,S2,TolArc);
413         ProcessRLine(slin,quad1,quad2,TolArc);
414       }
415     }//if (!nosolonS1 || !nosolonS2) {
416     else {
417       empt = ((slin.Length()==0) && (spnt.Length()==0));
418     }
419   }
420   
421   Standard_Integer  nblin = slin.Length(),
422                     aNbPnt = spnt.Length();
423   //
424   //modified by NIZNHY-PKV Tue Sep 06 10:03:35 2011f
425   if (aNbPnt) {
426     IntPatch_SequenceOfPoint aSIP;
427     //
428     for(i=1; i<=aNbPnt; ++i) {
429       Standard_Real aU1, aV1, aU2, aV2;
430       gp_Pnt2d aP2D;
431       TopAbs_State aState1, aState2;
432       //
433       const IntPatch_Point& aIP=spnt(i);
434       aIP.Parameters(aU1, aV1, aU2, aV2);
435       //
436       aP2D.SetCoord(aU1, aV1);
437       aState1=D1->Classify(aP2D, TolArc);
438       //
439       aP2D.SetCoord(aU2, aV2);
440       aState2=D2->Classify(aP2D, TolArc);
441       //
442       if(aState1!=TopAbs_OUT && aState2!=TopAbs_OUT) {
443         aSIP.Append(aIP);
444       }
445     }
446     //
447     spnt.Clear();
448     //
449     aNbPnt=aSIP.Length();
450     for(i=1; i<=aNbPnt; ++i) {
451       const IntPatch_Point& aIP=aSIP(i);
452       spnt.Append(aIP);
453     }
454     //
455   }//  if (aNbPnt) {
456   //modified by NIZNHY-PKV Tue Sep 06 10:18:20 2011t
457   //
458   for(i=1; i<=nblin; i++) {
459     IntPatch_IType thetype = slin.Value(i)->ArcType();
460     if(  (thetype ==  IntPatch_Ellipse)
461        ||(thetype ==  IntPatch_Circle)
462        ||(thetype ==  IntPatch_Lin)
463        ||(thetype ==  IntPatch_Parabola)
464        ||(thetype ==  IntPatch_Hyperbola)) { 
465       Handle(IntPatch_GLine)& glin = *((Handle(IntPatch_GLine)*)&slin.Value(i));
466     glin->ComputeVertexParameters(TolArc); 
467     }
468     else if(thetype == IntPatch_Analytic) { 
469       Handle(IntPatch_ALine)& aligold = *((Handle(IntPatch_ALine)*)&slin.Value(i));
470       aligold->ComputeVertexParameters(TolArc);
471     }
472     else if(thetype == IntPatch_Restriction) {
473       Handle(IntPatch_RLine)& rlig = *((Handle(IntPatch_RLine)*)&slin.Value(i));
474       rlig->ComputeVertexParameters(TolArc); 
475     }
476   }
477   //
478   //----------------------------------------------------------------
479   //-- On place 2 vertex sur les courbes de GLine qui n en 
480   //-- contiennent pas. 
481   for(i=1; i<=nblin; i++) {
482     gp_Pnt P;
483     IntPatch_Point point;
484     Standard_Real u1,v1,u2,v2; 
485     if(slin.Value(i)->ArcType() == IntPatch_Circle) { 
486       const Handle(IntPatch_GLine)& glin = *((Handle(IntPatch_GLine)*)&slin.Value(i));
487       if(glin->NbVertex() == 0) { 
488         gp_Circ Circ = glin->Circle();
489         P=ElCLib::Value(0.0,Circ);
490         quad1.Parameters(P,u1,v1);
491         quad2.Parameters(P,u2,v2);
492         point.SetValue(P,TolArc,Standard_False);
493         point.SetParameters(u1,v1,u2,v2);
494         point.SetParameter(0.0);
495         glin->AddVertex(point);
496
497         P=ElCLib::Value(0.0,Circ);
498         quad1.Parameters(P,u1,v1);
499         quad2.Parameters(P,u2,v2);
500         point.SetValue(P,TolArc,Standard_False);
501         point.SetParameters(u1,v1,u2,v2);
502         point.SetParameter(M_PI+M_PI);
503         glin->AddVertex(point);
504       }
505     }
506     
507     else if(slin.Value(i)->ArcType() == IntPatch_Ellipse) { 
508       const Handle(IntPatch_GLine)& glin = *((Handle(IntPatch_GLine)*)&slin.Value(i));
509       if(glin->NbVertex() == 0) { 
510         gp_Elips Elips = glin->Ellipse();
511         P=ElCLib::Value(0.0,Elips);
512         quad1.Parameters(P,u1,v1);
513         quad2.Parameters(P,u2,v2);
514         point.SetValue(P,TolArc,Standard_False);
515         point.SetParameters(u1,v1,u2,v2);
516         point.SetParameter(0.0);
517         glin->AddVertex(point);
518
519         P=ElCLib::Value(0.0,Elips);
520         quad1.Parameters(P,u1,v1);
521         quad2.Parameters(P,u2,v2);
522         point.SetValue(P,TolArc,Standard_False);
523         point.SetParameters(u1,v1,u2,v2);
524         point.SetParameter(M_PI+M_PI);
525         glin->AddVertex(point);
526       }
527     }
528   }
529   done = Standard_True;
530 }
531
532 //=======================================================================
533 //function : SetQuad
534 //purpose  : 
535 //=======================================================================
536 Standard_Integer SetQuad(const Handle(Adaptor3d_HSurface)& theS,
537                          GeomAbs_SurfaceType& theTS,
538                          IntSurf_Quadric& theQuad)
539 {
540   theTS = theS->GetType();
541   Standard_Integer iRet = 0;
542   switch (theTS) {
543   case GeomAbs_Plane:
544     theQuad.SetValue(theS->Plane());
545     iRet = 1;
546     break;
547   case GeomAbs_Cylinder:
548     theQuad.SetValue(theS->Cylinder());
549     iRet = 2;
550     break;
551   case GeomAbs_Cone:
552     theQuad.SetValue(theS->Cone());
553     iRet = 3;
554     break;
555   case GeomAbs_Sphere:
556     theQuad.SetValue(theS->Sphere());
557     iRet = 4;
558     break;
559   case GeomAbs_Torus:
560     theQuad.SetValue(theS->Torus());
561     iRet = 5;
562     break;
563   default:
564     break;
565   }
566   //
567   return iRet;
568 }
569