f8924fe57505cd7c707388f755d2ef914eed6f6d
[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 empt(Standard_True),
31 tgte(Standard_False),
32 oppo(Standard_False)
33 {
34 }
35 //=======================================================================
36 //function : IntPatch_ImpImpIntersection
37 //purpose  : 
38 //=======================================================================
39 IntPatch_ImpImpIntersection::IntPatch_ImpImpIntersection
40        (const Handle(Adaptor3d_HSurface)&  S1,
41         const Handle(Adaptor3d_TopolTool)& D1,
42         const Handle(Adaptor3d_HSurface)&  S2,
43         const Handle(Adaptor3d_TopolTool)& D2,
44         const Standard_Real TolArc,
45         const Standard_Real TolTang,
46         const Standard_Boolean theIsReqToKeepRLine)
47 {
48   Perform(S1,D1,S2,D2,TolArc,TolTang, theIsReqToKeepRLine);
49 }
50 //=======================================================================
51 //function : Perform
52 //purpose  : 
53 //=======================================================================
54 void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_HSurface)&  S1,
55                                           const Handle(Adaptor3d_TopolTool)& D1,
56                                           const Handle(Adaptor3d_HSurface)&  S2,
57                                           const Handle(Adaptor3d_TopolTool)& D2,
58                                           const Standard_Real TolArc,
59                                           const Standard_Real TolTang,
60                                           const Standard_Boolean theIsReqToKeepRLine)
61 {
62   myDone = IntStatus_Fail;
63   spnt.Clear();
64   slin.Clear();
65
66   Standard_Boolean isPostProcessingRequired = Standard_True;
67
68   empt = Standard_True;
69   tgte = Standard_False;
70   oppo = Standard_False;
71
72   Standard_Boolean all1 = Standard_False;
73   Standard_Boolean all2 = Standard_False;
74   Standard_Boolean SameSurf = Standard_False;
75   Standard_Boolean multpoint = Standard_False;
76
77   Standard_Boolean nosolonS1 = Standard_False;
78   // indique s il y a des points sur restriction du carreau 1
79   Standard_Boolean nosolonS2 = Standard_False;
80   // indique s il y a des points sur restriction du carreau 2
81   Standard_Integer i, nbpt, nbseg;
82   IntPatch_SequenceOfSegmentOfTheSOnBounds edg1,edg2;
83   IntPatch_SequenceOfPathPointOfTheSOnBounds pnt1,pnt2;
84   //
85   // On commence par intersecter les supports des surfaces
86   IntSurf_Quadric quad1, quad2;
87   IntPatch_ArcFunction AFunc;
88   const Standard_Real Tolang = 1.e-8;
89   GeomAbs_SurfaceType typs1, typs2;
90   Standard_Boolean bEmpty = Standard_False;
91   //
92   const Standard_Integer iT1 = SetQuad(S1, typs1, quad1);
93   const Standard_Integer iT2 = SetQuad(S2, typs2, quad2);
94   //
95   if (!iT1 || !iT2) {
96     throw Standard_ConstructionError();
97     return;
98   }
99   //
100   const Standard_Boolean bReverse = iT1 > iT2;
101   const Standard_Integer iTT = iT1*10 + iT2;
102   //
103   switch (iTT) {
104     case 11: { // Plane/Plane
105       if (!IntPP(quad1, quad2, Tolang, TolTang, SameSurf, slin)) {
106         return;
107       }
108       break;
109     }
110     //
111     case 12:
112     case 21: { // Plane/Cylinder
113       Standard_Real VMin, VMax, H;
114       //
115       const Handle(Adaptor3d_HSurface)& aSCyl = bReverse ? S1 : S2;
116       VMin = aSCyl->FirstVParameter();
117       VMax = aSCyl->LastVParameter();
118       H = (Precision::IsNegativeInfinite(VMin) || 
119            Precision::IsPositiveInfinite(VMax)) ? 0 : (VMax - VMin);
120       //
121       if (!IntPCy(quad1, quad2, Tolang, TolTang, bReverse, empt, slin, H)) {
122         return;
123       }
124       bEmpty = empt;
125       break;
126     }
127     //
128     case 13:
129     case 31: { // Plane/Cone
130       if (!IntPCo(quad1, quad2, Tolang, TolTang, bReverse, empt, multpoint, slin, spnt)) {
131         return;
132       }
133       bEmpty = empt;
134       break;
135     }
136     //
137     case 14:
138     case 41: { // Plane/Sphere
139       if (!IntPSp(quad1, quad2, Tolang, TolTang, bReverse, empt, slin, spnt)) {
140         return;
141       }
142       bEmpty = empt;
143       break;
144     }
145     //
146     case 15:
147     case 51: { // Plane/Torus
148       if (!IntPTo(quad1, quad2, TolTang, bReverse, empt, slin)) {
149         return;
150       }
151       bEmpty = empt;
152       break;
153     }
154     //
155     case 22:
156       { // Cylinder/Cylinder
157         Bnd_Box2d aBox1, aBox2;
158
159         const Standard_Real aU1f = S1->FirstUParameter();
160         Standard_Real aU1l = S1->LastUParameter();
161         const Standard_Real aU2f = S2->FirstUParameter();
162         Standard_Real aU2l = S2->LastUParameter();
163
164         const Standard_Real anUperiod = 2.0*M_PI;
165
166         if(aU1l - aU1f > anUperiod)
167           aU1l = aU1f + anUperiod;
168
169         if(aU2l - aU2f > anUperiod)
170           aU2l = aU2f + anUperiod;
171
172         aBox1.Add(gp_Pnt2d(aU1f, S1->FirstVParameter()));
173         aBox1.Add(gp_Pnt2d(aU1l, S1->LastVParameter()));
174         aBox2.Add(gp_Pnt2d(aU2f, S2->FirstVParameter()));
175         aBox2.Add(gp_Pnt2d(aU2l, S2->LastVParameter()));
176
177         // Resolution is too big if the cylinder radius is
178         // too small. Therefore, we shall bind its value above. 
179         // Here, we use simple constant.
180         const Standard_Real a2DTol = Min(1.0e-4, Min( S1->UResolution(TolTang),
181                                             S2->UResolution(TolTang)));
182
183         myDone = IntCyCy(quad1, quad2, TolTang, a2DTol, aBox1, aBox2,
184                                     empt, SameSurf, multpoint, slin, spnt);
185
186         if (myDone == IntPatch_ImpImpIntersection::IntStatus_Fail)
187         {
188           return;
189         }
190
191         bEmpty = empt;
192         if(!slin.IsEmpty())
193         {
194           const Handle(IntPatch_WLine)& aWLine = 
195                                     Handle(IntPatch_WLine)::DownCast(slin.Value(1));
196
197           if(!aWLine.IsNull())
198           {//No geometric solution
199             isPostProcessingRequired = Standard_False;
200           }
201         }
202
203         break;
204       }
205     //
206     case 23:
207     case 32: { // Cylinder/Cone
208       if (!IntCyCo(quad1, quad2, TolTang, bReverse, empt, multpoint, slin, spnt)) {
209         return;
210       }
211       bEmpty = empt;
212       break;
213     }
214     //
215     case 24:
216     case 42: { // Cylinder/Sphere
217       if (!IntCySp(quad1, quad2, TolTang, bReverse, empt, multpoint, slin, spnt)) {
218         return;
219       }
220       bEmpty = empt;
221       break;
222     }
223     //
224     case 25:
225     case 52: { // Cylinder/Torus
226       if (!IntCyTo(quad1, quad2, TolTang, bReverse, empt, slin)) {
227         return;
228       }
229       bEmpty = empt;
230       break;
231     }
232     //
233     case 33: { // Cone/Cone
234       if (!IntCoCo(quad1, quad2, TolTang, empt, SameSurf, multpoint, slin, spnt)) {
235         return;
236       }
237       bEmpty = empt;
238       break;
239     }
240     //
241     case 34:
242     case 43: { // Cone/Sphere
243       if (!IntCoSp(quad1, quad2, TolTang, bReverse, empt, multpoint, slin, spnt)) {
244         return;
245       }
246       bEmpty = empt;
247       break;
248     }
249     //
250     case 35:
251     case 53: { // Cone/Torus
252       if (!IntCoTo(quad1, quad2, TolTang, bReverse, empt, slin)) {
253         return;
254       }
255       break;
256     }
257     //
258     case 44: { // Sphere/Sphere
259       if (!IntSpSp(quad1, quad2, TolTang, empt, SameSurf, slin, spnt)) {
260         return;
261       }
262       bEmpty = empt;
263       break;
264     }
265     //
266     case 45:
267     case 54: { // Sphere/Torus
268       if (!IntSpTo(quad1, quad2, TolTang, bReverse, empt, slin)) {
269         return;
270       }
271       bEmpty = empt;
272       break;
273     }
274     //
275     case 55: { // Torus/Torus
276       if (!IntToTo(quad1, quad2, TolTang, SameSurf, empt, slin)) {
277         return;
278       }
279       bEmpty = empt;
280       break;
281     }
282     //
283     default: {
284       throw Standard_ConstructionError();
285       break;
286     }
287   }
288   //
289   if (bEmpty) {
290     if (myDone == IntStatus_Fail)
291       myDone = IntStatus_OK;
292
293     return;
294   }
295   //
296
297   if(isPostProcessingRequired)
298   {
299     if (!SameSurf) {
300       AFunc.SetQuadric(quad2);
301       AFunc.Set(S1);
302     
303       solrst.Perform(AFunc, D1, TolArc, TolTang);
304       if (!solrst.IsDone()) {
305         return;
306       }
307
308       if (solrst.AllArcSolution() && typs1 == typs2) {
309         all1 = Standard_True;
310       }
311       nbpt = solrst.NbPoints();
312       nbseg= solrst.NbSegments();
313       for (i = 1; i <= nbpt; i++)
314       {
315         const IntPatch_ThePathPointOfTheSOnBounds& aPt = solrst.Point(i);
316         pnt1.Append(aPt);
317       }
318       for (i = 1; i <= nbseg; i++)
319       {
320         const IntPatch_TheSegmentOfTheSOnBounds& aSegm = solrst.Segment(i);
321         edg1.Append(aSegm);
322       }
323       nosolonS1 = (nbpt == 0) && (nbseg == 0);
324
325       if (nosolonS1 && all1) {  // cas de face sans restrictions
326         all1 = Standard_False;
327       }
328     }//if (!SameSurf) {
329     else {
330       nosolonS1 = Standard_True;
331     }
332
333     if (!SameSurf) {
334       AFunc.SetQuadric(quad1);
335       AFunc.Set(S2);
336
337       solrst.Perform(AFunc, D2, TolArc, TolTang);
338       if (!solrst.IsDone()) {
339         return;
340       }
341     
342       if (solrst.AllArcSolution() && typs1 == typs2) {
343         all2 = Standard_True;
344       }
345
346       nbpt = solrst.NbPoints();
347       nbseg= solrst.NbSegments();
348       for (i=1; i<= nbpt; i++) {
349         const IntPatch_ThePathPointOfTheSOnBounds& aPt = solrst.Point(i);
350         pnt2.Append(aPt);
351       }
352     
353       for (i=1; i<= nbseg; i++) {
354         const IntPatch_TheSegmentOfTheSOnBounds& aSegm = solrst.Segment(i);
355         edg2.Append(aSegm);
356       }
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       myDone = IntStatus_OK;
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   myDone = IntStatus_OK;
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