b311480e |
1 | // Created on: 1992-10-19 |
2 | // Created by: Laurent PAINNOT |
3 | // Copyright (c) 1992-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
b311480e |
16 | |
7fd59977 |
17 | // Modified by cma, Fri Dec 10 18:11:56 1993 |
7fd59977 |
18 | |
19 | #include Extrema_EPC_hxx |
20 | #include ThePOnC_hxx |
21 | #include TheSequenceOfPOnC_hxx |
22 | #include ThePoint_hxx |
23 | #include TheVector_hxx |
24 | #include TheExtPElC_hxx |
25 | #include <StdFail_NotDone.hxx> |
26 | #include <Standard_Failure.hxx> |
27 | #include <GeomAbs_CurveType.hxx> |
28 | #include <Precision.hxx> |
29 | #include <ElCLib.hxx> |
30 | #include <TColStd_Array1OfReal.hxx> |
f6b08ecf |
31 | #include <TColStd_HArray1OfReal.hxx> |
c8bf1eb7 |
32 | #include <NCollection_Array1.hxx> |
7fd59977 |
33 | |
34 | |
35 | //======================================================================= |
36 | //function : Perform |
37 | //purpose : |
38 | //======================================================================= |
7fd59977 |
39 | void Extrema_GExtPC::Perform(const ThePoint& P) |
40 | { |
41 | mySqDist.Clear(); |
42 | mypoint.Clear(); |
43 | myismin.Clear(); |
44 | Standard_Integer i, NbExt, n; |
45 | Standard_Real U; |
46 | mysample = 17; |
47 | Standard_Real t3d = Precision::Confusion(); |
48 | if (Precision::IsInfinite(myuinf)) mydist1 = RealLast(); |
49 | else { |
50 | Pf = TheCurveTool::Value(*((TheCurve*)myC), myuinf); |
51 | mydist1 = P.SquareDistance(Pf); |
52 | } |
53 | |
54 | if (Precision::IsInfinite(myusup)) mydist2 = RealLast(); |
55 | else { |
56 | Pl = TheCurveTool::Value(*((TheCurve*)myC), myusup); |
57 | mydist2 = P.SquareDistance(Pl); |
58 | } |
59 | |
c8bf1eb7 |
60 | TheCurve & aCurve = *((TheCurve*)myC); |
61 | |
7fd59977 |
62 | switch(type) { |
63 | case GeomAbs_Circle: |
64 | { |
c8bf1eb7 |
65 | myExtPElC.Perform(P, TheCurveTool::Circle(aCurve), t3d, myuinf, myusup); |
7fd59977 |
66 | } |
67 | break; |
68 | case GeomAbs_Ellipse: |
69 | { |
c8bf1eb7 |
70 | myExtPElC.Perform(P, TheCurveTool::Ellipse(aCurve), t3d, myuinf, myusup); |
7fd59977 |
71 | } |
72 | break; |
73 | case GeomAbs_Parabola: |
74 | { |
c8bf1eb7 |
75 | myExtPElC.Perform(P, TheCurveTool::Parabola(aCurve), t3d,myuinf,myusup); |
7fd59977 |
76 | } |
77 | break; |
78 | case GeomAbs_Hyperbola: |
79 | { |
c8bf1eb7 |
80 | myExtPElC.Perform(P,TheCurveTool::Hyperbola(aCurve),t3d, myuinf, myusup); |
7fd59977 |
81 | } |
82 | break; |
83 | case GeomAbs_Line: |
84 | { |
c8bf1eb7 |
85 | myExtPElC.Perform(P, TheCurveTool::Line(aCurve), t3d, myuinf, myusup); |
7fd59977 |
86 | } |
87 | break; |
88 | case GeomAbs_BezierCurve: |
89 | { |
90 | myintuinf = myuinf; |
91 | myintusup = myusup; |
c8bf1eb7 |
92 | mysample = (TheCurveTool::Bezier(aCurve))->NbPoles() * 2; |
93 | myExtPC.Initialize(aCurve); |
7fd59977 |
94 | IntervalPerform(P); |
95 | return; |
96 | } |
97 | case GeomAbs_BSplineCurve: |
98 | { |
c8bf1eb7 |
99 | const Standard_Integer |
100 | aFirstIdx = TheCurveTool::BSpline(aCurve)->FirstUKnotIndex(), |
101 | aLastIdx = TheCurveTool::BSpline(aCurve)->LastUKnotIndex(); |
102 | // const reference can not be used due to implementation of BRep_Adaptor. |
103 | TColStd_Array1OfReal aKnots(aFirstIdx, aLastIdx); |
104 | TheCurveTool::BSpline(aCurve)->Knots(aKnots); |
105 | |
106 | // Workaround to work with: |
c5a10cf7 |
107 | // blend, where knots may be moved from parameter space. |
c8bf1eb7 |
108 | Standard_Real aPeriodJump = 0.0; |
c5a10cf7 |
109 | // Avoid problem with too close knots. |
0cbfb9f1 |
110 | const Standard_Real aTolCoeff = (myusup - myuinf) * Precision::PConfusion(); |
c8bf1eb7 |
111 | if (TheCurveTool::IsPeriodic(aCurve)) |
112 | { |
113 | Standard_Integer aPeriodShift = |
114 | Standard_Integer ((myuinf - aKnots(aFirstIdx)) / TheCurveTool::Period(aCurve)); |
115 | |
0cbfb9f1 |
116 | if (myuinf < aKnots(aFirstIdx) - aTolCoeff) |
c8bf1eb7 |
117 | aPeriodShift--; |
118 | |
119 | aPeriodJump = TheCurveTool::Period(aCurve) * aPeriodShift; |
120 | } |
121 | |
122 | Standard_Integer anIdx; |
123 | |
1581d651 |
124 | // Find first and last used knot. |
c8bf1eb7 |
125 | Standard_Integer aFirstUsedKnot = aFirstIdx, |
126 | aLastUsedKnot = aLastIdx; |
127 | for(anIdx = aFirstIdx; anIdx <= aLastIdx; anIdx++) |
128 | { |
129 | Standard_Real aKnot = aKnots(anIdx) + aPeriodJump; |
0cbfb9f1 |
130 | if (myuinf >= aKnot - aTolCoeff) |
c8bf1eb7 |
131 | aFirstUsedKnot = anIdx; |
132 | else |
133 | break; |
134 | |
135 | } |
136 | for(anIdx = aLastIdx; anIdx >= aFirstIdx; anIdx--) |
137 | { |
138 | Standard_Real aKnot = aKnots(anIdx) + aPeriodJump; |
0cbfb9f1 |
139 | if (myusup <= aKnot + aTolCoeff) |
c8bf1eb7 |
140 | aLastUsedKnot = anIdx; |
141 | else |
142 | break; |
143 | } |
144 | |
1581d651 |
145 | if (aFirstUsedKnot == aLastUsedKnot) |
146 | { |
147 | // Degenerated case: |
148 | // Some bounds lies out of curve param space. |
149 | // In this case build one interval with [myuinf, myusup]. |
150 | // Parameters of these indexes will be redefined. |
151 | aFirstUsedKnot = aFirstIdx; |
152 | aLastUsedKnot = aFirstIdx + 1; |
153 | } |
154 | |
c8bf1eb7 |
155 | mysample = (TheCurveTool::BSpline(aCurve))->Degree() + 1; |
156 | |
d8406b2f |
157 | if (mysample == 2) |
c8bf1eb7 |
158 | { |
d8406b2f |
159 | //BSpline of first degree, direct seaching extrema for each knot interval |
160 | ThePoint aPmin; |
161 | Standard_Real tmin = 0., distmin = RealLast(); |
162 | Standard_Real aMin1 = 0., aMin2 = 0.; |
163 | myExtPC.Initialize(aCurve); |
164 | for (anIdx = aFirstUsedKnot; anIdx < aLastUsedKnot; anIdx++) |
165 | { |
166 | Standard_Real aF = aKnots(anIdx) + aPeriodJump, |
167 | aL = aKnots(anIdx + 1) + aPeriodJump; |
168 | |
169 | if (anIdx == aFirstUsedKnot) |
170 | { |
171 | aF = myuinf; |
172 | } |
173 | else |
174 | if (anIdx == aLastUsedKnot - 1) |
175 | { |
176 | aL = myusup; |
177 | } |
c8bf1eb7 |
178 | |
c8bf1eb7 |
179 | |
d8406b2f |
180 | ThePoint aP1, aP2; |
181 | TheCurveTool::D0(aCurve, aF, aP1); |
182 | TheCurveTool::D0(aCurve, aL, aP2); |
183 | TheVector aBase1(P, aP1), aBase2(P, aP2); |
184 | TheVector aV(aP2, aP1); |
185 | Standard_Real aVal1 = aV.Dot(aBase1); // Derivative of (C(u) - P)^2 |
186 | Standard_Real aVal2 = aV.Dot(aBase2); // Derivative of (C(u) - P)^2 |
187 | if (anIdx == aFirstUsedKnot) |
188 | { |
189 | aMin1 = P.SquareDistance(aP1); |
190 | } |
191 | else |
192 | { |
193 | aMin1 = aMin2; |
194 | if (distmin > aMin1) |
195 | { |
196 | distmin = aMin1; |
197 | tmin = aF; |
198 | aPmin = aP1; |
199 | } |
200 | } |
201 | aMin2 = P.SquareDistance(aP2); |
202 | Standard_Real aMinSqDist = Min(aMin1, aMin2); |
203 | Standard_Real aMinDer = Min(Abs(aVal1), Abs(aVal2)); |
204 | if (!(Precision::IsInfinite(aVal1) || Precision::IsInfinite(aVal2))) |
205 | { |
206 | // Derivatives have opposite signs - min or max inside of interval (sufficient condition). |
207 | if (aVal1 * aVal2 <= 0.0 || |
208 | aMinSqDist < 100. * Precision::SquareConfusion() || |
209 | 2.*aMinDer < Precision::Confusion()) |
210 | { |
211 | myintuinf = aF; |
212 | myintusup = aL; |
213 | IntervalPerform(P); |
214 | } |
215 | } |
216 | } |
217 | if (!Precision::IsInfinite(distmin)) |
c8bf1eb7 |
218 | { |
d8406b2f |
219 | Standard_Boolean isToAdd = Standard_True; |
220 | NbExt = mypoint.Length(); |
221 | for (i = 1; i <= NbExt && isToAdd; i++) |
222 | { |
223 | Standard_Real t = mypoint.Value(i).Parameter(); |
224 | isToAdd = (distmin < mySqDist(i)) && (Abs(t - tmin) > mytolu); |
225 | } |
226 | if (isToAdd) |
227 | { |
228 | ThePOnC PC(tmin, aPmin); |
229 | mySqDist.Append(distmin); |
230 | myismin.Append(Standard_True); |
231 | mypoint.Append(PC); |
232 | } |
c8bf1eb7 |
233 | } |
234 | } |
d8406b2f |
235 | else |
c8bf1eb7 |
236 | { |
d8406b2f |
237 | |
238 | // Fill sample points. |
239 | Standard_Integer aValIdx = 1; |
240 | NCollection_Array1<Standard_Real> aVal(1, (mysample)* (aLastUsedKnot - aFirstUsedKnot) + 1); |
241 | NCollection_Array1<Standard_Real> aParam(1, (mysample)* (aLastUsedKnot - aFirstUsedKnot) + 1); |
242 | for (anIdx = aFirstUsedKnot; anIdx < aLastUsedKnot; anIdx++) |
c8bf1eb7 |
243 | { |
d8406b2f |
244 | Standard_Real aF = aKnots(anIdx) + aPeriodJump, |
245 | aL = aKnots(anIdx + 1) + aPeriodJump; |
246 | |
247 | if (anIdx == aFirstUsedKnot) |
248 | aF = myuinf; |
249 | if (anIdx == aLastUsedKnot - 1) |
250 | aL = myusup; |
c8bf1eb7 |
251 | |
d8406b2f |
252 | Standard_Real aStep = (aL - aF) / mysample; |
253 | for (Standard_Integer aPntIdx = 0; aPntIdx < mysample; aPntIdx++) |
254 | { |
255 | Standard_Real aCurrentParam = aF + aStep * aPntIdx; |
256 | aVal(aValIdx) = TheCurveTool::Value(aCurve, aCurrentParam).SquareDistance(P); |
257 | aParam(aValIdx) = aCurrentParam; |
258 | aValIdx++; |
259 | } |
c8bf1eb7 |
260 | } |
d8406b2f |
261 | // Fill last point. |
262 | aVal(aValIdx) = TheCurveTool::Value(aCurve, myusup).SquareDistance(P); |
263 | aParam(aValIdx) = myusup; |
c8bf1eb7 |
264 | |
d8406b2f |
265 | myExtPC.Initialize(aCurve); |
266 | |
267 | // Find extremas. |
268 | for (anIdx = aVal.Lower() + 1; anIdx < aVal.Upper(); anIdx++) |
c8bf1eb7 |
269 | { |
d8406b2f |
270 | if (aVal(anIdx) <= Precision::SquareConfusion()) |
271 | { |
272 | mySqDist.Append(aVal(anIdx)); |
273 | myismin.Append(Standard_True); |
274 | mypoint.Append(ThePOnC(aParam(anIdx), TheCurveTool::Value(aCurve, aParam(anIdx)))); |
275 | } |
276 | if ((aVal(anIdx) >= aVal(anIdx + 1) && |
277 | aVal(anIdx) >= aVal(anIdx - 1)) || |
278 | (aVal(anIdx) <= aVal(anIdx + 1) && |
279 | aVal(anIdx) <= aVal(anIdx - 1))) |
f4dee9bb |
280 | { |
d8406b2f |
281 | myintuinf = aParam(anIdx - 1); |
282 | myintusup = aParam(anIdx + 1); |
283 | |
f4dee9bb |
284 | IntervalPerform(P); |
285 | } |
c8bf1eb7 |
286 | } |
c8bf1eb7 |
287 | |
d8406b2f |
288 | // Solve on the first and last intervals. |
289 | if (mydist1 > Precision::SquareConfusion() && !Precision::IsPositiveInfinite(mydist1)) |
290 | { |
291 | ThePoint aP1, aP2; |
292 | TheVector aV1, aV2; |
293 | TheCurveTool::D1(aCurve, aParam.Value(aParam.Lower()), aP1, aV1); |
294 | TheCurveTool::D1(aCurve, aParam.Value(aParam.Lower() + 1), aP2, aV2); |
295 | TheVector aBase1(P, aP1), aBase2(P, aP2); |
296 | Standard_Real aVal1 = aV1.Dot(aBase1); // Derivative of (C(u) - P)^2 |
297 | Standard_Real aVal2 = aV2.Dot(aBase2); // Derivative of (C(u) - P)^2 |
298 | if (!(Precision::IsInfinite(aVal1) || Precision::IsInfinite(aVal2))) |
299 | { |
300 | // Derivatives have opposite signs - min or max inside of interval (sufficient condition). |
301 | // Necessary condition - when point lies on curve. |
302 | // Necessary condition - when derivative of point is too small. |
303 | if (aVal1 * aVal2 <= 0.0 || |
304 | aBase1.Dot(aBase2) <= 0.0 || |
305 | 2.0 * Abs(aVal1) < Precision::Confusion()) |
306 | { |
307 | myintuinf = aParam(aVal.Lower()); |
308 | myintusup = aParam(aVal.Lower() + 1); |
309 | IntervalPerform(P); |
310 | } |
311 | } |
312 | } |
c8bf1eb7 |
313 | |
d8406b2f |
314 | if (mydist2 > Precision::SquareConfusion() && !Precision::IsPositiveInfinite(mydist2)) |
c8bf1eb7 |
315 | { |
d8406b2f |
316 | ThePoint aP1, aP2; |
317 | TheVector aV1, aV2; |
318 | TheCurveTool::D1(aCurve, aParam.Value(aParam.Upper() - 1), aP1, aV1); |
319 | TheCurveTool::D1(aCurve, aParam.Value(aParam.Upper()), aP2, aV2); |
320 | TheVector aBase1(P, aP1), aBase2(P, aP2); |
321 | Standard_Real aVal1 = aV1.Dot(aBase1); // Derivative of (C(u) - P)^2 |
322 | Standard_Real aVal2 = aV2.Dot(aBase2); // Derivative of (C(u) - P)^2 |
323 | |
324 | if (!(Precision::IsInfinite(aVal1) || Precision::IsInfinite(aVal2))) |
f4dee9bb |
325 | { |
d8406b2f |
326 | // Derivatives have opposite signs - min or max inside of interval (sufficient condition). |
327 | // Necessary condition - when point lies on curve. |
328 | // Necessary condition - when derivative of point is too small. |
329 | if (aVal1 * aVal2 <= 0.0 || |
330 | aBase1.Dot(aBase2) <= 0.0 || |
331 | 2.0 * Abs(aVal2) < Precision::Confusion()) |
332 | { |
333 | myintuinf = aParam(aVal.Upper() - 1); |
334 | myintusup = aParam(aVal.Upper()); |
335 | IntervalPerform(P); |
336 | } |
f4dee9bb |
337 | } |
c8bf1eb7 |
338 | } |
339 | } |
c8bf1eb7 |
340 | mydone = Standard_True; |
341 | break; |
7fd59977 |
342 | } |
1aec3320 |
343 | default: |
7fd59977 |
344 | { |
f6b08ecf |
345 | const Standard_Integer aMaxSample = 17; |
7fd59977 |
346 | Standard_Boolean IntExtIsDone = Standard_False; |
347 | Standard_Boolean IntIsNotValid; |
f6b08ecf |
348 | Handle(TColStd_HArray1OfReal) theHInter; |
c8bf1eb7 |
349 | n = TheCurveTool::NbIntervals(aCurve, GeomAbs_C2); |
f6b08ecf |
350 | if (n > 1) |
351 | { |
352 | theHInter = new TColStd_HArray1OfReal(1, n + 1); |
353 | TheCurveTool::Intervals(aCurve, theHInter->ChangeArray1(), GeomAbs_C2); |
354 | } |
355 | else |
356 | { |
357 | theHInter = TheCurveTool::DeflCurvIntervals(aCurve); |
358 | n = theHInter->Length() - 1; |
359 | } |
360 | mysample = Max(mysample / n, aMaxSample); |
361 | Standard_Real maxint = 0.; |
362 | for (i = 1; i <= n; ++i) |
363 | { |
364 | Standard_Real dt = theHInter->Value(i + 1) - theHInter->Value(i); |
365 | if (maxint < dt) |
366 | { |
367 | maxint = dt; |
368 | } |
369 | } |
c8bf1eb7 |
370 | Standard_Boolean isPeriodic = TheCurveTool::IsPeriodic(aCurve); |
7fd59977 |
371 | TheVector V1; |
372 | ThePoint PP; |
373 | Standard_Real s1 = 0.0 ; |
c8bf1eb7 |
374 | Standard_Real s2 = 0.0; |
375 | myExtPC.Initialize(aCurve); |
376 | for (i = 1; i <= n; i++) |
377 | { |
f6b08ecf |
378 | myintuinf = theHInter->Value(i); |
379 | myintusup = theHInter->Value(i+1); |
380 | mysample = Max(RealToInt(aMaxSample*(myintusup - myintuinf) / maxint), 3); |
253881cf |
381 | |
382 | Standard_Real anInfToCheck = myintuinf; |
383 | Standard_Real aSupToCheck = myintusup; |
384 | |
385 | if (isPeriodic) { |
c8bf1eb7 |
386 | Standard_Real aPeriod = TheCurveTool::Period(aCurve); |
253881cf |
387 | anInfToCheck = ElCLib::InPeriod(myintuinf, myuinf, myuinf+aPeriod); |
388 | aSupToCheck = myintusup+(anInfToCheck-myintuinf); |
389 | } |
390 | IntIsNotValid = (myuinf > aSupToCheck) || (myusup < anInfToCheck); |
391 | |
392 | if(IntIsNotValid) continue; |
393 | |
394 | if (myuinf >= anInfToCheck) anInfToCheck = myuinf; |
395 | if (myusup <= aSupToCheck) aSupToCheck = myusup; |
396 | if((aSupToCheck - anInfToCheck) <= mytolu) continue; |
32ca7a51 |
397 | |
398 | if (i != 1) |
399 | { |
c8bf1eb7 |
400 | TheCurveTool::D1(aCurve, myintuinf, PP, V1); |
253881cf |
401 | s1 = (TheVector(P, PP))*V1; |
402 | if (s1*s2 < 0.0) { |
403 | mySqDist.Append(PP.SquareDistance(P)); |
404 | myismin.Append((s1 < 0.0)); |
405 | mypoint.Append(ThePOnC(myintuinf, PP)); |
406 | } |
407 | } |
408 | if (i != n) { |
c8bf1eb7 |
409 | TheCurveTool::D1(aCurve, myintusup, PP, V1); |
253881cf |
410 | s2 = (TheVector(P, PP))*V1; |
411 | } |
32ca7a51 |
412 | |
253881cf |
413 | IntervalPerform(P); |
414 | IntExtIsDone = IntExtIsDone || mydone; |
7fd59977 |
415 | } |
c8bf1eb7 |
416 | |
7fd59977 |
417 | mydone = IntExtIsDone; |
c8bf1eb7 |
418 | break; |
419 | } |
420 | } |
94f71cad |
421 | |
c8bf1eb7 |
422 | // Postprocessing. |
423 | if (type == GeomAbs_BSplineCurve || |
1aec3320 |
424 | type == GeomAbs_OffsetCurve || |
c8bf1eb7 |
425 | type == GeomAbs_OtherCurve) |
426 | { |
427 | // Additional checking if the point is on the first or last point of the curve |
428 | // and does not added yet. |
429 | if (mydist1 < Precision::SquareConfusion() || |
430 | mydist2 < Precision::SquareConfusion()) |
431 | { |
432 | Standard_Boolean isFirstAdded = Standard_False; |
433 | Standard_Boolean isLastAdded = Standard_False; |
434 | Standard_Integer aNbPoints = mypoint.Length(); |
435 | for (i = 1; i <= aNbPoints; i++) |
94f71cad |
436 | { |
c8bf1eb7 |
437 | U = mypoint.Value(i).Parameter(); |
438 | if (Abs(U - myuinf) < mytolu) |
439 | isFirstAdded = Standard_True; |
440 | else if (Abs(myusup - U) < mytolu) |
441 | isLastAdded = Standard_True; |
442 | } |
443 | if (!isFirstAdded && mydist1 < Precision::SquareConfusion()) |
444 | { |
445 | mySqDist.Prepend(mydist1); |
446 | myismin.Prepend(Standard_True); |
447 | mypoint.Prepend(ThePOnC(myuinf, Pf)); |
448 | } |
449 | if (!isLastAdded && mydist2 < Precision::SquareConfusion()) |
450 | { |
451 | mySqDist.Append(mydist2); |
452 | myismin.Append(Standard_True); |
453 | mypoint.Append(ThePOnC(myusup, Pl)); |
454 | } |
455 | mydone = Standard_True; |
456 | } |
457 | } |
458 | else |
459 | { |
460 | // In analytical case |
461 | mydone = myExtPElC.IsDone(); |
462 | if (mydone) |
463 | { |
464 | NbExt = myExtPElC.NbExt(); |
465 | for (i = 1; i <= NbExt; i++) |
466 | { |
467 | // Verification de la validite des parametres: |
468 | ThePOnC PC = myExtPElC.Point(i); |
469 | U = PC.Parameter(); |
470 | if (TheCurveTool::IsPeriodic(aCurve)) |
94f71cad |
471 | { |
c8bf1eb7 |
472 | U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(aCurve)); |
94f71cad |
473 | } |
c8bf1eb7 |
474 | if ((U >= myuinf-mytolu) && (U <= myusup+mytolu)) |
94f71cad |
475 | { |
c8bf1eb7 |
476 | PC.SetValues(U, myExtPElC.Point(i).Value()); |
477 | mySqDist.Append(myExtPElC.SquareDistance(i)); |
478 | myismin.Append(myExtPElC.IsMin(i)); |
479 | mypoint.Append(PC); |
94f71cad |
480 | } |
481 | } |
7fd59977 |
482 | } |
483 | } |
7fd59977 |
484 | } |
485 | |
486 | |
487 | //======================================================================= |
488 | //function : Initialize |
489 | //purpose : |
490 | //======================================================================= |
491 | |
492 | void Extrema_GExtPC::Initialize(const TheCurve& C, |
493 | const Standard_Real Uinf, |
494 | const Standard_Real Usup, |
495 | const Standard_Real TolF) |
496 | { |
497 | myC = (Standard_Address)&C; |
498 | myintuinf = myuinf = Uinf; |
499 | myintusup = myusup = Usup; |
500 | mytolf = TolF; |
501 | mytolu = TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion()); |
502 | type = TheCurveTool::GetType(C); |
503 | mydone = Standard_False; |
504 | mydist1 = RealLast(); |
505 | mydist2 = RealLast(); |
506 | mysample = 17; |
507 | } |
508 | |
509 | |
510 | //======================================================================= |
511 | //function : IntervalPerform |
512 | //purpose : |
513 | //======================================================================= |
514 | |
515 | void Extrema_GExtPC::IntervalPerform(const ThePoint& P) |
516 | { |
517 | Standard_Integer i; |
518 | Standard_Real U; |
c8bf1eb7 |
519 | myExtPC.Initialize(mysample, myintuinf, myintusup, mytolu, mytolf); |
7fd59977 |
520 | myExtPC.Perform(P); |
521 | mydone = myExtPC.IsDone(); |
c8bf1eb7 |
522 | if (mydone) |
523 | { |
7fd59977 |
524 | Standard_Integer NbExt = myExtPC.NbExt(); |
c8bf1eb7 |
525 | for (i = 1; i <= NbExt; i++) |
526 | { |
7fd59977 |
527 | // Verification de la validite des parametres pour le cas trimme: |
528 | ThePOnC PC = myExtPC.Point(i); |
529 | U = PC.Parameter(); |
c8bf1eb7 |
530 | if (TheCurveTool::IsPeriodic(*((TheCurve*)myC))) |
531 | { |
253881cf |
532 | U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(*((TheCurve*)myC))); |
7fd59977 |
533 | } |
c8bf1eb7 |
534 | if ((U >= myuinf - mytolu) && (U <= myusup + mytolu)) |
535 | { |
1dbdf099 |
536 | AddSol(U, PC.Value(), |
537 | myExtPC.SquareDistance(i), |
538 | myExtPC.IsMin(i)); |
7fd59977 |
539 | } |
540 | } |
541 | } |
542 | } |
543 | |
544 | |
1dbdf099 |
545 | //======================================================================= |
546 | //function : AddSol |
547 | //purpose : |
548 | //======================================================================= |
549 | |
550 | void Extrema_GExtPC::AddSol(const Standard_Real theU, const ThePoint& theP, |
551 | const Standard_Real theSqDist, |
552 | const Standard_Boolean isMin) |
553 | { |
554 | Standard_Integer i, NbExt = mypoint.Length(); |
555 | for (i = 1; i <= NbExt; i++) |
556 | { |
557 | Standard_Real t = mypoint.Value(i).Parameter(); |
558 | if (Abs(t - theU) <= mytolu) |
559 | { |
560 | return; |
561 | } |
562 | } |
563 | ThePOnC PC(theU, theP); |
564 | mySqDist.Append(theSqDist); |
565 | myismin.Append(isMin); |
566 | mypoint.Append(PC); |
567 | |
568 | } |
7fd59977 |
569 | |
570 | |
571 | //======================================================================= |
572 | //function : Extrema_GExtPC |
573 | //purpose : |
574 | //======================================================================= |
575 | |
576 | Extrema_GExtPC::Extrema_GExtPC() |
577 | { |
578 | myC = 0; |
579 | mydone = Standard_False; |
580 | mydist1 = RealLast(); |
581 | mydist2 = RealLast(); |
582 | mytolu = 0.0; |
583 | mytolf = 0.0; |
584 | mysample = 17; |
585 | myintuinf = myintusup = myuinf = myusup = Precision::Infinite(); |
586 | type = GeomAbs_OtherCurve; |
587 | } |
588 | |
589 | //======================================================================= |
590 | //function : Extrema_GExtPC |
591 | //purpose : |
592 | //======================================================================= |
593 | |
594 | Extrema_GExtPC::Extrema_GExtPC(const ThePoint& P, |
595 | const TheCurve& C, |
596 | const Standard_Real Uinf, |
597 | const Standard_Real Usup, |
598 | const Standard_Real TolF) |
599 | { |
600 | Initialize(C, Uinf, Usup, TolF); |
601 | Perform(P); |
602 | } |
603 | |
604 | //======================================================================= |
605 | //function : Extrema_GExtPC |
606 | //purpose : |
607 | //======================================================================= |
608 | |
609 | Extrema_GExtPC::Extrema_GExtPC(const ThePoint& P, |
610 | const TheCurve& C, |
611 | const Standard_Real TolF) |
612 | { |
613 | Initialize(C, TheCurveTool::FirstParameter(C), |
614 | TheCurveTool::LastParameter(C), TolF); |
615 | Perform(P); |
616 | } |
617 | |
618 | |
619 | //======================================================================= |
620 | //function : IsDone |
621 | //purpose : |
622 | //======================================================================= |
623 | |
624 | Standard_Boolean Extrema_GExtPC::IsDone() const |
625 | { |
626 | return mydone; |
627 | } |
628 | |
629 | |
630 | //======================================================================= |
631 | //function : Value |
632 | //purpose : |
633 | //======================================================================= |
634 | |
635 | Standard_Real Extrema_GExtPC::SquareDistance(const Standard_Integer N) const |
636 | { |
638ad7f3 |
637 | if ((N < 1) || (N > NbExt())) throw Standard_OutOfRange(); |
7fd59977 |
638 | return mySqDist.Value(N); |
639 | } |
640 | |
641 | |
642 | //======================================================================= |
643 | //function : NbExt |
644 | //purpose : |
645 | //======================================================================= |
646 | |
647 | Standard_Integer Extrema_GExtPC::NbExt() const |
648 | { |
638ad7f3 |
649 | if (!IsDone()) throw StdFail_NotDone(); |
7fd59977 |
650 | return mySqDist.Length(); |
651 | } |
652 | |
653 | |
654 | //======================================================================= |
655 | //function : IsMin |
656 | //purpose : |
657 | //======================================================================= |
658 | |
659 | Standard_Boolean Extrema_GExtPC::IsMin(const Standard_Integer N) const |
660 | { |
638ad7f3 |
661 | if ((N < 1) || (N > NbExt())) throw Standard_OutOfRange(); |
7fd59977 |
662 | return myismin.Value(N); |
663 | } |
664 | |
665 | |
666 | |
667 | //======================================================================= |
668 | //function : Point |
669 | //purpose : |
670 | //======================================================================= |
671 | |
5d99f2c8 |
672 | const ThePOnC & Extrema_GExtPC::Point(const Standard_Integer N) const |
7fd59977 |
673 | { |
638ad7f3 |
674 | if ((N < 1) || (N > NbExt())) throw Standard_OutOfRange(); |
7fd59977 |
675 | return mypoint.Value(N); |
676 | } |
677 | |
678 | |
679 | //======================================================================= |
680 | //function : TrimmedDistances |
681 | //purpose : |
682 | //======================================================================= |
683 | |
684 | void Extrema_GExtPC::TrimmedSquareDistances(Standard_Real& dist1, |
685 | Standard_Real& dist2, |
686 | ThePoint& P1, |
687 | ThePoint& P2) const |
688 | { |
689 | dist1 = mydist1; |
690 | dist2 = mydist2; |
691 | P1 = Pf; |
692 | P2 = Pl; |
693 | } |