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