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