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)); |
7fd59977 |
108 | TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2); |
109 | mysample = Max(mysample/n, 17); |
110 | TheVector V1; |
111 | ThePoint PP; |
112 | Standard_Real s1 = 0.0 ; |
113 | Standard_Real s2 = 0.0; |
114 | for (i = 1; i <= n; i++) { |
253881cf |
115 | myintuinf = theInter(i); |
116 | myintusup = theInter(i+1); |
117 | |
118 | Standard_Real anInfToCheck = myintuinf; |
119 | Standard_Real aSupToCheck = myintusup; |
120 | |
121 | if (isPeriodic) { |
122 | Standard_Real aPeriod = TheCurveTool::Period(*((TheCurve*)myC)); |
123 | anInfToCheck = ElCLib::InPeriod(myintuinf, myuinf, myuinf+aPeriod); |
124 | aSupToCheck = myintusup+(anInfToCheck-myintuinf); |
125 | } |
126 | IntIsNotValid = (myuinf > aSupToCheck) || (myusup < anInfToCheck); |
127 | |
128 | if(IntIsNotValid) continue; |
129 | |
130 | if (myuinf >= anInfToCheck) anInfToCheck = myuinf; |
131 | if (myusup <= aSupToCheck) aSupToCheck = myusup; |
132 | if((aSupToCheck - anInfToCheck) <= mytolu) continue; |
32ca7a51 |
133 | |
134 | if (i != 1) |
135 | { |
253881cf |
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 | } |
32ca7a51 |
148 | |
253881cf |
149 | IntervalPerform(P); |
150 | IntExtIsDone = IntExtIsDone || mydone; |
7fd59977 |
151 | } |
152 | mydone = IntExtIsDone; |
153 | return; |
154 | } |
155 | } |
156 | |
157 | |
158 | mydone = myExtPElC.IsDone(); |
159 | if (mydone) { |
160 | NbExt = myExtPElC.NbExt(); |
161 | for (i = 1; i <= NbExt; i++) { |
162 | // Verification de la validite des parametres: |
163 | ThePOnC PC = myExtPElC.Point(i); |
164 | U = PC.Parameter(); |
165 | if (TheCurveTool::IsPeriodic(*((TheCurve*)myC))) { |
253881cf |
166 | U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(*((TheCurve*)myC))); |
7fd59977 |
167 | } |
168 | if ((U >= myuinf-mytolu) && (U <= myusup+mytolu)){ |
253881cf |
169 | PC.SetValues(U, myExtPElC.Point(i).Value()); |
170 | mySqDist.Append(myExtPElC.SquareDistance(i)); |
171 | myismin.Append(myExtPElC.IsMin(i)); |
172 | mypoint.Append(PC); |
7fd59977 |
173 | } |
174 | } |
253881cf |
175 | } |
7fd59977 |
176 | } |
177 | |
178 | |
179 | //======================================================================= |
180 | //function : Initialize |
181 | //purpose : |
182 | //======================================================================= |
183 | |
184 | void Extrema_GExtPC::Initialize(const TheCurve& C, |
185 | const Standard_Real Uinf, |
186 | const Standard_Real Usup, |
187 | const Standard_Real TolF) |
188 | { |
189 | myC = (Standard_Address)&C; |
190 | myintuinf = myuinf = Uinf; |
191 | myintusup = myusup = Usup; |
192 | mytolf = TolF; |
193 | mytolu = TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion()); |
194 | type = TheCurveTool::GetType(C); |
195 | mydone = Standard_False; |
196 | mydist1 = RealLast(); |
197 | mydist2 = RealLast(); |
198 | mysample = 17; |
199 | } |
200 | |
201 | |
202 | //======================================================================= |
203 | //function : IntervalPerform |
204 | //purpose : |
205 | //======================================================================= |
206 | |
207 | void Extrema_GExtPC::IntervalPerform(const ThePoint& P) |
208 | { |
209 | Standard_Integer i; |
210 | Standard_Real U; |
211 | myExtPC.Initialize((*((TheCurve*)myC)), mysample, |
212 | myintuinf, myintusup, mytolu, mytolf); |
213 | myExtPC.Perform(P); |
214 | mydone = myExtPC.IsDone(); |
215 | if (mydone) { |
216 | Standard_Integer NbExt = myExtPC.NbExt(); |
217 | for (i = 1; i <= NbExt; i++) { |
218 | // Verification de la validite des parametres pour le cas trimme: |
219 | ThePOnC PC = myExtPC.Point(i); |
220 | U = PC.Parameter(); |
221 | if (TheCurveTool::IsPeriodic(*((TheCurve*)myC))) { |
253881cf |
222 | U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(*((TheCurve*)myC))); |
7fd59977 |
223 | } |
224 | if ((U >= myuinf - mytolu) && (U <= myusup + mytolu)) { |
253881cf |
225 | PC.SetValues(U, PC.Value()); |
226 | mySqDist.Append(myExtPC.SquareDistance(i)); |
227 | myismin.Append(myExtPC.IsMin(i)); |
228 | mypoint.Append(PC); |
7fd59977 |
229 | } |
230 | } |
231 | } |
232 | } |
233 | |
234 | |
235 | |
236 | |
237 | //======================================================================= |
238 | //function : Extrema_GExtPC |
239 | //purpose : |
240 | //======================================================================= |
241 | |
242 | Extrema_GExtPC::Extrema_GExtPC() |
243 | { |
244 | myC = 0; |
245 | mydone = Standard_False; |
246 | mydist1 = RealLast(); |
247 | mydist2 = RealLast(); |
248 | mytolu = 0.0; |
249 | mytolf = 0.0; |
250 | mysample = 17; |
251 | myintuinf = myintusup = myuinf = myusup = Precision::Infinite(); |
252 | type = GeomAbs_OtherCurve; |
253 | } |
254 | |
255 | //======================================================================= |
256 | //function : Extrema_GExtPC |
257 | //purpose : |
258 | //======================================================================= |
259 | |
260 | Extrema_GExtPC::Extrema_GExtPC(const ThePoint& P, |
261 | const TheCurve& C, |
262 | const Standard_Real Uinf, |
263 | const Standard_Real Usup, |
264 | const Standard_Real TolF) |
265 | { |
266 | Initialize(C, Uinf, Usup, TolF); |
267 | Perform(P); |
268 | } |
269 | |
270 | //======================================================================= |
271 | //function : Extrema_GExtPC |
272 | //purpose : |
273 | //======================================================================= |
274 | |
275 | Extrema_GExtPC::Extrema_GExtPC(const ThePoint& P, |
276 | const TheCurve& C, |
277 | const Standard_Real TolF) |
278 | { |
279 | Initialize(C, TheCurveTool::FirstParameter(C), |
280 | TheCurveTool::LastParameter(C), TolF); |
281 | Perform(P); |
282 | } |
283 | |
284 | |
285 | //======================================================================= |
286 | //function : IsDone |
287 | //purpose : |
288 | //======================================================================= |
289 | |
290 | Standard_Boolean Extrema_GExtPC::IsDone() const |
291 | { |
292 | return mydone; |
293 | } |
294 | |
295 | |
296 | //======================================================================= |
297 | //function : Value |
298 | //purpose : |
299 | //======================================================================= |
300 | |
301 | Standard_Real Extrema_GExtPC::SquareDistance(const Standard_Integer N) const |
302 | { |
303 | if(!mydone) StdFail_NotDone::Raise(); |
304 | if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise(); |
305 | return mySqDist.Value(N); |
306 | } |
307 | |
308 | |
309 | //======================================================================= |
310 | //function : NbExt |
311 | //purpose : |
312 | //======================================================================= |
313 | |
314 | Standard_Integer Extrema_GExtPC::NbExt() const |
315 | { |
316 | if(!mydone) StdFail_NotDone::Raise(); |
317 | return mySqDist.Length(); |
318 | } |
319 | |
320 | |
321 | //======================================================================= |
322 | //function : IsMin |
323 | //purpose : |
324 | //======================================================================= |
325 | |
326 | Standard_Boolean Extrema_GExtPC::IsMin(const Standard_Integer N) const |
327 | { |
328 | if(!mydone) StdFail_NotDone::Raise(); |
329 | if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise(); |
330 | return myismin.Value(N); |
331 | } |
332 | |
333 | |
334 | |
335 | //======================================================================= |
336 | //function : Point |
337 | //purpose : |
338 | //======================================================================= |
339 | |
340 | ThePOnC Extrema_GExtPC::Point(const Standard_Integer N) const |
341 | { |
342 | if(!mydone) StdFail_NotDone::Raise(); |
343 | if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise(); |
344 | return mypoint.Value(N); |
345 | } |
346 | |
347 | |
348 | //======================================================================= |
349 | //function : TrimmedDistances |
350 | //purpose : |
351 | //======================================================================= |
352 | |
353 | void Extrema_GExtPC::TrimmedSquareDistances(Standard_Real& dist1, |
354 | Standard_Real& dist2, |
355 | ThePoint& P1, |
356 | ThePoint& P2) const |
357 | { |
358 | dist1 = mydist1; |
359 | dist2 = mydist2; |
360 | P1 = Pf; |
361 | P2 = Pl; |
362 | } |
363 | |