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