1 // Created on: 1995-10-20
2 // Created by: Laurent BOURESCHE
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Cut and past sauvage depuis Geom!?!?
18 // 14-Mar-96 : xab implemented MovePointAndTangent
19 // 03-02-97 : pmn ->LocateU sur Periodic (PRO6963),
20 // bon appel a LocateParameter (PRO6973) et mise en conformite avec
21 // le cdl de LocateU, lorsque U est un noeud (PRO6988)
22
23 #include <BSplCLib.hxx>
24 #include <BSplCLib_KnotDistribution.hxx>
25 #include <BSplCLib_MultDistribution.hxx>
26 #include <gp.hxx>
27 #include <Law_BSpline.hxx>
28 #include <Standard_ConstructionError.hxx>
29 #include <Standard_DimensionError.hxx>
30 #include <Standard_DomainError.hxx>
31 #include <Standard_NoSuchObject.hxx>
32 #include <Standard_NotImplemented.hxx>
33 #include <Standard_OutOfRange.hxx>
34 #include <Standard_RangeError.hxx>
35 #include <Standard_Type.hxx>
36
IMPLEMENT_STANDARD_RTTIEXT(Law_BSpline,Standard_Transient)37 IMPLEMENT_STANDARD_RTTIEXT(Law_BSpline,Standard_Transient)
38
39 #define POLES (poles->Array1())
40 #define KNOTS (knots->Array1())
41 #define FKNOTS (flatknots->Array1())
42 #define FMULTS (BSplCLib::NoMults())
43
44 //=======================================================================
45 //function : SetPoles
46 //purpose :
47 //=======================================================================
48
49 static void SetPoles(const TColStd_Array1OfReal& Poles,
50 const TColStd_Array1OfReal& Weights,
51 TColStd_Array1OfReal& FP)
52 {
53 Standard_Integer i,j = FP.Lower();
54 for (i = Poles.Lower(); i <= Poles.Upper(); i++) {
55 Standard_Real w = Weights(i);
56 FP(j) = Poles(i) * w;
57 j++;
58 FP(j) = w;
59 j++;
60 }
61 }
62
63
64 //=======================================================================
65 //function : GetPoles
66 //purpose :
67 //=======================================================================
68
GetPoles(const TColStd_Array1OfReal & FP,TColStd_Array1OfReal & Poles,TColStd_Array1OfReal & Weights)69 static void GetPoles(const TColStd_Array1OfReal& FP,
70 TColStd_Array1OfReal& Poles,
71 TColStd_Array1OfReal& Weights)
72
73 {
74 Standard_Integer i,j = FP.Lower();
75 for (i = Poles.Lower(); i <= Poles.Upper(); i++) {
76 Standard_Real w = FP(j+1);
77 Weights(i) = w;
78 Poles(i) = FP(j) /w;
79 j+=2;
80 }
81 }
82
83
84 //=======================================================================
85 //function : CheckCurveData
86 //purpose : Internal use only
87 //=======================================================================
88
CheckCurveData(const TColStd_Array1OfReal & CPoles,const TColStd_Array1OfReal & CKnots,const TColStd_Array1OfInteger & CMults,const Standard_Integer Degree,const Standard_Boolean Periodic)89 static void CheckCurveData
90 (const TColStd_Array1OfReal& CPoles,
91 const TColStd_Array1OfReal& CKnots,
92 const TColStd_Array1OfInteger& CMults,
93 const Standard_Integer Degree,
94 const Standard_Boolean Periodic)
95 {
96 if (Degree < 1 || Degree > Law_BSpline::MaxDegree()) {
97 throw Standard_ConstructionError();
98 }
99
100 if (CPoles.Length() < 2) throw Standard_ConstructionError();
101 if (CKnots.Length() != CMults.Length()) throw Standard_ConstructionError();
102
103 for (Standard_Integer I = CKnots.Lower(); I < CKnots.Upper(); I++) {
104 if (CKnots (I+1) - CKnots (I) <= Epsilon (Abs(CKnots (I)))) {
105 throw Standard_ConstructionError();
106 }
107 }
108
109 if (CPoles.Length() != BSplCLib::NbPoles(Degree,Periodic,CMults))
110 throw Standard_ConstructionError();
111 }
112
113
114 //=======================================================================
115 //function : KnotAnalysis
116 //purpose : Internal use only
117 //=======================================================================
118
KnotAnalysis(const Standard_Integer Degree,const Standard_Boolean Periodic,const TColStd_Array1OfReal & CKnots,const TColStd_Array1OfInteger & CMults,GeomAbs_BSplKnotDistribution & KnotForm,Standard_Integer & MaxKnotMult)119 static void KnotAnalysis
120 (const Standard_Integer Degree,
121 const Standard_Boolean Periodic,
122 const TColStd_Array1OfReal& CKnots,
123 const TColStd_Array1OfInteger& CMults,
124 GeomAbs_BSplKnotDistribution& KnotForm,
125 Standard_Integer& MaxKnotMult)
126 {
127 KnotForm = GeomAbs_NonUniform;
128
129 BSplCLib_KnotDistribution KSet =
130 BSplCLib::KnotForm (CKnots, 1, CKnots.Length());
131
132
133 if (KSet == BSplCLib_Uniform) {
134 BSplCLib_MultDistribution MSet =
135 BSplCLib::MultForm (CMults, 1, CMults.Length());
136 switch (MSet) {
137 case BSplCLib_NonConstant :
138 break;
139 case BSplCLib_Constant :
140 if (CKnots.Length() == 2) {
141 KnotForm = GeomAbs_PiecewiseBezier;
142 }
143 else {
144 if (CMults (1) == 1) KnotForm = GeomAbs_Uniform;
145 }
146 break;
147 case BSplCLib_QuasiConstant :
148 if (CMults (1) == Degree + 1) {
149 Standard_Real M = CMults (2);
150 if (M == Degree ) KnotForm = GeomAbs_PiecewiseBezier;
151 else if (M == 1) KnotForm = GeomAbs_QuasiUniform;
152 }
153 break;
154 }
155 }
156
157 Standard_Integer FirstKM =
158 Periodic ? CKnots.Lower() : BSplCLib::FirstUKnotIndex (Degree,CMults);
159 Standard_Integer LastKM =
160 Periodic ? CKnots.Upper() : BSplCLib::LastUKnotIndex (Degree,CMults);
161 MaxKnotMult = 0;
162 if (LastKM - FirstKM != 1) {
163 Standard_Integer Multi;
164 for (Standard_Integer i = FirstKM + 1; i < LastKM; i++) {
165 Multi = CMults (i);
166 MaxKnotMult = Max (MaxKnotMult, Multi);
167 }
168 }
169 }
170
171
172 //=======================================================================
173 //function : Rational
174 //purpose : check rationality of an array of weights
175 //=======================================================================
176
Rational(const TColStd_Array1OfReal & W)177 static Standard_Boolean Rational(const TColStd_Array1OfReal& W)
178 {
179 Standard_Integer i, n = W.Length();
180 Standard_Boolean rat = Standard_False;
181 for (i = 1; i < n; i++) {
182 rat = Abs(W(i) - W(i+1)) > gp::Resolution();
183 if (rat) break;
184 }
185 return rat;
186 }
187
188 //=======================================================================
189 //function : Copy
190 //purpose :
191 //=======================================================================
192
Handle(Law_BSpline)193 Handle(Law_BSpline) Law_BSpline::Copy() const
194 {
195 Handle(Law_BSpline) C;
196 if (IsRational())
197 C = new Law_BSpline(poles->Array1(),
198 weights->Array1(),
199 knots->Array1(),
200 mults->Array1(),
201 deg,periodic);
202 else
203 C = new Law_BSpline(poles->Array1(),
204 knots->Array1(),
205 mults->Array1(),
206 deg,periodic);
207 return C;
208 }
209
210
211
212 //=======================================================================
213 //function : Law_BSpline
214 //purpose :
215 //=======================================================================
216
Law_BSpline(const TColStd_Array1OfReal & Poles,const TColStd_Array1OfReal & Knots,const TColStd_Array1OfInteger & Mults,const Standard_Integer Degree,const Standard_Boolean Periodic)217 Law_BSpline::Law_BSpline
218 (const TColStd_Array1OfReal& Poles,
219 const TColStd_Array1OfReal& Knots,
220 const TColStd_Array1OfInteger& Mults,
221 const Standard_Integer Degree,
222 const Standard_Boolean Periodic) :
223 rational(Standard_False),periodic(Periodic), deg(Degree)
224 {
225 // check
226
227 CheckCurveData (Poles,
228 Knots,
229 Mults,
230 Degree,
231 Periodic);
232
233
234 // copy arrays
235
236 poles = new TColStd_HArray1OfReal(1,Poles.Length());
237 poles->ChangeArray1() = Poles;
238
239
240 knots = new TColStd_HArray1OfReal(1,Knots.Length());
241 knots->ChangeArray1() = Knots;
242
243 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
244 mults->ChangeArray1() = Mults;
245
246 UpdateKnots();
247 }
248
249
250
251 //=======================================================================
252 //function : Law_BSpline
253 //purpose :
254 //=======================================================================
255
Law_BSpline(const TColStd_Array1OfReal & Poles,const TColStd_Array1OfReal & Weights,const TColStd_Array1OfReal & Knots,const TColStd_Array1OfInteger & Mults,const Standard_Integer Degree,const Standard_Boolean Periodic)256 Law_BSpline::Law_BSpline
257 (const TColStd_Array1OfReal& Poles,
258 const TColStd_Array1OfReal& Weights,
259 const TColStd_Array1OfReal& Knots,
260 const TColStd_Array1OfInteger& Mults,
261 const Standard_Integer Degree,
262 const Standard_Boolean Periodic) :
263 rational(Standard_True), periodic(Periodic), deg(Degree)
264
265 {
266
267 // check
268
269 CheckCurveData (Poles,
270 Knots,
271 Mults,
272 Degree,
273 Periodic);
274
275 if (Weights.Length() != Poles.Length())
276 throw Standard_ConstructionError("Law_BSpline");
277
278 Standard_Integer i;
279 for (i = Weights.Lower(); i <= Weights.Upper(); i++) {
280 if (Weights(i) <= gp::Resolution())
281 throw Standard_ConstructionError("Law_BSpline");
282 }
283
284 // check really rational
285 rational = Rational(Weights);
286
287 // copy arrays
288
289 poles = new TColStd_HArray1OfReal(1,Poles.Length());
290 poles->ChangeArray1() = Poles;
291 if (rational) {
292 weights = new TColStd_HArray1OfReal(1,Weights.Length());
293 weights->ChangeArray1() = Weights;
294 }
295
296 knots = new TColStd_HArray1OfReal(1,Knots.Length());
297 knots->ChangeArray1() = Knots;
298
299 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
300 mults->ChangeArray1() = Mults;
301
302 UpdateKnots();
303 }
304
305
306 //=======================================================================
307 //function : MaxDegree
308 //purpose :
309 //=======================================================================
310
MaxDegree()311 Standard_Integer Law_BSpline::MaxDegree ()
312 {
313 return BSplCLib::MaxDegree();
314 }
315
316
317 //=======================================================================
318 //function : IncreaseDegree
319 //purpose :
320 //=======================================================================
321
IncreaseDegree(const Standard_Integer Degree)322 void Law_BSpline::IncreaseDegree (const Standard_Integer Degree)
323 {
324 if (Degree == deg) return;
325
326 if (Degree < deg || Degree > Law_BSpline::MaxDegree()) {
327 throw Standard_ConstructionError();
328 }
329
330 Standard_Integer FromK1 = FirstUKnotIndex ();
331 Standard_Integer ToK2 = LastUKnotIndex ();
332
333 Standard_Integer Step = Degree - deg;
334
335 Handle(TColStd_HArray1OfReal) npoles = new
336 TColStd_HArray1OfReal(1,poles->Length() + Step * (ToK2-FromK1));
337
338 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
339 (deg,Degree,periodic,mults->Array1());
340
341 Handle(TColStd_HArray1OfReal) nknots =
342 new TColStd_HArray1OfReal(1,nbknots);
343
344 Handle(TColStd_HArray1OfInteger) nmults =
345 new TColStd_HArray1OfInteger(1,nbknots);
346
347 Handle(TColStd_HArray1OfReal) nweights;
348
349 if (IsRational()) {
350 nweights = new TColStd_HArray1OfReal(1,npoles->Upper());
351 TColStd_Array1OfReal adimpol(1,2*poles->Upper());
352 SetPoles(poles->Array1(),weights->Array1(),adimpol);
353 TColStd_Array1OfReal adimnpol(1,2*npoles->Upper());
354 BSplCLib::IncreaseDegree
355 (deg,Degree, periodic,2,adimpol,
356 knots->Array1(),mults->Array1(),adimnpol,
357 nknots->ChangeArray1(),nmults->ChangeArray1());
358 GetPoles(adimnpol,npoles->ChangeArray1(),nweights->ChangeArray1());
359 }
360 else {
361 BSplCLib::IncreaseDegree
362 (deg,Degree, periodic,1,poles->Array1(),
363 knots->Array1(),mults->Array1(),npoles->ChangeArray1(),
364 nknots->ChangeArray1(),nmults->ChangeArray1());
365 }
366
367 deg = Degree;
368 poles = npoles;
369 weights = nweights;
370 knots = nknots;
371 mults = nmults;
372 UpdateKnots();
373
374 }
375
376
377 //=======================================================================
378 //function : IncreaseMultiplicity
379 //purpose :
380 //=======================================================================
381
IncreaseMultiplicity(const Standard_Integer Index,const Standard_Integer M)382 void Law_BSpline::IncreaseMultiplicity (const Standard_Integer Index,
383 const Standard_Integer M)
384 {
385 TColStd_Array1OfReal k(1,1);
386 k(1) = knots->Value(Index);
387 TColStd_Array1OfInteger m(1,1);
388 m(1) = M - mults->Value(Index);
389 InsertKnots(k,m,Epsilon(1.));
390 }
391
392
393 //=======================================================================
394 //function : IncreaseMultiplicity
395 //purpose :
396 //=======================================================================
397
IncreaseMultiplicity(const Standard_Integer I1,const Standard_Integer I2,const Standard_Integer M)398 void Law_BSpline::IncreaseMultiplicity (const Standard_Integer I1,
399 const Standard_Integer I2,
400 const Standard_Integer M)
401 {
402 Handle(TColStd_HArray1OfReal) tk = knots;
403 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
404 TColStd_Array1OfInteger m(I1,I2);
405 Standard_Integer i;
406 for (i = I1; i <= I2; i++)
407 m(i) = M - mults->Value(i);
408 InsertKnots(k,m,Epsilon(1.));
409 }
410
411 //=======================================================================
412 //function : IncrementMultiplicity
413 //purpose :
414 //=======================================================================
415
IncrementMultiplicity(const Standard_Integer I1,const Standard_Integer I2,const Standard_Integer Step)416 void Law_BSpline::IncrementMultiplicity
417 (const Standard_Integer I1,
418 const Standard_Integer I2,
419 const Standard_Integer Step)
420 {
421 Handle(TColStd_HArray1OfReal) tk = knots;
422 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
423 TColStd_Array1OfInteger m(I1,I2) ;
424 m.Init(Step);
425 InsertKnots(k,m,Epsilon(1.));
426 }
427
428
429 //=======================================================================
430 //function : InsertKnot
431 //purpose :
432 //=======================================================================
433
InsertKnot(const Standard_Real U,const Standard_Integer M,const Standard_Real ParametricTolerance,const Standard_Boolean Add)434 void Law_BSpline::InsertKnot
435 (const Standard_Real U,
436 const Standard_Integer M,
437 const Standard_Real ParametricTolerance,
438 const Standard_Boolean Add)
439 {
440 TColStd_Array1OfReal k(1,1);
441 k(1) = U;
442 TColStd_Array1OfInteger m(1,1);
443 m(1) = M;
444 InsertKnots(k,m,ParametricTolerance,Add);
445 }
446
447 //=======================================================================
448 //function : InsertKnots
449 //purpose :
450 //=======================================================================
451
InsertKnots(const TColStd_Array1OfReal & Knots,const TColStd_Array1OfInteger & Mults,const Standard_Real Epsilon,const Standard_Boolean Add)452 void Law_BSpline::InsertKnots(const TColStd_Array1OfReal& Knots,
453 const TColStd_Array1OfInteger& Mults,
454 const Standard_Real Epsilon,
455 const Standard_Boolean Add)
456 {
457 // Check and compute new sizes
458 Standard_Integer nbpoles,nbknots;
459
460 if (!BSplCLib::PrepareInsertKnots(deg,periodic,
461 knots->Array1(),mults->Array1(),
462 Knots,&Mults,nbpoles,nbknots,Epsilon,Add))
463 throw Standard_ConstructionError("Law_BSpline::InsertKnots");
464
465 if (nbpoles == poles->Length()) return;
466
467 Handle(TColStd_HArray1OfReal) npoles = new TColStd_HArray1OfReal(1,nbpoles);
468 Handle(TColStd_HArray1OfReal) nknots = knots;
469 Handle(TColStd_HArray1OfInteger) nmults = mults;
470
471 if (nbknots != knots->Length()) {
472 nknots = new TColStd_HArray1OfReal(1,nbknots);
473 nmults = new TColStd_HArray1OfInteger(1,nbknots);
474 }
475
476 if (rational) {
477 Handle(TColStd_HArray1OfReal) nweights =
478 new TColStd_HArray1OfReal(1,nbpoles);
479 TColStd_Array1OfReal adimpol(1,2*poles->Upper());
480 SetPoles(poles->Array1(),weights->Array1(),adimpol);
481 TColStd_Array1OfReal adimnpol(1,2*npoles->Upper());
482 BSplCLib::InsertKnots(deg,periodic,2,adimpol,
483 knots->Array1(), mults->Array1(),
484 Knots, &Mults,adimnpol,
485 nknots->ChangeArray1(), nmults->ChangeArray1(),
486 Epsilon, Add);
487 GetPoles(adimnpol,npoles->ChangeArray1(),nweights->ChangeArray1());
488 weights = nweights;
489 }
490 else {
491 BSplCLib::InsertKnots(deg,periodic,1,poles->Array1(),
492 knots->Array1(), mults->Array1(),
493 Knots, &Mults,
494 npoles->ChangeArray1(),
495 nknots->ChangeArray1(), nmults->ChangeArray1(),
496 Epsilon, Add);
497 }
498
499 poles = npoles;
500 knots = nknots;
501 mults = nmults;
502 UpdateKnots();
503
504 }
505
506 //=======================================================================
507 //function : RemoveKnot
508 //purpose :
509 //=======================================================================
510
RemoveKnot(const Standard_Integer Index,const Standard_Integer M,const Standard_Real Tolerance)511 Standard_Boolean Law_BSpline::RemoveKnot(const Standard_Integer Index,
512 const Standard_Integer M,
513 const Standard_Real Tolerance)
514 {
515 if (M < 0) return Standard_True;
516
517 Standard_Integer I1 = FirstUKnotIndex ();
518 Standard_Integer I2 = LastUKnotIndex ();
519
520 if ( !periodic && (Index <= I1 || Index >= I2) ) {
521 throw Standard_OutOfRange();
522 }
523 else if ( periodic && (Index < I1 || Index > I2)) {
524 throw Standard_OutOfRange();
525 }
526
527 const TColStd_Array1OfReal & oldpoles = poles->Array1();
528 Standard_Integer step = mults->Value(Index) - M;
529 if (step <= 0) return Standard_True;
530
531 Handle(TColStd_HArray1OfReal) npoles =
532 new TColStd_HArray1OfReal(1,oldpoles.Length()-step);
533
534 Handle(TColStd_HArray1OfReal) nknots = knots;
535 Handle(TColStd_HArray1OfInteger) nmults = mults;
536
537 if (M == 0) {
538 nknots = new TColStd_HArray1OfReal(1,knots->Length()-1);
539 nmults = new TColStd_HArray1OfInteger(1,knots->Length()-1);
540 }
541
542 if (IsRational()) {
543 Handle(TColStd_HArray1OfReal) nweights =
544 new TColStd_HArray1OfReal(1,npoles->Length());
545 TColStd_Array1OfReal adimpol(1,2*poles->Upper());
546 SetPoles(poles->Array1(),weights->Array1(),adimpol);
547 TColStd_Array1OfReal adimnpol(1,2*npoles->Upper());
548 if (!BSplCLib::RemoveKnot(Index, M, deg, periodic,2,adimpol,
549 knots->Array1(),mults->Array1(),adimnpol,
550 nknots->ChangeArray1(),
551 nmults->ChangeArray1(),Tolerance))
552 return Standard_False;
553 GetPoles(adimnpol,npoles->ChangeArray1(),nweights->ChangeArray1());
554 weights = nweights;
555 }
556 else {
557 if (!BSplCLib::RemoveKnot(Index, M, deg, periodic,1,poles->Array1(),
558 knots->Array1(),mults->Array1(),
559 npoles->ChangeArray1(), nknots->ChangeArray1(),
560 nmults->ChangeArray1(),Tolerance))
561 return Standard_False;
562 }
563
564 poles = npoles;
565 knots = nknots;
566 mults = nmults;
567
568 UpdateKnots();
569 return Standard_True;
570 }
571
572 //----------------------------------------------------------------------
573 //----------------------------------------------------------------------
574
575 # if 0
576
577 --- methodes otees du CDL -> spec trop vagues : on ne sait pas ou rajouter
578 le noeud
579
580 //=======================================================================
581 //function : InsertPoleAfter
582 //purpose :
583 //=======================================================================
584
585 void Law_BSpline::InsertPoleAfter
586 (const Standard_Integer Index,
587 const Standard_Real& P)
588 {
589 InsertPoleAfter(Index,P,1.);
590 }
591
592
593
594 //=======================================================================
595 //function : InsertPoleAfter
596 //purpose :
597 //=======================================================================
598
599 void Law_BSpline::InsertPoleAfter
600 (const Standard_Integer Index,
601 const Standard_Real& P,
602 const Standard_Real Weight)
603 {
604 if (Index < 0 || Index > poles->Length()) throw Standard_OutOfRange();
605
606 if (Weight <= gp::Resolution()) throw Standard_ConstructionError();
607
608
609 // find the spans which are modified with the inserting pole
610 // --> evaluate NewKnot & KnotIndex : Value of the new knot to insert.
611 Standard_Integer KnotIndex, k, sigma;
612 Standard_Real NewKnot;
613
614 if (periodic) {
615 sigma = 0;
616 k = 1;
617 while ( sigma < Index) {
618 sigma += mults->Value(k);
619 k++;
620 }
621 KnotIndex = k - 1;
622 NewKnot = ( knots->Value(KnotIndex) + knots->Value(KnotIndex+1)) / 2.;
623 }
624 else {
625 sigma = 0;
626 k = 1;
627 while ( sigma < Index) {
628 sigma += mults->Value(k);
629 k++;
630 }
631 Standard_Integer first = k - 1;
632 sigma -= Index;
633 while ( sigma < (deg+1)) {
634 sigma += mults->Value(k);
635 k++;
636 }
637 Standard_Integer last = k - 1;
638
639 KnotIndex = first + (( last - first) / 2);
640 NewKnot = ( knots->Value(KnotIndex) + knots->Value(KnotIndex+1)) / 2.;
641 }
642
643 Standard_Integer nbknots = knots->Length();
644 Handle(TColStd_HArray1OfReal) nknots =
645 new TColStd_HArray1OfReal(1,nbknots+1);
646 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
647 Handle(TColStd_HArray1OfInteger) nmults =
648 new TColStd_HArray1OfInteger(1,nbknots+1);
649 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
650
651 // insert the knot
652
653 Standard_Integer i;
654 for ( i = 1; i<= KnotIndex; i++) {
655 newknots(i) = knots->Value(i);
656 newmults(i) = mults->Value(i);
657 }
658 newknots(KnotIndex+1) = NewKnot;
659 newmults(KnotIndex+1) = 1;
660 for ( i = KnotIndex+1; i <= nbknots; i++) {
661 newknots(i+1) = knots->Value(i);
662 newmults(i+1) = mults->Value(i);
663 }
664
665 Standard_Integer nbpoles = poles->Length();
666 Handle(TColStd_HArray1OfReal) npoles =
667 new TColStd_HArray1OfReal(1,nbpoles+1);
668 TColStd_Array1OfReal& newpoles = npoles->ChangeArray1();
669
670 // insert the pole
671
672 for (i = 1; i <= Index; i++)
673 newpoles(i) = poles->Value(i);
674
675 newpoles(Index+1) = P;
676
677 for (i = Index+1; i <= nbpoles; i++)
678 newpoles(i+1) = poles->Value(i);
679
680 // insert the weight
681
682 Handle(TColStd_HArray1OfReal) nweights;
683 Standard_Boolean rat = IsRational() || Abs(Weight-1.) > gp::Resolution();
684
685 if (rat) {
686 nweights = new TColStd_HArray1OfReal(1,nbpoles+1);
687 TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
688
689 for (i = 1; i <= Index; i++)
690 if (IsRational())
691 newweights(i) = weights->Value(i);
692 else
693 newweights(i) = 1.;
694
695 newweights(Index+1) = Weight;
696
697 for (i = Index+1; i <= nbpoles; i++)
698 if (IsRational())
699 newweights(i+1) = weights->Value(i);
700 else
701 newweights(i+1) = 1.;
702 }
703
704 poles = npoles;
705 weights = nweights;
706 knots = nknots;
707 mults = nmults;
708 UpdateKnots();
709 }
710
711
712 //=======================================================================
713 //function : InsertPoleBefore
714 //purpose :
715 //=======================================================================
716
717 void Law_BSpline::InsertPoleBefore
718 (const Standard_Integer Index,
719 const Standard_Real& P )
720 {
721 InsertPoleAfter(Index-1,P,1.);
722 }
723
724
725
726 //=======================================================================
727 //function : InsertPoleBefore
728 //purpose :
729 //=======================================================================
730
731 void Law_BSpline::InsertPoleBefore
732 (const Standard_Integer Index,
733 const Standard_Real& P,
734 const Standard_Real Weight)
735 {
736 InsertPoleAfter(Index-1,P,Weight);
737 }
738
739 //=======================================================================
740 //function : RemovePole
741 //purpose :
742 //=======================================================================
743
744 void Law_BSpline::RemovePole
745 (const Standard_Integer Index)
746 {
747 if (Index < 1 || Index > poles->Length()) throw Standard_OutOfRange();
748
749 if (poles->Length() <= 2) throw Standard_ConstructionError();
750
751 if (knotSet == GeomAbs_NonUniform || knotSet == GeomAbs_PiecewiseBezier)
752 throw Standard_ConstructionError();
753
754 Standard_Integer i;
755 Handle(TColStd_HArray1OfReal) nknots =
756 new TColStd_HArray1OfReal(1,knots->Length()-1);
757 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
758
759 Handle(TColStd_HArray1OfInteger) nmults =
760 new TColStd_HArray1OfInteger(1,mults->Length()-1);
761 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
762
763 for (i = 1; i < newknots.Length(); i++) {
764 newknots (i) = knots->Value (i);
765 newmults (i) = 1;
766 }
767 newmults(1) = mults->Value(1);
768 newknots(newknots.Upper()) = knots->Value (knots->Upper());
769 newmults(newmults.Upper()) = mults->Value (mults->Upper());
770
771
772 Handle(TColStd_HArray1OfReal) npoles =
773 new TColStd_HArray1OfReal(1, poles->Upper()-1);
774 TColStd_Array1OfReal& newpoles = npoles->ChangeArray1();
775
776 for (i = 1; i < Index; i++)
777 newpoles(i) = poles->Value(i);
778 for (i = Index; i < newpoles.Length(); i++)
779 newpoles(i) = poles->Value(i+1);
780
781 Handle(TColStd_HArray1OfReal) nweights;
782 if (IsRational()) {
783 nweights = new TColStd_HArray1OfReal(1,newpoles.Length());
784 TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
785 for (i = 1; i < Index; i++)
786 newweights(i) = weights->Value(i);
787 for (i = Index; i < newweights.Length(); i++)
788 newweights(i) = weights->Value(i+1);
789 }
790
791 poles = npoles;
792 weights = nweights;
793 knots = nknots;
794 mults = nmults;
795 UpdateKnots();
796 }
797
798
799
800
801 #endif
802
803
804 //=======================================================================
805 //function : Reverse
806 //purpose :
807 //=======================================================================
808
Reverse()809 void Law_BSpline::Reverse ()
810 {
811 BSplCLib::Reverse(knots->ChangeArray1());
812 BSplCLib::Reverse(mults->ChangeArray1());
813 Standard_Integer last;
814 if (periodic)
815 last = flatknots->Upper() - deg - 1;
816 else
817 last = poles->Upper();
818 BSplCLib::Reverse(poles->ChangeArray1(),last);
819 if (rational)
820 BSplCLib::Reverse(weights->ChangeArray1(),last);
821 UpdateKnots();
822 }
823
824
825 //=======================================================================
826 //function : ReversedParameter
827 //purpose :
828 //=======================================================================
829
ReversedParameter(const Standard_Real U) const830 Standard_Real Law_BSpline::ReversedParameter
831 (const Standard_Real U) const
832 {
833 return (FirstParameter() + LastParameter() - U);
834 }
835
836
837 //=======================================================================
838 //function : Segment
839 //purpose :
840 //=======================================================================
841
Segment(const Standard_Real U1,const Standard_Real U2)842 void Law_BSpline::Segment(const Standard_Real U1,
843 const Standard_Real U2)
844 {
845 Standard_DomainError_Raise_if ( U2 < U1,
846 "Law_BSpline::Segment");
847 Standard_Real Eps = Epsilon(Max(Abs(U1),Abs(U2)));
848 Standard_Real delta = U2 - U1;
849
850 Standard_Real NewU1, NewU2;
851 Standard_Real U;
852 Standard_Integer index;
853
854 TColStd_Array1OfReal Knots(1,2);
855 TColStd_Array1OfInteger Mults(1,2);
856
857 index = 0;
858 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
859 U1,periodic,knots->Lower(),knots->Upper(),
860 index,NewU1);
861 index = 0;
862 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
863 U2,periodic,knots->Lower(),knots->Upper(),
864 index,NewU2);
865 Knots( 1) = Min( NewU1, NewU2);
866 Knots( 2) = Max( NewU1, NewU2);
867 Mults( 1) = Mults( 2) = deg;
868 InsertKnots( Knots, Mults, Eps);
869
870 if (periodic) { // set the origine at NewU1
871 Standard_Integer index0 = 0;
872 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
873 U1,periodic,knots->Lower(),knots->Upper(),
874 index0,U);
875 if ( Abs(knots->Value(index0+1)-U) < Eps)
876 index0++;
877 SetOrigin(index0);
878 SetNotPeriodic();
879 }
880
881 // compute index1 and index2 to set the new knots and mults
882 Standard_Integer index1 = 0, index2 = 0;
883 Standard_Integer FromU1 = knots->Lower();
884 Standard_Integer ToU2 = knots->Upper();
885 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
886 NewU1,periodic,FromU1,ToU2,index1,U);
887 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
888 NewU1 + delta,periodic,FromU1,ToU2,index2,U);
889 if ( Abs(knots->Value(index2+1)-U) < Eps)
890 index2++;
891
892 Standard_Integer nbknots = index2 - index1 + 1;
893
894 Handle(TColStd_HArray1OfReal)
895 nknots = new TColStd_HArray1OfReal(1,nbknots);
896 Handle(TColStd_HArray1OfInteger)
897 nmults = new TColStd_HArray1OfInteger(1,nbknots);
898
899 Standard_Integer i , k = 1;
900 for ( i = index1; i<= index2; i++) {
901 nknots->SetValue(k, knots->Value(i));
902 nmults->SetValue(k, mults->Value(i));
903 k++;
904 }
905 nmults->SetValue( 1, deg + 1);
906 nmults->SetValue(nbknots, deg + 1);
907
908
909 // compute index1 and index2 to set the new poles and weights
910 Standard_Integer pindex1
911 = BSplCLib::PoleIndex(deg,index1,periodic,mults->Array1());
912 Standard_Integer pindex2
913 = BSplCLib::PoleIndex(deg,index2,periodic,mults->Array1());
914
915 pindex1++;
916 pindex2 = Min( pindex2+1, poles->Length());
917
918 Standard_Integer nbpoles = pindex2 - pindex1 + 1;
919
920 Handle(TColStd_HArray1OfReal)
921 nweights = new TColStd_HArray1OfReal(1,nbpoles);
922 Handle(TColStd_HArray1OfReal)
923 npoles = new TColStd_HArray1OfReal(1,nbpoles);
924
925 k = 1;
926 if ( rational) {
927 nweights = new TColStd_HArray1OfReal( 1, nbpoles);
928 for ( i = pindex1; i <= pindex2; i++) {
929 npoles->SetValue(k, poles->Value(i));
930 nweights->SetValue(k, weights->Value(i));
931 k++;
932 }
933 }
934 else {
935 for ( i = pindex1; i <= pindex2; i++) {
936 npoles->SetValue(k, poles->Value(i));
937 k++;
938 }
939 }
940
941 knots = nknots;
942 mults = nmults;
943 poles = npoles;
944 if ( rational)
945 weights = nweights;
946
947 UpdateKnots();
948 }
949
950
951 //=======================================================================
952 //function : SetKnot
953 //purpose :
954 //=======================================================================
955
SetKnot(const Standard_Integer Index,const Standard_Real K)956 void Law_BSpline::SetKnot
957 (const Standard_Integer Index,
958 const Standard_Real K)
959 {
960 if (Index < 1 || Index > knots->Length()) throw Standard_OutOfRange();
961 Standard_Real DK = Abs(Epsilon (K));
962 if (Index == 1) {
963 if (K >= knots->Value(2) - DK) throw Standard_ConstructionError();
964 }
965 else if (Index == knots->Length()) {
966 if (K <= knots->Value (knots->Length()-1) + DK) {
967 throw Standard_ConstructionError();
968 }
969 }
970 else {
971 if (K <= knots->Value(Index-1) + DK ||
972 K >= knots->Value(Index+1) - DK ) {
973 throw Standard_ConstructionError();
974 }
975 }
976 if (K != knots->Value (Index)) {
977 knots->SetValue (Index, K);
978 UpdateKnots();
979 }
980 }
981
982
983 //=======================================================================
984 //function : SetKnots
985 //purpose :
986 //=======================================================================
987
SetKnots(const TColStd_Array1OfReal & K)988 void Law_BSpline::SetKnots
989 (const TColStd_Array1OfReal& K)
990 {
991 CheckCurveData(poles->Array1(),K,mults->Array1(),deg,periodic);
992 knots->ChangeArray1() = K;
993 UpdateKnots();
994 }
995
996
997 //=======================================================================
998 //function : SetKnot
999 //purpose :
1000 //=======================================================================
1001
SetKnot(const Standard_Integer Index,const Standard_Real K,const Standard_Integer M)1002 void Law_BSpline::SetKnot
1003 (const Standard_Integer Index,
1004 const Standard_Real K,
1005 const Standard_Integer M)
1006 {
1007 IncreaseMultiplicity (Index, M);
1008 SetKnot (Index, K);
1009 }
1010
1011
1012 //=======================================================================
1013 //function : SetPeriodic
1014 //purpose :
1015 //=======================================================================
1016
SetPeriodic()1017 void Law_BSpline::SetPeriodic ()
1018 {
1019 Standard_Integer first = FirstUKnotIndex();
1020 Standard_Integer last = LastUKnotIndex();
1021
1022 Handle(TColStd_HArray1OfReal) tk = knots;
1023 TColStd_Array1OfReal cknots((knots->Array1())(first),first,last);
1024 knots = new TColStd_HArray1OfReal(1,cknots.Length());
1025 knots->ChangeArray1() = cknots;
1026
1027 Handle(TColStd_HArray1OfInteger) tm = mults;
1028 TColStd_Array1OfInteger cmults((mults->Array1())(first),first,last);
1029 cmults(first) = cmults(last) = Max( cmults(first), cmults(last));
1030 mults = new TColStd_HArray1OfInteger(1,cmults.Length());
1031 mults->ChangeArray1() = cmults;
1032
1033 // compute new number of poles;
1034 Standard_Integer nbp = BSplCLib::NbPoles(deg,Standard_True,cmults);
1035
1036 Handle(TColStd_HArray1OfReal) tp = poles;
1037 TColStd_Array1OfReal cpoles((poles->Array1())(1),1,nbp);
1038 poles = new TColStd_HArray1OfReal(1,nbp);
1039 poles->ChangeArray1() = cpoles;
1040
1041 if (rational) {
1042 Handle(TColStd_HArray1OfReal) tw = weights;
1043 TColStd_Array1OfReal cweights((weights->Array1())(1),1,nbp);
1044 weights = new TColStd_HArray1OfReal(1,nbp);
1045 weights->ChangeArray1() = cweights;
1046 }
1047
1048 periodic = Standard_True;
1049
1050 UpdateKnots();
1051 }
1052
1053
1054 //=======================================================================
1055 //function : SetOrigin
1056 //purpose :
1057 //=======================================================================
1058
SetOrigin(const Standard_Integer Index)1059 void Law_BSpline::SetOrigin(const Standard_Integer Index)
1060 {
1061 Standard_NoSuchObject_Raise_if( !periodic,
1062 "Law_BSpline::SetOrigin");
1063 Standard_Integer i,k;
1064 Standard_Integer first = FirstUKnotIndex();
1065 Standard_Integer last = LastUKnotIndex();
1066
1067 Standard_DomainError_Raise_if( (Index < first) || (Index > last),
1068 "Law_BSpline::SetOrigine");
1069
1070 Standard_Integer nbknots = knots->Length();
1071 Standard_Integer nbpoles = poles->Length();
1072
1073 Handle(TColStd_HArray1OfReal) nknots =
1074 new TColStd_HArray1OfReal(1,nbknots);
1075 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
1076
1077 Handle(TColStd_HArray1OfInteger) nmults =
1078 new TColStd_HArray1OfInteger(1,nbknots);
1079 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
1080
1081 // set the knots and mults
1082 Standard_Real period = knots->Value(last) - knots->Value(first);
1083 k = 1;
1084 for ( i = Index; i <= last ; i++) {
1085 newknots(k) = knots->Value(i);
1086 newmults(k) = mults->Value(i);
1087 k++;
1088 }
1089 for ( i = first+1; i <= Index; i++) {
1090 newknots(k) = knots->Value(i) + period;
1091 newmults(k) = mults->Value(i);
1092 k++;
1093 }
1094
1095 Standard_Integer index = 1;
1096 for (i = first+1; i <= Index; i++)
1097 index += mults->Value(i);
1098
1099 // set the poles and weights
1100 Handle(TColStd_HArray1OfReal) npoles =
1101 new TColStd_HArray1OfReal(1,nbpoles);
1102 Handle(TColStd_HArray1OfReal) nweights =
1103 new TColStd_HArray1OfReal(1,nbpoles);
1104 TColStd_Array1OfReal & newpoles = npoles->ChangeArray1();
1105 TColStd_Array1OfReal & newweights = nweights->ChangeArray1();
1106 first = poles->Lower();
1107 last = poles->Upper();
1108 if ( rational) {
1109 k = 1;
1110 for ( i = index; i <= last; i++) {
1111 newpoles(k) = poles->Value(i);
1112 newweights(k) = weights->Value(i);
1113 k++;
1114 }
1115 for ( i = first; i < index; i++) {
1116 newpoles(k) = poles->Value(i);
1117 newweights(k) = weights->Value(i);
1118 k++;
1119 }
1120 }
1121 else {
1122 k = 1;
1123 for ( i = index; i <= last; i++) {
1124 newpoles(k) = poles->Value(i);
1125 k++;
1126 }
1127 for ( i = first; i < index; i++) {
1128 newpoles(k) = poles->Value(i);
1129 k++;
1130 }
1131 }
1132
1133 poles = npoles;
1134 knots = nknots;
1135 mults = nmults;
1136 if (rational)
1137 weights = nweights;
1138 UpdateKnots();
1139 }
1140
1141
1142
1143 //=======================================================================
1144 //function : SetNotPeriodic
1145 //purpose :
1146 //=======================================================================
1147
SetNotPeriodic()1148 void Law_BSpline::SetNotPeriodic ()
1149 {
1150 if ( periodic) {
1151 Standard_Integer NbKnots, NbPoles;
1152 BSplCLib::PrepareUnperiodize( deg, mults->Array1(),NbKnots,NbPoles);
1153
1154 Handle(TColStd_HArray1OfReal) npoles
1155 = new TColStd_HArray1OfReal(1,NbPoles);
1156
1157 Handle(TColStd_HArray1OfReal) nknots
1158 = new TColStd_HArray1OfReal(1,NbKnots);
1159
1160 Handle(TColStd_HArray1OfInteger) nmults
1161 = new TColStd_HArray1OfInteger(1,NbKnots);
1162
1163 Handle(TColStd_HArray1OfReal) nweights;
1164
1165 if (IsRational()) {
1166
1167 nweights = new TColStd_HArray1OfReal(1,NbPoles);
1168
1169 TColStd_Array1OfReal adimpol(1,2*poles->Upper());
1170 SetPoles(poles->Array1(),weights->Array1(),adimpol);
1171 TColStd_Array1OfReal adimnpol(1,2*npoles->Upper());
1172 BSplCLib::Unperiodize
1173 (deg,1,mults->Array1(),knots->Array1(),adimpol,
1174 nmults->ChangeArray1(),nknots->ChangeArray1(),
1175 adimnpol);
1176 GetPoles(adimnpol,npoles->ChangeArray1(),nweights->ChangeArray1());
1177 }
1178 else {
1179
1180 BSplCLib::Unperiodize(deg,1,mults->Array1(),knots->Array1(),
1181 poles->Array1(),nmults->ChangeArray1(),
1182 nknots->ChangeArray1(),npoles->ChangeArray1());
1183
1184 }
1185 poles = npoles;
1186 weights = nweights;
1187 mults = nmults;
1188 knots = nknots;
1189 periodic = Standard_False;
1190
1191 UpdateKnots();
1192 }
1193 }
1194
1195
1196 //=======================================================================
1197 //function : SetPole
1198 //purpose :
1199 //=======================================================================
1200
SetPole(const Standard_Integer Index,const Standard_Real P)1201 void Law_BSpline::SetPole
1202 (const Standard_Integer Index,
1203 const Standard_Real P)
1204 {
1205 if (Index < 1 || Index > poles->Length()) throw Standard_OutOfRange();
1206 poles->SetValue (Index, P);
1207 }
1208
1209
1210 //=======================================================================
1211 //function : SetPole
1212 //purpose :
1213 //=======================================================================
1214
SetPole(const Standard_Integer Index,const Standard_Real P,const Standard_Real W)1215 void Law_BSpline::SetPole
1216 (const Standard_Integer Index,
1217 const Standard_Real P,
1218 const Standard_Real W)
1219 {
1220 SetPole(Index,P);
1221 SetWeight(Index,W);
1222 }
1223
1224 //=======================================================================
1225 //function : SetWeight
1226 //purpose :
1227 //=======================================================================
1228
SetWeight(const Standard_Integer Index,const Standard_Real W)1229 void Law_BSpline::SetWeight
1230 (const Standard_Integer Index,
1231 const Standard_Real W)
1232 {
1233 if (Index < 1 || Index > poles->Length()) throw Standard_OutOfRange();
1234
1235 if (W <= gp::Resolution ()) throw Standard_ConstructionError();
1236
1237
1238 Standard_Boolean rat = IsRational() || (Abs(W - 1.) > gp::Resolution());
1239
1240 if ( rat) {
1241 if (rat && !IsRational())
1242 weights = new TColStd_HArray1OfReal(1,poles->Length(),1.);
1243
1244 weights->SetValue (Index, W);
1245
1246 if (IsRational()) {
1247 rat = Rational(weights->Array1());
1248 if (!rat) weights.Nullify();
1249 }
1250
1251 rational = !weights.IsNull();
1252 }
1253 }
1254
1255
1256 //=======================================================================
1257 //function : UpdateKnots
1258 //purpose :
1259 //=======================================================================
1260
1261
UpdateKnots()1262 void Law_BSpline::UpdateKnots()
1263 {
1264
1265 rational = !weights.IsNull();
1266
1267 Standard_Integer MaxKnotMult = 0;
1268 KnotAnalysis (deg,
1269 periodic,
1270 knots->Array1(),
1271 mults->Array1(),
1272 knotSet, MaxKnotMult);
1273
1274 if (knotSet == GeomAbs_Uniform && !periodic) {
1275 flatknots = knots;
1276 }
1277 else {
1278 flatknots = new TColStd_HArray1OfReal
1279 (1, BSplCLib::KnotSequenceLength(mults->Array1(),deg,periodic));
1280
1281 BSplCLib::KnotSequence (knots->Array1(),
1282 mults->Array1(),
1283 deg,periodic,
1284 flatknots->ChangeArray1());
1285 }
1286
1287 if (MaxKnotMult == 0) smooth = GeomAbs_CN;
1288 else {
1289 switch (deg - MaxKnotMult) {
1290 case 0: smooth = GeomAbs_C0; break;
1291 case 1: smooth = GeomAbs_C1; break;
1292 case 2: smooth = GeomAbs_C2; break;
1293 case 3: smooth = GeomAbs_C3; break;
1294 default: smooth = GeomAbs_C3; break;
1295 }
1296 }
1297 }
1298
1299
1300 //=======================================================================
1301 //function : Normalizes the parameters if the curve is periodic
1302 //purpose : that is compute the cache so that it is valid
1303 //=======================================================================
1304
PeriodicNormalization(Standard_Real & Parameter) const1305 void Law_BSpline::PeriodicNormalization(Standard_Real& Parameter) const
1306 {
1307 Standard_Real Period ;
1308
1309 if (periodic){
1310 Period = flatknots->Value(flatknots->Upper() - deg) -
1311 flatknots->Value (deg + 1) ;
1312 while (Parameter > flatknots->Value(flatknots->Upper()-deg)){
1313 Parameter -= Period ;
1314 }
1315 while (Parameter < flatknots->Value((deg + 1))){
1316 Parameter += Period ;
1317 }
1318 }
1319 }
1320
1321
1322 //=======================================================================
1323 //function : IsCN
1324 //purpose :
1325 //=======================================================================
1326
IsCN(const Standard_Integer N) const1327 Standard_Boolean Law_BSpline::IsCN ( const Standard_Integer N) const
1328 {
1329 Standard_RangeError_Raise_if
1330 (N < 0, "Law_BSpline::IsCN");
1331
1332 switch (smooth) {
1333 case GeomAbs_CN : return Standard_True;
1334 case GeomAbs_C0 : return N <= 0;
1335 case GeomAbs_G1 : return N <= 0;
1336 case GeomAbs_C1 : return N <= 1;
1337 case GeomAbs_G2 : return N <= 1;
1338 case GeomAbs_C2 : return N <= 2;
1339 case GeomAbs_C3 :
1340 return N <= 3 ? Standard_True :
1341 N <= deg - BSplCLib::MaxKnotMult (mults->Array1(), mults->Lower() + 1, mults->Upper() - 1);
1342 default:
1343 return Standard_False;
1344 }
1345 }
1346
1347
1348
1349 //=======================================================================
1350 //function : IsClosed
1351 //purpose :
1352 //=======================================================================
1353
IsClosed() const1354 Standard_Boolean Law_BSpline::IsClosed () const
1355 { return (Abs(StartPoint()-EndPoint())) <= gp::Resolution (); }
1356
1357
1358
1359 //=======================================================================
1360 //function : IsPeriodic
1361 //purpose :
1362 //=======================================================================
1363
IsPeriodic() const1364 Standard_Boolean Law_BSpline::IsPeriodic () const
1365 { return periodic; }
1366
1367 //=======================================================================
1368 //function : Continuity
1369 //purpose :
1370 //=======================================================================
1371
Continuity() const1372 GeomAbs_Shape Law_BSpline::Continuity () const
1373 { return smooth; }
1374
1375 //=======================================================================
1376 //function : Degree
1377 //purpose :
1378 //=======================================================================
1379
Degree() const1380 Standard_Integer Law_BSpline::Degree () const
1381 { return deg; }
1382
1383
1384 //=======================================================================
1385 //function : Value
1386 //purpose :
1387 //=======================================================================
1388
Value(const Standard_Real U) const1389 Standard_Real Law_BSpline::Value(const Standard_Real U)const
1390 {
1391 Standard_Real P;
1392 D0(U,P);
1393 return P;
1394 }
1395
1396
1397 //=======================================================================
1398 //function : D0
1399 //purpose :
1400 //=======================================================================
1401
D0(const Standard_Real U,Standard_Real & P) const1402 void Law_BSpline::D0 (const Standard_Real U,
1403 Standard_Real& P) const
1404 {
1405 Standard_Real NewU = U ;
1406 PeriodicNormalization(NewU) ;
1407 if (rational) {
1408 BSplCLib::D0(NewU,0,deg,periodic,POLES, &weights->Array1(),FKNOTS,FMULTS,P);
1409 }
1410 else {
1411 BSplCLib::D0(NewU,0,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,P);
1412 }
1413 }
1414
1415
1416
1417
1418 //=======================================================================
1419 //function : D1
1420 //purpose :
1421 //=======================================================================
1422
D1(const Standard_Real U,Standard_Real & P,Standard_Real & V1) const1423 void Law_BSpline::D1 (const Standard_Real U,
1424 Standard_Real& P,
1425 Standard_Real& V1) const
1426 {
1427 Standard_Real NewU = U ;
1428 PeriodicNormalization(NewU) ;
1429 if (rational) {
1430 BSplCLib::D1(NewU,0,deg,periodic,POLES, &weights->Array1(),FKNOTS,FMULTS,
1431 P,V1) ;
1432 }
1433 else {
1434 BSplCLib::D1(NewU,0,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,
1435 P,V1) ;
1436 }
1437 }
1438
1439
1440
1441 //=======================================================================
1442 //function : D2
1443 //purpose :
1444 //=======================================================================
1445
D2(const Standard_Real U,Standard_Real & P,Standard_Real & V1,Standard_Real & V2) const1446 void Law_BSpline::D2(const Standard_Real U ,
1447 Standard_Real& P ,
1448 Standard_Real& V1,
1449 Standard_Real& V2 ) const
1450 {
1451 Standard_Real NewU = U ;
1452 PeriodicNormalization(NewU) ;
1453 if (rational) {
1454 BSplCLib::D2(NewU,0,deg,periodic,POLES,&weights->Array1(),FKNOTS,FMULTS,
1455 P, V1, V2) ;
1456 }
1457 else {
1458 BSplCLib::D2(NewU,0,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,
1459 P, V1, V2) ;
1460 }
1461 }
1462
1463
1464
1465 //=======================================================================
1466 //function : D3
1467 //purpose :
1468 //=======================================================================
1469
D3(const Standard_Real U,Standard_Real & P,Standard_Real & V1,Standard_Real & V2,Standard_Real & V3) const1470 void Law_BSpline::D3(const Standard_Real U ,
1471 Standard_Real& P ,
1472 Standard_Real& V1,
1473 Standard_Real& V2,
1474 Standard_Real& V3 ) const
1475 {
1476 Standard_Real NewU = U ;
1477 PeriodicNormalization(NewU) ;
1478 if (rational) {
1479 BSplCLib::D3(NewU,0,deg,periodic,POLES,&weights->Array1(),FKNOTS,FMULTS,
1480 P, V1, V2, V3) ;
1481 }
1482 else {
1483 BSplCLib::D3(NewU,0,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,
1484 P, V1, V2, V3) ;
1485 }
1486 }
1487
1488
1489
1490 //=======================================================================
1491 //function : DN
1492 //purpose :
1493 //=======================================================================
1494
DN(const Standard_Real U,const Standard_Integer N) const1495 Standard_Real Law_BSpline::DN(const Standard_Real U,
1496 const Standard_Integer N ) const
1497 {
1498 Standard_Real V;
1499 if (rational) {
1500 BSplCLib::DN(U,N,0,deg,periodic,POLES,&weights->Array1(),FKNOTS,FMULTS,V);
1501 }
1502 else {
1503 BSplCLib::DN(U,N,0,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,V);
1504 }
1505 return V;
1506 }
1507
1508
1509
1510 //=======================================================================
1511 //function : EndPoint
1512 //purpose :
1513 //=======================================================================
1514
EndPoint() const1515 Standard_Real Law_BSpline::EndPoint () const
1516 {
1517 if (mults->Value (knots->Upper ()) == deg + 1)
1518 return poles->Value (poles->Upper());
1519 else
1520 return Value(LastParameter());
1521 }
1522
1523
1524 //=======================================================================
1525 //function : FirstUKnotIndex
1526 //purpose :
1527 //=======================================================================
1528
FirstUKnotIndex() const1529 Standard_Integer Law_BSpline::FirstUKnotIndex () const
1530 {
1531 if (periodic) return 1;
1532 else return BSplCLib::FirstUKnotIndex (deg, mults->Array1());
1533 }
1534
1535
1536 //=======================================================================
1537 //function : FirstParameter
1538 //purpose :
1539 //=======================================================================
1540
FirstParameter() const1541 Standard_Real Law_BSpline::FirstParameter () const
1542 {
1543 return flatknots->Value (deg+1);
1544 }
1545
1546
1547 //=======================================================================
1548 //function : Knot
1549 //purpose :
1550 //=======================================================================
1551
Knot(const Standard_Integer Index) const1552 Standard_Real Law_BSpline::Knot (const Standard_Integer Index) const
1553 {
1554 Standard_OutOfRange_Raise_if
1555 (Index < 1 || Index > knots->Length(), "Law_BSpline::Knot");
1556 return knots->Value (Index);
1557 }
1558
1559
1560
1561 //=======================================================================
1562 //function : KnotDistribution
1563 //purpose :
1564 //=======================================================================
1565
KnotDistribution() const1566 GeomAbs_BSplKnotDistribution Law_BSpline::KnotDistribution () const
1567 {
1568 return knotSet;
1569 }
1570
1571
1572 //=======================================================================
1573 //function : Knots
1574 //purpose :
1575 //=======================================================================
1576
Knots(TColStd_Array1OfReal & K) const1577 void Law_BSpline::Knots (TColStd_Array1OfReal& K) const
1578 {
1579 Standard_DimensionError_Raise_if
1580 (K.Length() != knots->Length(), "Law_BSpline::Knots");
1581 K = knots->Array1();
1582 }
1583
1584
1585 //=======================================================================
1586 //function : KnotSequence
1587 //purpose :
1588 //=======================================================================
1589
KnotSequence(TColStd_Array1OfReal & K) const1590 void Law_BSpline::KnotSequence (TColStd_Array1OfReal& K) const
1591 {
1592 Standard_DimensionError_Raise_if
1593 (K.Length() != flatknots->Length(), "Law_BSpline::KnotSequence");
1594 K = flatknots->Array1();
1595 }
1596
1597
1598
1599 //=======================================================================
1600 //function : LastUKnotIndex
1601 //purpose :
1602 //=======================================================================
1603
LastUKnotIndex() const1604 Standard_Integer Law_BSpline::LastUKnotIndex() const
1605 {
1606 if (periodic) return knots->Length();
1607 else return BSplCLib::LastUKnotIndex (deg, mults->Array1());
1608 }
1609
1610
1611 //=======================================================================
1612 //function : LastParameter
1613 //purpose :
1614 //=======================================================================
1615
LastParameter() const1616 Standard_Real Law_BSpline::LastParameter () const
1617 {
1618 return flatknots->Value (flatknots->Upper()-deg);
1619 }
1620
1621
1622 //=======================================================================
1623 //function : LocalValue
1624 //purpose :
1625 //=======================================================================
1626
LocalValue(const Standard_Real U,const Standard_Integer FromK1,const Standard_Integer ToK2) const1627 Standard_Real Law_BSpline::LocalValue
1628 (const Standard_Real U,
1629 const Standard_Integer FromK1,
1630 const Standard_Integer ToK2) const
1631 {
1632 Standard_Real P;
1633 LocalD0(U,FromK1,ToK2,P);
1634 return P;
1635 }
1636
1637 //=======================================================================
1638 //function : LocalD0
1639 //purpose :
1640 //=======================================================================
1641
LocalD0(const Standard_Real U,const Standard_Integer FromK1,const Standard_Integer ToK2,Standard_Real & P) const1642 void Law_BSpline::LocalD0
1643 (const Standard_Real U,
1644 const Standard_Integer FromK1,
1645 const Standard_Integer ToK2,
1646 Standard_Real& P) const
1647 {
1648 Standard_DomainError_Raise_if (FromK1 == ToK2,
1649 "Law_BSpline::LocalValue");
1650 Standard_Real u = U;
1651 Standard_Integer index = 0;
1652 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic,FromK1,ToK2, index,u);
1653 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
1654 if (rational) {
1655 BSplCLib::D0(u,index,deg,periodic,POLES,&weights->Array1(),FKNOTS,FMULTS,P);
1656 }
1657 else {
1658 BSplCLib::D0(u,index,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,P);
1659 }
1660 }
1661
1662 //=======================================================================
1663 //function : LocalD1
1664 //purpose :
1665 //=======================================================================
1666
LocalD1(const Standard_Real U,const Standard_Integer FromK1,const Standard_Integer ToK2,Standard_Real & P,Standard_Real & V1) const1667 void Law_BSpline::LocalD1 (const Standard_Real U,
1668 const Standard_Integer FromK1,
1669 const Standard_Integer ToK2,
1670 Standard_Real& P,
1671 Standard_Real& V1) const
1672 {
1673 Standard_DomainError_Raise_if (FromK1 == ToK2,
1674 "Law_BSpline::LocalD1");
1675 Standard_Real u = U;
1676 Standard_Integer index = 0;
1677 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
1678 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
1679 if (rational) {
1680 BSplCLib::D1(u,index,deg,periodic,POLES,&weights->Array1(),FKNOTS,FMULTS,P,V1);
1681 }
1682 else {
1683 BSplCLib::D1(u,index,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,P,V1);
1684 }
1685 }
1686
1687
1688 //=======================================================================
1689 //function : LocalD2
1690 //purpose :
1691 //=======================================================================
1692
LocalD2(const Standard_Real U,const Standard_Integer FromK1,const Standard_Integer ToK2,Standard_Real & P,Standard_Real & V1,Standard_Real & V2) const1693 void Law_BSpline::LocalD2
1694 (const Standard_Real U,
1695 const Standard_Integer FromK1,
1696 const Standard_Integer ToK2,
1697 Standard_Real& P,
1698 Standard_Real& V1,
1699 Standard_Real& V2) const
1700 {
1701 Standard_DomainError_Raise_if (FromK1 == ToK2,
1702 "Law_BSpline::LocalD2");
1703 Standard_Real u = U;
1704 Standard_Integer index = 0;
1705 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
1706 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
1707 if (rational) {
1708 BSplCLib::D2(u,index,deg,periodic,POLES, &weights->Array1(),FKNOTS,FMULTS,P,V1,V2);
1709 }
1710 else {
1711 BSplCLib::D2(u,index,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,P,V1,V2);
1712 }
1713 }
1714
1715
1716 //=======================================================================
1717 //function : LocalD3
1718 //purpose :
1719 //=======================================================================
1720
LocalD3(const Standard_Real U,const Standard_Integer FromK1,const Standard_Integer ToK2,Standard_Real & P,Standard_Real & V1,Standard_Real & V2,Standard_Real & V3) const1721 void Law_BSpline::LocalD3
1722 (const Standard_Real U,
1723 const Standard_Integer FromK1,
1724 const Standard_Integer ToK2,
1725 Standard_Real& P,
1726 Standard_Real& V1,
1727 Standard_Real& V2,
1728 Standard_Real& V3) const
1729 {
1730 Standard_DomainError_Raise_if (FromK1 == ToK2,
1731 "Law_BSpline::LocalD3");
1732 Standard_Real u = U;
1733 Standard_Integer index = 0;
1734 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
1735 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
1736 if (rational) {
1737 BSplCLib::D3(u,index,deg,periodic,POLES,&weights->Array1(),FKNOTS,FMULTS,P,V1,V2,V3);
1738 }
1739 else {
1740 BSplCLib::D3(u,index,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,P,V1,V2,V3);
1741 }
1742 }
1743
1744
1745
1746 //=======================================================================
1747 //function : LocalDN
1748 //purpose :
1749 //=======================================================================
1750
LocalDN(const Standard_Real U,const Standard_Integer FromK1,const Standard_Integer ToK2,const Standard_Integer N) const1751 Standard_Real Law_BSpline::LocalDN
1752 (const Standard_Real U,
1753 const Standard_Integer FromK1,
1754 const Standard_Integer ToK2,
1755 const Standard_Integer N ) const
1756 {
1757 Standard_DomainError_Raise_if (FromK1 == ToK2,
1758 "Law_BSpline::LocalD3");
1759 Standard_Real u = U;
1760 Standard_Integer index = 0;
1761 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
1762 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
1763
1764 Standard_Real V;
1765 if (rational) {
1766 BSplCLib::DN(u,N,index,deg,periodic,POLES,&weights->Array1(),FKNOTS,FMULTS,V);
1767 }
1768 else {
1769 BSplCLib::DN(u,N,index,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,V);
1770 }
1771 return V;
1772 }
1773
1774
1775
1776 //=======================================================================
1777 //function : Multiplicity
1778 //purpose :
1779 //=======================================================================
1780
Multiplicity(const Standard_Integer Index) const1781 Standard_Integer Law_BSpline::Multiplicity
1782 (const Standard_Integer Index) const
1783 {
1784 Standard_OutOfRange_Raise_if (Index < 1 || Index > mults->Length(),
1785 "Law_BSpline::Multiplicity");
1786 return mults->Value (Index);
1787 }
1788
1789
1790 //=======================================================================
1791 //function : Multiplicities
1792 //purpose :
1793 //=======================================================================
1794
Multiplicities(TColStd_Array1OfInteger & M) const1795 void Law_BSpline::Multiplicities (TColStd_Array1OfInteger& M) const
1796 {
1797 Standard_DimensionError_Raise_if (M.Length() != mults->Length(),
1798 "Law_BSpline::Multiplicities");
1799 M = mults->Array1();
1800 }
1801
1802
1803 //=======================================================================
1804 //function : NbKnots
1805 //purpose :
1806 //=======================================================================
1807
NbKnots() const1808 Standard_Integer Law_BSpline::NbKnots () const
1809 { return knots->Length(); }
1810
1811 //=======================================================================
1812 //function : NbPoles
1813 //purpose :
1814 //=======================================================================
1815
NbPoles() const1816 Standard_Integer Law_BSpline::NbPoles () const
1817 { return poles->Length(); }
1818
1819
1820 //=======================================================================
1821 //function : Pole
1822 //purpose :
1823 //=======================================================================
1824
Pole(const Standard_Integer Index) const1825 Standard_Real Law_BSpline::Pole (const Standard_Integer Index) const
1826 {
1827 Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
1828 "Law_BSpline::Pole");
1829 return poles->Value (Index);
1830 }
1831
1832
1833 //=======================================================================
1834 //function : Poles
1835 //purpose :
1836 //=======================================================================
1837
Poles(TColStd_Array1OfReal & P) const1838 void Law_BSpline::Poles (TColStd_Array1OfReal& P) const
1839 {
1840 Standard_DimensionError_Raise_if (P.Length() != poles->Length(),
1841 "Law_BSpline::Poles");
1842 P = poles->Array1();
1843 }
1844
1845
1846 //=======================================================================
1847 //function : StartPoint
1848 //purpose :
1849 //=======================================================================
1850
StartPoint() const1851 Standard_Real Law_BSpline::StartPoint () const
1852 {
1853 if (mults->Value (1) == deg + 1)
1854 return poles->Value (1);
1855 else
1856 return Value(FirstParameter());
1857 }
1858
1859 //=======================================================================
1860 //function : Weight
1861 //purpose :
1862 //=======================================================================
1863
Weight(const Standard_Integer Index) const1864 Standard_Real Law_BSpline::Weight
1865 (const Standard_Integer Index) const
1866 {
1867 Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
1868 "Law_BSpline::Weight");
1869 if (IsRational())
1870 return weights->Value (Index);
1871 else
1872 return 1.;
1873 }
1874
1875
1876
1877 //=======================================================================
1878 //function : Weights
1879 //purpose :
1880 //=======================================================================
1881
Weights(TColStd_Array1OfReal & W) const1882 void Law_BSpline::Weights
1883 (TColStd_Array1OfReal& W) const
1884 {
1885 Standard_DimensionError_Raise_if (W.Length() != poles->Length(),
1886 "Law_BSpline::Weights");
1887 if (IsRational())
1888 W = weights->Array1();
1889 else {
1890 Standard_Integer i;
1891 for (i = W.Lower(); i <= W.Upper(); i++)
1892 W(i) = 1.;
1893 }
1894 }
1895
1896
1897
1898 //=======================================================================
1899 //function : IsRational
1900 //purpose :
1901 //=======================================================================
1902
IsRational() const1903 Standard_Boolean Law_BSpline::IsRational () const
1904 {
1905 return !weights.IsNull();
1906 }
1907
1908
1909 //=======================================================================
1910 //function : LocateU
1911 //purpose :
1912 //=======================================================================
1913
LocateU(const Standard_Real U,const Standard_Real ParametricTolerance,Standard_Integer & I1,Standard_Integer & I2,const Standard_Boolean WithKnotRepetition) const1914 void Law_BSpline::LocateU
1915 (const Standard_Real U,
1916 const Standard_Real ParametricTolerance,
1917 Standard_Integer& I1,
1918 Standard_Integer& I2,
1919 const Standard_Boolean WithKnotRepetition) const
1920 {
1921 Standard_Real NewU = U;
1922 Handle(TColStd_HArray1OfReal) TheKnots;
1923 if (WithKnotRepetition) TheKnots = flatknots;
1924 else TheKnots = knots;
1925
1926 PeriodicNormalization(NewU); //Attention a la periode
1927
1928 const TColStd_Array1OfReal & CKnots = TheKnots->Array1();
1929 Standard_Real UFirst = CKnots (1);
1930 Standard_Real ULast = CKnots (CKnots.Length());
1931 if (Abs (U - UFirst) <= Abs(ParametricTolerance)) { I1 = I2 = 1; }
1932 else if (Abs (U - ULast) <= Abs(ParametricTolerance)) {
1933 I1 = I2 = CKnots.Length();
1934 }
1935 else if (NewU < UFirst - Abs(ParametricTolerance)) {
1936 I2 = 1;
1937 I1 = 0;
1938 }
1939 else if (NewU > ULast + Abs(ParametricTolerance)) {
1940 I1 = CKnots.Length();
1941 I2 = I1 + 1;
1942 }
1943 else {
1944 I1 = 1;
1945 BSplCLib::Hunt (CKnots, NewU, I1);
1946 I1 = Max (Min (I1, CKnots.Upper()), CKnots.Lower());
1947 while (I1 + 1 <= CKnots.Upper()
1948 && Abs (CKnots (I1 + 1) - NewU) <= Abs(ParametricTolerance))
1949 {
1950 I1++;
1951 }
1952 if ( Abs( CKnots(I1) - NewU) <= Abs(ParametricTolerance)) {
1953 I2 = I1;
1954 }
1955 else {
1956 I2 = I1 + 1;
1957 }
1958 }
1959 }
1960 //=======================================================================
1961 //function : MovePointAndTangent
1962 //purpose :
1963 //=======================================================================
1964
1965 void Law_BSpline::
MovePointAndTangent(const Standard_Real U,const Standard_Real P,const Standard_Real Tangent,const Standard_Real Tolerance,const Standard_Integer StartingCondition,const Standard_Integer EndingCondition,Standard_Integer & ErrorStatus)1966 MovePointAndTangent(const Standard_Real U,
1967 const Standard_Real P,
1968 const Standard_Real Tangent,
1969 const Standard_Real Tolerance,
1970 const Standard_Integer StartingCondition,
1971 const Standard_Integer EndingCondition,
1972 Standard_Integer& ErrorStatus)
1973 {
1974 TColStd_Array1OfReal new_poles(1, poles->Length());
1975 Standard_Real delta,
1976 *poles_array,
1977 *new_poles_array,
1978 delta_derivative;
1979 const Standard_Integer dimension = 1 ;
1980 D1(U,
1981 delta,
1982 delta_derivative) ;
1983 delta = P - delta ;
1984
1985 delta_derivative = Tangent - delta_derivative ;
1986 poles_array = (Standard_Real *)
1987 &poles->Array1()(1) ;
1988 new_poles_array = (Standard_Real *)
1989 &new_poles(1) ;
1990 BSplCLib::MovePointAndTangent (U,
1991 dimension,
1992 delta,
1993 delta_derivative,
1994 Tolerance,
1995 deg,
1996 StartingCondition,
1997 EndingCondition,
1998 poles_array[0],
1999 rational ? &weights->Array1() : BSplCLib::NoWeights(),
2000 flatknots->Array1(),
2001 new_poles_array[0],
2002 ErrorStatus);
2003 if (!ErrorStatus) {
2004 poles->ChangeArray1() = new_poles;
2005 }
2006 }
2007
2008
2009 //=======================================================================
2010 //function : Resolution
2011 //purpose :
2012 //=======================================================================
2013
Resolution(const Standard_Real Tolerance3D,Standard_Real & UTolerance) const2014 void Law_BSpline::Resolution(const Standard_Real Tolerance3D,
2015 Standard_Real & UTolerance) const
2016 {
2017 void* bid = (void*)(&(poles->Value(1)));
2018 Standard_Real* bidr = (Standard_Real*)bid;
2019 if (rational) {
2020 BSplCLib::Resolution(*bidr,1,poles->Length(),
2021 &weights->Array1(),FKNOTS,deg,
2022 Tolerance3D,
2023 UTolerance) ;
2024 }
2025 else {
2026
2027 BSplCLib::Resolution(*bidr,1,poles->Length(),
2028 BSplCLib::NoWeights(),FKNOTS,deg,
2029 Tolerance3D,
2030 UTolerance) ;
2031 }
2032 }
2033