0022883: Extrema can not find projection of 3D point on surface.
[occt.git] / src / Extrema / Extrema_ExtPS.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19 //-----------------------------------------------------------------
20
21 #include <Extrema_ExtPS.ixx>
22 #include <Extrema_GenExtPS.hxx>
23 #include <StdFail_NotDone.hxx>
24 #include <Standard_NotImplemented.hxx>
25 #include <Precision.hxx>
26 #include <GeomAbs_CurveType.hxx>
27 #include <Adaptor3d_SurfaceOfLinearExtrusion.hxx>
28 #include <Adaptor3d_SurfaceOfRevolution.hxx>
29 #include <ElCLib.hxx>
30 #include <gp_Pnt.hxx>
31 #include <gp_Pln.hxx>
32 #include <gp_Cylinder.hxx>
33 #include <gp_Cone.hxx>
34 #include <gp_Sphere.hxx>
35 #include <gp_Torus.hxx>
36 #include <Extrema_ExtPExtS.hxx>
37 #include <Extrema_ExtPRevS.hxx>
38 #include <Extrema_POnSurf.hxx>
39 #include <GeomAbs_IsoType.hxx>
40
41 //=======================================================================
42 //function : IsoIsDeg
43 //purpose  : 
44 //=======================================================================
45
46 static Standard_Boolean IsoIsDeg  (const Adaptor3d_Surface& S,
47                                    const Standard_Real      Param,
48                                    const GeomAbs_IsoType    IT,
49                                    const Standard_Real      TolMin,
50                                    const Standard_Real      TolMax) 
51 {
52     Standard_Real U1=0.,U2=0.,V1=0.,V2=0.,T;
53     Standard_Boolean Along = Standard_True;
54     U1 = S.FirstUParameter();
55     U2 = S.LastUParameter();
56     V1 = S.FirstVParameter();
57     V2 = S.LastVParameter();
58     gp_Vec D1U,D1V;
59     gp_Pnt P;
60     Standard_Real Step,D1NormMax;
61     if (IT == GeomAbs_IsoV) 
62     {
63       if( !Precision::IsInfinite(U1) &&  !Precision::IsInfinite(U2) )
64       {
65         Step = (U2 - U1)/10;
66         if(Step < Precision::PConfusion()) {
67           return Standard_False;
68         }
69         D1NormMax=0.;
70
71         for (T=U1;T<=U2;T=T+Step) 
72         {
73           S.D1(T,Param,P,D1U,D1V);
74           D1NormMax=Max(D1NormMax,D1U.Magnitude());
75         }
76
77         if (D1NormMax >TolMax || D1NormMax < TolMin ) 
78           Along = Standard_False;
79       }
80     }
81     else 
82     {
83       if( !Precision::IsInfinite(V1) &&  !Precision::IsInfinite(V2) )
84       {
85         Step = (V2 - V1)/10;
86         if(Step < Precision::PConfusion()) {
87           return Standard_False;
88         }
89         D1NormMax=0.;
90         for (T=V1;T<=V2;T=T+Step) 
91         {
92           S.D1(Param,T,P,D1U,D1V);
93           D1NormMax=Max(D1NormMax,D1V.Magnitude());
94         }
95
96         if (D1NormMax >TolMax || D1NormMax < TolMin ) 
97           Along = Standard_False;
98       }
99
100
101
102     }
103     return Along;
104 }
105
106 //=======================================================================
107 //function : TreatSolution
108 //purpose  : 
109 //=======================================================================
110
111 void Extrema_ExtPS::TreatSolution (const Extrema_POnSurf& PS,
112                                    const Standard_Real Val)
113 {
114   Standard_Real U, V;
115   PS.Parameter(U, V);
116   if (myS->IsUPeriodic()) {
117     U = ElCLib::InPeriod(U, myuinf, myuinf+myS->UPeriod());
118   }
119   if (myS->IsVPeriodic()) {
120     V = ElCLib::InPeriod(V, myvinf, myvinf+myS->VPeriod());
121   }
122   if ((myuinf-U) <= mytolu && (U-myusup) <= mytolu &&
123       (myvinf-V) <= mytolv && (V-myvsup) <= mytolv) {
124     myPoints.Append(Extrema_POnSurf (U, V, PS.Value()));
125     mySqDist.Append(Val);
126   }
127 }
128
129
130 //=======================================================================
131 //function : Extrema_ExtPS
132 //purpose  : 
133 //=======================================================================
134
135 Extrema_ExtPS::Extrema_ExtPS() 
136 {
137   myDone = Standard_False;
138 }
139
140
141 //=======================================================================
142 //function : Extrema_ExtPS
143 //purpose  : 
144 //=======================================================================
145
146 Extrema_ExtPS::Extrema_ExtPS(const gp_Pnt&          P,
147                              const Adaptor3d_Surface& S,
148                              const Standard_Real    TolU,
149                              const Standard_Real    TolV,
150            const Extrema_ExtFlag F,
151            const Extrema_ExtAlgo A)
152
153 {
154   myExtPS.SetFlag(F);
155   myExtPS.SetAlgo(A);
156   Initialize(S, S.FirstUParameter(), S.LastUParameter(), 
157                 S.FirstVParameter(), S.LastVParameter(), 
158                 TolU, TolV);
159   Perform(P);
160 }
161
162 //=======================================================================
163 //function : Extrema_ExtPS
164 //purpose  : 
165 //=======================================================================
166
167 Extrema_ExtPS::Extrema_ExtPS(const gp_Pnt&          P,
168                              const Adaptor3d_Surface& S,
169                              const Standard_Real    Uinf,       
170                              const Standard_Real    Usup,
171                              const Standard_Real    Vinf,       
172                              const Standard_Real    Vsup,
173                              const Standard_Real    TolU,
174                              const Standard_Real    TolV,
175            const Extrema_ExtFlag F,
176            const Extrema_ExtAlgo A)
177
178 {
179   myExtPS.SetFlag(F);
180   myExtPS.SetAlgo(A);
181   Initialize(S, Uinf, Usup, Vinf, Vsup, TolU, TolV);
182   Perform(P);
183 }
184
185
186 //=======================================================================
187 //function : Initialize
188 //purpose  : 
189 //=======================================================================
190
191 void Extrema_ExtPS::Initialize(const Adaptor3d_Surface& S,
192                                const Standard_Real    Uinf,     
193                                const Standard_Real    Usup,
194                                const Standard_Real    Vinf,     
195                                const Standard_Real    Vsup,
196                                const Standard_Real    TolU,
197                                const Standard_Real    TolV)
198 {
199   myS = (Adaptor3d_SurfacePtr)&S;
200   myuinf = Uinf;
201   myusup = Usup;
202   myvinf = Vinf;
203   myvsup = Vsup;
204
205   if (Precision::IsNegativeInfinite(myuinf)) myuinf = -1e10;
206   if (Precision::IsPositiveInfinite(myusup)) myusup = 1e10;
207   if (Precision::IsNegativeInfinite(myvinf)) myvinf = -1e10;
208   if (Precision::IsPositiveInfinite(myvsup)) myvsup = 1e10;
209
210   mytolu = TolU;
211   mytolv = TolV;
212   mytype = myS->GetType();
213
214   Standard_Boolean isB = ( myS->GetType() == GeomAbs_BSplineSurface ||
215                            myS->GetType() == GeomAbs_BezierSurface );
216
217   Standard_Integer nbU = (isB) ? 44 : 32;
218   Standard_Integer nbV = (isB) ? 44 : 32;
219
220   Standard_Boolean bUIsoIsDeg = Standard_False, bVIsoIsDeg = Standard_False;
221
222   if(myS->GetType() != GeomAbs_Plane) {
223     bUIsoIsDeg = IsoIsDeg(S, myuinf, GeomAbs_IsoU, 0., 1.e-9) ||
224                  IsoIsDeg(S, myusup, GeomAbs_IsoU, 0., 1.e-9);
225     bVIsoIsDeg = IsoIsDeg(S, myvinf, GeomAbs_IsoV, 0., 1.e-9) ||
226                  IsoIsDeg(S, myvsup, GeomAbs_IsoV, 0., 1.e-9);
227   }
228
229   if(bUIsoIsDeg) nbU = 300;
230   if(bVIsoIsDeg) nbV = 300;
231
232   myExtPS.Initialize(*myS, nbU, nbV, myuinf, myusup, myvinf, myvsup, mytolu, mytolv);
233 }
234
235 //=======================================================================
236 //function : Perform
237 //purpose  : 
238 //=======================================================================
239
240 void Extrema_ExtPS::Perform(const gp_Pnt& P)
241 {
242   myPoints.Clear();
243   mySqDist.Clear();
244   Standard_Integer i;
245   
246   
247   switch(mytype) {
248     
249   case GeomAbs_Cylinder:
250     myExtPElS.Perform(P, myS->Cylinder(), Precision::Confusion());
251     break;
252   case GeomAbs_Plane:
253     myExtPElS.Perform(P, myS->Plane(), Precision::Confusion());
254     break;
255   case GeomAbs_Cone:
256     myExtPElS.Perform(P, myS->Cone(), Precision::Confusion());
257     break;
258   case GeomAbs_Sphere:
259     myExtPElS.Perform(P, myS->Sphere(), Precision::Confusion());
260     break;
261   case GeomAbs_Torus:
262     myExtPElS.Perform(P, myS->Torus(), Precision::Confusion());
263     break;
264
265     
266   case GeomAbs_SurfaceOfExtrusion: {
267     Extrema_ExtPExtS anExtPExtS(P,
268                                 Adaptor3d_SurfaceOfLinearExtrusion(myS->BasisCurve(),
269                                                                    myS->Direction()),
270                                 myuinf,myusup, myvinf,myvsup, mytolu,mytolv);
271     myDone = anExtPExtS.IsDone();
272     if (myDone) 
273       for (i = 1; i <= anExtPExtS.NbExt(); i++) {
274         TreatSolution (anExtPExtS.Point(i), anExtPExtS.SquareDistance(i));
275       }
276     return;
277   }
278
279     
280   case GeomAbs_SurfaceOfRevolution: {
281     Extrema_ExtPRevS anExtPRevS(P,
282                                 Adaptor3d_SurfaceOfRevolution(myS->BasisCurve(),
283                                                               myS->AxeOfRevolution()),
284                                 myuinf, myusup,myvinf, myvsup,mytolu, mytolv);
285     myDone = anExtPRevS.IsDone();
286     if (myDone) 
287       for (i = 1; i <= anExtPRevS.NbExt(); i++) {
288         TreatSolution (anExtPRevS.Point(i), anExtPRevS.SquareDistance(i));
289       }
290     return;
291   }
292
293     
294   default: 
295     myExtPS.Perform(P);
296     myDone = myExtPS.IsDone();
297     if (myDone) 
298       for (i = 1; i <= myExtPS.NbExt(); i++) 
299         TreatSolution (myExtPS.Point(i), myExtPS.SquareDistance(i));
300     return;
301   }
302
303   
304   myDone = myExtPElS.IsDone();
305   if (myDone) 
306     for (i = 1; i <= myExtPElS.NbExt(); i++) 
307       TreatSolution (myExtPElS.Point(i), myExtPElS.SquareDistance(i));
308   return;
309 }
310
311
312
313 Standard_Boolean Extrema_ExtPS::IsDone() const
314 {
315   return myDone;
316 }
317
318
319 Standard_Real Extrema_ExtPS::SquareDistance(const Standard_Integer N) const
320 {
321   if(!myDone) StdFail_NotDone::Raise();
322   if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
323   return mySqDist.Value(N);
324 }
325
326
327 Standard_Integer Extrema_ExtPS::NbExt() const
328 {
329   if(!myDone) StdFail_NotDone::Raise();
330   return mySqDist.Length();
331 }
332
333
334
335 Extrema_POnSurf Extrema_ExtPS::Point(const Standard_Integer N) const
336 {
337   if(!myDone) StdFail_NotDone::Raise();
338   return myPoints.Value(N);
339 }
340
341
342 void Extrema_ExtPS::TrimmedSquareDistances(Standard_Real& dUfVf,
343                                       Standard_Real& dUfVl,
344                                       Standard_Real& dUlVf,
345                                       Standard_Real& dUlVl,
346                                       gp_Pnt&        PUfVf,
347                                       gp_Pnt&        PUfVl,
348                                       gp_Pnt&        PUlVf,
349                                       gp_Pnt&        PUlVl) const
350 {
351   dUfVf = d11;
352   dUfVl = d12;
353   dUlVf = d21;
354   dUlVl = d22;
355   PUfVf = P11;
356   PUfVl = P12;
357   PUlVf = P21;
358   PUlVl = P22;
359 }
360
361 void Extrema_ExtPS::SetFlag(const Extrema_ExtFlag F)
362 {
363   myExtPS.SetFlag(F);
364 }
365
366 void Extrema_ExtPS::SetAlgo(const Extrema_ExtAlgo A)
367 {
368   myExtPS.SetAlgo(A);
369 }