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