30d0aebed3ce0e7fa07f7137e77140cb93acb6d8
[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 ? S2 : S1;
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         pnt1.Append(solrst.Point(i));
312       }
313       for (i=1; i<= nbseg; i++) {
314         edg1.Append(solrst.Segment(i));
315       }
316       nosolonS1 = (nbpt == 0) && (nbseg == 0);
317
318       if (nosolonS1 && all1) {  // cas de face sans restrictions
319         all1 = Standard_False;
320       }
321     }//if (!SameSurf) {
322     else {
323       nosolonS1 = Standard_True;
324     }
325
326     if (!SameSurf) {
327       AFunc.SetQuadric(quad1);
328       AFunc.Set(S2);
329
330       solrst.Perform(AFunc, D2, TolArc, TolTang);
331       if (!solrst.IsDone()) {
332         return;
333       }
334     
335       if (solrst.AllArcSolution() && typs1 == typs2) {
336         all2 = Standard_True;
337       }
338       nbpt = solrst.NbPoints();
339       nbseg= solrst.NbSegments();
340       for (i=1; i<= nbpt; i++) {
341         pnt2.Append(solrst.Point(i));
342       }
343     
344       for (i=1; i<= nbseg; i++) {
345         edg2.Append(solrst.Segment(i));
346       }
347       nosolonS2 = (nbpt == 0) && (nbseg == 0);
348
349       if (nosolonS2 && all2) {  // cas de face sans restrictions
350         all2 = Standard_False;
351       }
352     }// if (!SameSurf) {
353     else {
354       nosolonS2 = Standard_True;
355     }
356     //
357     if (SameSurf || (all1 && all2)) {
358       // faces "paralleles" parfaites
359       empt = Standard_False;
360       tgte = Standard_True;
361       slin.Clear();
362       spnt.Clear();
363
364       gp_Pnt Ptreference;
365
366       switch (typs1) {
367       case GeomAbs_Plane:      {
368         Ptreference = (S1->Plane()).Location();
369       }
370         break;
371       case GeomAbs_Cylinder: {
372         Ptreference = ElSLib::Value(0.,0.,S1->Cylinder());
373       }
374         break;
375       case GeomAbs_Sphere:      {
376         Ptreference = ElSLib::Value(M_PI/4.,M_PI/4.,S1->Sphere());
377       }
378         break;
379       case GeomAbs_Cone:      {
380         Ptreference = ElSLib::Value(0.,10.,S1->Cone());
381       }
382         break;
383       case GeomAbs_Torus:      {
384         Ptreference = ElSLib::Value(0.,0.,S1->Torus());
385       }
386         break;
387       default: 
388         break;
389       }
390       //
391       oppo = quad1.Normale(Ptreference).Dot(quad2.Normale(Ptreference)) < 0.0;
392       myDone = IntStatus_OK;
393       return;
394     }// if (SameSurf || (all1 && all2)) {
395
396     if (!nosolonS1 || !nosolonS2) {
397       empt = Standard_False;
398       // C est la qu il faut commencer a bosser...
399       PutPointsOnLine(S1,S2,pnt1, slin, Standard_True, D1, quad1,quad2,
400                       multpoint,TolArc);
401     
402       PutPointsOnLine(S1,S2,pnt2, slin, Standard_False,D2, quad2,quad1,
403                       multpoint,TolArc);
404
405       if (edg1.Length() != 0) {
406         ProcessSegments(edg1,slin,quad1,quad2,Standard_True,TolArc);
407       }
408
409       if (edg2.Length() != 0) {
410         ProcessSegments(edg2,slin,quad1,quad2,Standard_False,TolArc);
411       }
412
413       if (edg1.Length() !=0 || edg2.Length() !=0) {
414         //      ProcessRLine(slin,S1,S2,TolArc);
415         ProcessRLine(slin,quad1,quad2,TolArc, theIsReqToKeepRLine);
416       }
417     }//if (!nosolonS1 || !nosolonS2) {
418     else {
419       empt = ((slin.Length()==0) && (spnt.Length()==0));
420     }
421   }
422   
423   Standard_Integer  nblin = slin.Length(),
424                     aNbPnt = spnt.Length();
425   //
426   //modified by NIZNHY-PKV Tue Sep 06 10:03:35 2011f
427   if (aNbPnt) {
428     IntPatch_SequenceOfPoint aSIP;
429     //
430     for(i=1; i<=aNbPnt; ++i) {
431       Standard_Real aU1, aV1, aU2, aV2;
432       gp_Pnt2d aP2D;
433       TopAbs_State aState1, aState2;
434       //
435       const IntPatch_Point& aIP=spnt(i);
436       aIP.Parameters(aU1, aV1, aU2, aV2);
437       //
438       aP2D.SetCoord(aU1, aV1);
439       aState1=D1->Classify(aP2D, TolArc);
440       //
441       aP2D.SetCoord(aU2, aV2);
442       aState2=D2->Classify(aP2D, TolArc);
443       //
444       if(aState1!=TopAbs_OUT && aState2!=TopAbs_OUT) {
445         aSIP.Append(aIP);
446       }
447     }
448     //
449     spnt.Clear();
450     //
451     aNbPnt=aSIP.Length();
452     for(i=1; i<=aNbPnt; ++i) {
453       const IntPatch_Point& aIP=aSIP(i);
454       spnt.Append(aIP);
455     }
456     //
457   }//  if (aNbPnt) {
458   //modified by NIZNHY-PKV Tue Sep 06 10:18:20 2011t
459   //
460   for(i=1; i<=nblin; i++) {
461     IntPatch_IType thetype = slin.Value(i)->ArcType();
462     if(  (thetype ==  IntPatch_Ellipse)
463        ||(thetype ==  IntPatch_Circle)
464        ||(thetype ==  IntPatch_Lin)
465        ||(thetype ==  IntPatch_Parabola)
466        ||(thetype ==  IntPatch_Hyperbola)) { 
467       Handle(IntPatch_GLine)& glin = *((Handle(IntPatch_GLine)*)&slin.Value(i));
468     glin->ComputeVertexParameters(TolArc); 
469     }
470     else if(thetype == IntPatch_Analytic) { 
471       Handle(IntPatch_ALine)& aligold = *((Handle(IntPatch_ALine)*)&slin.Value(i));
472       aligold->ComputeVertexParameters(TolArc);
473     }
474     else if(thetype == IntPatch_Restriction) {
475       Handle(IntPatch_RLine)& rlig = *((Handle(IntPatch_RLine)*)&slin.Value(i));
476       rlig->ComputeVertexParameters(TolArc); 
477     }
478   }
479   //
480   //----------------------------------------------------------------
481   //-- On place 2 vertex sur les courbes de GLine qui n en 
482   //-- contiennent pas. 
483   for(i=1; i<=nblin; i++) {
484     gp_Pnt P;
485     IntPatch_Point point;
486     Standard_Real u1,v1,u2,v2; 
487     if(slin.Value(i)->ArcType() == IntPatch_Circle) { 
488       const Handle(IntPatch_GLine)& glin = *((Handle(IntPatch_GLine)*)&slin.Value(i));
489       if(glin->NbVertex() == 0) { 
490         gp_Circ Circ = glin->Circle();
491         P=ElCLib::Value(0.0,Circ);
492         quad1.Parameters(P,u1,v1);
493         quad2.Parameters(P,u2,v2);
494         point.SetValue(P,TolArc,Standard_False);
495         point.SetParameters(u1,v1,u2,v2);
496         point.SetParameter(0.0);
497         glin->AddVertex(point);
498
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(M_PI+M_PI);
505         glin->AddVertex(point);
506       }
507     }
508     
509     else if(slin.Value(i)->ArcType() == IntPatch_Ellipse) { 
510       const Handle(IntPatch_GLine)& glin = *((Handle(IntPatch_GLine)*)&slin.Value(i));
511       if(glin->NbVertex() == 0) { 
512         gp_Elips Elips = glin->Ellipse();
513         P=ElCLib::Value(0.0,Elips);
514         quad1.Parameters(P,u1,v1);
515         quad2.Parameters(P,u2,v2);
516         point.SetValue(P,TolArc,Standard_False);
517         point.SetParameters(u1,v1,u2,v2);
518         point.SetParameter(0.0);
519         glin->AddVertex(point);
520
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(M_PI+M_PI);
527         glin->AddVertex(point);
528       }
529     }
530   }
531   myDone = IntStatus_OK;
532 }
533
534 //=======================================================================
535 //function : SetQuad
536 //purpose  : 
537 //=======================================================================
538 Standard_Integer SetQuad(const Handle(Adaptor3d_HSurface)& theS,
539                          GeomAbs_SurfaceType& theTS,
540                          IntSurf_Quadric& theQuad)
541 {
542   theTS = theS->GetType();
543   Standard_Integer iRet = 0;
544   switch (theTS) {
545   case GeomAbs_Plane:
546     theQuad.SetValue(theS->Plane());
547     iRet = 1;
548     break;
549   case GeomAbs_Cylinder:
550     theQuad.SetValue(theS->Cylinder());
551     iRet = 2;
552     break;
553   case GeomAbs_Cone:
554     theQuad.SetValue(theS->Cone());
555     iRet = 3;
556     break;
557   case GeomAbs_Sphere:
558     theQuad.SetValue(theS->Sphere());
559     iRet = 4;
560     break;
561   case GeomAbs_Torus:
562     theQuad.SetValue(theS->Torus());
563     iRet = 5;
564     break;
565   default:
566     break;
567   }
568   //
569   return iRet;
570 }
571