b311480e |
1 | // Created on: 1992-10-19 |
2 | // Created by: Laurent PAINNOT |
3 | // Copyright (c) 1992-1999 Matra Datavision |
4 | // Copyright (c) 1999-2012 OPEN CASCADE SAS |
5 | // |
6 | // The content of this file is subject to the Open CASCADE Technology Public |
7 | // License Version 6.5 (the "License"). You may not use the content of this file |
8 | // except in compliance with the License. Please obtain a copy of the License |
9 | // at http://www.opencascade.org and read it completely before using this file. |
10 | // |
11 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
12 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
13 | // |
14 | // The Original Code and all software distributed under the License is |
15 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
16 | // Initial Developer hereby disclaims all such warranties, including without |
17 | // limitation, any warranties of merchantability, fitness for a particular |
18 | // purpose or non-infringement. Please see the License for the specific terms |
19 | // and conditions governing the rights and limitations under the License. |
20 | |
7fd59977 |
21 | // Modified by cma, Fri Dec 10 18:11:56 1993 |
7fd59977 |
22 | |
23 | #include Extrema_EPC_hxx |
24 | #include ThePOnC_hxx |
25 | #include TheSequenceOfPOnC_hxx |
26 | #include ThePoint_hxx |
27 | #include TheVector_hxx |
28 | #include TheExtPElC_hxx |
29 | #include <StdFail_NotDone.hxx> |
30 | #include <Standard_Failure.hxx> |
31 | #include <GeomAbs_CurveType.hxx> |
32 | #include <Precision.hxx> |
33 | #include <ElCLib.hxx> |
34 | #include <TColStd_Array1OfReal.hxx> |
35 | |
36 | |
37 | //======================================================================= |
38 | //function : Perform |
39 | //purpose : |
40 | //======================================================================= |
41 | |
42 | void Extrema_GExtPC::Perform(const ThePoint& P) |
43 | { |
44 | mySqDist.Clear(); |
45 | mypoint.Clear(); |
46 | myismin.Clear(); |
47 | Standard_Integer i, NbExt, n; |
48 | Standard_Real U; |
49 | mysample = 17; |
50 | Standard_Real t3d = Precision::Confusion(); |
51 | if (Precision::IsInfinite(myuinf)) mydist1 = RealLast(); |
52 | else { |
53 | Pf = TheCurveTool::Value(*((TheCurve*)myC), myuinf); |
54 | mydist1 = P.SquareDistance(Pf); |
55 | } |
56 | |
57 | if (Precision::IsInfinite(myusup)) mydist2 = RealLast(); |
58 | else { |
59 | Pl = TheCurveTool::Value(*((TheCurve*)myC), myusup); |
60 | mydist2 = P.SquareDistance(Pl); |
61 | } |
62 | |
63 | switch(type) { |
64 | case GeomAbs_Circle: |
65 | { |
66 | myExtPElC.Perform(P, TheCurveTool::Circle(*((TheCurve*)myC)), t3d, myuinf, myusup); |
67 | } |
68 | break; |
69 | case GeomAbs_Ellipse: |
70 | { |
71 | myExtPElC.Perform(P, TheCurveTool::Ellipse(*((TheCurve*)myC)), t3d, myuinf, myusup); |
72 | } |
73 | break; |
74 | case GeomAbs_Parabola: |
75 | { |
76 | myExtPElC.Perform(P, TheCurveTool::Parabola(*((TheCurve*)myC)), t3d,myuinf,myusup); |
77 | } |
78 | break; |
79 | case GeomAbs_Hyperbola: |
80 | { |
81 | myExtPElC.Perform(P,TheCurveTool::Hyperbola(*((TheCurve*)myC)),t3d, myuinf, myusup); |
82 | } |
83 | break; |
84 | case GeomAbs_Line: |
85 | { |
86 | myExtPElC.Perform(P, TheCurveTool::Line(*((TheCurve*)myC)), t3d, myuinf, myusup); |
87 | } |
88 | break; |
89 | case GeomAbs_BezierCurve: |
90 | { |
91 | myintuinf = myuinf; |
92 | myintusup = myusup; |
93 | mysample = (TheCurveTool::Bezier(*((TheCurve*)myC)))->NbPoles()*2; |
94 | IntervalPerform(P); |
95 | return; |
96 | } |
97 | case GeomAbs_BSplineCurve: |
98 | { |
99 | mysample = (TheCurveTool::BSpline(*((TheCurve*)myC)))->NbPoles()*2; |
100 | } |
101 | case GeomAbs_OtherCurve: |
102 | { |
103 | Standard_Boolean IntExtIsDone = Standard_False; |
104 | Standard_Boolean IntIsNotValid; |
105 | n = TheCurveTool::NbIntervals(*((TheCurve*)myC), GeomAbs_C2); |
106 | TColStd_Array1OfReal theInter(1, n+1); |
253881cf |
107 | Standard_Boolean isPeriodic = TheCurveTool::IsPeriodic(*((TheCurve*)myC)); |
108 | Standard_Real aPeriodicShift = 0.; |
7fd59977 |
109 | TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2); |
110 | mysample = Max(mysample/n, 17); |
111 | TheVector V1; |
112 | ThePoint PP; |
113 | Standard_Real s1 = 0.0 ; |
114 | Standard_Real s2 = 0.0; |
115 | for (i = 1; i <= n; i++) { |
253881cf |
116 | myintuinf = theInter(i); |
117 | myintusup = theInter(i+1); |
118 | |
119 | Standard_Real anInfToCheck = myintuinf; |
120 | Standard_Real aSupToCheck = myintusup; |
121 | |
122 | if (isPeriodic) { |
123 | Standard_Real aPeriod = TheCurveTool::Period(*((TheCurve*)myC)); |
124 | anInfToCheck = ElCLib::InPeriod(myintuinf, myuinf, myuinf+aPeriod); |
125 | aSupToCheck = myintusup+(anInfToCheck-myintuinf); |
126 | } |
127 | IntIsNotValid = (myuinf > aSupToCheck) || (myusup < anInfToCheck); |
128 | |
129 | if(IntIsNotValid) continue; |
130 | |
131 | if (myuinf >= anInfToCheck) anInfToCheck = myuinf; |
132 | if (myusup <= aSupToCheck) aSupToCheck = myusup; |
133 | if((aSupToCheck - anInfToCheck) <= mytolu) continue; |
134 | |
135 | if (i != 1) { |
136 | TheCurveTool::D1(*((TheCurve*)myC), myintuinf, PP, V1); |
137 | s1 = (TheVector(P, PP))*V1; |
138 | if (s1*s2 < 0.0) { |
139 | mySqDist.Append(PP.SquareDistance(P)); |
140 | myismin.Append((s1 < 0.0)); |
141 | mypoint.Append(ThePOnC(myintuinf, PP)); |
142 | } |
143 | } |
144 | if (i != n) { |
145 | TheCurveTool::D1(*((TheCurve*)myC), myintusup, PP, V1); |
146 | s2 = (TheVector(P, PP))*V1; |
147 | } |
148 | IntervalPerform(P); |
149 | IntExtIsDone = IntExtIsDone || mydone; |
7fd59977 |
150 | } |
151 | mydone = IntExtIsDone; |
152 | return; |
153 | } |
154 | } |
155 | |
156 | |
157 | mydone = myExtPElC.IsDone(); |
158 | if (mydone) { |
159 | NbExt = myExtPElC.NbExt(); |
160 | for (i = 1; i <= NbExt; i++) { |
161 | // Verification de la validite des parametres: |
162 | ThePOnC PC = myExtPElC.Point(i); |
163 | U = PC.Parameter(); |
164 | if (TheCurveTool::IsPeriodic(*((TheCurve*)myC))) { |
253881cf |
165 | U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(*((TheCurve*)myC))); |
7fd59977 |
166 | } |
167 | if ((U >= myuinf-mytolu) && (U <= myusup+mytolu)){ |
253881cf |
168 | PC.SetValues(U, myExtPElC.Point(i).Value()); |
169 | mySqDist.Append(myExtPElC.SquareDistance(i)); |
170 | myismin.Append(myExtPElC.IsMin(i)); |
171 | mypoint.Append(PC); |
7fd59977 |
172 | } |
173 | } |
253881cf |
174 | } |
7fd59977 |
175 | } |
176 | |
177 | |
178 | //======================================================================= |
179 | //function : Initialize |
180 | //purpose : |
181 | //======================================================================= |
182 | |
183 | void Extrema_GExtPC::Initialize(const TheCurve& C, |
184 | const Standard_Real Uinf, |
185 | const Standard_Real Usup, |
186 | const Standard_Real TolF) |
187 | { |
188 | myC = (Standard_Address)&C; |
189 | myintuinf = myuinf = Uinf; |
190 | myintusup = myusup = Usup; |
191 | mytolf = TolF; |
192 | mytolu = TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion()); |
193 | type = TheCurveTool::GetType(C); |
194 | mydone = Standard_False; |
195 | mydist1 = RealLast(); |
196 | mydist2 = RealLast(); |
197 | mysample = 17; |
198 | } |
199 | |
200 | |
201 | //======================================================================= |
202 | //function : IntervalPerform |
203 | //purpose : |
204 | //======================================================================= |
205 | |
206 | void Extrema_GExtPC::IntervalPerform(const ThePoint& P) |
207 | { |
208 | Standard_Integer i; |
209 | Standard_Real U; |
210 | myExtPC.Initialize((*((TheCurve*)myC)), mysample, |
211 | myintuinf, myintusup, mytolu, mytolf); |
212 | myExtPC.Perform(P); |
213 | mydone = myExtPC.IsDone(); |
214 | if (mydone) { |
215 | Standard_Integer NbExt = myExtPC.NbExt(); |
216 | for (i = 1; i <= NbExt; i++) { |
217 | // Verification de la validite des parametres pour le cas trimme: |
218 | ThePOnC PC = myExtPC.Point(i); |
219 | U = PC.Parameter(); |
220 | if (TheCurveTool::IsPeriodic(*((TheCurve*)myC))) { |
253881cf |
221 | U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(*((TheCurve*)myC))); |
7fd59977 |
222 | } |
223 | if ((U >= myuinf - mytolu) && (U <= myusup + mytolu)) { |
253881cf |
224 | PC.SetValues(U, PC.Value()); |
225 | mySqDist.Append(myExtPC.SquareDistance(i)); |
226 | myismin.Append(myExtPC.IsMin(i)); |
227 | mypoint.Append(PC); |
7fd59977 |
228 | } |
229 | } |
230 | } |
231 | } |
232 | |
233 | |
234 | |
235 | |
236 | //======================================================================= |
237 | //function : Extrema_GExtPC |
238 | //purpose : |
239 | //======================================================================= |
240 | |
241 | Extrema_GExtPC::Extrema_GExtPC() |
242 | { |
243 | myC = 0; |
244 | mydone = Standard_False; |
245 | mydist1 = RealLast(); |
246 | mydist2 = RealLast(); |
247 | mytolu = 0.0; |
248 | mytolf = 0.0; |
249 | mysample = 17; |
250 | myintuinf = myintusup = myuinf = myusup = Precision::Infinite(); |
251 | type = GeomAbs_OtherCurve; |
252 | } |
253 | |
254 | //======================================================================= |
255 | //function : Extrema_GExtPC |
256 | //purpose : |
257 | //======================================================================= |
258 | |
259 | Extrema_GExtPC::Extrema_GExtPC(const ThePoint& P, |
260 | const TheCurve& C, |
261 | const Standard_Real Uinf, |
262 | const Standard_Real Usup, |
263 | const Standard_Real TolF) |
264 | { |
265 | Initialize(C, Uinf, Usup, TolF); |
266 | Perform(P); |
267 | } |
268 | |
269 | //======================================================================= |
270 | //function : Extrema_GExtPC |
271 | //purpose : |
272 | //======================================================================= |
273 | |
274 | Extrema_GExtPC::Extrema_GExtPC(const ThePoint& P, |
275 | const TheCurve& C, |
276 | const Standard_Real TolF) |
277 | { |
278 | Initialize(C, TheCurveTool::FirstParameter(C), |
279 | TheCurveTool::LastParameter(C), TolF); |
280 | Perform(P); |
281 | } |
282 | |
283 | |
284 | //======================================================================= |
285 | //function : IsDone |
286 | //purpose : |
287 | //======================================================================= |
288 | |
289 | Standard_Boolean Extrema_GExtPC::IsDone() const |
290 | { |
291 | return mydone; |
292 | } |
293 | |
294 | |
295 | //======================================================================= |
296 | //function : Value |
297 | //purpose : |
298 | //======================================================================= |
299 | |
300 | Standard_Real Extrema_GExtPC::SquareDistance(const Standard_Integer N) const |
301 | { |
302 | if(!mydone) StdFail_NotDone::Raise(); |
303 | if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise(); |
304 | return mySqDist.Value(N); |
305 | } |
306 | |
307 | |
308 | //======================================================================= |
309 | //function : NbExt |
310 | //purpose : |
311 | //======================================================================= |
312 | |
313 | Standard_Integer Extrema_GExtPC::NbExt() const |
314 | { |
315 | if(!mydone) StdFail_NotDone::Raise(); |
316 | return mySqDist.Length(); |
317 | } |
318 | |
319 | |
320 | //======================================================================= |
321 | //function : IsMin |
322 | //purpose : |
323 | //======================================================================= |
324 | |
325 | Standard_Boolean Extrema_GExtPC::IsMin(const Standard_Integer N) const |
326 | { |
327 | if(!mydone) StdFail_NotDone::Raise(); |
328 | if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise(); |
329 | return myismin.Value(N); |
330 | } |
331 | |
332 | |
333 | |
334 | //======================================================================= |
335 | //function : Point |
336 | //purpose : |
337 | //======================================================================= |
338 | |
339 | ThePOnC Extrema_GExtPC::Point(const Standard_Integer N) const |
340 | { |
341 | if(!mydone) StdFail_NotDone::Raise(); |
342 | if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise(); |
343 | return mypoint.Value(N); |
344 | } |
345 | |
346 | |
347 | //======================================================================= |
348 | //function : TrimmedDistances |
349 | //purpose : |
350 | //======================================================================= |
351 | |
352 | void Extrema_GExtPC::TrimmedSquareDistances(Standard_Real& dist1, |
353 | Standard_Real& dist2, |
354 | ThePoint& P1, |
355 | ThePoint& P2) const |
356 | { |
357 | dist1 = mydist1; |
358 | dist2 = mydist2; |
359 | P1 = Pf; |
360 | P2 = Pl; |
361 | } |
362 | |