0026937: Eliminate NO_CXX_EXCEPTION macro support
[occt.git] / src / Geom / Geom_BSplineCurve.cxx
CommitLineData
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 54IMPLEMENT_STANDARD_RTTIEXT(Geom_BSplineCurve,Geom_BoundedCurve)
55
7fd59977 56//=======================================================================
57//function : CheckCurveData
58//purpose : Internal use only
59//=======================================================================
7fd59977 60static 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
89static 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
105Handle(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
127Geom_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
166Geom_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
225Standard_Integer Geom_BSplineCurve::MaxDegree ()
226{
227 return BSplCLib::MaxDegree();
228}
229
230//=======================================================================
231//function : IncreaseDegree
232//purpose :
233//=======================================================================
234
235void 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
296void 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
311void 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
329void 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
346void 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
364void 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
423Standard_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
494void 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
514Standard_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
525void 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
682void 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
714void 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
728void 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
742void 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
784void 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
873void 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
919void 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
972void 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
986void 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
1000void 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
1034void 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 1063void 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
1113void 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
1154void 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