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