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