b311480e |
1 | // Created on: 1995-05-05 |
2 | // Created by: Modelistation |
3 | // Copyright (c) 1995-1999 Matra Datavision |
4 | // Copyright (c) 1999-2012 OPEN CASCADE SAS |
7fd59977 |
5 | // |
b311480e |
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. |
7fd59977 |
13 | // |
b311480e |
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 | |
21 | |
22 | // Dimension independant used to implement GCPnts_AbscissaPoint |
7fd59977 |
23 | |
24 | // compute the type |
25 | // and the length ratio if GCPnts_LengthParametrized |
26 | #include <GCPnts_AbscissaType.hxx> |
27 | #include <gp_Vec.hxx> |
28 | #include <gp_Vec2d.hxx> |
29 | #include <gp_Circ.hxx> |
30 | #include <gp_Circ2d.hxx> |
31 | #include <Precision.hxx> |
32 | #include <TColStd_Array1OfReal.hxx> |
33 | #include <BSplCLib.hxx> |
34 | |
35 | static GCPnts_AbscissaType computeType( TheCurve& C, |
36 | Standard_Real& Ratio) |
37 | { |
38 | GCPnts_AbscissaType LocalType ; |
39 | |
40 | if (C.NbIntervals(GeomAbs_CN) > 1) |
41 | return GCPnts_AbsComposite; |
42 | |
43 | switch (C.GetType()) { |
44 | |
45 | case GeomAbs_Line: |
46 | Ratio = 1.0e0 ; |
47 | return GCPnts_LengthParametrized; |
48 | |
49 | case GeomAbs_Circle: |
50 | Ratio = C.Circle().Radius(); |
51 | return GCPnts_LengthParametrized; |
52 | |
53 | case GeomAbs_BezierCurve: |
54 | { |
55 | Handle_TheBezierCurve Bz = C.Bezier(); |
56 | if ((Bz->NbPoles() == 2) && !(Bz->IsRational())) { |
57 | Ratio = Bz->DN(0,1).Magnitude(); |
58 | LocalType = GCPnts_LengthParametrized; |
59 | } |
60 | else |
61 | LocalType = GCPnts_Parametrized; |
62 | return LocalType ; |
63 | } |
64 | case GeomAbs_BSplineCurve: |
65 | { |
66 | Handle_TheBSplineCurve Bs = C.BSpline(); |
67 | if ((Bs->NbPoles() == 2) && !(Bs->IsRational())) { |
68 | Ratio = Bs->DN(Bs->FirstParameter(),1).Magnitude(); |
69 | LocalType = GCPnts_LengthParametrized; |
70 | } |
71 | else |
72 | LocalType = GCPnts_Parametrized; |
73 | return LocalType ; |
74 | } |
75 | default: |
76 | return GCPnts_Parametrized; |
77 | |
78 | } |
79 | } |
80 | |
81 | // compute a point at distance Abscis from parameter U0 |
82 | // using Ui as initial guess |
83 | |
84 | static void Compute(CPnts_AbscissaPoint& theComputer, |
85 | TheCurve& C, |
86 | Standard_Real& Abscis, |
87 | Standard_Real& U0, |
88 | Standard_Real& Ui, |
89 | const Standard_Real EPSILON) |
90 | { |
91 | // test for easy solution |
92 | if (Abs(Abscis) <= Precision::Confusion()) { |
93 | theComputer.SetParameter(U0); |
94 | return; |
95 | } |
96 | |
97 | Standard_Real Ratio; |
98 | GCPnts_AbscissaType Type = computeType(C,Ratio); |
99 | |
100 | switch (Type) { |
101 | case GCPnts_LengthParametrized : |
102 | theComputer.SetParameter(U0 + Abscis / Ratio); |
103 | return; |
104 | |
105 | case GCPnts_Parametrized : |
106 | theComputer.Init(C); |
107 | theComputer.Perform(Abscis, U0, Ui, EPSILON); |
108 | return; |
109 | |
110 | case GCPnts_AbsComposite : |
111 | { |
112 | Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN); |
113 | TColStd_Array1OfReal TI(1,NbIntervals+1); |
114 | C.Intervals(TI,GeomAbs_CN); |
115 | Standard_Real L = 0.0, sign = 1.; |
116 | Standard_Integer Index = 1; |
117 | BSplCLib::Hunt(TI,U0,Index); |
118 | Standard_Integer Direction = 1; |
119 | if (Abscis < 0) { |
120 | Direction = 0; |
121 | Abscis = -Abscis; |
122 | sign = -1.; |
123 | } |
124 | |
125 | while ((Index >= 1) && (Index <= NbIntervals)) { |
126 | |
127 | L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction)); |
128 | if (Abs(L - Abscis) <= Precision::Confusion()) { |
129 | theComputer.SetParameter(TI(Index+Direction)); |
130 | return; |
131 | } |
132 | if(L > Abscis) { |
133 | if ((Ui < TI(Index)) || (Ui > TI(Index+1))) { |
134 | Ui = (Abscis / L) * (TI(Index+1) - U0); |
135 | if (Direction) |
136 | Ui = U0 + Ui; |
137 | else |
138 | Ui = U0 - Ui; |
139 | } |
140 | theComputer.Init(C,TI(Index),TI(Index+1)); |
141 | theComputer.Perform(sign*Abscis, U0, Ui, EPSILON); |
142 | return; |
143 | } |
144 | else { |
145 | U0 = TI(Index+Direction); |
146 | Abscis -= L; |
147 | } |
148 | if (Direction) |
149 | Index++; |
150 | else |
151 | Index--; |
152 | } |
153 | |
154 | // Push a little bit outside the limits (hairy !!!) |
155 | Ui = U0 + 0.1; |
156 | theComputer.Init(C,U0,U0+0.2); |
157 | theComputer.Perform(sign*Abscis, U0, Ui, EPSILON); |
158 | return; |
159 | } |
160 | break; |
161 | } |
162 | |
163 | } |
164 | |
165 | // introduced by rbv for curvilinear parametrization |
166 | // performs more apropriate tolerance managment |
167 | |
168 | static void AdvCompute(CPnts_AbscissaPoint& theComputer, |
169 | TheCurve& C, |
170 | Standard_Real& Abscis, |
171 | Standard_Real& U0, |
172 | Standard_Real& Ui, |
173 | const Standard_Real EPSILON) |
174 | { |
175 | // test for easy solution |
176 | if (Abs(Abscis) <= EPSILON) { |
177 | theComputer.SetParameter(U0); |
178 | return; |
179 | } |
180 | |
181 | Standard_Real Ratio; |
182 | GCPnts_AbscissaType Type = computeType(C,Ratio); |
183 | |
184 | switch (Type) { |
185 | case GCPnts_LengthParametrized : |
186 | theComputer.SetParameter(U0 + Abscis / Ratio); |
187 | return; |
188 | |
189 | case GCPnts_Parametrized : |
190 | // theComputer.Init(C); |
191 | theComputer.Init(C, EPSILON); //rbv's modification |
192 | // |
193 | theComputer.AdvPerform(Abscis, U0, Ui, EPSILON); |
194 | return; |
195 | |
196 | case GCPnts_AbsComposite : |
197 | { |
198 | Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN); |
199 | TColStd_Array1OfReal TI(1,NbIntervals+1); |
200 | C.Intervals(TI,GeomAbs_CN); |
201 | Standard_Real L = 0.0, sign = 1.; |
202 | Standard_Integer Index = 1; |
203 | BSplCLib::Hunt(TI,U0,Index); |
204 | |
205 | Standard_Integer Direction = 1; |
206 | if (Abscis < 0) { |
207 | Direction = 0; |
208 | Abscis = -Abscis; |
209 | sign = -1.; |
210 | } |
211 | |
212 | if(Index == 0 && Direction > 0) { |
213 | L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction), EPSILON); |
214 | if (Abs(L - Abscis) <= /*Precision::Confusion()*/EPSILON) { |
215 | theComputer.SetParameter(TI(Index+Direction)); |
216 | return; |
217 | } |
218 | if(L > Abscis) { |
219 | if ( Ui > TI(Index+1) ) { |
220 | Ui = (Abscis / L) * (TI(Index+1) - U0); |
221 | Ui = U0 + Ui; |
222 | } |
223 | theComputer.Init(C,U0,TI(Index+1), EPSILON); |
224 | theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON); |
225 | return; |
226 | } |
227 | else { |
228 | U0 = TI(Index+Direction); |
229 | Abscis -= L; |
230 | } |
231 | Index++; |
232 | } |
233 | |
234 | |
235 | while ((Index >= 1) && (Index <= NbIntervals)) { |
236 | |
237 | L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction), EPSILON); |
238 | if (Abs(L - Abscis) <= /*Precision::Confusion()*/EPSILON) { |
239 | theComputer.SetParameter(TI(Index+Direction)); |
240 | return; |
241 | } |
242 | if(L > Abscis) { |
243 | if ((Ui < TI(Index)) || (Ui > TI(Index+1))) { |
244 | Ui = (Abscis / L) * (TI(Index+1) - U0); |
245 | if (Direction) |
246 | Ui = U0 + Ui; |
247 | else |
248 | Ui = U0 - Ui; |
249 | } |
250 | theComputer.Init(C,TI(Index),TI(Index+1), EPSILON); |
251 | theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON); |
252 | return; |
253 | } |
254 | else { |
255 | U0 = TI(Index+Direction); |
256 | Abscis -= L; |
257 | } |
258 | if (Direction) { |
259 | Index++; |
260 | |
261 | } |
262 | else { |
263 | Index--; |
264 | |
265 | } |
266 | } |
267 | |
268 | // Push a little bit outside the limits (hairy !!!) |
269 | |
270 | Standard_Boolean nonperiodic = !C.IsPeriodic(); |
271 | Ui = U0 + sign*0.1; |
272 | Standard_Real U1 = U0 + sign*.2; |
273 | if(nonperiodic) { |
274 | if(sign > 0) { |
275 | Ui = Min(Ui,C.LastParameter()); |
276 | U1 = Min(U1, C.LastParameter()); |
277 | } |
278 | else { |
279 | Ui = Max(Ui,C.FirstParameter()); |
280 | U1 = Max(U1, C.FirstParameter()); |
281 | } |
282 | } |
283 | |
284 | theComputer.Init(C, U0, U1, EPSILON); |
285 | theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON); |
286 | return; |
287 | } |
288 | break; |
289 | } |
290 | |
291 | } |
292 | |
293 | //======================================================================= |
294 | //function : Length |
295 | //purpose : |
296 | //======================================================================= |
297 | |
298 | Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C) |
299 | { |
300 | return GCPnts_AbscissaPoint::Length(C,C.FirstParameter(), |
301 | C.LastParameter()); |
302 | } |
303 | |
304 | //======================================================================= |
305 | //function : Length |
306 | //purpose : |
307 | //======================================================================= |
308 | |
309 | Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C, |
310 | const Standard_Real Tol) |
311 | { |
312 | return GCPnts_AbscissaPoint::Length(C,C.FirstParameter(), |
313 | C.LastParameter(),Tol); |
314 | } |
315 | |
316 | |
317 | //======================================================================= |
318 | //function : Length |
319 | //purpose : |
320 | //======================================================================= |
321 | |
322 | Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C, |
323 | const Standard_Real U1, |
324 | const Standard_Real U2) |
325 | { |
326 | Standard_Real Ratio; |
327 | GCPnts_AbscissaType Type = computeType(C,Ratio); |
328 | switch (Type) { |
329 | |
330 | case GCPnts_LengthParametrized: |
331 | return Abs(U2-U1) * Ratio; |
332 | |
333 | case GCPnts_Parametrized: |
334 | return CPnts_AbscissaPoint::Length(C, U1, U2); |
335 | |
336 | case GCPnts_AbsComposite: |
337 | { |
338 | Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN); |
339 | TColStd_Array1OfReal TI(1,NbIntervals+1); |
340 | C.Intervals(TI,GeomAbs_CN); |
341 | Standard_Real UU1 = Min(U1, U2); |
342 | Standard_Real UU2 = Max(U1, U2); |
343 | Standard_Real L = 0.0; |
344 | for(Standard_Integer Index = 1; Index <= NbIntervals; Index++) { |
345 | if (TI(Index) > UU2) break; |
346 | if (TI(Index+1) < UU1) continue; |
347 | L += CPnts_AbscissaPoint::Length(C, |
348 | Max(TI(Index),UU1), |
349 | Min(TI(Index+1),UU2)); |
350 | } |
351 | return L; |
352 | } |
353 | } |
354 | return RealLast(); |
355 | } |
356 | |
357 | //======================================================================= |
358 | //function : Length |
359 | //purpose : |
360 | //======================================================================= |
361 | |
362 | Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C, |
363 | const Standard_Real U1, |
364 | const Standard_Real U2, |
365 | const Standard_Real Tol) |
366 | { |
367 | Standard_Real Ratio; |
368 | GCPnts_AbscissaType Type = computeType(C,Ratio); |
369 | switch (Type) { |
370 | |
371 | case GCPnts_LengthParametrized: |
372 | return Abs(U2-U1) * Ratio; |
373 | |
374 | case GCPnts_Parametrized: |
375 | return CPnts_AbscissaPoint::Length(C, U1, U2, Tol); |
376 | |
377 | case GCPnts_AbsComposite: |
378 | { |
379 | Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN); |
380 | TColStd_Array1OfReal TI(1,NbIntervals+1); |
381 | C.Intervals(TI,GeomAbs_CN); |
382 | Standard_Real UU1 = Min(U1, U2); |
383 | Standard_Real UU2 = Max(U1, U2); |
384 | Standard_Real L = 0.0; |
385 | for(Standard_Integer Index = 1; Index <= NbIntervals; Index++) { |
386 | if (TI(Index) > UU2) break; |
387 | if (TI(Index+1) < UU1) continue; |
388 | L += CPnts_AbscissaPoint::Length(C, |
389 | Max(TI(Index),UU1), |
390 | Min(TI(Index+1),UU2), |
391 | Tol); |
392 | } |
393 | return L; |
394 | } |
395 | } |
396 | return RealLast(); |
397 | } |
398 | |
399 | |
400 | //======================================================================= |
401 | //function : GCPnts_AbscissaPoint |
402 | //purpose : |
403 | //======================================================================= |
404 | |
405 | GCPnts_AbscissaPoint::GCPnts_AbscissaPoint |
406 | (TheCurve& C, |
407 | const Standard_Real Abscissa, |
408 | const Standard_Real U0) |
409 | { |
410 | Standard_Real L = GCPnts_AbscissaPoint::Length(C); |
411 | if (L < Precision::Confusion()) { |
412 | Standard_ConstructionError::Raise(); |
413 | } |
414 | Standard_Real Abscis = Abscissa; |
415 | Standard_Real UU0 = U0; |
416 | Standard_Real UUi = U0 + |
417 | (Abscis / L) * (C.LastParameter() - C.FirstParameter()); |
418 | Compute(myComputer, C, Abscis, UU0, UUi, |
419 | C.Resolution(Precision::Confusion())); |
420 | } |
421 | |
422 | //======================================================================= |
423 | //function : GCPnts_AbscissaPoint |
424 | //purpose : rbv for curvilinear parametrization |
425 | //======================================================================= |
426 | |
427 | GCPnts_AbscissaPoint::GCPnts_AbscissaPoint |
428 | (const Standard_Real Tol, |
429 | TheCurve& C, |
430 | const Standard_Real Abscissa, |
431 | const Standard_Real U0) |
432 | { |
433 | Standard_Real L = GCPnts_AbscissaPoint::Length(C, Tol); |
434 | /* if (L < Precision::Confusion()) { |
435 | cout<<"FirstParameter = "<<C.FirstParameter()<<endl; |
436 | cout<<"LastParameter = "<<C.LastParameter()<<endl; |
437 | Standard_ConstructionError::Raise("GCPnts_AbscissaPoint::GCPnts_AbscissaPoint"); |
438 | } |
439 | */ |
440 | Standard_Real Abscis = Abscissa; |
441 | Standard_Real UU0 = U0; |
442 | Standard_Real UUi; |
443 | if (L >= Precision::Confusion()) |
444 | UUi= U0 + |
445 | (Abscis / L) * (C.LastParameter() - C.FirstParameter()); |
446 | else UUi = U0; |
447 | |
448 | AdvCompute(myComputer, C, Abscis, UU0, UUi, Tol); |
449 | } |
450 | |
451 | //======================================================================= |
452 | //function : GCPnts_AbscissaPoint |
453 | //purpose : |
454 | //======================================================================= |
455 | |
456 | GCPnts_AbscissaPoint::GCPnts_AbscissaPoint |
457 | (TheCurve& C, |
458 | const Standard_Real Abscissa, |
459 | const Standard_Real U0, |
460 | const Standard_Real Ui) |
461 | { |
462 | Standard_Real Abscis = Abscissa; |
463 | Standard_Real UU0 = U0; |
464 | Standard_Real UUi = Ui; |
465 | Compute(myComputer, C, Abscis, UU0, UUi, |
466 | C.Resolution(Precision::Confusion())); |
467 | } |
468 | |
469 | //======================================================================= |
470 | //function : GCPnts_AbscissaPoint |
471 | //purpose : rbv for curvilinear parametrization |
472 | //======================================================================= |
473 | |
474 | GCPnts_AbscissaPoint::GCPnts_AbscissaPoint |
475 | (TheCurve& C, |
476 | const Standard_Real Abscissa, |
477 | const Standard_Real U0, |
478 | const Standard_Real Ui, |
479 | const Standard_Real Tol) |
480 | { |
481 | Standard_Real Abscis = Abscissa; |
482 | Standard_Real UU0 = U0; |
483 | Standard_Real UUi = Ui; |
484 | AdvCompute(myComputer, C, Abscis, UU0, UUi, Tol); |
485 | } |