7fd59977 |
1 | // File: Extrema_ExtPElC2d.cxx |
2 | // Created: Mon Dec 13 12:37:09 1993 |
3 | // Author: Christophe MARION |
4 | // <cma@zerox> |
5 | |
6 | #include <Precision.hxx> |
7 | #include <Extrema_ExtPElC2d.ixx> |
8 | #include <StdFail_NotDone.hxx> |
9 | #include <math_DirectPolynomialRoots.hxx> |
10 | #include <math_TrigonometricFunctionRoots.hxx> |
11 | #include <ElCLib.hxx> |
12 | #include <Standard_OutOfRange.hxx> |
13 | #include <Standard_NotImplemented.hxx> |
14 | //============================================================================= |
15 | |
16 | Extrema_ExtPElC2d::Extrema_ExtPElC2d () { myDone = Standard_False; } |
17 | //============================================================================= |
18 | |
19 | Extrema_ExtPElC2d::Extrema_ExtPElC2d |
20 | (const gp_Pnt2d& P, |
21 | const gp_Lin2d& L, |
22 | const Standard_Real Tol, |
23 | const Standard_Real Uinf, |
24 | const Standard_Real Usup) |
25 | { |
26 | Perform(P, L, Tol, Uinf, Usup); |
27 | } |
28 | |
29 | void Extrema_ExtPElC2d::Perform(const gp_Pnt2d& P, |
30 | const gp_Lin2d& L, |
31 | const Standard_Real Tol, |
32 | const Standard_Real Uinf, |
33 | const Standard_Real Usup) |
34 | { |
35 | myDone = Standard_True; |
36 | gp_Pnt2d OR, MyP; |
37 | myNbExt = 0; |
38 | |
39 | gp_Vec2d V1 = gp_Vec2d(L.Direction()); |
40 | OR = L.Location(); |
41 | gp_Vec2d V(OR, P); |
42 | Standard_Real Mydist = V1.Dot(V); |
43 | if ((Mydist >= Uinf -Tol) && |
44 | (Mydist <= Usup+ Tol)){ |
45 | myNbExt = 1; |
46 | MyP = OR.Translated(Mydist*V1); |
47 | Extrema_POnCurv2d MyPOnCurve(Mydist, MyP); |
48 | mySqDist[0] = P.SquareDistance(MyP); |
49 | myPoint[0] = MyPOnCurve; |
50 | myIsMin[0] = Standard_True; |
51 | } |
52 | } |
53 | |
54 | //============================================================================= |
55 | |
56 | Extrema_ExtPElC2d::Extrema_ExtPElC2d |
57 | (const gp_Pnt2d& P, |
58 | const gp_Circ2d& C, |
59 | const Standard_Real Tol, |
60 | const Standard_Real Uinf, |
61 | const Standard_Real Usup) |
62 | { |
63 | Perform(P, C, Tol, Uinf, Usup); |
64 | } |
65 | |
66 | void Extrema_ExtPElC2d::Perform(const gp_Pnt2d& P, |
67 | const gp_Circ2d& C, |
68 | const Standard_Real Tol, |
69 | const Standard_Real Uinf, |
70 | const Standard_Real Usup) |
71 | { |
72 | Standard_Real radius, U1, U2; |
73 | // gp_Pnt2d OC, P1, P2, OL; |
74 | gp_Pnt2d OC, P1, P2; |
75 | OC = C.Location(); |
76 | myNbExt = 0; |
77 | |
78 | if (OC.IsEqual(P, Precision::Confusion())) { |
79 | myDone = Standard_False; |
80 | } |
81 | else { |
82 | myDone = Standard_True; |
83 | gp_Dir2d V(gp_Vec2d(P, OC)); |
84 | radius = C.Radius(); |
85 | P1 = OC.Translated(radius*V); |
86 | U1 = ElCLib::Parameter(C, P1); |
87 | U2 = U1 + PI; |
88 | P2 = OC.Translated(-radius*V); |
89 | Standard_Real myuinf = Uinf; |
90 | ElCLib::AdjustPeriodic(Uinf, Uinf+2*PI, Precision::PConfusion(), myuinf, U1); |
91 | ElCLib::AdjustPeriodic(Uinf, Uinf+2*PI, Precision::PConfusion(), myuinf, U2); |
92 | if (((U1-2*PI-Uinf) < Tol) && ((U1-2*PI-Uinf) > -Tol)) U1 = Uinf; |
93 | if (((U2-2*PI-Uinf) < Tol) && ((U2-2*PI-Uinf) > -Tol)) U2 = Uinf; |
94 | |
95 | if (((Uinf-U1) < Tol) && ((U1-Usup) < Tol)) { |
96 | Extrema_POnCurv2d MyPOnCurve(U1, P1); |
97 | mySqDist[0] = P.SquareDistance(P1); |
98 | myPoint[0] = MyPOnCurve; |
99 | myIsMin[0] = Standard_True; |
100 | myNbExt++; |
101 | } |
102 | |
103 | if (((Uinf-U2) < Tol) && ((U2-Usup) < Tol)) { |
104 | Extrema_POnCurv2d MyPOnCurve(U2, P2); |
105 | mySqDist[myNbExt] = P.SquareDistance(P2); |
106 | myPoint[myNbExt] = MyPOnCurve; |
107 | myIsMin[myNbExt] = Standard_True; |
108 | myNbExt++; |
109 | } |
110 | } |
111 | } |
112 | |
113 | //============================================================================= |
114 | |
115 | |
116 | Extrema_ExtPElC2d::Extrema_ExtPElC2d (const gp_Pnt2d& P, |
117 | const gp_Elips2d& E, |
118 | const Standard_Real Tol, |
119 | const Standard_Real Uinf, |
120 | const Standard_Real Usup) |
121 | { |
122 | Perform(P, E, Tol, Uinf, Usup); |
123 | } |
124 | |
125 | |
126 | |
127 | void Extrema_ExtPElC2d::Perform (const gp_Pnt2d& P, |
128 | const gp_Elips2d& E, |
129 | const Standard_Real Tol, |
130 | const Standard_Real Uinf, |
131 | const Standard_Real Usup) |
132 | { |
133 | // gp_Pnt2d OR, P1, P2; |
134 | gp_Pnt2d OR; |
135 | OR = E.Location(); |
136 | |
137 | Standard_Integer NoSol, NbSol; |
138 | Standard_Real A = E.MajorRadius(); |
139 | Standard_Real B = E.MinorRadius(); |
140 | gp_Vec2d V(OR,P); |
141 | |
142 | if (OR.IsEqual(P, Precision::Confusion()) && |
143 | (Abs(A-B) <= Tol)) { |
144 | myDone = Standard_False; |
145 | } |
146 | else { |
147 | #ifdef DEB |
148 | Standard_Real VMagn = V.Magnitude(); |
149 | #else |
150 | V.Magnitude(); |
151 | #endif |
152 | Standard_Real X = V.Dot(gp_Vec2d(E.XAxis().Direction())); |
153 | Standard_Real Y = V.Dot(gp_Vec2d(E.YAxis().Direction())); |
154 | |
155 | math_TrigonometricFunctionRoots Sol(0.,(B*B-A*A)/2.,-B*Y,A*X,0.,Uinf,Usup); |
156 | |
157 | if (!Sol.IsDone()) { return; } |
158 | gp_Pnt2d Cu; |
159 | Standard_Real Us; |
160 | NbSol = Sol.NbSolutions(); |
161 | myNbExt = 0; |
162 | for (NoSol = 1; NoSol <= NbSol; NoSol++) { |
163 | Us = Sol.Value(NoSol); |
164 | Cu = ElCLib::Value(Us, E); |
165 | mySqDist[myNbExt] = Cu.SquareDistance(P); |
166 | myIsMin[myNbExt] = (NoSol == 0); |
167 | myPoint[myNbExt] = Extrema_POnCurv2d(Us,Cu); |
168 | myNbExt++; |
169 | } |
170 | myDone = Standard_True; |
171 | } |
172 | } |
173 | //============================================================================= |
174 | |
175 | Extrema_ExtPElC2d::Extrema_ExtPElC2d (const gp_Pnt2d& P, |
176 | const gp_Hypr2d& C, |
177 | const Standard_Real Tol, |
178 | const Standard_Real Uinf, |
179 | const Standard_Real Usup) |
180 | { |
181 | Perform(P, C, Tol, Uinf, Usup); |
182 | } |
183 | |
184 | |
185 | void Extrema_ExtPElC2d::Perform(const gp_Pnt2d& P, |
186 | const gp_Hypr2d& H, |
187 | const Standard_Real Tol, |
188 | const Standard_Real Uinf, |
189 | const Standard_Real Usup) |
190 | { |
191 | gp_Pnt2d O = H.Location(); |
192 | myDone = Standard_False; |
193 | myNbExt = 0; |
194 | |
195 | Standard_Real R = H.MajorRadius(); |
196 | Standard_Real r = H.MinorRadius(); |
197 | gp_Vec2d OPp(O,P); |
198 | #ifdef DEB |
199 | Standard_Real OPpMagn = OPp.Magnitude(); |
200 | #else |
201 | OPp.Magnitude(); |
202 | #endif |
203 | Standard_Real Tol2 = Tol * Tol; |
204 | Standard_Real X = OPp.Dot(gp_Vec2d(H.XAxis().Direction())); |
205 | Standard_Real Y = OPp.Dot(gp_Vec2d(H.YAxis().Direction())); |
206 | Standard_Real C1 = (R*R+r*r)/4.; |
207 | math_DirectPolynomialRoots Sol(C1,-(X*R+Y*r)/2.,0.,(X*R-Y*r)/2.,-C1); |
208 | if (!Sol.IsDone()) { return; } |
209 | gp_Pnt2d Cu; |
210 | Standard_Real Us, Vs; |
211 | Standard_Integer NbSol = Sol.NbSolutions(); |
212 | Standard_Boolean DejaEnr; |
213 | Standard_Integer NoExt; |
214 | gp_Pnt2d TbExt[4]; |
215 | for (Standard_Integer NoSol = 1; NoSol <= NbSol; NoSol++) { |
216 | Vs = Sol.Value(NoSol); |
217 | if (Vs > 0.) { |
218 | Us = Log(Vs); |
219 | if ((Us >= Uinf) && (Us <= Usup)) { |
220 | Cu = ElCLib::Value(Us,H); |
221 | DejaEnr = Standard_False; |
222 | for (NoExt = 0; NoExt < myNbExt; NoExt++) { |
223 | if (TbExt[NoExt].SquareDistance(Cu) < Tol2) { |
224 | DejaEnr = Standard_True; |
225 | break; |
226 | } |
227 | } |
228 | if (!DejaEnr) { |
229 | TbExt[myNbExt] = Cu; |
230 | mySqDist[myNbExt] = Cu.SquareDistance(P); |
231 | myIsMin[myNbExt] = (NoSol == 0); |
232 | myPoint[myNbExt] = Extrema_POnCurv2d(Us,Cu); |
233 | myNbExt++; |
234 | } |
235 | } // if ((Us >= Uinf) && (Us <= Usup)) |
236 | } // if (Vs > 0.) |
237 | } // for (Standard_Integer NoSol = 1; ... |
238 | myDone = Standard_True; |
239 | } |
240 | |
241 | //============================================================================= |
242 | |
243 | Extrema_ExtPElC2d::Extrema_ExtPElC2d (const gp_Pnt2d& P, |
244 | const gp_Parab2d& C, |
245 | const Standard_Real Tol, |
246 | const Standard_Real Uinf, |
247 | const Standard_Real Usup) |
248 | { |
249 | Perform(P, C, Tol, Uinf, Usup); |
250 | } |
251 | |
252 | |
253 | void Extrema_ExtPElC2d::Perform(const gp_Pnt2d& P, |
254 | const gp_Parab2d& C, |
255 | const Standard_Real Tol, |
256 | const Standard_Real Uinf, |
257 | const Standard_Real Usup) |
258 | { |
259 | myDone = Standard_False; |
260 | myNbExt = 0; |
261 | gp_Pnt2d O = C.Location(); |
262 | |
263 | Standard_Real Tol2 = Tol * Tol; |
264 | Standard_Real F = C.Focal(); |
265 | gp_Vec2d OPp (O,P); |
266 | #ifdef DEB |
267 | Standard_Real OPpMagn = OPp.Magnitude(); |
268 | #else |
269 | OPp.Magnitude(); |
270 | #endif |
271 | Standard_Real X = OPp.Dot(gp_Vec2d(C.MirrorAxis().Direction())); |
272 | Standard_Real Y = OPp.Dot(gp_Vec2d(C.Axis().YAxis().Direction())); |
273 | |
274 | math_DirectPolynomialRoots Sol(1./(4.*F),0.,2.*F-X,-2.*F*Y); |
275 | if (!Sol.IsDone()) { return; } |
276 | gp_Pnt2d Cu; |
277 | Standard_Real Us; |
278 | Standard_Integer NbSol = Sol.NbSolutions(); |
279 | Standard_Boolean DejaEnr; |
280 | Standard_Integer NoExt; |
281 | gp_Pnt2d TbExt[3]; |
282 | for (Standard_Integer NoSol = 1; NoSol <= NbSol; NoSol++) { |
283 | Us = Sol.Value(NoSol); |
284 | if ((Us >= Uinf) && (Us <= Usup)) { |
285 | Cu = ElCLib::Value(Us,C); |
286 | DejaEnr = Standard_False; |
287 | for (NoExt = 0; NoExt < myNbExt; NoExt++) { |
288 | if (TbExt[NoExt].SquareDistance(Cu) < Tol2) { |
289 | DejaEnr = Standard_True; |
290 | break; |
291 | } |
292 | } |
293 | if (!DejaEnr) { |
294 | TbExt[myNbExt] = Cu; |
295 | mySqDist[myNbExt] = Cu.SquareDistance(P); |
296 | myIsMin[myNbExt] = (NoSol == 0); |
297 | myPoint[myNbExt] = Extrema_POnCurv2d(Us,Cu); |
298 | myNbExt++; |
299 | } |
300 | } // if ((Us >= Uinf) && (Us <= Usup)) |
301 | } // for (Standard_Integer NoSol = 1; ... |
302 | myDone = Standard_True; |
303 | } |
304 | //============================================================================= |
305 | |
306 | Standard_Boolean Extrema_ExtPElC2d::IsDone () const { return myDone; } |
307 | //============================================================================= |
308 | |
309 | Standard_Integer Extrema_ExtPElC2d::NbExt () const |
310 | { |
311 | if (!IsDone()) { StdFail_NotDone::Raise(); } |
312 | return myNbExt; |
313 | } |
314 | //============================================================================= |
315 | |
316 | Standard_Real Extrema_ExtPElC2d::SquareDistance (const Standard_Integer N) const |
317 | { |
318 | if ((N < 1) || (N > NbExt())) { Standard_OutOfRange::Raise(); } |
319 | return mySqDist[N-1]; |
320 | } |
321 | //============================================================================= |
322 | |
323 | Standard_Boolean Extrema_ExtPElC2d::IsMin (const Standard_Integer N) const |
324 | { |
325 | if ((N < 1) || (N > NbExt())) { Standard_OutOfRange::Raise(); } |
326 | return myIsMin[N-1]; |
327 | } |
328 | //============================================================================= |
329 | |
330 | Extrema_POnCurv2d Extrema_ExtPElC2d::Point (const Standard_Integer N) const |
331 | { |
332 | if ((N < 1) || (N > NbExt())) { Standard_OutOfRange::Raise(); } |
333 | return myPoint[N-1]; |
334 | } |
335 | //============================================================================= |