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