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