0026252: GeomAdaptor_Surface should use inner adaptor to calculate values of complex...
[occt.git] / src / Extrema / Extrema_ExtPS.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 //-----------------------------------------------------------------
16
17 #include <GeomAdaptor_HSurfaceOfLinearExtrusion.hxx>
18 #include <GeomAdaptor_HSurfaceOfRevolution.hxx>
19 #include <Adaptor3d_Surface.hxx>
20 #include <ElCLib.hxx>
21 #include <Extrema_ExtPExtS.hxx>
22 #include <Extrema_ExtPRevS.hxx>
23 #include <Extrema_ExtPS.hxx>
24 #include <Extrema_GenExtPS.hxx>
25 #include <Extrema_POnSurf.hxx>
26 #include <GeomAbs_CurveType.hxx>
27 #include <GeomAbs_IsoType.hxx>
28 #include <gp_Cone.hxx>
29 #include <gp_Cylinder.hxx>
30 #include <gp_Pln.hxx>
31 #include <gp_Pnt.hxx>
32 #include <gp_Sphere.hxx>
33 #include <gp_Torus.hxx>
34 #include <Precision.hxx>
35 #include <Standard_NotImplemented.hxx>
36 #include <Standard_OutOfRange.hxx>
37 #include <Standard_TypeMismatch.hxx>
38 #include <StdFail_NotDone.hxx>
39
40 //=======================================================================
41 //function : IsoIsDeg
42 //purpose  : 
43 //=======================================================================
44 static Standard_Boolean IsoIsDeg  (const Adaptor3d_Surface& S,
45                                    const Standard_Real      Param,
46                                    const GeomAbs_IsoType    IT,
47                                    const Standard_Real      TolMin,
48                                    const Standard_Real      TolMax) 
49 {
50     Standard_Real U1=0.,U2=0.,V1=0.,V2=0.,T;
51     Standard_Boolean Along = Standard_True;
52     U1 = S.FirstUParameter();
53     U2 = S.LastUParameter();
54     V1 = S.FirstVParameter();
55     V2 = S.LastVParameter();
56     gp_Vec D1U,D1V;
57     gp_Pnt P;
58     Standard_Real Step,D1NormMax;
59     if (IT == GeomAbs_IsoV) 
60     {
61       if( !Precision::IsInfinite(U1) &&  !Precision::IsInfinite(U2) )
62       {
63         Step = (U2 - U1)/10;
64         if(Step < Precision::PConfusion()) {
65           return Standard_False;
66         }
67         D1NormMax=0.;
68
69         for (T=U1;T<=U2;T=T+Step) 
70         {
71           S.D1(T,Param,P,D1U,D1V);
72           D1NormMax=Max(D1NormMax,D1U.Magnitude());
73         }
74
75         if (D1NormMax >TolMax || D1NormMax < TolMin ) 
76           Along = Standard_False;
77       }
78     }
79     else 
80     {
81       if( !Precision::IsInfinite(V1) &&  !Precision::IsInfinite(V2) )
82       {
83         Step = (V2 - V1)/10;
84         if(Step < Precision::PConfusion()) {
85           return Standard_False;
86         }
87         D1NormMax=0.;
88         for (T=V1;T<=V2;T=T+Step) 
89         {
90           S.D1(Param,T,P,D1U,D1V);
91           D1NormMax=Max(D1NormMax,D1V.Magnitude());
92         }
93
94         if (D1NormMax >TolMax || D1NormMax < TolMin ) 
95           Along = Standard_False;
96       }
97
98
99
100     }
101     return Along;
102 }
103
104 //=======================================================================
105 //function : TreatSolution
106 //purpose  : 
107 //=======================================================================
108
109 void Extrema_ExtPS::TreatSolution (const Extrema_POnSurf& PS,
110                                    const Standard_Real Val)
111 {
112   Standard_Real U, V;
113   PS.Parameter(U, V);
114   if (myS->IsUPeriodic()) {
115     U = ElCLib::InPeriod(U, myuinf, myuinf + myS->UPeriod());
116     
117     // Handle trimmed surfaces.
118     if (U > myusup + mytolu)
119       U -= myS->UPeriod();
120     if (U < myuinf - mytolu)
121       U += myS->UPeriod();
122   }
123   if (myS->IsVPeriodic()) {
124     V = ElCLib::InPeriod(V, myvinf, myvinf + myS->VPeriod());
125
126     // Handle trimmed surfaces.
127     if (V > myvsup + mytolv)
128       V -= myS->VPeriod();
129     if (V < myvinf - mytolv)
130       V += myS->VPeriod();
131   }
132   if ((myuinf-U) <= mytolu && (U-myusup) <= mytolu &&
133       (myvinf-V) <= mytolv && (V-myvsup) <= mytolv) {
134     myPoints.Append(Extrema_POnSurf (U, V, PS.Value()));
135     mySqDist.Append(Val);
136   }
137 }
138
139
140 //=======================================================================
141 //function : Extrema_ExtPS
142 //purpose  : 
143 //=======================================================================
144
145 Extrema_ExtPS::Extrema_ExtPS()
146 {
147   myDone = Standard_False;
148 }
149
150
151 //=======================================================================
152 //function : Extrema_ExtPS
153 //purpose  : 
154 //=======================================================================
155
156 Extrema_ExtPS::Extrema_ExtPS (const gp_Pnt&            theP,
157                               const Adaptor3d_Surface& theS,
158                               const Standard_Real      theTolU,
159                               const Standard_Real      theTolV,
160                               const Extrema_ExtFlag    theF,
161                               const Extrema_ExtAlgo    theA)
162 {
163   myExtPS.SetFlag (theF);
164   myExtPS.SetAlgo (theA);
165
166   Initialize (theS,
167               theS.FirstUParameter(),
168               theS.LastUParameter(),
169               theS.FirstVParameter(),
170               theS.LastVParameter(),
171               theTolU,
172               theTolV);
173
174   Perform (theP);
175 }
176
177 //=======================================================================
178 //function : Extrema_ExtPS
179 //purpose  : 
180 //=======================================================================
181
182 Extrema_ExtPS::Extrema_ExtPS (const gp_Pnt&            theP,
183                               const Adaptor3d_Surface& theS,
184                               const Standard_Real      theUinf,
185                               const Standard_Real      theUsup,
186                               const Standard_Real      theVinf,
187                               const Standard_Real      theVsup,
188                               const Standard_Real      theTolU,
189                               const Standard_Real      theTolV,
190                               const Extrema_ExtFlag    theF,
191                               const Extrema_ExtAlgo    theA)
192 {
193   myExtPS.SetFlag (theF);
194   myExtPS.SetAlgo (theA);
195
196   Initialize (theS,
197               theUinf,
198               theUsup,
199               theVinf,
200               theVsup,
201               theTolU,
202               theTolV);
203
204   Perform (theP);
205 }
206
207
208 //=======================================================================
209 //function : Initialize
210 //purpose  : 
211 //=======================================================================
212
213 void Extrema_ExtPS::Initialize (const Adaptor3d_Surface& theS,
214                                 const Standard_Real      theUinf,
215                                 const Standard_Real      theUsup,
216                                 const Standard_Real      theVinf,
217                                 const Standard_Real      theVsup,
218                                 const Standard_Real      theTolU,
219                                 const Standard_Real      theTolV)
220 {
221   myS = (Adaptor3d_SurfacePtr)&theS;
222   myuinf = theUinf;
223   myusup = theUsup;
224   myvinf = theVinf;
225   myvsup = theVsup;
226
227   if (Precision::IsNegativeInfinite(myuinf)) myuinf = -1e10;
228   if (Precision::IsPositiveInfinite(myusup)) myusup = 1e10;
229   if (Precision::IsNegativeInfinite(myvinf)) myvinf = -1e10;
230   if (Precision::IsPositiveInfinite(myvsup)) myvsup = 1e10;
231
232   mytolu = theTolU;
233   mytolv = theTolV;
234   mytype = myS->GetType();
235
236   Standard_Boolean isB = ( myS->GetType() == GeomAbs_BSplineSurface ||
237                            myS->GetType() == GeomAbs_BezierSurface );
238
239   Standard_Integer nbU = (isB) ? 44 : 32;
240   Standard_Integer nbV = (isB) ? 44 : 32;
241
242   Standard_Boolean bUIsoIsDeg = Standard_False, bVIsoIsDeg = Standard_False;
243
244   if(myS->GetType() != GeomAbs_Plane) {
245     bUIsoIsDeg = IsoIsDeg(theS, myuinf, GeomAbs_IsoU, 0., 1.e-9) ||
246                  IsoIsDeg(theS, myusup, GeomAbs_IsoU, 0., 1.e-9);
247     bVIsoIsDeg = IsoIsDeg(theS, myvinf, GeomAbs_IsoV, 0., 1.e-9) ||
248                  IsoIsDeg(theS, myvsup, GeomAbs_IsoV, 0., 1.e-9);
249   }
250
251   if(bUIsoIsDeg) nbU = 300;
252   if(bVIsoIsDeg) nbV = 300;
253
254   myExtPS.Initialize(*myS, nbU, nbV, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
255
256   myExtPExtS.Nullify();
257   myExtPRevS.Nullify();
258 }
259
260 //=======================================================================
261 //function : Perform
262 //purpose  : 
263 //=======================================================================
264
265 void Extrema_ExtPS::Perform(const gp_Pnt& thePoint)
266 {
267   myPoints.Clear();
268   mySqDist.Clear();
269
270   switch (mytype)
271   {
272     case GeomAbs_Cylinder:
273       myExtPElS.Perform (thePoint, myS->Cylinder(), Precision::Confusion());
274       break;
275     case GeomAbs_Plane:
276       myExtPElS.Perform (thePoint, myS->Plane(), Precision::Confusion());
277       break;
278     case GeomAbs_Cone:
279       myExtPElS.Perform (thePoint, myS->Cone(), Precision::Confusion());
280       break;
281     case GeomAbs_Sphere:
282       myExtPElS.Perform (thePoint, myS->Sphere(), Precision::Confusion());
283       break;
284     case GeomAbs_Torus:
285       myExtPElS.Perform (thePoint, myS->Torus(), Precision::Confusion());
286       break;
287
288     case GeomAbs_SurfaceOfExtrusion:
289     {
290       if (myExtPExtS.IsNull())
291       {
292         Handle(GeomAdaptor_HSurfaceOfLinearExtrusion) aS (new GeomAdaptor_HSurfaceOfLinearExtrusion (
293           GeomAdaptor_SurfaceOfLinearExtrusion (myS->BasisCurve(), myS->Direction())));
294
295         myExtPExtS = new Extrema_ExtPExtS (thePoint, aS, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
296       }
297       else
298       {
299         myExtPExtS->Perform (thePoint);
300       }
301
302       myDone = myExtPExtS->IsDone();
303       if (myDone)
304       {
305         for (Standard_Integer anIdx = 1; anIdx <= myExtPExtS->NbExt(); ++anIdx)
306         {
307           TreatSolution (myExtPExtS->Point (anIdx), myExtPExtS->SquareDistance (anIdx));
308         }
309       }
310
311       return;
312     }
313
314     case GeomAbs_SurfaceOfRevolution:
315     {
316       if (myExtPRevS.IsNull())
317       {
318         Handle(GeomAdaptor_HSurfaceOfRevolution) aS (new GeomAdaptor_HSurfaceOfRevolution (
319           GeomAdaptor_SurfaceOfRevolution (myS->BasisCurve(), myS->AxeOfRevolution())));
320
321         myExtPRevS = new Extrema_ExtPRevS (thePoint, aS, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
322       }
323       else
324       {
325         myExtPRevS->Perform (thePoint);
326       }
327
328       myDone = myExtPRevS->IsDone();
329       if (myDone)
330       {
331         for (Standard_Integer anIdx = 1; anIdx <= myExtPRevS->NbExt(); ++anIdx)
332         {
333           TreatSolution (myExtPRevS->Point (anIdx), myExtPRevS->SquareDistance (anIdx));
334         }
335       }
336
337       return;
338     }
339
340     default:
341     {
342       myExtPS.Perform (thePoint);
343       myDone = myExtPS.IsDone();
344       if (myDone)
345       {
346         for (Standard_Integer anIdx = 1; anIdx <= myExtPS.NbExt(); ++anIdx)
347         {
348           TreatSolution (myExtPS.Point (anIdx), myExtPS.SquareDistance (anIdx));
349         }
350       }
351       return;
352     }
353   }
354
355   myDone = myExtPElS.IsDone();
356   if (myDone)
357   {
358     for (Standard_Integer anIdx = 1; anIdx <= myExtPElS.NbExt(); ++anIdx)
359     {
360       TreatSolution (myExtPElS.Point (anIdx), myExtPElS.SquareDistance (anIdx));
361     }
362   }
363 }
364
365
366 Standard_Boolean Extrema_ExtPS::IsDone() const
367 {
368   return myDone;
369 }
370
371
372 Standard_Real Extrema_ExtPS::SquareDistance(const Standard_Integer N) const
373 {
374   if(!myDone) StdFail_NotDone::Raise();
375   if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
376   return mySqDist.Value(N);
377 }
378
379
380 Standard_Integer Extrema_ExtPS::NbExt() const
381 {
382   if(!myDone) StdFail_NotDone::Raise();
383   return mySqDist.Length();
384 }
385
386
387 const Extrema_POnSurf& Extrema_ExtPS::Point(const Standard_Integer N) const
388 {
389   if(!myDone) StdFail_NotDone::Raise();
390   return myPoints.Value(N);
391 }
392
393
394 void Extrema_ExtPS::TrimmedSquareDistances(Standard_Real& dUfVf,
395                                       Standard_Real& dUfVl,
396                                       Standard_Real& dUlVf,
397                                       Standard_Real& dUlVl,
398                                       gp_Pnt&        PUfVf,
399                                       gp_Pnt&        PUfVl,
400                                       gp_Pnt&        PUlVf,
401                                       gp_Pnt&        PUlVl) const
402 {
403   dUfVf = d11;
404   dUfVl = d12;
405   dUlVf = d21;
406   dUlVl = d22;
407   PUfVf = P11;
408   PUfVl = P12;
409   PUlVf = P21;
410   PUlVl = P22;
411 }
412
413 void Extrema_ExtPS::SetFlag(const Extrema_ExtFlag F)
414 {
415   myExtPS.SetFlag(F);
416 }
417
418 void Extrema_ExtPS::SetAlgo(const Extrema_ExtAlgo A)
419 {
420   myExtPS.SetAlgo(A);
421 }