0026310: Very slow boolean cut operations on cylinders
[occt.git] / src / IntTools / IntTools_TopolTool.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14
15 #include <Adaptor3d_HSurface.hxx>
16 #include <ElSLib.hxx>
17 #include <Geom_BezierSurface.hxx>
18 #include <Geom_BSplineSurface.hxx>
19 #include <gp_Circ.hxx>
20 #include <gp_Cone.hxx>
21 #include <gp_Pnt.hxx>
22 #include <gp_Pnt2d.hxx>
23 #include <IntTools_TopolTool.hxx>
24 #include <Precision.hxx>
25 #include <Standard_DomainError.hxx>
26 #include <Standard_NotImplemented.hxx>
27 #include <Standard_Type.hxx>
28 #include <TColgp_Array2OfPnt.hxx>
29 #include <TColStd_HArray1OfReal.hxx>
30
31 static void Analyse(const TColgp_Array2OfPnt& array2,
32                     Standard_Integer&         theNbSamplesU,
33                     Standard_Integer&         theNbSamplesV);
34
35 // =====================================================================================
36 // function: Constructor
37 // purpose:
38 // =====================================================================================
39 IntTools_TopolTool::IntTools_TopolTool()
40 {
41   myNbSmplU = 0;
42   myNbSmplV = 0;
43   myDU = 1.;
44   myDV = 1.;
45 }
46
47 // =====================================================================================
48 // function: Constructor
49 // purpose:
50 // =====================================================================================
51 IntTools_TopolTool::IntTools_TopolTool(const Handle(Adaptor3d_HSurface)& theSurface)
52 {
53   Initialize(theSurface);
54   myNbSmplU = 0;
55   myNbSmplV = 0;
56   myDU = 1.;
57   myDV = 1.;
58 }
59
60 // =====================================================================================
61 // function: Initialize
62 // purpose:
63 // =====================================================================================
64 void IntTools_TopolTool::Initialize() 
65 {
66   Standard_NotImplemented::Raise("IntTools_TopolTool::Initialize ()");
67 }
68
69 // =====================================================================================
70 // function: Initialize
71 // purpose:
72 // =====================================================================================
73 void IntTools_TopolTool::Initialize(const Handle(Adaptor3d_HSurface)& theSurface) 
74 {
75   Adaptor3d_TopolTool::Initialize(theSurface);
76   //myS = theSurface;
77   myNbSmplU = 0;
78   myNbSmplV = 0;
79   myDU = 1.;
80   myDV = 1.;
81 }
82
83 // =====================================================================================
84 // function: ComputeSamplePoints
85 // purpose:
86 // =====================================================================================
87 void IntTools_TopolTool::ComputeSamplePoints() 
88 {
89   Standard_Real uinf, usup, vinf, vsup;
90   uinf = myS->FirstUParameter();  
91   usup = myS->LastUParameter();
92   vinf = myS->FirstVParameter();  
93   vsup = myS->LastVParameter();
94   const Standard_Integer aMaxNbSample = 50;
95
96   if (usup < uinf) { Standard_Real temp = uinf; uinf = usup; usup = temp; }
97   if (vsup < vinf) { Standard_Real temp = vinf; vinf = vsup; vsup = temp; }
98   Standard_Boolean isbiguinf, isbigusup, isbigvinf, isbigvsup;
99   isbiguinf = Precision::IsNegativeInfinite(uinf);
100   isbigusup = Precision::IsPositiveInfinite(usup);
101   isbigvinf = Precision::IsNegativeInfinite(vinf);
102   isbigvsup = Precision::IsPositiveInfinite(vsup);
103
104   if(isbiguinf && isbigusup) {uinf = -1.e5; usup = 1.e5;}
105   else if(isbiguinf) {uinf = usup - 2.e5;}
106   else if(isbigusup) {usup = uinf + 2.e5;}
107
108   if(isbigvinf && isbigvsup) {vinf = -1.e5; vsup = 1.e5;}
109   else if(isbigvinf) {vinf = vsup - 2.e5;}
110   else if(isbigvsup) {vsup = vinf + 2.e5;}
111   myU0 = uinf;
112   myV0 = vinf;
113
114   Standard_Integer nbsu = 0,nbsv = 0;
115   GeomAbs_SurfaceType typS = myS->GetType();
116
117   switch(typS) {
118   case GeomAbs_Plane: { 
119     nbsu = 10; nbsv = 10;
120   }
121     break;
122   case GeomAbs_Cylinder: {
123     Standard_Real aRadius = myS->Cylinder().Radius();
124     Standard_Real aMaxAngle = M_PI * 0.5;
125     Standard_Real aDeflection = 1.e-02;
126
127     if(aRadius > aDeflection) {
128       aMaxAngle = ACos(1. - aDeflection / aRadius) * 2.;
129     }
130     if(aMaxAngle > Precision::Angular()) {
131       nbsu = Standard_Integer((usup-uinf) / aMaxAngle);
132     }
133     nbsv = (Standard_Integer)(vsup-vinf);
134     nbsv /= 10;
135
136     if(nbsu < 2) nbsu = 2;
137     if(nbsv < 2) nbsv = 2;
138
139 //    if(nbsu < 10) nbsu = 10;
140 //    if(nbsv < 10) nbsv = 10;
141     if(nbsu > aMaxNbSample) nbsu = aMaxNbSample;
142     if(nbsv > aMaxNbSample) nbsv = aMaxNbSample;
143   }
144     break;
145   case GeomAbs_Cone: {
146     gp_Cone aCone = myS->Cone();
147     gp_Circ aCircle = ElSLib::ConeVIso(aCone.Position(), aCone.RefRadius(), aCone.SemiAngle(), vinf);
148     Standard_Real aRadius = aCircle.Radius();
149     aCircle = ElSLib::ConeVIso(aCone.Position(), aCone.RefRadius(), aCone.SemiAngle(), vsup);
150
151     if(aRadius < aCircle.Radius())
152       aRadius = aCircle.Radius();
153     Standard_Real aMaxAngle = M_PI * 0.5;
154     Standard_Real aDeflection = 1.e-02;
155
156     if(aRadius > aDeflection) {
157       aMaxAngle = ACos(1. - aDeflection / aRadius) * 2.;
158     }
159
160     if(aMaxAngle > Precision::Angular()) {
161       nbsu = Standard_Integer((usup - uinf) / aMaxAngle);
162     }
163     nbsv = (Standard_Integer)(vsup - vinf);
164     nbsv /= 10;
165
166 //     if(nbsu < 2) nbsu = 2;
167 //     if(nbsv < 2) nbsv = 2;
168
169     if(nbsu < 10) nbsu = 10;
170     if(nbsv < 10) nbsv = 10;
171     if(nbsu > aMaxNbSample) nbsu = aMaxNbSample;
172     if(nbsv > aMaxNbSample) nbsv = aMaxNbSample;
173   }
174     break;
175   case GeomAbs_Sphere:
176   case GeomAbs_Torus: {
177     gp_Circ aCircle;
178     Standard_Real aRadius1, aRadius2;
179
180     if(typS == GeomAbs_Torus) {
181       gp_Torus aTorus = myS->Torus();
182       aCircle = ElSLib::TorusUIso(aTorus.Position(), aTorus.MajorRadius(), aTorus.MinorRadius(), uinf);
183       aRadius2 = aCircle.Radius();
184       aCircle = ElSLib::TorusUIso(aTorus.Position(), aTorus.MajorRadius(), aTorus.MinorRadius(), usup);
185       aRadius2 = (aRadius2 < aCircle.Radius()) ? aCircle.Radius() : aRadius2;
186       
187       aCircle = ElSLib::TorusVIso(aTorus.Position(), aTorus.MajorRadius(), aTorus.MinorRadius(), vinf);
188       aRadius1 = aCircle.Radius();
189       aCircle = ElSLib::TorusVIso(aTorus.Position(), aTorus.MajorRadius(), aTorus.MinorRadius(), vsup);
190       aRadius1 = (aRadius1 < aCircle.Radius()) ? aCircle.Radius() : aRadius1;
191     }
192     else {
193       gp_Sphere aSphere = myS->Sphere();
194       aRadius1 = aSphere.Radius();
195       aRadius2 = aSphere.Radius();
196     }
197     Standard_Real aMaxAngle = M_PI * 0.5;
198     Standard_Real aDeflection = 1.e-02;
199     
200     if(aRadius1 > aDeflection) {
201       aMaxAngle = ACos(1. - aDeflection / aRadius1) * 2.;
202     }
203     
204     if(aMaxAngle > Precision::Angular()) {
205       nbsu = Standard_Integer((usup - uinf) / aMaxAngle);
206     }
207     aMaxAngle = M_PI * 0.5;
208
209     if(aRadius2 > aDeflection) {
210       aMaxAngle = ACos(1. - aDeflection / aRadius2) * 2.;
211     }
212     
213     if(aMaxAngle > Precision::Angular()) {
214       nbsv = Standard_Integer((vsup - vinf) / aMaxAngle);
215     }
216     if(nbsu < 10) nbsu = 10;
217     if(nbsv < 10) nbsv = 10;
218     if(nbsu > aMaxNbSample) nbsu = aMaxNbSample;
219     if(nbsv > aMaxNbSample) nbsv = aMaxNbSample;
220   }
221     break;
222   case GeomAbs_BezierSurface: {
223     nbsv = 3 + myS->NbVPoles(); 
224     nbsu = 3 + myS->NbUPoles();
225
226     if(nbsu > 10 || nbsv > 10) {
227       TColgp_Array2OfPnt array2(1, myS->NbUPoles(), 1, myS->NbVPoles());
228       myS->Bezier()->Poles(array2);
229       Analyse(array2, nbsu, nbsv);
230     }
231
232     if(nbsu < 10) nbsu = 10;
233     if(nbsv < 10) nbsv = 10;
234   }
235     break;
236   case GeomAbs_BSplineSurface: {
237     nbsv = myS->NbVKnots();     nbsv *= myS->VDegree();     if(nbsv < 4) nbsv=4;    
238     nbsu = myS->NbUKnots();     nbsu *= myS->UDegree();     if(nbsu < 4) nbsu=4;
239     
240     if(nbsu > 10 || nbsv > 10) {
241       TColgp_Array2OfPnt array2(1, myS->NbUPoles(), 1, myS->NbVPoles());
242       myS->BSpline()->Poles(array2);
243       Analyse(array2, nbsu, nbsv);
244     }
245     if(nbsu < 10) nbsu = 10;
246     if(nbsv < 10) nbsv = 10;
247   }
248     break;
249   case GeomAbs_SurfaceOfExtrusion: {
250     nbsu = 15;
251     nbsv = (Standard_Integer)(vsup - vinf);
252     nbsv /= 10;
253     if(nbsv < 15) nbsv = 15;
254     if(nbsv > aMaxNbSample) nbsv = aMaxNbSample;
255   }
256     break;
257   case GeomAbs_SurfaceOfRevolution: {
258     nbsv = 15; nbsu = 15;
259   }
260     break;
261   default: {
262     nbsu = 10; nbsv = 10;
263   }
264     break;
265   }
266   myNbSmplU = nbsu;
267   myNbSmplV = nbsv;
268
269   myNbSamplesU = myNbSmplU;
270   myNbSamplesV = myNbSmplV;
271
272   myDU = (usup - uinf)/(myNbSmplU + 1);
273   myDV = (vsup - vinf)/(myNbSmplV + 1);
274 }
275
276 // =====================================================================================
277 // function: NbSamplesU
278 // purpose:
279 // =====================================================================================
280 Standard_Integer IntTools_TopolTool::NbSamplesU() 
281 {
282   if(myNbSmplU <= 0) {
283     ComputeSamplePoints();
284   }
285   return myNbSmplU;
286 }
287
288 // =====================================================================================
289 // function: NbSamplesV
290 // purpose:
291 // =====================================================================================
292 Standard_Integer IntTools_TopolTool::NbSamplesV() 
293 {
294   if(myNbSmplV <= 0) {
295     ComputeSamplePoints();
296   }
297   return myNbSmplV;
298 }
299
300 // =====================================================================================
301 // function: NbSamples
302 // purpose:
303 // =====================================================================================
304 Standard_Integer IntTools_TopolTool::NbSamples() 
305 {
306   if(myNbSmplU <= 0) { 
307     ComputeSamplePoints();    
308   }
309   return(myNbSmplU * myNbSmplV);
310 }
311
312 // =====================================================================================
313 // function: SamplePoint
314 // purpose:
315 // =====================================================================================
316 void IntTools_TopolTool::SamplePoint(const Standard_Integer Index,
317                                      gp_Pnt2d&              P2d,
318                                      gp_Pnt&                P3d) 
319 {
320   if (myUPars.IsNull())
321     {
322       if(myNbSmplU <= 0) { 
323         ComputeSamplePoints();    
324       }
325       Standard_Integer iv = 1 + Index / myNbSmplU;
326       Standard_Integer iu = 1 + Index - (iv - 1) * myNbSmplU;
327       Standard_Real u = myU0 + iu * myDU;
328       Standard_Real v = myV0 + iv * myDV;
329       P2d.SetCoord(u, v);
330       P3d = myS->Value(u, v);
331     }
332   else
333     Adaptor3d_TopolTool::SamplePoint(Index, P2d, P3d);
334 }
335
336
337 //=======================================================================
338 // function : Analyse
339 // purpose  : 
340 //=======================================================================
341 void Analyse(const TColgp_Array2OfPnt& array2,
342              Standard_Integer&         theNbSamplesU,
343              Standard_Integer&         theNbSamplesV) 
344
345   gp_Vec Vi,Vip1;
346   Standard_Integer sh,nbch,i,j;
347   const Standard_Integer nbup = array2.UpperRow() - array2.LowerRow() + 1;
348   const Standard_Integer nbvp = array2.UpperCol() - array2.LowerCol() + 1;
349   
350   sh = 1;
351   nbch = 0;
352   if(nbvp>2) {
353
354     for(i = array2.LowerRow(); i <= array2.UpperRow(); i++) {
355       const gp_Pnt& A=array2.Value(i,1);
356       const gp_Pnt& B=array2.Value(i,2);
357       const gp_Pnt& C=array2.Value(i,3);
358       Vi.SetCoord(C.X()-B.X()-B.X()+A.X(),
359                   C.Y()-B.Y()-B.Y()+A.Y(),
360                   C.Z()-B.Z()-B.Z()+A.Z());
361       Standard_Integer locnbch=0;
362
363       for(j = array2.LowerCol() + 2; j < array2.UpperCol();j++) {  //-- essai
364         const gp_Pnt& Ax=array2.Value(i,j-1);
365         const gp_Pnt& Bx=array2.Value(i,j);
366         const gp_Pnt& Cx=array2.Value(i,j+1);
367         Vip1.SetCoord(Cx.X()-Bx.X()-Bx.X()+Ax.X(),
368                       Cx.Y()-Bx.Y()-Bx.Y()+Ax.Y(),
369                       Cx.Z()-Bx.Z()-Bx.Z()+Ax.Z());
370         Standard_Real pd = Vi.Dot(Vip1);
371         Vi=Vip1;
372         if(pd>1.0e-7 || pd<-1.0e-7) {  
373           if(pd>0) {  if(sh==-1) {   sh=1; locnbch++;   }  }
374           else {        if(sh==1) {  sh=-1; locnbch++;  }  }
375         }
376       }
377       if(locnbch>nbch) { 
378         nbch=locnbch; 
379       }
380     }
381   }
382   theNbSamplesV = nbch+5;
383   
384
385   nbch=0;
386   if(nbup > 2) { 
387     for(j = array2.LowerCol(); j <= array2.UpperCol(); j++) { 
388       const gp_Pnt& A=array2.Value(array2.LowerRow(),     j);
389       const gp_Pnt& B=array2.Value(array2.LowerRow() + 1, j);
390       const gp_Pnt& C=array2.Value(array2.LowerRow() + 2, j);
391       Vi.SetCoord(C.X()-B.X()-B.X()+A.X(),
392                   C.Y()-B.Y()-B.Y()+A.Y(),
393                   C.Z()-B.Z()-B.Z()+A.Z());
394       Standard_Integer locnbch=0;
395
396       for(i = array2.LowerRow() + 2; i < array2.UpperRow(); i++) {  //-- essai
397         const gp_Pnt& Ax=array2.Value(i-1,j);
398         const gp_Pnt& Bx=array2.Value(i,j);
399         const gp_Pnt& Cx=array2.Value(i+1,j);
400         Vip1.SetCoord(Cx.X()-Bx.X()-Bx.X()+Ax.X(),
401                     Cx.Y()-Bx.Y()-Bx.Y()+Ax.Y(),
402                     Cx.Z()-Bx.Z()-Bx.Z()+Ax.Z());
403         Standard_Real pd = Vi.Dot(Vip1);
404         Vi=Vip1;
405         if(pd>1.0e-7 || pd<-1.0e-7) {  
406           if(pd>0) {  if(sh==-1) {   sh=1; locnbch++;   }  }
407           else {        if(sh==1) {  sh=-1; locnbch++;  }  }
408         }
409       }
410       if(locnbch>nbch) nbch=locnbch;
411     }  
412   }
413   theNbSamplesU = nbch+5;
414 }
415
416 //Modified IFV
417 //=======================================================================
418 //function : SamplePnts
419 //purpose  : 
420 //=======================================================================
421
422 void IntTools_TopolTool::SamplePnts(const Standard_Real theDefl, 
423                                     const Standard_Integer theNUmin,
424                                     const Standard_Integer theNVmin)
425
426   Adaptor3d_TopolTool::SamplePnts(theDefl, theNUmin, theNVmin);
427
428   myNbSmplU = Adaptor3d_TopolTool::NbSamplesU();
429   myNbSmplV = Adaptor3d_TopolTool::NbSamplesV();
430
431   myU0 = myUPars->Value(1);
432   myV0 = myVPars->Value(1);
433
434   myDU = (myUPars->Value(myNbSmplU) - myU0)/(myNbSmplU-1);  
435   myDV = (myVPars->Value(myNbSmplV) - myU0)/(myNbSmplV-1);
436 }