b311480e |
1 | // Created on: 1993-03-25 |
2 | // Created by: JCV |
3 | // Copyright (c) 1993-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. |
7fd59977 |
16 | |
7fd59977 |
17 | //Avril 1991 : constructeurs + methodes de lecture. |
18 | //Mai 1991 : revue des specifs + debut de realisation des classes tool => |
19 | // implementation des methodes Set et calcul du point courant. |
20 | //Juillet 1991 : voir egalement File Geom2d_BSplineCurve_1.cxx |
21 | //Juin 1992 : mise a plat des valeurs nodales - amelioration des |
22 | // performances sur calcul du point courant |
23 | |
24 | //RLE Aug 1993 Remove Swaps, Init methods, Remove typedefs |
25 | // 14-Mar-96 : xab implemented MovePointAndTangent |
26 | |
27 | //SAMTECH Jan 2002 : add text to Raise() |
28 | |
29 | #define No_Standard_OutOfRange |
30 | |
31 | #include <Geom2d_BSplineCurve.ixx> |
32 | #include <gp.hxx> |
33 | #include <BSplCLib.hxx> |
34 | #include <BSplCLib_KnotDistribution.hxx> |
35 | #include <BSplCLib_MultDistribution.hxx> |
7b1c1b7c |
36 | #include <Precision.hxx> |
7fd59977 |
37 | #include <Standard_NotImplemented.hxx> |
38 | #include <Standard_ConstructionError.hxx> |
39 | #include <Standard_OutOfRange.hxx> |
40 | |
41 | //======================================================================= |
42 | //function : CheckCurveData |
43 | //purpose : Internal use only |
44 | //======================================================================= |
45 | |
46 | static void CheckCurveData |
47 | (const TColgp_Array1OfPnt2d& CPoles, |
48 | const TColStd_Array1OfReal& CKnots, |
49 | const TColStd_Array1OfInteger& CMults, |
50 | const Standard_Integer Degree, |
51 | const Standard_Boolean Periodic) |
52 | { |
53 | if (Degree < 1 || Degree > Geom2d_BSplineCurve::MaxDegree()) { |
54 | Standard_ConstructionError::Raise("BSpline curve : invalid degree"); |
55 | } |
56 | |
57 | if (CPoles.Length() < 2) Standard_ConstructionError::Raise("BSpline curve : at least 2 poles required"); |
58 | if (CKnots.Length() != CMults.Length()) Standard_ConstructionError::Raise("BSpline curve : Knot and Mult array size mismatch"); |
59 | |
60 | for (Standard_Integer I = CKnots.Lower(); I < CKnots.Upper(); I++) { |
61 | if (CKnots (I+1) - CKnots (I) <= Epsilon (Abs(CKnots (I)))) { |
62 | Standard_ConstructionError::Raise("BSpline curve : Knots interval values too close"); |
63 | } |
64 | } |
65 | |
66 | if (CPoles.Length() != BSplCLib::NbPoles(Degree,Periodic,CMults)) |
67 | Standard_ConstructionError::Raise("BSpline curve : # Poles and degree mismatch"); |
68 | } |
69 | |
7fd59977 |
70 | //======================================================================= |
71 | //function : Rational |
72 | //purpose : check rationality of an array of weights |
73 | //======================================================================= |
74 | |
75 | static Standard_Boolean Rational(const TColStd_Array1OfReal& W) |
76 | { |
77 | Standard_Integer i, n = W.Length(); |
78 | Standard_Boolean rat = Standard_False; |
79 | for (i = 1; i < n; i++) { |
80 | rat = Abs(W(i) - W(i+1)) > gp::Resolution(); |
81 | if (rat) break; |
82 | } |
83 | return rat; |
84 | } |
85 | |
86 | //======================================================================= |
87 | //function : Copy |
88 | //purpose : |
89 | //======================================================================= |
90 | |
91 | Handle(Geom2d_Geometry) Geom2d_BSplineCurve::Copy() const |
92 | { |
93 | Handle(Geom2d_BSplineCurve) C; |
94 | if (IsRational()) |
95 | C = new Geom2d_BSplineCurve(poles->Array1(), |
96 | weights->Array1(), |
97 | knots->Array1(), |
98 | mults->Array1(), |
99 | deg,periodic); |
100 | else |
101 | C = new Geom2d_BSplineCurve(poles->Array1(), |
102 | knots->Array1(), |
103 | mults->Array1(), |
104 | deg,periodic); |
105 | return C; |
106 | } |
107 | |
108 | //======================================================================= |
109 | //function : Geom2d_BSplineCurve |
110 | //purpose : |
111 | //======================================================================= |
112 | |
113 | Geom2d_BSplineCurve::Geom2d_BSplineCurve |
114 | (const TColgp_Array1OfPnt2d& Poles, |
115 | const TColStd_Array1OfReal& Knots, |
116 | const TColStd_Array1OfInteger& Mults, |
117 | const Standard_Integer Degree, |
118 | const Standard_Boolean Periodic) : |
119 | rational(Standard_False), |
120 | periodic(Periodic), |
121 | deg(Degree), |
122 | maxderivinvok(Standard_False) |
123 | { |
124 | // check |
125 | |
126 | CheckCurveData (Poles, |
127 | Knots, |
128 | Mults, |
129 | Degree, |
130 | Periodic); |
131 | |
132 | |
133 | // copy arrays |
134 | |
135 | poles = new TColgp_HArray1OfPnt2d(1,Poles.Length()); |
136 | poles->ChangeArray1() = Poles; |
137 | |
138 | knots = new TColStd_HArray1OfReal(1,Knots.Length()); |
139 | knots->ChangeArray1() = Knots; |
140 | |
141 | mults = new TColStd_HArray1OfInteger(1,Mults.Length()); |
142 | mults->ChangeArray1() = Mults; |
143 | |
144 | UpdateKnots(); |
145 | cachepoles = new TColgp_HArray1OfPnt2d(1,Degree + 1); |
146 | parametercache = 0.0e0 ; |
147 | spanlenghtcache = 0.0e0 ; |
148 | spanindexcache = 0 ; |
149 | } |
150 | |
151 | //======================================================================= |
152 | //function : Geom2d_BSplineCurve |
153 | //purpose : |
154 | //======================================================================= |
155 | |
156 | Geom2d_BSplineCurve::Geom2d_BSplineCurve |
157 | (const TColgp_Array1OfPnt2d& Poles, |
158 | const TColStd_Array1OfReal& Weights, |
159 | const TColStd_Array1OfReal& Knots, |
160 | const TColStd_Array1OfInteger& Mults, |
161 | const Standard_Integer Degree, |
162 | const Standard_Boolean Periodic) : |
163 | rational(Standard_True), |
164 | periodic(Periodic), |
165 | deg(Degree), |
166 | maxderivinvok(Standard_False) |
167 | |
168 | { |
169 | |
170 | // check |
171 | |
172 | CheckCurveData (Poles, |
173 | Knots, |
174 | Mults, |
175 | Degree, |
176 | Periodic); |
177 | |
178 | if (Weights.Length() != Poles.Length()) |
179 | Standard_ConstructionError::Raise("Geom2d_BSplineCurve :Weights and Poles array size mismatch"); |
180 | |
181 | Standard_Integer i; |
182 | for (i = Weights.Lower(); i <= Weights.Upper(); i++) { |
183 | if (Weights(i) <= gp::Resolution()) { |
184 | Standard_ConstructionError::Raise("Geom2d_BSplineCurve: Weights values too small"); |
185 | } |
186 | } |
187 | |
188 | // check really rational |
189 | rational = Rational(Weights); |
190 | |
191 | // copy arrays |
192 | |
193 | poles = new TColgp_HArray1OfPnt2d(1,Poles.Length()); |
194 | poles->ChangeArray1() = Poles; |
195 | cachepoles = new TColgp_HArray1OfPnt2d(1,Degree + 1); |
196 | if (rational) { |
197 | weights = new TColStd_HArray1OfReal(1,Weights.Length()); |
198 | weights->ChangeArray1() = Weights; |
199 | cacheweights = new TColStd_HArray1OfReal(1,Degree + 1); |
200 | } |
201 | |
202 | knots = new TColStd_HArray1OfReal(1,Knots.Length()); |
203 | knots->ChangeArray1() = Knots; |
204 | |
205 | mults = new TColStd_HArray1OfInteger(1,Mults.Length()); |
206 | mults->ChangeArray1() = Mults; |
207 | |
208 | UpdateKnots(); |
209 | |
210 | parametercache = 0.0e0 ; |
211 | spanlenghtcache = 0.0e0 ; |
212 | spanindexcache = 0 ; |
213 | } |
214 | |
215 | //======================================================================= |
216 | //function : MaxDegree |
217 | //purpose : |
218 | //======================================================================= |
219 | |
220 | Standard_Integer Geom2d_BSplineCurve::MaxDegree () |
221 | { |
222 | return BSplCLib::MaxDegree(); |
223 | } |
224 | |
225 | //======================================================================= |
226 | //function : IncreaseDegree |
227 | //purpose : |
228 | //======================================================================= |
229 | |
230 | void Geom2d_BSplineCurve::IncreaseDegree |
231 | (const Standard_Integer Degree) |
232 | { |
233 | if (Degree == deg) return; |
234 | |
235 | if (Degree < deg || Degree > Geom2d_BSplineCurve::MaxDegree()) { |
236 | Standard_ConstructionError::Raise("BSpline curve : IncreaseDegree : bad degree value"); |
237 | } |
238 | |
239 | Standard_Integer FromK1 = FirstUKnotIndex (); |
240 | Standard_Integer ToK2 = LastUKnotIndex (); |
241 | |
242 | Standard_Integer Step = Degree - deg; |
243 | |
244 | Handle(TColgp_HArray1OfPnt2d) npoles = new |
245 | TColgp_HArray1OfPnt2d(1,poles->Length() + Step * (ToK2-FromK1)); |
246 | |
247 | Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots |
248 | (deg,Degree,periodic,mults->Array1()); |
249 | |
250 | Handle(TColStd_HArray1OfReal) nknots = |
251 | new TColStd_HArray1OfReal(1,nbknots); |
252 | |
253 | Handle(TColStd_HArray1OfInteger) nmults = |
254 | new TColStd_HArray1OfInteger(1,nbknots); |
255 | |
256 | Handle(TColStd_HArray1OfReal) nweights; |
257 | |
258 | if (IsRational()) { |
259 | |
260 | nweights = new TColStd_HArray1OfReal(1,npoles->Upper()); |
261 | |
262 | BSplCLib::IncreaseDegree |
263 | (deg,Degree, periodic, |
264 | poles->Array1(),weights->Array1(), |
265 | knots->Array1(),mults->Array1(), |
266 | npoles->ChangeArray1(),nweights->ChangeArray1(), |
267 | nknots->ChangeArray1(),nmults->ChangeArray1()); |
268 | } |
269 | else { |
270 | |
271 | BSplCLib::IncreaseDegree |
272 | (deg,Degree, periodic, |
273 | poles->Array1(), |
274 | *((TColStd_Array1OfReal*) NULL), |
275 | knots->Array1(),mults->Array1(), |
276 | npoles->ChangeArray1(), |
277 | *((TColStd_Array1OfReal*) NULL), |
278 | nknots->ChangeArray1(),nmults->ChangeArray1()); |
279 | } |
280 | |
281 | deg = Degree; |
282 | poles = npoles; |
283 | weights = nweights; |
284 | knots = nknots; |
285 | mults = nmults; |
286 | UpdateKnots(); |
287 | } |
288 | |
289 | //======================================================================= |
290 | //function : IncreaseMultiplicity |
291 | //purpose : |
292 | //======================================================================= |
293 | |
294 | void Geom2d_BSplineCurve::IncreaseMultiplicity |
295 | (const Standard_Integer Index, |
296 | const Standard_Integer M) |
297 | { |
298 | TColStd_Array1OfReal k(1,1); |
299 | k(1) = knots->Value(Index); |
300 | TColStd_Array1OfInteger m(1,1); |
301 | m(1) = M - mults->Value(Index); |
302 | InsertKnots(k,m,Epsilon(1.),Standard_True); |
303 | } |
304 | |
305 | //======================================================================= |
306 | //function : IncreaseMultiplicity |
307 | //purpose : |
308 | //======================================================================= |
309 | |
310 | void Geom2d_BSplineCurve::IncreaseMultiplicity |
311 | (const Standard_Integer I1, |
312 | const Standard_Integer I2, |
313 | const Standard_Integer M) |
314 | { |
315 | Handle(TColStd_HArray1OfReal) tk = knots; |
316 | TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2); |
317 | TColStd_Array1OfInteger m(I1,I2); |
318 | Standard_Integer i; |
319 | for (i = I1; i <= I2; i++) |
320 | m(i) = M - mults->Value(i); |
321 | InsertKnots(k,m,Epsilon(1.),Standard_True); |
322 | } |
323 | |
324 | //======================================================================= |
325 | //function : IncrementMultiplicity |
326 | //purpose : |
327 | //======================================================================= |
328 | |
329 | void Geom2d_BSplineCurve::IncrementMultiplicity |
330 | (const Standard_Integer I1, |
331 | const Standard_Integer I2, |
332 | const Standard_Integer Step) |
333 | { |
334 | Handle(TColStd_HArray1OfReal) tk = knots; |
335 | TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2); |
336 | TColStd_Array1OfInteger m(I1,I2); |
337 | m.Init(Step); |
338 | InsertKnots(k,m,Epsilon(1.),Standard_True); |
339 | } |
340 | |
341 | //======================================================================= |
342 | //function : InsertKnot |
343 | //purpose : |
344 | //======================================================================= |
345 | |
346 | void Geom2d_BSplineCurve::InsertKnot |
347 | (const Standard_Real U, |
348 | const Standard_Integer M, |
349 | const Standard_Real ParametricTolerance) |
350 | { |
351 | TColStd_Array1OfReal k(1,1); |
352 | k(1) = U; |
353 | TColStd_Array1OfInteger m(1,1); |
354 | m(1) = M; |
355 | InsertKnots(k,m,ParametricTolerance); |
356 | } |
357 | |
358 | //======================================================================= |
359 | //function : InsertKnots |
360 | //purpose : |
361 | //======================================================================= |
362 | void Geom2d_BSplineCurve::InsertKnots(const TColStd_Array1OfReal& Knots, |
363 | const TColStd_Array1OfInteger& Mults, |
364 | const Standard_Real Epsilon, |
365 | const Standard_Boolean Add) |
366 | { |
367 | // Check and compute new sizes |
368 | Standard_Integer nbpoles,nbknots; |
369 | |
370 | if (!BSplCLib::PrepareInsertKnots(deg,periodic, |
371 | knots->Array1(),mults->Array1(), |
372 | Knots,Mults,nbpoles,nbknots,Epsilon,Add)) |
373 | Standard_ConstructionError::Raise("Geom2d_BSplineCurve::InsertKnots"); |
374 | |
375 | if (nbpoles == poles->Length()) return; |
376 | |
377 | Handle(TColgp_HArray1OfPnt2d) npoles = new TColgp_HArray1OfPnt2d(1,nbpoles); |
378 | Handle(TColStd_HArray1OfReal) nknots = knots; |
379 | Handle(TColStd_HArray1OfInteger) nmults = mults; |
380 | |
381 | if (nbknots != knots->Length()) { |
382 | nknots = new TColStd_HArray1OfReal(1,nbknots); |
383 | nmults = new TColStd_HArray1OfInteger(1,nbknots); |
384 | } |
385 | |
386 | if (rational) { |
387 | Handle(TColStd_HArray1OfReal) nweights = |
388 | new TColStd_HArray1OfReal(1,nbpoles); |
389 | BSplCLib::InsertKnots(deg,periodic, |
390 | poles->Array1(), weights->Array1(), |
391 | knots->Array1(), mults->Array1(), |
392 | Knots, Mults, |
393 | npoles->ChangeArray1(), nweights->ChangeArray1(), |
394 | nknots->ChangeArray1(), nmults->ChangeArray1(), |
395 | Epsilon,Add); |
396 | weights = nweights; |
397 | } |
398 | else { |
399 | BSplCLib::InsertKnots(deg,periodic, |
400 | poles->Array1(), |
401 | *((TColStd_Array1OfReal*) NULL), |
402 | knots->Array1(), mults->Array1(), |
403 | Knots, Mults, |
404 | npoles->ChangeArray1(), |
405 | *((TColStd_Array1OfReal*) NULL), |
406 | nknots->ChangeArray1(), nmults->ChangeArray1(), |
407 | Epsilon,Add); |
408 | } |
409 | |
410 | poles = npoles; |
411 | knots = nknots; |
412 | mults = nmults; |
413 | UpdateKnots(); |
414 | |
415 | } |
416 | |
417 | //======================================================================= |
418 | //function : RemoveKnot |
419 | //purpose : |
420 | //======================================================================= |
421 | |
422 | Standard_Boolean Geom2d_BSplineCurve::RemoveKnot |
423 | (const Standard_Integer Index, |
424 | const Standard_Integer M, |
425 | const Standard_Real Tolerance) |
426 | { |
427 | if (M < 0) return Standard_True; |
428 | |
429 | Standard_Integer I1 = FirstUKnotIndex (); |
430 | Standard_Integer I2 = LastUKnotIndex (); |
431 | |
432 | if (Index < I1 || Index > I2) { |
433 | Standard_OutOfRange::Raise("BSpline curve : RemoveKnot : index out of range"); |
434 | } |
435 | |
436 | const TColgp_Array1OfPnt2d & oldpoles = poles->Array1(); |
437 | |
438 | Standard_Integer step = mults->Value(Index) - M; |
439 | if (step <= 0) return Standard_True; |
440 | |
441 | Handle(TColgp_HArray1OfPnt2d) npoles = |
442 | new TColgp_HArray1OfPnt2d(1,oldpoles.Length()-step); |
443 | |
444 | Handle(TColStd_HArray1OfReal) nknots = knots; |
445 | Handle(TColStd_HArray1OfInteger) nmults = mults; |
446 | |
447 | if (M == 0) { |
448 | nknots = new TColStd_HArray1OfReal(1,knots->Length()-1); |
449 | nmults = new TColStd_HArray1OfInteger(1,knots->Length()-1); |
450 | } |
451 | |
452 | if (IsRational()) { |
453 | Handle(TColStd_HArray1OfReal) nweights = |
454 | new TColStd_HArray1OfReal(1,npoles->Length()); |
455 | if (!BSplCLib::RemoveKnot |
456 | (Index, M, deg, periodic, |
457 | poles->Array1(),weights->Array1(), |
458 | knots->Array1(),mults->Array1(), |
459 | npoles->ChangeArray1(), nweights->ChangeArray1(), |
460 | nknots->ChangeArray1(),nmults->ChangeArray1(), |
461 | Tolerance)) |
462 | return Standard_False; |
463 | weights = nweights; |
464 | } |
465 | else { |
466 | if (!BSplCLib::RemoveKnot |
467 | (Index, M, deg, periodic, |
468 | poles->Array1(), |
469 | *((TColStd_Array1OfReal*) NULL), |
470 | knots->Array1(),mults->Array1(), |
471 | npoles->ChangeArray1(), |
472 | *((TColStd_Array1OfReal*) NULL), |
473 | nknots->ChangeArray1(),nmults->ChangeArray1(), |
474 | Tolerance)) |
475 | return Standard_False; |
476 | } |
477 | |
478 | poles = npoles; |
479 | knots = nknots; |
480 | mults = nmults; |
481 | |
482 | UpdateKnots(); |
483 | maxderivinvok = 0; |
484 | return Standard_True; |
485 | } |
486 | |
487 | //======================================================================= |
488 | //function : InsertPoleAfter |
489 | //purpose : |
490 | //======================================================================= |
491 | |
492 | void Geom2d_BSplineCurve::InsertPoleAfter |
493 | (const Standard_Integer Index, |
494 | const gp_Pnt2d& P, |
495 | const Standard_Real Weight) |
496 | { |
497 | if (Index < 0 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve : InsertPoleAfter: Index and #pole mismatch"); |
498 | |
499 | if (Weight <= gp::Resolution()) Standard_ConstructionError::Raise("BSpline curve : InsertPoleAfter: Weight too small"); |
500 | |
501 | if (knotSet == GeomAbs_NonUniform || knotSet == GeomAbs_PiecewiseBezier) { |
502 | Standard_ConstructionError::Raise("BSpline curve : InsertPoleAfter : bad knotSet type"); |
503 | } |
504 | |
505 | const TColStd_Array1OfReal& cknots = knots->Array1(); |
506 | Standard_Integer nbknots = cknots.Length(); |
507 | |
508 | Handle(TColStd_HArray1OfReal) nknots = |
509 | new TColStd_HArray1OfReal(1,nbknots+1); |
510 | |
511 | TColStd_Array1OfReal& newknots = nknots->ChangeArray1(); |
512 | |
513 | Standard_Integer i; |
514 | for (i = 1; i < nbknots; i++) { |
515 | newknots (i) = cknots(i); |
516 | } |
517 | |
518 | newknots (nbknots+1) = 2 * newknots (nbknots) - newknots(nbknots-1); |
519 | |
520 | Handle(TColStd_HArray1OfInteger) nmults = |
521 | new TColStd_HArray1OfInteger(1,nbknots+1); |
522 | |
523 | TColStd_Array1OfInteger& newmults = nmults->ChangeArray1(); |
524 | const TColStd_Array1OfInteger& cmults = mults->Array1(); |
525 | |
526 | for (i = 2; i <= nbknots; i++) newmults (i) = 1; |
527 | newmults (1) = cmults(1); |
528 | newmults (nbknots+1) = cmults(nbknots+1); |
529 | |
530 | const TColgp_Array1OfPnt2d& cpoles = poles->Array1(); |
531 | Standard_Integer nbpoles = cpoles.Length(); |
532 | Handle(TColgp_HArray1OfPnt2d) npoles = |
533 | new TColgp_HArray1OfPnt2d(1, nbpoles+1); |
534 | TColgp_Array1OfPnt2d& newpoles = npoles->ChangeArray1(); |
535 | |
536 | // insert the pole |
537 | |
538 | for (i = 1; i <= Index; i++) |
539 | newpoles(i) = cpoles(i); |
540 | |
541 | newpoles(Index+1) = P; |
542 | |
543 | for (i = Index+1; i <= nbpoles; i++) |
544 | newpoles(i+1) = cpoles(i); |
545 | |
546 | // Insert the weight |
547 | |
548 | Handle(TColStd_HArray1OfReal) nweights; |
549 | Standard_Boolean rat = IsRational() || Abs(Weight-1.) > gp::Resolution(); |
550 | |
551 | if (rat) { |
552 | nweights = new TColStd_HArray1OfReal(1,nbpoles+1); |
553 | TColStd_Array1OfReal& newweights = nweights->ChangeArray1(); |
554 | |
555 | for (i = 1; i <= Index; i++) |
556 | if (IsRational()) |
557 | newweights(i) = weights->Value(i); |
558 | else |
559 | newweights(i) = 1.; |
560 | |
561 | newweights(Index+1) = Weight; |
562 | |
563 | for (i = Index+1; i <= nbpoles; i++) |
564 | if (IsRational()) |
565 | newweights(i+1) = weights->Value(i); |
566 | else |
567 | newweights(i+1) = 1.; |
568 | } |
569 | |
570 | poles = npoles; |
571 | weights = nweights; |
572 | knots = nknots; |
573 | mults = nmults; |
574 | maxderivinvok = 0; |
575 | UpdateKnots(); |
576 | } |
577 | |
578 | //======================================================================= |
579 | //function : InsertPoleBefore |
580 | //purpose : |
581 | //======================================================================= |
582 | |
583 | void Geom2d_BSplineCurve::InsertPoleBefore |
584 | (const Standard_Integer Index, |
585 | const gp_Pnt2d& P, |
586 | const Standard_Real Weight) |
587 | { |
588 | InsertPoleAfter(Index-1,P,Weight); |
589 | } |
590 | |
591 | //======================================================================= |
592 | //function : RemovePole |
593 | //purpose : |
594 | //======================================================================= |
595 | |
596 | void Geom2d_BSplineCurve::RemovePole |
597 | (const Standard_Integer Index) |
598 | { |
599 | if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve :RemovePole : Index and #pole mismatch"); |
600 | |
601 | if (poles->Length() <= 2) Standard_ConstructionError::Raise("BSpline curve : RemovePole : #pole is already minimum"); |
602 | |
603 | if (knotSet == GeomAbs_NonUniform || knotSet == GeomAbs_PiecewiseBezier) |
604 | Standard_ConstructionError::Raise("BSpline curve : RemovePole: bad knotSet type"); |
605 | |
606 | Standard_Integer i; |
607 | Handle(TColStd_HArray1OfReal) nknots = |
608 | new TColStd_HArray1OfReal(1,knots->Length()-1); |
609 | TColStd_Array1OfReal& newknots = nknots->ChangeArray1(); |
610 | |
611 | Handle(TColStd_HArray1OfInteger) nmults = |
612 | new TColStd_HArray1OfInteger(1,mults->Length()-1); |
613 | TColStd_Array1OfInteger& newmults = nmults->ChangeArray1(); |
614 | |
615 | for (i = 1; i < newknots.Length(); i++) { |
616 | newknots (i) = knots->Value (i); |
617 | newmults (i) = 1; |
618 | } |
619 | newmults(1) = mults->Value(1); |
620 | newknots(newknots.Upper()) = knots->Value (knots->Upper()); |
621 | newmults(newmults.Upper()) = mults->Value (mults->Upper()); |
622 | |
623 | |
624 | Handle(TColgp_HArray1OfPnt2d) npoles = |
625 | new TColgp_HArray1OfPnt2d(1, poles->Upper()-1); |
626 | TColgp_Array1OfPnt2d& newpoles = npoles->ChangeArray1(); |
627 | |
628 | for (i = 1; i < Index; i++) |
629 | newpoles(i) = poles->Value(i); |
630 | for (i = Index; i < newpoles.Length(); i++) |
631 | newpoles(i) = poles->Value(i+1); |
632 | |
633 | Handle(TColStd_HArray1OfReal) nweights; |
634 | if (IsRational()) { |
635 | nweights = new TColStd_HArray1OfReal(1,newpoles.Length()); |
636 | TColStd_Array1OfReal& newweights = nweights->ChangeArray1(); |
637 | for (i = 1; i < Index; i++) |
638 | newweights(i) = weights->Value(i); |
639 | for (i = Index; i < newweights.Length(); i++) |
640 | newweights(i) = weights->Value(i+1); |
641 | } |
642 | |
643 | poles = npoles; |
644 | weights = nweights; |
645 | knots = nknots; |
646 | mults = nmults; |
647 | UpdateKnots(); |
648 | } |
649 | |
650 | //======================================================================= |
651 | //function : Reverse |
652 | //purpose : |
653 | //======================================================================= |
654 | |
655 | void Geom2d_BSplineCurve::Reverse () |
656 | { |
657 | BSplCLib::Reverse(knots->ChangeArray1()); |
658 | BSplCLib::Reverse(mults->ChangeArray1()); |
659 | Standard_Integer last; |
660 | if (periodic) |
661 | last = flatknots->Upper() - deg - 1; |
662 | else |
663 | last = poles->Upper(); |
664 | BSplCLib::Reverse(poles->ChangeArray1(),last); |
665 | if (rational) |
666 | BSplCLib::Reverse(weights->ChangeArray1(),last); |
667 | UpdateKnots(); |
668 | } |
669 | |
670 | //======================================================================= |
671 | //function : ReversedParameter |
672 | //purpose : |
673 | //======================================================================= |
674 | |
675 | Standard_Real Geom2d_BSplineCurve::ReversedParameter( const Standard_Real U) const |
676 | { |
677 | return (FirstParameter() + LastParameter() - U); |
678 | } |
679 | |
680 | //======================================================================= |
681 | //function : Segment |
682 | //purpose : |
683 | //======================================================================= |
684 | void Geom2d_BSplineCurve::Segment(const Standard_Real aU1, |
685 | const Standard_Real aU2) |
686 | { |
687 | Standard_DomainError_Raise_if ( aU2 < aU1, "Geom2d_BSplineCurve::Segment"); |
688 | // |
689 | Standard_Real AbsUMax = Max(Abs(FirstParameter()),Abs(LastParameter())); |
7b1c1b7c |
690 | Standard_Real Eps = Max (Epsilon(AbsUMax), Precision::PConfusion()); |
7fd59977 |
691 | Standard_Real NewU1, NewU2; |
692 | Standard_Real U, DU=0; |
693 | Standard_Integer i, k, index; |
694 | // |
695 | //f |
696 | // Checking the input bounds aUj (j=1,2). |
697 | // For the case when aUj==knot(i), |
698 | // in order to prevent the insertion of a new knot that will be too closed |
699 | // to the existing knot, |
700 | // we assign Uj=knot(i) |
701 | Standard_Integer n1, n2; |
702 | Standard_Real U1, U2; |
703 | // |
704 | U1=aU1; |
705 | U2=aU2; |
706 | n1=knots->Lower(); |
707 | n2=knots->Upper(); |
708 | for (i=n1; i<=n2; ++i) { |
709 | U=knots->Value(i); |
710 | if (Abs(U-aU1)<=Eps) { |
711 | U1=U; |
712 | } |
713 | else if (Abs(U-aU2)<=Eps) { |
714 | U2=U; |
715 | } |
716 | } |
717 | // Henceforward we use U1, U2 as bounds of the segment |
718 | //t |
719 | // |
720 | TColStd_Array1OfReal Knots(1,2); |
721 | TColStd_Array1OfInteger Mults(1,2); |
722 | // |
723 | // define param ditance to keep (eap, Apr 18 2002, occ311) |
724 | if (periodic) { |
725 | Standard_Real Period = LastParameter() - FirstParameter(); |
726 | DU = U2 - U1; |
727 | while (DU > Period) { |
728 | DU -= Period; |
729 | } |
730 | if (DU <= Epsilon(Period)) { |
731 | DU = Period; |
732 | } |
733 | } |
734 | // |
735 | index = 0; |
736 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), |
737 | U1,periodic,knots->Lower(),knots->Upper(), |
738 | index,NewU1); |
739 | index = 0; |
740 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), |
741 | U2,periodic,knots->Lower(),knots->Upper(), |
742 | index,NewU2); |
743 | Knots(1) = Min( NewU1, NewU2); |
744 | Knots(2) = Max( NewU1, NewU2); |
745 | Mults(1) = Mults( 2) = deg; |
746 | InsertKnots(Knots, Mults, Eps); |
747 | |
748 | if (periodic) { // set the origine at NewU1 |
749 | index = 0; |
750 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), |
751 | U1,periodic,knots->Lower(),knots->Upper(), |
752 | index,U); |
753 | // Eps = Epsilon(knots->Value(index+1)); |
754 | if ( Abs(knots->Value(index+1)-U) <= Eps) { |
755 | index++; |
756 | } |
757 | SetOrigin(index); |
758 | SetNotPeriodic(); |
759 | NewU2 = NewU1 + DU; |
760 | } |
761 | |
762 | // compute index1 and index2 to set the new knots and mults |
763 | Standard_Integer index1 = 0, index2 = 0; |
764 | Standard_Integer FromU1 = knots->Lower(); |
765 | Standard_Integer ToU2 = knots->Upper(); |
766 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), |
767 | NewU1,periodic,FromU1,ToU2,index1,U); |
768 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), |
769 | NewU2,periodic,FromU1,ToU2,index2,U); |
770 | // Eps = Epsilon(knots->Value(index2+1)); |
771 | if ( Abs(knots->Value(index2+1)-U) <= Eps){ |
772 | index2++; |
773 | } |
774 | |
775 | Standard_Integer nbknots = index2 - index1 + 1; |
776 | |
777 | Handle(TColStd_HArray1OfReal) |
778 | nknots = new TColStd_HArray1OfReal(1,nbknots); |
779 | Handle(TColStd_HArray1OfInteger) |
780 | nmults = new TColStd_HArray1OfInteger(1,nbknots); |
781 | |
782 | // to restore changed U1 |
783 | if (DU > 0) {// if was periodic |
784 | DU = NewU1 - U1; |
785 | } |
786 | // |
787 | k = 1; |
788 | // |
789 | for ( i = index1; i<= index2; i++) { |
790 | nknots->SetValue(k, knots->Value(i) - DU); |
791 | nmults->SetValue(k, mults->Value(i)); |
792 | k++; |
793 | } |
794 | nmults->SetValue( 1, deg + 1); |
795 | nmults->SetValue(nbknots, deg + 1); |
796 | |
797 | |
798 | // compute index1 and index2 to set the new poles and weights |
799 | Standard_Integer pindex1 |
800 | = BSplCLib::PoleIndex(deg,index1,periodic,mults->Array1()); |
801 | Standard_Integer pindex2 |
802 | = BSplCLib::PoleIndex(deg,index2,periodic,mults->Array1()); |
803 | |
804 | pindex1++; |
805 | pindex2 = Min( pindex2+1, poles->Length()); |
806 | |
807 | Standard_Integer nbpoles = pindex2 - pindex1 + 1; |
808 | |
809 | Handle(TColStd_HArray1OfReal) |
810 | nweights = new TColStd_HArray1OfReal(1,nbpoles); |
811 | Handle(TColgp_HArray1OfPnt2d) |
812 | npoles = new TColgp_HArray1OfPnt2d(1,nbpoles); |
813 | |
814 | k = 1; |
815 | if ( rational) { |
816 | nweights = new TColStd_HArray1OfReal( 1, nbpoles); |
817 | for ( i = pindex1; i <= pindex2; i++) { |
818 | npoles->SetValue(k, poles->Value(i)); |
819 | nweights->SetValue(k, weights->Value(i)); |
820 | k++; |
821 | } |
822 | } |
823 | else { |
824 | for ( i = pindex1; i <= pindex2; i++) { |
825 | npoles->SetValue(k, poles->Value(i)); |
826 | k++; |
827 | } |
828 | } |
829 | |
830 | knots = nknots; |
831 | mults = nmults; |
832 | poles = npoles; |
833 | if (rational){ |
834 | weights = nweights; |
835 | } |
836 | UpdateKnots(); |
837 | } |
838 | |
839 | //======================================================================= |
840 | //function : SetKnot |
841 | //purpose : |
842 | //======================================================================= |
843 | |
844 | void Geom2d_BSplineCurve::SetKnot |
845 | (const Standard_Integer Index, |
846 | const Standard_Real K) |
847 | { |
848 | if (Index < 1 || Index > knots->Length()) Standard_OutOfRange::Raise("BSpline curve : SetKnot: Index and #pole mismatch"); |
849 | Standard_Real DK = Abs(Epsilon (K)); |
850 | if (Index == 1) { |
851 | if (K >= knots->Value(2) - DK) Standard_ConstructionError::Raise("BSpline curve :SetKnot :K out of range"); |
852 | } |
853 | else if (Index == knots->Length()) { |
854 | if (K <= knots->Value (knots->Length()-1) + DK) { |
855 | Standard_ConstructionError::Raise("BSpline curve : SetKnot : K out of range"); |
856 | } |
857 | } |
858 | else { |
859 | if (K <= knots->Value(Index-1) + DK || |
860 | K >= knots->Value(Index+1) - DK ) { |
861 | Standard_ConstructionError::Raise("BSpline curve : SetKnot: K out of range"); |
862 | } |
863 | } |
864 | if (K != knots->Value (Index)) { |
865 | knots->SetValue (Index, K); |
866 | maxderivinvok = 0; |
867 | UpdateKnots(); |
868 | } |
869 | } |
870 | |
871 | //======================================================================= |
872 | //function : SetKnots |
873 | //purpose : |
874 | //======================================================================= |
875 | |
876 | void Geom2d_BSplineCurve::SetKnots |
877 | (const TColStd_Array1OfReal& K) |
878 | { |
879 | CheckCurveData(poles->Array1(),K,mults->Array1(),deg,periodic); |
880 | knots->ChangeArray1() = K; |
881 | maxderivinvok = 0; |
882 | UpdateKnots(); |
883 | } |
884 | |
885 | //======================================================================= |
886 | //function : SetKnot |
887 | //purpose : |
888 | //======================================================================= |
889 | |
890 | void Geom2d_BSplineCurve::SetKnot |
891 | (const Standard_Integer Index, |
892 | const Standard_Real K, |
893 | const Standard_Integer M) |
894 | { |
895 | IncreaseMultiplicity (Index, M); |
896 | SetKnot (Index, K); |
897 | } |
898 | |
899 | //======================================================================= |
900 | //function : SetPeriodic |
901 | //purpose : |
902 | //======================================================================= |
903 | |
904 | void Geom2d_BSplineCurve::SetPeriodic () |
905 | { |
906 | Standard_Integer first = FirstUKnotIndex(); |
907 | Standard_Integer last = LastUKnotIndex(); |
908 | |
909 | Handle(TColStd_HArray1OfReal) tk = knots; |
910 | TColStd_Array1OfReal cknots((knots->Array1())(first),first,last); |
911 | knots = new TColStd_HArray1OfReal(1,cknots.Length()); |
912 | knots->ChangeArray1() = cknots; |
913 | |
914 | Handle(TColStd_HArray1OfInteger) tm = mults; |
915 | TColStd_Array1OfInteger cmults((mults->Array1())(first),first,last); |
916 | cmults(first) = cmults(last) = Min(deg, Max( cmults(first), cmults(last))); |
917 | mults = new TColStd_HArray1OfInteger(1,cmults.Length()); |
918 | mults->ChangeArray1() = cmults; |
919 | |
920 | // compute new number of poles; |
921 | Standard_Integer nbp = BSplCLib::NbPoles(deg,Standard_True,cmults); |
922 | |
923 | Handle(TColgp_HArray1OfPnt2d) tp = poles; |
924 | TColgp_Array1OfPnt2d cpoles((poles->Array1())(1),1,nbp); |
925 | poles = new TColgp_HArray1OfPnt2d(1,nbp); |
926 | poles->ChangeArray1() = cpoles; |
927 | |
928 | if (rational) { |
929 | Handle(TColStd_HArray1OfReal) tw = weights; |
930 | TColStd_Array1OfReal cweights((weights->Array1())(1),1,nbp); |
931 | weights = new TColStd_HArray1OfReal(1,nbp); |
932 | weights->ChangeArray1() = cweights; |
933 | } |
934 | |
935 | periodic = Standard_True; |
936 | |
937 | maxderivinvok = 0; |
938 | UpdateKnots(); |
939 | } |
940 | |
941 | //======================================================================= |
942 | //function : SetOrigin |
943 | //purpose : |
944 | //======================================================================= |
945 | |
946 | void Geom2d_BSplineCurve::SetOrigin(const Standard_Integer Index) |
947 | { |
948 | Standard_NoSuchObject_Raise_if( !periodic, |
949 | "Geom2d_BSplineCurve::SetOrigin"); |
950 | Standard_Integer i,k; |
951 | Standard_Integer first = FirstUKnotIndex(); |
952 | Standard_Integer last = LastUKnotIndex(); |
953 | |
954 | Standard_DomainError_Raise_if( (Index < first) || (Index > last), |
955 | "Geom2d_BSplineCurve::SetOrigine"); |
956 | |
957 | Standard_Integer nbknots = knots->Length(); |
958 | Standard_Integer nbpoles = poles->Length(); |
959 | |
960 | Handle(TColStd_HArray1OfReal) nknots = |
961 | new TColStd_HArray1OfReal(1,nbknots); |
962 | TColStd_Array1OfReal& newknots = nknots->ChangeArray1(); |
963 | |
964 | Handle(TColStd_HArray1OfInteger) nmults = |
965 | new TColStd_HArray1OfInteger(1,nbknots); |
966 | TColStd_Array1OfInteger& newmults = nmults->ChangeArray1(); |
967 | |
968 | // set the knots and mults |
969 | Standard_Real period = knots->Value(last) - knots->Value(first); |
970 | k = 1; |
971 | for ( i = Index; i <= last ; i++) { |
972 | newknots(k) = knots->Value(i); |
973 | newmults(k) = mults->Value(i); |
974 | k++; |
975 | } |
976 | for ( i = first+1; i <= Index; i++) { |
977 | newknots(k) = knots->Value(i) + period; |
978 | newmults(k) = mults->Value(i); |
979 | k++; |
980 | } |
981 | |
982 | Standard_Integer index = 1; |
983 | for (i = first+1; i <= Index; i++) |
984 | index += mults->Value(i); |
985 | |
986 | // set the poles and weights |
987 | Handle(TColgp_HArray1OfPnt2d) npoles = |
988 | new TColgp_HArray1OfPnt2d(1,nbpoles); |
989 | Handle(TColStd_HArray1OfReal) nweights = |
990 | new TColStd_HArray1OfReal(1,nbpoles); |
991 | TColgp_Array1OfPnt2d & newpoles = npoles->ChangeArray1(); |
992 | TColStd_Array1OfReal & newweights = nweights->ChangeArray1(); |
993 | first = poles->Lower(); |
994 | last = poles->Upper(); |
995 | if ( rational) { |
996 | k = 1; |
997 | for ( i = index; i <= last; i++) { |
998 | newpoles(k) = poles->Value(i); |
999 | newweights(k) = weights->Value(i); |
1000 | k++; |
1001 | } |
1002 | for ( i = first; i < index; i++) { |
1003 | newpoles(k) = poles->Value(i); |
1004 | newweights(k) = weights->Value(i); |
1005 | k++; |
1006 | } |
1007 | } |
1008 | else { |
1009 | k = 1; |
1010 | for ( i = index; i <= last; i++) { |
1011 | newpoles(k) = poles->Value(i); |
1012 | k++; |
1013 | } |
1014 | for ( i = first; i < index; i++) { |
1015 | newpoles(k) = poles->Value(i); |
1016 | k++; |
1017 | } |
1018 | } |
1019 | |
1020 | poles = npoles; |
1021 | knots = nknots; |
1022 | mults = nmults; |
1023 | if (rational) |
1024 | weights = nweights; |
1025 | maxderivinvok = 0; |
1026 | UpdateKnots(); |
1027 | } |
1028 | |
1029 | //======================================================================= |
1030 | //function : SetNotPeriodic |
1031 | //purpose : |
1032 | //======================================================================= |
1033 | |
1034 | void Geom2d_BSplineCurve::SetNotPeriodic () |
1035 | { |
1036 | if (periodic) { |
1037 | Standard_Integer NbKnots, NbPoles; |
1038 | BSplCLib::PrepareUnperiodize( deg, mults->Array1(),NbKnots,NbPoles); |
1039 | |
1040 | Handle(TColgp_HArray1OfPnt2d) npoles |
1041 | = new TColgp_HArray1OfPnt2d(1,NbPoles); |
1042 | |
1043 | Handle(TColStd_HArray1OfReal) nknots |
1044 | = new TColStd_HArray1OfReal(1,NbKnots); |
1045 | |
1046 | Handle(TColStd_HArray1OfInteger) nmults |
1047 | = new TColStd_HArray1OfInteger(1,NbKnots); |
1048 | |
1049 | Handle(TColStd_HArray1OfReal) nweights; |
1050 | |
1051 | if (IsRational()) { |
1052 | |
1053 | nweights = new TColStd_HArray1OfReal(1,NbPoles); |
1054 | |
1055 | BSplCLib::Unperiodize |
1056 | (deg,mults->Array1(),knots->Array1(),poles->Array1(), |
1057 | weights->Array1(),nmults->ChangeArray1(), |
1058 | nknots->ChangeArray1(),npoles->ChangeArray1(), |
1059 | nweights->ChangeArray1()); |
1060 | |
1061 | } |
1062 | else { |
1063 | |
1064 | BSplCLib::Unperiodize |
1065 | (deg,mults->Array1(),knots->Array1(),poles->Array1(), |
1066 | *((TColStd_Array1OfReal*) NULL),nmults->ChangeArray1(), |
1067 | nknots->ChangeArray1(),npoles->ChangeArray1(), |
1068 | *((TColStd_Array1OfReal*) NULL)); |
1069 | |
1070 | } |
1071 | poles = npoles; |
1072 | weights = nweights; |
1073 | mults = nmults; |
1074 | knots = nknots; |
1075 | periodic = Standard_False; |
1076 | maxderivinvok = 0; |
1077 | UpdateKnots(); |
1078 | } |
1079 | } |
1080 | |
1081 | //======================================================================= |
1082 | //function : SetPole |
1083 | //purpose : |
1084 | //======================================================================= |
1085 | |
1086 | void Geom2d_BSplineCurve::SetPole |
1087 | (const Standard_Integer Index, |
1088 | const gp_Pnt2d& P) |
1089 | { |
1090 | if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve : SetPole : index and #pole mismatch"); |
1091 | poles->SetValue (Index, P); |
1092 | maxderivinvok = 0; |
1093 | InvalidateCache(); |
1094 | } |
1095 | |
1096 | //======================================================================= |
1097 | //function : SetPole |
1098 | //purpose : |
1099 | //======================================================================= |
1100 | |
1101 | void Geom2d_BSplineCurve::SetPole |
1102 | (const Standard_Integer Index, |
1103 | const gp_Pnt2d& P, |
1104 | const Standard_Real W) |
1105 | { |
1106 | SetPole(Index,P); |
1107 | SetWeight(Index,W); |
1108 | } |
1109 | |
1110 | //======================================================================= |
1111 | //function : SetWeight |
1112 | //purpose : |
1113 | //======================================================================= |
1114 | |
1115 | void Geom2d_BSplineCurve::SetWeight |
1116 | (const Standard_Integer Index, |
1117 | const Standard_Real W) |
1118 | { |
1119 | if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve : SetWeight: Index and #pole mismatch"); |
1120 | |
1121 | if (W <= gp::Resolution ()) Standard_ConstructionError::Raise("BSpline curve : SetWeight: Weight too small"); |
1122 | |
1123 | |
1124 | Standard_Boolean rat = IsRational() || (Abs(W - 1.) > gp::Resolution()); |
1125 | |
1126 | if ( rat) { |
1127 | if (rat && !IsRational()) { |
1128 | weights = new TColStd_HArray1OfReal(1,poles->Length()); |
1129 | weights->Init(1.); |
1130 | } |
1131 | |
1132 | weights->SetValue (Index, W); |
1133 | |
1134 | if (IsRational()) { |
1135 | rat = Rational(weights->Array1()); |
1136 | if (!rat) weights.Nullify(); |
1137 | } |
1138 | |
1139 | rational = !weights.IsNull(); |
1140 | } |
1141 | |
1142 | maxderivinvok = 0; |
1143 | InvalidateCache() ; |
1144 | } |
1145 | |
1146 | //======================================================================= |
1147 | //function : MovePoint |
1148 | //purpose : |
1149 | //======================================================================= |
1150 | |
1151 | void Geom2d_BSplineCurve::MovePoint(const Standard_Real U, |
1152 | const gp_Pnt2d& P, |
1153 | const Standard_Integer Index1, |
1154 | const Standard_Integer Index2, |
1155 | Standard_Integer& FirstModifiedPole, |
1156 | Standard_Integer& LastmodifiedPole) |
1157 | { |
1158 | if (Index1 < 1 || Index1 > poles->Length() || |
1159 | Index2 < 1 || Index2 > poles->Length() || Index1 > Index2) { |
1160 | Standard_OutOfRange::Raise("BSpline curve : MovePoint: Index and #pole mismatch"); |
1161 | } |
1162 | TColgp_Array1OfPnt2d npoles(1, poles->Length()); |
1163 | gp_Pnt2d P0; |
1164 | D0(U, P0); |
1165 | gp_Vec2d Displ(P0, P); |
1166 | BSplCLib::MovePoint(U, Displ, Index1, Index2, deg, rational, poles->Array1(), |
1167 | weights->Array1(), flatknots->Array1(), |
1168 | FirstModifiedPole, LastmodifiedPole, npoles); |
1169 | if (FirstModifiedPole) { |
1170 | poles->ChangeArray1() = npoles; |
1171 | maxderivinvok = 0; |
1172 | InvalidateCache() ; |
1173 | } |
1174 | } |
1175 | |
1176 | //======================================================================= |
1177 | //function : MovePointAndTangent |
1178 | //purpose : |
1179 | //======================================================================= |
1180 | |
1181 | void Geom2d_BSplineCurve:: |
1182 | MovePointAndTangent(const Standard_Real U, |
1183 | const gp_Pnt2d& P, |
1184 | const gp_Vec2d& Tangent, |
1185 | const Standard_Real Tolerance, |
1186 | const Standard_Integer StartingCondition, |
1187 | const Standard_Integer EndingCondition, |
1188 | Standard_Integer& ErrorStatus) |
1189 | { |
1190 | Standard_Integer ii ; |
1191 | if (IsPeriodic()) { |
1192 | // |
1193 | // for the time being do not deal with periodic curves |
1194 | // |
1195 | SetNotPeriodic() ; |
1196 | } |
1197 | TColgp_Array1OfPnt2d new_poles(1, poles->Length()); |
1198 | gp_Pnt2d P0; |
1199 | |
1200 | |
1201 | gp_Vec2d delta_derivative; |
1202 | D1(U, P0, |
1203 | delta_derivative) ; |
1204 | gp_Vec2d delta(P0, P); |
1205 | for (ii = 1 ; ii <= 2 ; ii++) { |
1206 | delta_derivative.SetCoord(ii, |
1207 | Tangent.Coord(ii)- delta_derivative.Coord(ii)) ; |
1208 | } |
1209 | BSplCLib::MovePointAndTangent(U, |
1210 | delta, |
1211 | delta_derivative, |
1212 | Tolerance, |
1213 | deg, |
1214 | rational, |
1215 | StartingCondition, |
1216 | EndingCondition, |
1217 | poles->Array1(), |
1218 | weights->Array1(), |
1219 | flatknots->Array1(), |
1220 | new_poles, |
1221 | ErrorStatus) ; |
1222 | if (!ErrorStatus) { |
1223 | poles->ChangeArray1() = new_poles; |
1224 | maxderivinvok = 0; |
1225 | InvalidateCache() ; |
1226 | } |
1227 | } |
1228 | |
1229 | //======================================================================= |
1230 | //function : UpdateKnots |
1231 | //purpose : |
1232 | //======================================================================= |
1233 | |
1234 | void Geom2d_BSplineCurve::UpdateKnots() |
1235 | { |
1236 | |
1237 | rational = !weights.IsNull(); |
1238 | |
1239 | Standard_Integer MaxKnotMult = 0; |
06be28a4 |
1240 | BSplCLib::KnotAnalysis (deg, |
7fd59977 |
1241 | periodic, |
1242 | knots->Array1(), |
1243 | mults->Array1(), |
1244 | knotSet, MaxKnotMult); |
1245 | |
1246 | if (knotSet == GeomAbs_Uniform && !periodic) { |
1247 | flatknots = knots; |
1248 | } |
1249 | else { |
1250 | flatknots = new TColStd_HArray1OfReal |
1251 | (1, BSplCLib::KnotSequenceLength(mults->Array1(),deg,periodic)); |
1252 | |
1253 | BSplCLib::KnotSequence (knots->Array1(), |
1254 | mults->Array1(), |
1255 | deg,periodic, |
1256 | flatknots->ChangeArray1()); |
1257 | } |
1258 | |
1259 | if (MaxKnotMult == 0) smooth = GeomAbs_CN; |
1260 | else { |
1261 | switch (deg - MaxKnotMult) { |
1262 | case 0 : smooth = GeomAbs_C0; break; |
1263 | case 1 : smooth = GeomAbs_C1; break; |
1264 | case 2 : smooth = GeomAbs_C2; break; |
1265 | case 3 : smooth = GeomAbs_C3; break; |
1266 | default : smooth = GeomAbs_C3; break; |
1267 | } |
1268 | } |
1269 | InvalidateCache() ; |
1270 | } |
1271 | |
1272 | //======================================================================= |
1273 | //function : Invalidate the Cache |
1274 | //purpose : as the name says |
1275 | //======================================================================= |
1276 | |
1277 | void Geom2d_BSplineCurve::InvalidateCache() |
1278 | { |
1279 | validcache = 0 ; |
1280 | } |
1281 | |
1282 | //======================================================================= |
1283 | //function : check if the Cache is valid |
1284 | //purpose : as the name says |
1285 | //======================================================================= |
1286 | |
1287 | Standard_Boolean Geom2d_BSplineCurve::IsCacheValid |
1288 | (const Standard_Real U) const |
1289 | { |
1290 | //Roman Lygin 26.12.08, see comments in Geom_BSplineCurve::IsCacheValid() |
1291 | Standard_Real aDelta = U - parametercache; |
1292 | |
1293 | return ( validcache && |
1294 | (aDelta >= 0.0e0) && |
1295 | ((aDelta < spanlenghtcache) || (spanindexcache == flatknots->Upper() - deg)) ); |
1296 | } |
1297 | |
1298 | //======================================================================= |
1299 | //function : Normalizes the parameters if the curve is periodic |
1300 | //purpose : that is compute the cache so that it is valid |
1301 | //======================================================================= |
1302 | |
1303 | void Geom2d_BSplineCurve::PeriodicNormalization(Standard_Real& Parameter) const |
1304 | { |
1305 | Standard_Real Period ; |
1306 | |
1307 | if (periodic) { |
1308 | Period = flatknots->Value(flatknots->Upper() - deg) - flatknots->Value (deg + 1) ; |
1309 | while (Parameter > flatknots->Value(flatknots->Upper()-deg)) { |
1310 | Parameter -= Period ; |
1311 | } |
1312 | while (Parameter < flatknots->Value((deg + 1))) { |
1313 | Parameter += Period ; |
1314 | } |
1315 | } |
1316 | } |
1317 | |
1318 | //======================================================================= |
1319 | //function : Validate the Cache |
1320 | //purpose : that is compute the cache so that it is valid |
1321 | //======================================================================= |
1322 | |
1323 | void Geom2d_BSplineCurve::ValidateCache(const Standard_Real Parameter) |
1324 | { |
1325 | Standard_Real NewParameter ; |
1326 | Standard_Integer LocalIndex = 0 ; |
1327 | // |
1328 | // check if the degree did not change |
1329 | // |
52ba6031 |
1330 | if (cachepoles->Upper() < deg + 1) |
7fd59977 |
1331 | cachepoles = new TColgp_HArray1OfPnt2d(1,deg + 1); |
52ba6031 |
1332 | if (rational) |
1333 | { |
1334 | if (cacheweights.IsNull() || cacheweights->Upper() < deg + 1) |
1335 | cacheweights = new TColStd_HArray1OfReal(1,deg + 1); |
7fd59977 |
1336 | } |
52ba6031 |
1337 | else if (!cacheweights.IsNull()) |
1338 | cacheweights.Nullify(); |
7fd59977 |
1339 | |
1340 | BSplCLib::LocateParameter(deg, |
1341 | (flatknots->Array1()), |
1342 | (BSplCLib::NoMults()), |
1343 | Parameter, |
1344 | periodic, |
1345 | LocalIndex, |
1346 | NewParameter); |
1347 | spanindexcache = LocalIndex ; |
1348 | if (Parameter == flatknots->Value(LocalIndex + 1)) { |
1349 | |
1350 | LocalIndex += 1 ; |
1351 | parametercache = flatknots->Value(LocalIndex) ; |
1352 | if (LocalIndex == flatknots->Upper() - deg) { |
1353 | // |
1354 | // for the last span if the parameter is outside of |
1355 | // the domain of the curve than use the last knot |
1356 | // and normalize with the last span Still set the |
1357 | // spanindexcache to flatknots->Upper() - deg so that |
1358 | // the IsCacheValid will know for sure we are extending |
1359 | // the Bspline |
1360 | // |
1361 | |
1362 | spanlenghtcache = flatknots->Value(LocalIndex - 1) - parametercache ; |
1363 | } |
1364 | else { |
1365 | spanlenghtcache = flatknots->Value(LocalIndex + 1) - parametercache ; |
1366 | } |
1367 | } |
1368 | else { |
1369 | parametercache = flatknots->Value(LocalIndex) ; |
1370 | spanlenghtcache = flatknots->Value(LocalIndex + 1) - parametercache ; |
1371 | } |
1372 | |
1373 | if (rational) { |
1374 | BSplCLib::BuildCache(parametercache, |
1375 | spanlenghtcache, |
1376 | periodic, |
1377 | deg, |
1378 | (flatknots->Array1()), |
1379 | poles->Array1(), |
1380 | weights->Array1(), |
1381 | cachepoles->ChangeArray1(), |
1382 | cacheweights->ChangeArray1()) ; |
1383 | } |
1384 | else { |
1385 | BSplCLib::BuildCache(parametercache, |
1386 | spanlenghtcache, |
1387 | periodic, |
1388 | deg, |
1389 | (flatknots->Array1()), |
1390 | poles->Array1(), |
1391 | *((TColStd_Array1OfReal*) NULL), |
1392 | cachepoles->ChangeArray1(), |
1393 | *((TColStd_Array1OfReal*) NULL)) ; |
1394 | } |
1395 | validcache = 1 ; |
1396 | } |
1397 | |