0022627: Change OCCT memory management defaults
[occt.git] / src / Extrema / Extrema_ExtCS.cxx
1 // File:        Extrema_ExtCS.cxx
2 // Created:     Tue Jul 18 10:33:04 1995
3 // Author:      Modelistation
4 //              <model@metrox>
5
6 //  Modified by skv - Thu Jul  7 12:29:34 2005 OCC9134
7
8 #include <Extrema_ExtCS.ixx>
9 #include <Extrema_GenExtCS.hxx>
10 #include <StdFail_NotDone.hxx>
11 #include <Standard_NotImplemented.hxx>
12 #include <StdFail_InfiniteSolutions.hxx>
13 #include <Precision.hxx>
14 #include <GeomAbs_CurveType.hxx>
15 #include <gp_Pnt.hxx>
16 #include <gp_Pln.hxx>
17 #include <gp_Cylinder.hxx>
18 #include <gp_Cone.hxx>
19 #include <gp_Sphere.hxx>
20 #include <gp_Torus.hxx>
21 #include <gp_Lin.hxx>
22
23 #include <ElCLib.hxx>
24 #include <Extrema_ExtPElC.hxx>
25 #include <Bnd_Box.hxx>
26 #include <BndLib_AddSurface.hxx>
27 #include <Extrema_ExtPElS.hxx>
28
29 Extrema_ExtCS::Extrema_ExtCS() 
30 {
31   myDone = Standard_False;
32 }
33
34 Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve&   C,
35                              const Adaptor3d_Surface& S,
36                              const Standard_Real    TolC,
37                              const Standard_Real    TolS)
38
39 {
40   Initialize(S, S.FirstUParameter(), S.LastUParameter(), 
41              S.FirstVParameter(), S.LastVParameter(), 
42              TolC, TolS);
43   Perform(C, C.FirstParameter(), C.LastParameter());
44 }
45
46 Extrema_ExtCS::Extrema_ExtCS(const Adaptor3d_Curve&   C,
47                              const Adaptor3d_Surface& S,
48                              const Standard_Real    UCinf,
49                              const Standard_Real    UCsup,
50                              const Standard_Real    Uinf,       
51                              const Standard_Real    Usup,
52                              const Standard_Real    Vinf,       
53                              const Standard_Real    Vsup,
54                              const Standard_Real    TolC,
55                              const Standard_Real    TolS)
56
57 {
58   Initialize(S, Uinf, Usup, Vinf, Vsup, TolC, TolS);
59   Perform(C, UCinf, UCsup);
60 }
61
62
63 void Extrema_ExtCS::Initialize(const Adaptor3d_Surface& S,
64                                const Standard_Real    Uinf,     
65                                const Standard_Real    Usup,
66                                const Standard_Real    Vinf,     
67                                const Standard_Real    Vsup,
68                                const Standard_Real    TolC,
69                                const Standard_Real    TolS)
70 {
71   myS = (Adaptor3d_SurfacePtr)&S;
72   myIsPar = Standard_False;
73   myuinf  = Uinf;
74   myusup  = Usup;
75   myvinf  = Vinf;
76   myvsup  = Vsup;
77   mytolC  = TolC;
78   mytolS  = TolS;
79   myStype  = myS->GetType();
80 }
81
82                                 
83 void Extrema_ExtCS::Perform(const Adaptor3d_Curve& C,
84                             const Standard_Real  Uinf,
85                             const Standard_Real  Usup)
86 {
87   myucinf = Uinf;
88   myucsup = Usup;
89   myPOnS.Clear();
90   myPOnC.Clear();
91   mySqDist.Clear();
92   Standard_Integer i;
93   Standard_Integer NbT, NbU, NbV;
94   NbT = NbU = NbV = 10;
95   GeomAbs_CurveType myCtype  = C.GetType();
96
97
98   switch(myCtype) {
99
100   case GeomAbs_Line: 
101     {
102       
103       switch(myStype) {
104       case GeomAbs_Sphere:
105         myExtElCS.Perform(C.Line(), myS->Sphere());
106         break;   
107       case GeomAbs_Cylinder:
108         myExtElCS.Perform(C.Line(), myS->Cylinder());
109         break;
110       case GeomAbs_Plane:
111         myExtElCS.Perform(C.Line(), myS->Plane());
112         if (myExtElCS.IsParallel())   break;
113
114       case GeomAbs_Torus:
115       case GeomAbs_Cone:
116       case GeomAbs_BezierSurface:
117       case GeomAbs_BSplineSurface:
118       case GeomAbs_SurfaceOfRevolution:
119       case GeomAbs_SurfaceOfExtrusion:
120       case GeomAbs_OtherSurface:
121         {
122           Standard_Real cfirst = myucinf, clast = myucsup;
123           Standard_Real ufirst = myS->FirstUParameter(), ulast = myS->LastUParameter(), 
124                         vfirst = myS->FirstVParameter(), vlast = myS->LastVParameter();
125
126           if(Precision::IsInfinite(Abs(cfirst)) || Precision::IsInfinite(Abs(clast))) {
127
128             Bnd_Box aSurfBox;
129       BndLib_AddSurface::Add(*myS, ufirst, ulast, vfirst, vlast, Precision::Confusion(), aSurfBox);
130             Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
131             aSurfBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
132             Standard_Real tmin = Precision::Infinite(), tmax = -tmin;
133             gp_Lin aLin = C.Line();
134             
135
136             if(!( Precision::IsInfinite(Abs(xmin)) || Precision::IsInfinite(Abs(xmax)) || 
137                   Precision::IsInfinite(Abs(ymin)) || Precision::IsInfinite(Abs(ymax)) || 
138                   Precision::IsInfinite(Abs(zmin)) || Precision::IsInfinite(Abs(zmax)))  ) {
139               
140               Extrema_ExtPElC anExt;
141               Extrema_POnCurv aPntOnLin;
142               Standard_Real aParOnLin;
143               Standard_Real lim = Precision::Infinite();
144               gp_Pnt aLimPntArray[8];
145               
146               aLimPntArray[0].SetCoord(xmin, ymin, zmin);
147               aLimPntArray[1].SetCoord(xmax, ymin, zmin);
148               aLimPntArray[2].SetCoord(xmin, ymax, zmin);
149               aLimPntArray[3].SetCoord(xmax, ymax, zmin);
150               aLimPntArray[4].SetCoord(xmin, ymin, zmax);
151               aLimPntArray[5].SetCoord(xmax, ymin, zmax);
152               aLimPntArray[6].SetCoord(xmin, ymax, zmax);
153               aLimPntArray[7].SetCoord(xmax, ymax, zmax);
154
155               for(i = 0; i <= 7; i++) {
156                 anExt.Perform(aLimPntArray[i], aLin, Precision::Confusion(), -lim, lim);
157                 aPntOnLin = anExt.Point(1);
158                 aParOnLin = aPntOnLin.Parameter();
159                 tmin = Min(aParOnLin, tmin);
160                 tmax = Max(aParOnLin, tmax);
161               }
162               
163             }
164             else {
165               tmin = -1.e+50;
166               tmax =  1.e+50;
167             }
168
169
170             cfirst = Max(cfirst, tmin);
171             clast  = Min(clast,  tmax);
172
173           }
174
175
176             
177           Extrema_GenExtCS Ext(C, *myS, NbT, NbU, NbV, cfirst, clast, ufirst, ulast,
178                                vfirst, vlast, mytolC, mytolS);
179
180           myDone = Ext.IsDone();
181           if (myDone) {
182             Standard_Integer NbExt = Ext.NbExt();
183             Standard_Real T,U,V;
184             Extrema_POnCurv PC;
185             Extrema_POnSurf PS;
186             for (i = 1; i <= NbExt; i++) {
187               PC = Ext.PointOnCurve(i);
188               PS = Ext.PointOnSurface(i);
189               T = PC.Parameter();
190               PS.Parameter(U, V);
191               if (myS->IsUPeriodic())
192                 U = ElCLib::InPeriod(U, myuinf, myuinf+myS->UPeriod());
193               if (myS->IsVPeriodic())
194                 V = ElCLib::InPeriod(V, myvinf, myvinf+myS->VPeriod());
195
196               if ((myucinf-T) <= mytolC && (T-myucsup) <= mytolC &&
197                   (myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
198                   (myvinf-V) <= mytolS && (V-myvsup) <= mytolS) {
199                 mySqDist.Append(Ext.SquareDistance(i));
200                 myPOnC.Append(PC);
201                 myPOnS.Append(Extrema_POnSurf(U, V, PS.Value()));
202
203               
204               }
205             }
206           }
207           return;
208           
209         }
210 #ifndef DEB
211       default:
212 #endif
213         break;
214       }
215       break;
216     }
217 //  Modified by skv - Thu Jul  7 12:29:34 2005 OCC9134 Begin
218   case GeomAbs_Circle:
219     {
220       if(myStype == GeomAbs_Cylinder) {
221         myExtElCS.Perform(C.Circle(), myS->Cylinder());
222         break;
223       }
224     }
225   case GeomAbs_Hyperbola: 
226     {
227       if(myCtype == GeomAbs_Hyperbola && myStype == GeomAbs_Plane) {
228 //  Modified by skv - Thu Jul  7 12:29:34 2005 OCC9134 End
229         myExtElCS.Perform(C.Hyperbola(), myS->Plane());
230         break;
231       }
232     }
233   default:
234     {
235       Extrema_GenExtCS Ext;
236       Ext.Initialize(*myS, NbU, NbV, mytolS);
237       if(myCtype == GeomAbs_Hyperbola) {
238         Standard_Real tmin = Max(-20., C.FirstParameter());
239         Standard_Real tmax = Min(20., C.LastParameter());
240         Ext.Perform(C, NbT, tmin, tmax, mytolC); // to avoid overflow
241       }
242       else {
243         if(myCtype == GeomAbs_Circle && NbT < 13) {
244           NbT = 13;
245         }
246         Ext.Perform(C, NbT, mytolC);
247       }
248         
249       myDone = Ext.IsDone();
250       if (myDone) {
251         Standard_Integer NbExt = Ext.NbExt();
252         Standard_Real T,U,V;
253         Extrema_POnCurv PC;
254         Extrema_POnSurf PS;
255         for (i = 1; i <= NbExt; i++) {
256           PC = Ext.PointOnCurve(i);
257           PS = Ext.PointOnSurface(i);
258           T = PC.Parameter();
259           PS.Parameter(U, V);
260           if (C.IsPeriodic())
261             T = ElCLib::InPeriod(T, myucinf, myucinf+C.Period());
262           if (myS->IsUPeriodic())
263             U = ElCLib::InPeriod(U, myuinf, myuinf+myS->UPeriod());
264           if (myS->IsVPeriodic())
265             V = ElCLib::InPeriod(V, myvinf, myvinf+myS->VPeriod());
266           
267           if ((myucinf-T) <= mytolC && (T-myucsup) <= mytolC &&
268               (myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
269               (myvinf-V) <= mytolS && (V-myvsup) <= mytolS) {
270             mySqDist.Append(Ext.SquareDistance(i));
271             PC.SetValues(T, PC.Value());
272             myPOnC.Append(PC);
273             myPOnS.Append(Extrema_POnSurf(U, V, PS.Value()));
274           }
275         }
276       }
277       return;
278     }
279     break;
280   }
281   
282   myDone = myExtElCS.IsDone();
283   if (myDone) {
284     myIsPar = myExtElCS.IsParallel();
285     if (myIsPar) {
286       mySqDist.Append(myExtElCS.SquareDistance(1));
287     }
288     else {
289       Standard_Integer NbExt = myExtElCS.NbExt();
290       Standard_Real U, V;
291       for (i = 1; i <= NbExt; i++) {
292         Extrema_POnCurv PC;
293         Extrema_POnSurf PS;
294         myExtElCS.Points(i, PC, PS);
295         Standard_Real Ucurve = PC.Parameter();
296         PS.Parameter(U, V);
297
298         if((myStype == GeomAbs_Sphere) || (myStype == GeomAbs_Cylinder)) {
299           U = ElCLib::InPeriod(U, myuinf, myuinf+2.*M_PI);
300         }
301
302         if ((myuinf-U) <= mytolS && (U-myusup) <= mytolS &&
303             (myvinf-V) <= mytolS && (V-myvsup) <= mytolS &&
304             (myucinf-Ucurve) <= mytolC && (Ucurve-myucsup) <= mytolC) {
305           mySqDist.Append(myExtElCS.SquareDistance(i));
306           myPOnS.Append(Extrema_POnSurf(U, V, PS.Value()));
307           myPOnC.Append(PC);
308         }
309       }
310     }
311   }
312   
313 }
314
315
316 Standard_Boolean Extrema_ExtCS::IsDone() const
317 {
318   return myDone;
319 }
320
321 Standard_Boolean Extrema_ExtCS::IsParallel() const
322 {
323   return myIsPar;
324 }
325
326
327 Standard_Real Extrema_ExtCS::SquareDistance(const Standard_Integer N) const
328 {
329   if(!myDone) StdFail_NotDone::Raise();
330   if (myIsPar && N != 1) StdFail_InfiniteSolutions::Raise();
331   if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
332   return mySqDist.Value(N);
333 }
334
335
336 Standard_Integer Extrema_ExtCS::NbExt() const
337 {
338   if(!myDone) StdFail_NotDone::Raise();
339   return mySqDist.Length();
340 }
341
342
343
344 void Extrema_ExtCS::Points(const Standard_Integer N,
345                             Extrema_POnCurv&       P1,
346                             Extrema_POnSurf&       P2) const
347 {
348   if(!myDone) StdFail_NotDone::Raise();
349   P1 = myPOnC.Value(N);
350   P2 = myPOnS.Value(N);
351 }