b311480e |
1 | // Created on: 1993-03-09 |
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 Geom_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, Remove typedefs, Update BSplCLib |
25 | // debug periodic, IncreaseDegree |
7fd59977 |
26 | // 21-Mar-95 : xab implemented cache |
27 | // 14-Mar-96 : xab implemented MovePointAndTangent |
28 | // 13-Oct-96 : pmn Bug dans SetPeriodic (PRO6088) et Segment (PRO6250) |
29 | |
30 | #define No_Standard_OutOfRange |
31 | |
42cf5bc1 |
32 | |
7fd59977 |
33 | #include <BSplCLib.hxx> |
34 | #include <BSplCLib_KnotDistribution.hxx> |
35 | #include <BSplCLib_MultDistribution.hxx> |
42cf5bc1 |
36 | #include <ElCLib.hxx> |
37 | #include <Geom_BSplineCurve.hxx> |
38 | #include <Geom_Geometry.hxx> |
39 | #include <Geom_UndefinedDerivative.hxx> |
40 | #include <gp.hxx> |
41 | #include <gp_Pnt.hxx> |
42 | #include <gp_Trsf.hxx> |
43 | #include <gp_Vec.hxx> |
7fd59977 |
44 | #include <Standard_ConstructionError.hxx> |
42cf5bc1 |
45 | #include <Standard_DimensionError.hxx> |
46 | #include <Standard_DomainError.hxx> |
47 | #include <Standard_NoSuchObject.hxx> |
48 | #include <Standard_NotImplemented.hxx> |
7fd59977 |
49 | #include <Standard_OutOfRange.hxx> |
42cf5bc1 |
50 | #include <Standard_RangeError.hxx> |
7fd59977 |
51 | #include <Standard_Real.hxx> |
42cf5bc1 |
52 | #include <Standard_Type.hxx> |
7fd59977 |
53 | |
92efcf78 |
54 | IMPLEMENT_STANDARD_RTTIEXT(Geom_BSplineCurve,Geom_BoundedCurve) |
55 | |
7fd59977 |
56 | //======================================================================= |
57 | //function : CheckCurveData |
58 | //purpose : Internal use only |
59 | //======================================================================= |
7fd59977 |
60 | static void CheckCurveData |
61 | (const TColgp_Array1OfPnt& CPoles, |
62 | const TColStd_Array1OfReal& CKnots, |
63 | const TColStd_Array1OfInteger& CMults, |
64 | const Standard_Integer Degree, |
65 | const Standard_Boolean Periodic) |
66 | { |
67 | if (Degree < 1 || Degree > Geom_BSplineCurve::MaxDegree()) { |
9775fa61 |
68 | throw Standard_ConstructionError(); |
7fd59977 |
69 | } |
70 | |
9775fa61 |
71 | if (CPoles.Length() < 2) throw Standard_ConstructionError(); |
72 | if (CKnots.Length() != CMults.Length()) throw Standard_ConstructionError(); |
7fd59977 |
73 | |
74 | for (Standard_Integer I = CKnots.Lower(); I < CKnots.Upper(); I++) { |
75 | if (CKnots (I+1) - CKnots (I) <= Epsilon (Abs(CKnots (I)))) { |
9775fa61 |
76 | throw Standard_ConstructionError(); |
7fd59977 |
77 | } |
78 | } |
79 | |
80 | if (CPoles.Length() != BSplCLib::NbPoles(Degree,Periodic,CMults)) |
9775fa61 |
81 | throw Standard_ConstructionError(); |
7fd59977 |
82 | } |
83 | |
7fd59977 |
84 | //======================================================================= |
85 | //function : Rational |
86 | //purpose : check rationality of an array of weights |
87 | //======================================================================= |
88 | |
89 | static Standard_Boolean Rational(const TColStd_Array1OfReal& W) |
90 | { |
91 | Standard_Integer i, n = W.Length(); |
92 | Standard_Boolean rat = Standard_False; |
93 | for (i = 1; i < n; i++) { |
94 | rat = Abs(W(i) - W(i+1)) > gp::Resolution(); |
95 | if (rat) break; |
96 | } |
97 | return rat; |
98 | } |
99 | |
100 | //======================================================================= |
101 | //function : Copy |
102 | //purpose : |
103 | //======================================================================= |
104 | |
105 | Handle(Geom_Geometry) Geom_BSplineCurve::Copy() const |
106 | { |
107 | Handle(Geom_BSplineCurve) C; |
108 | if (IsRational()) |
109 | C = new Geom_BSplineCurve(poles->Array1(), |
110 | weights->Array1(), |
111 | knots->Array1(), |
112 | mults->Array1(), |
113 | deg,periodic); |
114 | else |
115 | C = new Geom_BSplineCurve(poles->Array1(), |
116 | knots->Array1(), |
117 | mults->Array1(), |
118 | deg,periodic); |
119 | return C; |
120 | } |
121 | |
122 | //======================================================================= |
123 | //function : Geom_BSplineCurve |
124 | //purpose : |
125 | //======================================================================= |
126 | |
127 | Geom_BSplineCurve::Geom_BSplineCurve |
128 | (const TColgp_Array1OfPnt& Poles, |
129 | const TColStd_Array1OfReal& Knots, |
130 | const TColStd_Array1OfInteger& Mults, |
131 | const Standard_Integer Degree, |
132 | const Standard_Boolean Periodic) : |
133 | rational(Standard_False), |
134 | periodic(Periodic), |
135 | deg(Degree), |
136 | maxderivinvok(Standard_False) |
137 | { |
138 | // check |
139 | |
94f71cad |
140 | CheckCurveData(Poles, |
141 | Knots, |
142 | Mults, |
143 | Degree, |
144 | Periodic); |
7fd59977 |
145 | |
146 | // copy arrays |
147 | |
148 | poles = new TColgp_HArray1OfPnt(1,Poles.Length()); |
149 | poles->ChangeArray1() = Poles; |
150 | |
151 | |
152 | knots = new TColStd_HArray1OfReal(1,Knots.Length()); |
153 | knots->ChangeArray1() = Knots; |
154 | |
155 | mults = new TColStd_HArray1OfInteger(1,Mults.Length()); |
156 | mults->ChangeArray1() = Mults; |
157 | |
158 | UpdateKnots(); |
7fd59977 |
159 | } |
160 | |
161 | //======================================================================= |
162 | //function : Geom_BSplineCurve |
163 | //purpose : |
164 | //======================================================================= |
165 | |
166 | Geom_BSplineCurve::Geom_BSplineCurve |
167 | (const TColgp_Array1OfPnt& Poles, |
168 | const TColStd_Array1OfReal& Weights, |
169 | const TColStd_Array1OfReal& Knots, |
170 | const TColStd_Array1OfInteger& Mults, |
171 | const Standard_Integer Degree, |
172 | const Standard_Boolean Periodic, |
173 | const Standard_Boolean CheckRational) : |
174 | rational(Standard_True), |
175 | periodic(Periodic), |
176 | deg(Degree), |
177 | maxderivinvok(Standard_False) |
178 | |
179 | { |
180 | |
181 | // check |
182 | |
94f71cad |
183 | CheckCurveData(Poles, |
184 | Knots, |
185 | Mults, |
186 | Degree, |
187 | Periodic); |
7fd59977 |
188 | |
189 | if (Weights.Length() != Poles.Length()) |
9775fa61 |
190 | throw Standard_ConstructionError("Geom_BSplineCurve"); |
7fd59977 |
191 | |
192 | Standard_Integer i; |
193 | for (i = Weights.Lower(); i <= Weights.Upper(); i++) { |
194 | if (Weights(i) <= gp::Resolution()) |
9775fa61 |
195 | throw Standard_ConstructionError("Geom_BSplineCurve"); |
7fd59977 |
196 | } |
197 | |
198 | // check really rational |
199 | if (CheckRational) |
200 | rational = Rational(Weights); |
201 | |
202 | // copy arrays |
203 | |
204 | poles = new TColgp_HArray1OfPnt(1,Poles.Length()); |
205 | poles->ChangeArray1() = Poles; |
7fd59977 |
206 | if (rational) { |
207 | weights = new TColStd_HArray1OfReal(1,Weights.Length()); |
208 | weights->ChangeArray1() = Weights; |
7fd59977 |
209 | } |
210 | |
211 | knots = new TColStd_HArray1OfReal(1,Knots.Length()); |
212 | knots->ChangeArray1() = Knots; |
213 | |
214 | mults = new TColStd_HArray1OfInteger(1,Mults.Length()); |
215 | mults->ChangeArray1() = Mults; |
216 | |
217 | UpdateKnots(); |
7fd59977 |
218 | } |
219 | |
220 | //======================================================================= |
221 | //function : MaxDegree |
222 | //purpose : |
223 | //======================================================================= |
224 | |
225 | Standard_Integer Geom_BSplineCurve::MaxDegree () |
226 | { |
227 | return BSplCLib::MaxDegree(); |
228 | } |
229 | |
230 | //======================================================================= |
231 | //function : IncreaseDegree |
232 | //purpose : |
233 | //======================================================================= |
234 | |
235 | void Geom_BSplineCurve::IncreaseDegree (const Standard_Integer Degree) |
236 | { |
237 | if (Degree == deg) return; |
238 | |
239 | if (Degree < deg || Degree > Geom_BSplineCurve::MaxDegree()) { |
9775fa61 |
240 | throw Standard_ConstructionError(); |
7fd59977 |
241 | } |
242 | Standard_Integer FromK1 = FirstUKnotIndex (); |
243 | Standard_Integer ToK2 = LastUKnotIndex (); |
244 | |
245 | Standard_Integer Step = Degree - deg; |
246 | |
247 | Handle(TColgp_HArray1OfPnt) npoles = new |
248 | TColgp_HArray1OfPnt(1,poles->Length() + Step * (ToK2-FromK1)); |
249 | |
250 | Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots |
251 | (deg,Degree,periodic,mults->Array1()); |
252 | |
253 | Handle(TColStd_HArray1OfReal) nknots = |
254 | new TColStd_HArray1OfReal(1,nbknots); |
255 | |
256 | Handle(TColStd_HArray1OfInteger) nmults = |
257 | new TColStd_HArray1OfInteger(1,nbknots); |
258 | |
259 | Handle(TColStd_HArray1OfReal) nweights; |
260 | |
261 | if (IsRational()) { |
262 | |
263 | nweights = new TColStd_HArray1OfReal(1,npoles->Upper()); |
264 | |
265 | BSplCLib::IncreaseDegree |
266 | (deg,Degree, periodic, |
0e14656b |
267 | poles->Array1(),&weights->Array1(), |
7fd59977 |
268 | knots->Array1(),mults->Array1(), |
0e14656b |
269 | npoles->ChangeArray1(),&nweights->ChangeArray1(), |
7fd59977 |
270 | nknots->ChangeArray1(),nmults->ChangeArray1()); |
271 | } |
272 | else { |
273 | BSplCLib::IncreaseDegree |
274 | (deg,Degree, periodic, |
275 | poles->Array1(),BSplCLib::NoWeights(), |
276 | knots->Array1(),mults->Array1(), |
277 | npoles->ChangeArray1(), |
0e14656b |
278 | BSplCLib::NoWeights(), |
7fd59977 |
279 | nknots->ChangeArray1(),nmults->ChangeArray1()); |
280 | } |
281 | |
282 | deg = Degree; |
283 | poles = npoles; |
284 | weights = nweights; |
285 | knots = nknots; |
286 | mults = nmults; |
287 | UpdateKnots(); |
288 | |
289 | } |
290 | |
291 | //======================================================================= |
292 | //function : IncreaseMultiplicity |
293 | //purpose : |
294 | //======================================================================= |
295 | |
296 | void Geom_BSplineCurve::IncreaseMultiplicity (const Standard_Integer Index, |
297 | const Standard_Integer M) |
298 | { |
299 | TColStd_Array1OfReal k(1,1); |
300 | k(1) = knots->Value(Index); |
301 | TColStd_Array1OfInteger m(1,1); |
302 | m(1) = M - mults->Value(Index); |
303 | InsertKnots(k,m,Epsilon(1.),Standard_True); |
304 | } |
305 | |
306 | //======================================================================= |
307 | //function : IncreaseMultiplicity |
308 | //purpose : |
309 | //======================================================================= |
310 | |
311 | void Geom_BSplineCurve::IncreaseMultiplicity (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 Geom_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 Geom_BSplineCurve::InsertKnot |
347 | (const Standard_Real U, |
348 | const Standard_Integer M, |
349 | const Standard_Real ParametricTolerance, |
350 | const Standard_Boolean Add) |
351 | { |
352 | TColStd_Array1OfReal k(1,1); |
353 | k(1) = U; |
354 | TColStd_Array1OfInteger m(1,1); |
355 | m(1) = M; |
356 | InsertKnots(k,m,ParametricTolerance,Add); |
357 | } |
358 | |
359 | //======================================================================= |
360 | //function : InsertKnots |
361 | //purpose : |
362 | //======================================================================= |
363 | |
364 | void Geom_BSplineCurve::InsertKnots(const TColStd_Array1OfReal& Knots, |
365 | const TColStd_Array1OfInteger& Mults, |
366 | const Standard_Real Epsilon, |
367 | const Standard_Boolean Add) |
368 | { |
369 | // Check and compute new sizes |
370 | Standard_Integer nbpoles,nbknots; |
371 | |
372 | if (!BSplCLib::PrepareInsertKnots(deg,periodic, |
373 | knots->Array1(),mults->Array1(), |
0e14656b |
374 | Knots,&Mults,nbpoles,nbknots,Epsilon,Add)) |
9775fa61 |
375 | throw Standard_ConstructionError("Geom_BSplineCurve::InsertKnots"); |
7fd59977 |
376 | |
377 | if (nbpoles == poles->Length()) return; |
378 | |
379 | Handle(TColgp_HArray1OfPnt) npoles = new TColgp_HArray1OfPnt(1,nbpoles); |
380 | Handle(TColStd_HArray1OfReal) nknots = knots; |
381 | Handle(TColStd_HArray1OfInteger) nmults = mults; |
382 | |
383 | if (nbknots != knots->Length()) { |
384 | nknots = new TColStd_HArray1OfReal(1,nbknots); |
385 | nmults = new TColStd_HArray1OfInteger(1,nbknots); |
386 | } |
387 | |
388 | if (rational) { |
389 | Handle(TColStd_HArray1OfReal) nweights = |
390 | new TColStd_HArray1OfReal(1,nbpoles); |
391 | BSplCLib::InsertKnots(deg,periodic, |
0e14656b |
392 | poles->Array1(), &weights->Array1(), |
7fd59977 |
393 | knots->Array1(), mults->Array1(), |
0e14656b |
394 | Knots, &Mults, |
395 | npoles->ChangeArray1(), &nweights->ChangeArray1(), |
7fd59977 |
396 | nknots->ChangeArray1(), nmults->ChangeArray1(), |
397 | Epsilon, Add); |
398 | weights = nweights; |
399 | } |
400 | else { |
401 | BSplCLib::InsertKnots(deg,periodic, |
402 | poles->Array1(), BSplCLib::NoWeights(), |
403 | knots->Array1(), mults->Array1(), |
0e14656b |
404 | Knots, &Mults, |
7fd59977 |
405 | npoles->ChangeArray1(), |
0e14656b |
406 | BSplCLib::NoWeights(), |
7fd59977 |
407 | nknots->ChangeArray1(), nmults->ChangeArray1(), |
408 | Epsilon, Add); |
409 | } |
410 | |
411 | poles = npoles; |
412 | knots = nknots; |
413 | mults = nmults; |
414 | UpdateKnots(); |
415 | |
416 | } |
417 | |
418 | //======================================================================= |
419 | //function : RemoveKnot |
420 | //purpose : |
421 | //======================================================================= |
422 | |
423 | Standard_Boolean Geom_BSplineCurve::RemoveKnot(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 ( !periodic && (Index <= I1 || Index >= I2) ) { |
9775fa61 |
433 | throw Standard_OutOfRange(); |
7fd59977 |
434 | } |
435 | else if ( periodic && (Index < I1 || Index > I2)) { |
9775fa61 |
436 | throw Standard_OutOfRange(); |
7fd59977 |
437 | } |
438 | |
439 | const TColgp_Array1OfPnt & oldpoles = poles->Array1(); |
440 | |
441 | Standard_Integer step = mults->Value(Index) - M; |
442 | if (step <= 0) return Standard_True; |
443 | |
444 | Handle(TColgp_HArray1OfPnt) npoles = |
445 | new TColgp_HArray1OfPnt(1,oldpoles.Length()-step); |
446 | |
447 | Handle(TColStd_HArray1OfReal) nknots = knots; |
448 | Handle(TColStd_HArray1OfInteger) nmults = mults; |
449 | |
450 | if (M == 0) { |
451 | nknots = new TColStd_HArray1OfReal(1,knots->Length()-1); |
452 | nmults = new TColStd_HArray1OfInteger(1,knots->Length()-1); |
453 | } |
454 | |
455 | if (IsRational()) { |
456 | Handle(TColStd_HArray1OfReal) nweights = |
457 | new TColStd_HArray1OfReal(1,npoles->Length()); |
458 | if (!BSplCLib::RemoveKnot |
459 | (Index, M, deg, periodic, |
0e14656b |
460 | poles->Array1(),&weights->Array1(), |
7fd59977 |
461 | knots->Array1(),mults->Array1(), |
0e14656b |
462 | npoles->ChangeArray1(), &nweights->ChangeArray1(), |
7fd59977 |
463 | nknots->ChangeArray1(),nmults->ChangeArray1(), |
464 | Tolerance)) |
465 | return Standard_False; |
466 | weights = nweights; |
467 | } |
468 | else { |
469 | if (!BSplCLib::RemoveKnot |
470 | (Index, M, deg, periodic, |
471 | poles->Array1(), BSplCLib::NoWeights(), |
472 | knots->Array1(),mults->Array1(), |
473 | npoles->ChangeArray1(), |
0e14656b |
474 | BSplCLib::NoWeights(), |
7fd59977 |
475 | nknots->ChangeArray1(),nmults->ChangeArray1(), |
476 | Tolerance)) |
477 | return Standard_False; |
478 | } |
479 | |
480 | poles = npoles; |
481 | knots = nknots; |
482 | mults = nmults; |
483 | |
484 | UpdateKnots(); |
485 | maxderivinvok = 0; |
486 | return Standard_True; |
487 | } |
488 | |
489 | //======================================================================= |
490 | //function : Reverse |
491 | //purpose : |
492 | //======================================================================= |
493 | |
494 | void Geom_BSplineCurve::Reverse () |
495 | { |
496 | BSplCLib::Reverse(knots->ChangeArray1()); |
497 | BSplCLib::Reverse(mults->ChangeArray1()); |
498 | Standard_Integer last; |
499 | if (periodic) |
500 | last = flatknots->Upper() - deg - 1; |
501 | else |
502 | last = poles->Upper(); |
503 | BSplCLib::Reverse(poles->ChangeArray1(),last); |
504 | if (rational) |
505 | BSplCLib::Reverse(weights->ChangeArray1(),last); |
506 | UpdateKnots(); |
507 | } |
508 | |
509 | //======================================================================= |
510 | //function : ReversedParameter |
511 | //purpose : |
512 | //======================================================================= |
513 | |
514 | Standard_Real Geom_BSplineCurve::ReversedParameter |
515 | (const Standard_Real U) const |
516 | { |
517 | return (FirstParameter() + LastParameter() - U); |
518 | } |
519 | |
520 | //======================================================================= |
521 | //function : Segment |
522 | //purpose : |
523 | //======================================================================= |
524 | |
525 | void Geom_BSplineCurve::Segment(const Standard_Real U1, |
526 | const Standard_Real U2) |
527 | { |
369a38aa |
528 | if (U2 < U1) |
9775fa61 |
529 | throw Standard_DomainError("Geom_BSplineCurve::Segment"); |
7fd59977 |
530 | |
531 | Standard_Real NewU1, NewU2; |
532 | Standard_Real U,DU=0,aDDU=0; |
533 | Standard_Integer index; |
534 | Standard_Boolean wasPeriodic = periodic; |
535 | |
536 | TColStd_Array1OfReal Knots(1,2); |
537 | TColStd_Array1OfInteger Mults(1,2); |
538 | |
539 | // define param ditance to keep (eap, Apr 18 2002, occ311) |
540 | if (periodic) { |
541 | Standard_Real Period = LastParameter() - FirstParameter(); |
542 | DU = U2 - U1; |
369a38aa |
543 | if (DU - Period > Precision::PConfusion()) |
9775fa61 |
544 | throw Standard_DomainError("Geom_BSplineCurve::Segment"); |
369a38aa |
545 | if (DU > Period) |
7fd59977 |
546 | DU = Period; |
547 | aDDU = DU; |
548 | } |
549 | |
550 | index = 0; |
551 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), |
552 | U1,periodic,knots->Lower(),knots->Upper(), |
553 | index,NewU1); |
554 | index = 0; |
555 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), |
556 | U2,periodic,knots->Lower(),knots->Upper(), |
557 | index,NewU2); |
558 | |
559 | //-- DBB |
560 | Standard_Real aNu2 = NewU2; |
561 | //-- DBB |
562 | |
563 | |
564 | Knots( 1) = Min( NewU1, NewU2); |
565 | Knots( 2) = Max( NewU1, NewU2); |
566 | Mults( 1) = Mults( 2) = deg; |
567 | |
568 | Standard_Real AbsUMax = Max(Abs(NewU1),Abs(NewU2)); |
569 | |
570 | // Modified by Sergey KHROMOV - Fri Apr 11 12:15:40 2003 Begin |
571 | AbsUMax = Max(AbsUMax, Max(Abs(FirstParameter()),Abs(LastParameter()))); |
572 | // Modified by Sergey KHROMOV - Fri Apr 11 12:15:40 2003 End |
573 | |
574 | Standard_Real Eps = 100. * Epsilon(AbsUMax); |
575 | |
576 | InsertKnots( Knots, Mults, Eps); |
577 | |
578 | if (periodic) { // set the origine at NewU1 |
579 | index = 0; |
580 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), |
581 | U1,periodic,knots->Lower(),knots->Upper(), |
582 | index,U); |
583 | // Test si l'insertion est Ok et decalage sinon. |
584 | if ( Abs(knots->Value(index+1)-U) <= Eps) // <= pour etre homogene a InsertKnots |
585 | index++; |
586 | SetOrigin(index); |
587 | SetNotPeriodic(); |
588 | NewU2 = NewU1 + DU; |
589 | } |
590 | |
591 | // compute index1 and index2 to set the new knots and mults |
592 | Standard_Integer index1 = 0, index2 = 0; |
593 | Standard_Integer FromU1 = knots->Lower(); |
594 | Standard_Integer ToU2 = knots->Upper(); |
595 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), |
596 | NewU1,periodic,FromU1,ToU2,index1,U); |
597 | if ( Abs(knots->Value(index1+1)-U) <= Eps) |
598 | index1++; |
599 | |
600 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), |
601 | NewU2,periodic,FromU1,ToU2,index2,U); |
94f71cad |
602 | if ( Abs(knots->Value(index2+1)-U) <= Eps || index2 == index1) |
7fd59977 |
603 | index2++; |
604 | |
605 | Standard_Integer nbknots = index2 - index1 + 1; |
606 | |
607 | Handle(TColStd_HArray1OfReal) |
608 | nknots = new TColStd_HArray1OfReal(1,nbknots); |
609 | Handle(TColStd_HArray1OfInteger) |
610 | nmults = new TColStd_HArray1OfInteger(1,nbknots); |
611 | |
612 | // to restore changed U1 |
613 | if (DU > 0) // if was periodic |
614 | DU = NewU1 - U1; |
615 | |
616 | Standard_Integer i , k = 1; |
617 | for ( i = index1; i<= index2; i++) { |
618 | nknots->SetValue(k, knots->Value(i) - DU); |
619 | nmults->SetValue(k, mults->Value(i)); |
620 | k++; |
621 | } |
622 | nmults->SetValue( 1, deg + 1); |
623 | nmults->SetValue(nbknots, deg + 1); |
624 | |
625 | |
626 | // compute index1 and index2 to set the new poles and weights |
627 | Standard_Integer pindex1 |
628 | = BSplCLib::PoleIndex(deg,index1,periodic,mults->Array1()); |
629 | Standard_Integer pindex2 |
630 | = BSplCLib::PoleIndex(deg,index2,periodic,mults->Array1()); |
631 | |
632 | pindex1++; |
633 | pindex2 = Min( pindex2+1, poles->Length()); |
634 | |
635 | Standard_Integer nbpoles = pindex2 - pindex1 + 1; |
636 | |
637 | Handle(TColStd_HArray1OfReal) |
638 | nweights = new TColStd_HArray1OfReal(1,nbpoles); |
639 | Handle(TColgp_HArray1OfPnt) |
640 | npoles = new TColgp_HArray1OfPnt(1,nbpoles); |
641 | |
642 | k = 1; |
643 | if ( rational) { |
644 | nweights = new TColStd_HArray1OfReal( 1, nbpoles); |
645 | for ( i = pindex1; i <= pindex2; i++) { |
646 | npoles->SetValue(k, poles->Value(i)); |
647 | nweights->SetValue(k, weights->Value(i)); |
648 | k++; |
649 | } |
650 | } |
651 | else { |
652 | for ( i = pindex1; i <= pindex2; i++) { |
653 | npoles->SetValue(k, poles->Value(i)); |
654 | k++; |
655 | } |
656 | } |
657 | |
658 | //-- DBB |
659 | if( wasPeriodic ) { |
660 | nknots->ChangeValue(nknots->Lower()) = U1; |
661 | if( aNu2 < U2 ) { |
662 | nknots->ChangeValue(nknots->Upper()) = U1 + aDDU; |
663 | } |
664 | } |
665 | //-- DBB |
666 | |
667 | knots = nknots; |
668 | mults = nmults; |
669 | poles = npoles; |
670 | if ( rational) |
671 | weights = nweights; |
672 | |
673 | maxderivinvok = 0; |
674 | UpdateKnots(); |
675 | } |
676 | |
677 | //======================================================================= |
678 | //function : SetKnot |
679 | //purpose : |
680 | //======================================================================= |
681 | |
682 | void Geom_BSplineCurve::SetKnot |
683 | (const Standard_Integer Index, |
684 | const Standard_Real K) |
685 | { |
9775fa61 |
686 | if (Index < 1 || Index > knots->Length()) throw Standard_OutOfRange(); |
7fd59977 |
687 | Standard_Real DK = Abs(Epsilon (K)); |
688 | if (Index == 1) { |
9775fa61 |
689 | if (K >= knots->Value(2) - DK) throw Standard_ConstructionError(); |
7fd59977 |
690 | } |
691 | else if (Index == knots->Length()) { |
692 | if (K <= knots->Value (knots->Length()-1) + DK) { |
9775fa61 |
693 | throw Standard_ConstructionError(); |
7fd59977 |
694 | } |
695 | } |
696 | else { |
697 | if (K <= knots->Value(Index-1) + DK || |
698 | K >= knots->Value(Index+1) - DK ) { |
9775fa61 |
699 | throw Standard_ConstructionError(); |
7fd59977 |
700 | } |
701 | } |
702 | if (K != knots->Value (Index)) { |
703 | knots->SetValue (Index, K); |
704 | maxderivinvok = 0; |
705 | UpdateKnots(); |
706 | } |
707 | } |
708 | |
709 | //======================================================================= |
710 | //function : SetKnots |
711 | //purpose : |
712 | //======================================================================= |
713 | |
714 | void Geom_BSplineCurve::SetKnots |
715 | (const TColStd_Array1OfReal& K) |
716 | { |
717 | CheckCurveData(poles->Array1(),K,mults->Array1(),deg,periodic); |
718 | knots->ChangeArray1() = K; |
719 | maxderivinvok = 0; |
720 | UpdateKnots(); |
721 | } |
722 | |
723 | //======================================================================= |
724 | //function : SetKnot |
725 | //purpose : |
726 | //======================================================================= |
727 | |
728 | void Geom_BSplineCurve::SetKnot |
729 | (const Standard_Integer Index, |
730 | const Standard_Real K, |
731 | const Standard_Integer M) |
732 | { |
733 | IncreaseMultiplicity (Index, M); |
734 | SetKnot (Index, K); |
735 | } |
736 | |
737 | //======================================================================= |
738 | //function : SetPeriodic |
739 | //purpose : |
740 | //======================================================================= |
741 | |
742 | void Geom_BSplineCurve::SetPeriodic () |
743 | { |
744 | Standard_Integer first = FirstUKnotIndex(); |
745 | Standard_Integer last = LastUKnotIndex(); |
746 | |
747 | Handle(TColStd_HArray1OfReal) tk = knots; |
748 | TColStd_Array1OfReal cknots((knots->Array1())(first),first,last); |
749 | knots = new TColStd_HArray1OfReal(1,cknots.Length()); |
750 | knots->ChangeArray1() = cknots; |
751 | |
752 | Handle(TColStd_HArray1OfInteger) tm = mults; |
753 | TColStd_Array1OfInteger cmults((mults->Array1())(first),first,last); |
754 | cmults(first) = cmults(last) = Min(deg, Max( cmults(first), cmults(last))); |
755 | mults = new TColStd_HArray1OfInteger(1,cmults.Length()); |
756 | mults->ChangeArray1() = cmults; |
757 | |
758 | // compute new number of poles; |
759 | Standard_Integer nbp = BSplCLib::NbPoles(deg,Standard_True,cmults); |
760 | |
761 | Handle(TColgp_HArray1OfPnt) tp = poles; |
762 | TColgp_Array1OfPnt cpoles((poles->Array1())(1),1,nbp); |
763 | poles = new TColgp_HArray1OfPnt(1,nbp); |
764 | poles->ChangeArray1() = cpoles; |
765 | |
766 | if (rational) { |
767 | Handle(TColStd_HArray1OfReal) tw = weights; |
768 | TColStd_Array1OfReal cweights((weights->Array1())(1),1,nbp); |
769 | weights = new TColStd_HArray1OfReal(1,nbp); |
770 | weights->ChangeArray1() = cweights; |
771 | } |
772 | |
773 | periodic = Standard_True; |
774 | |
775 | maxderivinvok = 0; |
776 | UpdateKnots(); |
777 | } |
778 | |
779 | //======================================================================= |
780 | //function : SetOrigin |
781 | //purpose : |
782 | //======================================================================= |
783 | |
784 | void Geom_BSplineCurve::SetOrigin(const Standard_Integer Index) |
785 | { |
369a38aa |
786 | if (!periodic) |
9775fa61 |
787 | throw Standard_NoSuchObject("Geom_BSplineCurve::SetOrigin"); |
369a38aa |
788 | |
7fd59977 |
789 | Standard_Integer i,k; |
790 | Standard_Integer first = FirstUKnotIndex(); |
791 | Standard_Integer last = LastUKnotIndex(); |
792 | |
369a38aa |
793 | if ((Index < first) || (Index > last)) |
9775fa61 |
794 | throw Standard_DomainError("Geom_BSplineCurve::SetOrigin"); |
7fd59977 |
795 | |
796 | Standard_Integer nbknots = knots->Length(); |
797 | Standard_Integer nbpoles = poles->Length(); |
798 | |
799 | Handle(TColStd_HArray1OfReal) nknots = |
800 | new TColStd_HArray1OfReal(1,nbknots); |
801 | TColStd_Array1OfReal& newknots = nknots->ChangeArray1(); |
802 | |
803 | Handle(TColStd_HArray1OfInteger) nmults = |
804 | new TColStd_HArray1OfInteger(1,nbknots); |
805 | TColStd_Array1OfInteger& newmults = nmults->ChangeArray1(); |
806 | |
807 | // set the knots and mults |
808 | Standard_Real period = knots->Value(last) - knots->Value(first); |
809 | k = 1; |
810 | for ( i = Index; i <= last ; i++) { |
811 | newknots(k) = knots->Value(i); |
812 | newmults(k) = mults->Value(i); |
813 | k++; |
814 | } |
815 | for ( i = first+1; i <= Index; i++) { |
816 | newknots(k) = knots->Value(i) + period; |
817 | newmults(k) = mults->Value(i); |
818 | k++; |
819 | } |
820 | |
821 | Standard_Integer index = 1; |
822 | for (i = first+1; i <= Index; i++) |
823 | index += mults->Value(i); |
824 | |
825 | // set the poles and weights |
826 | Handle(TColgp_HArray1OfPnt) npoles = |
827 | new TColgp_HArray1OfPnt(1,nbpoles); |
828 | Handle(TColStd_HArray1OfReal) nweights = |
829 | new TColStd_HArray1OfReal(1,nbpoles); |
830 | TColgp_Array1OfPnt & newpoles = npoles->ChangeArray1(); |
831 | TColStd_Array1OfReal & newweights = nweights->ChangeArray1(); |
832 | first = poles->Lower(); |
833 | last = poles->Upper(); |
834 | if ( rational) { |
835 | k = 1; |
836 | for ( i = index; i <= last; i++) { |
837 | newpoles(k) = poles->Value(i); |
838 | newweights(k) = weights->Value(i); |
839 | k++; |
840 | } |
841 | for ( i = first; i < index; i++) { |
842 | newpoles(k) = poles->Value(i); |
843 | newweights(k) = weights->Value(i); |
844 | k++; |
845 | } |
846 | } |
847 | else { |
848 | k = 1; |
849 | for ( i = index; i <= last; i++) { |
850 | newpoles(k) = poles->Value(i); |
851 | k++; |
852 | } |
853 | for ( i = first; i < index; i++) { |
854 | newpoles(k) = poles->Value(i); |
855 | k++; |
856 | } |
857 | } |
858 | |
859 | poles = npoles; |
860 | knots = nknots; |
861 | mults = nmults; |
862 | if (rational) |
863 | weights = nweights; |
864 | maxderivinvok = 0; |
865 | UpdateKnots(); |
866 | } |
867 | |
868 | //======================================================================= |
869 | //function : SetOrigin |
870 | //purpose : |
871 | //======================================================================= |
872 | |
873 | void Geom_BSplineCurve::SetOrigin(const Standard_Real U, |
874 | const Standard_Real Tol) |
875 | { |
369a38aa |
876 | if (!periodic) |
9775fa61 |
877 | throw Standard_NoSuchObject("Geom_BSplineCurve::SetOrigin"); |
7fd59977 |
878 | //U est il dans la period. |
879 | Standard_Real uf = FirstParameter(), ul = LastParameter(); |
880 | Standard_Real u = U, period = ul - uf; |
881 | while (Tol < (uf-u)) u += period; |
882 | while (Tol > (ul-u)) u -= period; |
883 | |
884 | if(Abs(U-u)>Tol) { //On reparametre la courbe |
885 | Standard_Real delta = U-u; |
886 | uf += delta; |
887 | ul += delta; |
888 | TColStd_Array1OfReal& kn = knots->ChangeArray1(); |
889 | Standard_Integer fk = kn.Lower(), lk = kn.Upper(); |
890 | for(Standard_Integer i = fk; i <= lk; i++){ |
891 | kn.ChangeValue(i) += delta; |
892 | } |
893 | UpdateKnots(); |
894 | } |
895 | if(Abs(U-uf)<Tol) return; |
896 | |
897 | TColStd_Array1OfReal& kn = knots->ChangeArray1(); |
898 | Standard_Integer fk = kn.Lower(), lk = kn.Upper(),ik=0; |
899 | Standard_Real delta = RealLast(); |
900 | for(Standard_Integer i = fk; i<= lk; i++){ |
901 | Standard_Real dki = kn.Value(i)-U; |
902 | if(Abs(dki)<Abs(delta)){ |
903 | ik = i; |
904 | delta = dki; |
905 | } |
906 | } |
907 | if(Abs(delta)>Tol){ |
908 | InsertKnot(U); |
909 | if(delta < 0.) ik++; |
910 | } |
911 | SetOrigin(ik); |
912 | } |
913 | |
914 | //======================================================================= |
915 | //function : SetNotPeriodic |
916 | //purpose : |
917 | //======================================================================= |
918 | |
919 | void Geom_BSplineCurve::SetNotPeriodic () |
920 | { |
921 | if ( periodic) { |
922 | Standard_Integer NbKnots, NbPoles; |
923 | BSplCLib::PrepareUnperiodize( deg, mults->Array1(),NbKnots,NbPoles); |
924 | |
925 | Handle(TColgp_HArray1OfPnt) npoles |
926 | = new TColgp_HArray1OfPnt(1,NbPoles); |
927 | |
928 | Handle(TColStd_HArray1OfReal) nknots |
929 | = new TColStd_HArray1OfReal(1,NbKnots); |
930 | |
931 | Handle(TColStd_HArray1OfInteger) nmults |
932 | = new TColStd_HArray1OfInteger(1,NbKnots); |
933 | |
934 | Handle(TColStd_HArray1OfReal) nweights; |
935 | |
936 | if (IsRational()) { |
937 | |
938 | nweights = new TColStd_HArray1OfReal(1,NbPoles); |
939 | |
940 | BSplCLib::Unperiodize |
941 | (deg,mults->Array1(),knots->Array1(),poles->Array1(), |
0e14656b |
942 | &weights->Array1(),nmults->ChangeArray1(), |
7fd59977 |
943 | nknots->ChangeArray1(),npoles->ChangeArray1(), |
0e14656b |
944 | &nweights->ChangeArray1()); |
7fd59977 |
945 | |
946 | } |
947 | else { |
948 | |
949 | BSplCLib::Unperiodize |
950 | (deg,mults->Array1(),knots->Array1(),poles->Array1(), |
951 | BSplCLib::NoWeights(),nmults->ChangeArray1(), |
952 | nknots->ChangeArray1(),npoles->ChangeArray1(), |
0e14656b |
953 | BSplCLib::NoWeights()); |
7fd59977 |
954 | |
955 | } |
956 | poles = npoles; |
957 | weights = nweights; |
958 | mults = nmults; |
959 | knots = nknots; |
960 | periodic = Standard_False; |
961 | |
962 | maxderivinvok = 0; |
963 | UpdateKnots(); |
964 | } |
965 | } |
966 | |
967 | //======================================================================= |
968 | //function : SetPole |
969 | //purpose : |
970 | //======================================================================= |
971 | |
972 | void Geom_BSplineCurve::SetPole |
973 | (const Standard_Integer Index, |
974 | const gp_Pnt& P) |
975 | { |
9775fa61 |
976 | if (Index < 1 || Index > poles->Length()) throw Standard_OutOfRange(); |
7fd59977 |
977 | poles->SetValue (Index, P); |
978 | maxderivinvok = 0; |
7fd59977 |
979 | } |
980 | |
981 | //======================================================================= |
982 | //function : SetPole |
983 | //purpose : |
984 | //======================================================================= |
985 | |
986 | void Geom_BSplineCurve::SetPole |
987 | (const Standard_Integer Index, |
988 | const gp_Pnt& P, |
989 | const Standard_Real W) |
990 | { |
991 | SetPole(Index,P); |
992 | SetWeight(Index,W); |
993 | } |
994 | |
995 | //======================================================================= |
996 | //function : SetWeight |
997 | //purpose : |
998 | //======================================================================= |
999 | |
1000 | void Geom_BSplineCurve::SetWeight |
1001 | (const Standard_Integer Index, |
1002 | const Standard_Real W) |
1003 | { |
9775fa61 |
1004 | if (Index < 1 || Index > poles->Length()) throw Standard_OutOfRange(); |
7fd59977 |
1005 | |
9775fa61 |
1006 | if (W <= gp::Resolution ()) throw Standard_ConstructionError(); |
7fd59977 |
1007 | |
1008 | |
1009 | Standard_Boolean rat = IsRational() || (Abs(W - 1.) > gp::Resolution()); |
1010 | |
1011 | if ( rat) { |
1012 | if (rat && !IsRational()) { |
1013 | weights = new TColStd_HArray1OfReal(1,poles->Length()); |
1014 | weights->Init(1.); |
1015 | } |
1016 | |
1017 | weights->SetValue (Index, W); |
1018 | |
1019 | if (IsRational()) { |
1020 | rat = Rational(weights->Array1()); |
1021 | if (!rat) weights.Nullify(); |
1022 | } |
1023 | |
1024 | rational = !weights.IsNull(); |
1025 | } |
1026 | maxderivinvok = 0; |
7fd59977 |
1027 | } |
1028 | |
1029 | //======================================================================= |
1030 | //function : MovePoint |
1031 | //purpose : |
1032 | //======================================================================= |
1033 | |
1034 | void Geom_BSplineCurve::MovePoint(const Standard_Real U, |
94f71cad |
1035 | const gp_Pnt& P, |
1036 | const Standard_Integer Index1, |
1037 | const Standard_Integer Index2, |
1038 | Standard_Integer& FirstModifiedPole, |
1039 | Standard_Integer& LastmodifiedPole) |
7fd59977 |
1040 | { |
1041 | if (Index1 < 1 || Index1 > poles->Length() || |
1042 | Index2 < 1 || Index2 > poles->Length() || Index1 > Index2) { |
9775fa61 |
1043 | throw Standard_OutOfRange(); |
7fd59977 |
1044 | } |
1045 | TColgp_Array1OfPnt npoles(1, poles->Length()); |
1046 | gp_Pnt P0; |
1047 | D0(U, P0); |
1048 | gp_Vec Displ(P0, P); |
1049 | BSplCLib::MovePoint(U, Displ, Index1, Index2, deg, rational, poles->Array1(), |
94f71cad |
1050 | weights->Array1(), flatknots->Array1(), |
1051 | FirstModifiedPole, LastmodifiedPole, npoles); |
7fd59977 |
1052 | if (FirstModifiedPole) { |
1053 | poles->ChangeArray1() = npoles; |
1054 | maxderivinvok = 0; |
7fd59977 |
1055 | } |
1056 | } |
1057 | |
1058 | //======================================================================= |
1059 | //function : MovePointAndTangent |
1060 | //purpose : |
1061 | //======================================================================= |
1062 | |
94f71cad |
1063 | void Geom_BSplineCurve::MovePointAndTangent(const Standard_Real U, |
1064 | const gp_Pnt& P, |
1065 | const gp_Vec& Tangent, |
1066 | const Standard_Real Tolerance, |
1067 | const Standard_Integer StartingCondition, |
1068 | const Standard_Integer EndingCondition, |
1069 | Standard_Integer& ErrorStatus) |
7fd59977 |
1070 | { |
1071 | Standard_Integer ii ; |
1072 | if (IsPeriodic()) { |
1073 | // |
1074 | // for the time being do not deal with periodic curves |
1075 | // |
1076 | SetNotPeriodic() ; |
1077 | } |
1078 | TColgp_Array1OfPnt new_poles(1, poles->Length()); |
1079 | gp_Pnt P0; |
1080 | |
1081 | |
1082 | gp_Vec delta_derivative; |
1083 | D1(U, P0, |
1084 | delta_derivative) ; |
1085 | gp_Vec delta(P0, P); |
1086 | for (ii = 1 ; ii <= 3 ; ii++) { |
94f71cad |
1087 | delta_derivative.SetCoord(ii, Tangent.Coord(ii)-delta_derivative.Coord(ii)); |
7fd59977 |
1088 | } |
1089 | BSplCLib::MovePointAndTangent(U, |
94f71cad |
1090 | delta, |
1091 | delta_derivative, |
1092 | Tolerance, |
1093 | deg, |
1094 | rational, |
1095 | StartingCondition, |
1096 | EndingCondition, |
1097 | poles->Array1(), |
1098 | weights->Array1(), |
1099 | flatknots->Array1(), |
1100 | new_poles, |
1101 | ErrorStatus) ; |
7fd59977 |
1102 | if (!ErrorStatus) { |
1103 | poles->ChangeArray1() = new_poles; |
1104 | maxderivinvok = 0; |
7fd59977 |
1105 | } |
1106 | } |
1107 | |
1108 | //======================================================================= |
1109 | //function : UpdateKnots |
1110 | //purpose : |
1111 | //======================================================================= |
1112 | |
1113 | void Geom_BSplineCurve::UpdateKnots() |
1114 | { |
1115 | rational = !weights.IsNull(); |
1116 | |
1117 | Standard_Integer MaxKnotMult = 0; |
94f71cad |
1118 | BSplCLib::KnotAnalysis(deg, |
1119 | periodic, |
1120 | knots->Array1(), |
1121 | mults->Array1(), |
1122 | knotSet, MaxKnotMult); |
7fd59977 |
1123 | |
1124 | if (knotSet == GeomAbs_Uniform && !periodic) { |
1125 | flatknots = knots; |
1126 | } |
1127 | else { |
1128 | flatknots = new TColStd_HArray1OfReal |
1129 | (1, BSplCLib::KnotSequenceLength(mults->Array1(),deg,periodic)); |
1130 | |
94f71cad |
1131 | BSplCLib::KnotSequence(knots->Array1(), |
1132 | mults->Array1(), |
1133 | deg,periodic, |
1134 | flatknots->ChangeArray1()); |
7fd59977 |
1135 | } |
1136 | |
1137 | if (MaxKnotMult == 0) smooth = GeomAbs_CN; |
1138 | else { |
1139 | switch (deg - MaxKnotMult) { |
1140 | case 0 : smooth = GeomAbs_C0; break; |
1141 | case 1 : smooth = GeomAbs_C1; break; |
1142 | case 2 : smooth = GeomAbs_C2; break; |
1143 | case 3 : smooth = GeomAbs_C3; break; |
1144 | default : smooth = GeomAbs_C3; break; |
1145 | } |
1146 | } |
7fd59977 |
1147 | } |
1148 | |
1149 | //======================================================================= |
1150 | //function : Normalizes the parameters if the curve is periodic |
1151 | //purpose : that is compute the cache so that it is valid |
1152 | //======================================================================= |
1153 | |
1154 | void Geom_BSplineCurve::PeriodicNormalization(Standard_Real& Parameter) const |
1155 | { |
1156 | Standard_Real Period ; |
1157 | |
1158 | if (periodic) { |
1159 | Period = flatknots->Value(flatknots->Upper() - deg) - flatknots->Value (deg + 1) ; |
1160 | while (Parameter > flatknots->Value(flatknots->Upper()-deg)) { |
1161 | Parameter -= Period ; |
1162 | } |
1163 | while (Parameter < flatknots->Value((deg + 1))) { |
1164 | Parameter += Period ; |
1165 | } |
1166 | } |
1167 | } |
1168 | |