Integration of OCCT 6.5.0 from SVN
[occt.git] / src / Geom / Geom_BSplineCurve_1.cxx
CommitLineData
7fd59977 1// File: Geom_BSplineCurve_1.cxx
2// Created: Tue Mar 9 19:35:13 1993
3// Author: JCV
4// <fid@phylox>
5// Copyright: Matra Datavision 1993
6
7// Created: Fri Jul 5 16:37:59 1991
8// Author: JCV
9
10// 03-02-97 : pmn ->LocateU sur Periodic (PRO6963),
11// bon appel a LocateParameter (PRO6973) et mise en conformite avec
12// le cdl de LocateU, lorsque U est un noeud (PRO6988)
13
14#define No_Standard_OutOfRange
15#define No_Standard_DimensionError
16
17#include <Geom_BSplineCurve.jxx>
18#include <BSplCLib.hxx>
19#include <gp.hxx>
20
21#include <Geom_UndefinedDerivative.hxx>
22#include <Standard_DimensionError.hxx>
23#include <Standard_OutOfRange.hxx>
24#include <Standard_DomainError.hxx>
25#include <Standard_RangeError.hxx>
26
27#define POLES (poles->Array1())
28#define KNOTS (knots->Array1())
29#define FKNOTS (flatknots->Array1())
30#define FMULTS (BSplCLib::NoMults())
31
32//=======================================================================
33//function : IsCN
34//purpose :
35//=======================================================================
36
37Standard_Boolean Geom_BSplineCurve::IsCN ( const Standard_Integer N) const
38{
39 Standard_RangeError_Raise_if
40 (N < 0, "Geom_BSplineCurve::IsCN");
41
42 switch (smooth) {
43 case GeomAbs_CN : return Standard_True;
44 case GeomAbs_C0 : return N <= 0;
45 case GeomAbs_G1 : return N <= 0;
46 case GeomAbs_C1 : return N <= 1;
47 case GeomAbs_G2 : return N <= 1;
48 case GeomAbs_C2 : return N <= 2;
49 case GeomAbs_C3 :
50 return N <= 3 ? Standard_True :
51 N <= deg - BSplCLib::MaxKnotMult (mults->Array1(), mults->Lower() + 1, mults->Upper() - 1);
52 default:
53 return Standard_False;
54 }
55}
56
57//=======================================================================
58//function : IsClosed
59//purpose :
60//=======================================================================
61
62Standard_Boolean Geom_BSplineCurve::IsClosed () const
63//-- { return (StartPoint().Distance (EndPoint())) <= gp::Resolution (); }
64{ return (StartPoint().SquareDistance(EndPoint())) <= 1e-16; }
65
66//=======================================================================
67//function : IsPeriodic
68//purpose :
69//=======================================================================
70
71Standard_Boolean Geom_BSplineCurve::IsPeriodic () const
72{ return periodic; }
73
74//=======================================================================
75//function : Continuity
76//purpose :
77//=======================================================================
78
79GeomAbs_Shape Geom_BSplineCurve::Continuity () const
80{ return smooth; }
81
82//=======================================================================
83//function : Degree
84//purpose :
85//=======================================================================
86
87Standard_Integer Geom_BSplineCurve::Degree () const
88{ return deg; }
89
90//=======================================================================
91//function : D0
92//purpose :
93//=======================================================================
94
95void Geom_BSplineCurve::D0 ( const Standard_Real U,
96 gp_Pnt& P) const
97{
98 Standard_Real NewU = U ;
99 PeriodicNormalization(NewU) ;
100 if (!IsCacheValid(NewU))
101 {
102 Geom_BSplineCurve * MyCurve = (Geom_BSplineCurve *) this ;
103 MyCurve->ValidateCache(NewU) ;
104 }
105 if (rational) {
106
107 BSplCLib::CacheD0(NewU,
108 deg,
109 parametercache,
110 spanlenghtcache,
111 (cachepoles->Array1()),
112 cacheweights->Array1(),
113 P) ;
114
115 }
116 else {
117
118 BSplCLib::CacheD0(NewU,
119 deg,
120 parametercache,
121 spanlenghtcache,
122 (cachepoles->Array1()),
123 *((TColStd_Array1OfReal*) NULL),
124 P) ;
125 }
126}
127
128//=======================================================================
129//function : D1
130//purpose :
131//=======================================================================
132
133void Geom_BSplineCurve::D1 (const Standard_Real U,
134 gp_Pnt& P,
135 gp_Vec& V1) const
136{
137Standard_Real NewU = U ;
138 PeriodicNormalization(NewU) ;
139 if (!IsCacheValid(NewU))
140 {
141 Geom_BSplineCurve * MyCurve = (Geom_BSplineCurve *) this ;
142 MyCurve->ValidateCache(NewU) ;
143 }
144 if (rational) {
145 BSplCLib::CacheD1(NewU,
146 deg,
147 parametercache,
148 spanlenghtcache,
149 (cachepoles->Array1()),
150 cacheweights->Array1(),
151 P,
152 V1) ;
153 }
154 else {
155 BSplCLib::CacheD1(NewU,
156 deg,
157 parametercache,
158 spanlenghtcache,
159 (cachepoles->Array1()),
160 *((TColStd_Array1OfReal*) NULL),
161 P,
162 V1) ;
163 }
164}
165
166//=======================================================================
167//function : D2
168//purpose :
169//=======================================================================
170
171void Geom_BSplineCurve::D2 (const Standard_Real U ,
172 gp_Pnt& P ,
173 gp_Vec& V1,
174 gp_Vec& V2 ) const
175{
176
177 Standard_Real NewU = U ;
178 PeriodicNormalization(NewU) ;
179 if (!IsCacheValid(NewU))
180 {
181 Geom_BSplineCurve * MyCurve = (Geom_BSplineCurve *) this ;
182 MyCurve->ValidateCache(NewU) ;
183 }
184 if (rational) {
185 BSplCLib::CacheD2(NewU,
186 deg,
187 parametercache,
188 spanlenghtcache,
189 (cachepoles->Array1()),
190 cacheweights->Array1(),
191 P,
192 V1,
193 V2) ;
194 }
195 else {
196 BSplCLib::CacheD2(NewU,
197 deg,
198 parametercache,
199 spanlenghtcache,
200 (cachepoles->Array1()),
201 *((TColStd_Array1OfReal*) NULL),
202 P,
203 V1,
204 V2) ;
205 }
206}
207
208//=======================================================================
209//function : D3
210//purpose :
211//=======================================================================
212
213void Geom_BSplineCurve::D3 (const Standard_Real U ,
214 gp_Pnt& P ,
215 gp_Vec& V1,
216 gp_Vec& V2,
217 gp_Vec& V3 ) const
218{
219
220Standard_Real NewU = U ;
221 PeriodicNormalization(NewU) ;
222 if (!IsCacheValid(NewU))
223 {
224 Geom_BSplineCurve * MyCurve = (Geom_BSplineCurve *) this ;
225 MyCurve->ValidateCache(NewU) ;
226 }
227 if (rational) {
228 BSplCLib::CacheD3(NewU,
229 deg,
230 parametercache,
231 spanlenghtcache,
232 (cachepoles->Array1()),
233 cacheweights->Array1(),
234 P,
235 V1,
236 V2,
237 V3) ;
238 }
239 else {
240 BSplCLib::CacheD3(NewU,
241 deg,
242 parametercache,
243 spanlenghtcache,
244 (cachepoles->Array1()),
245 *((TColStd_Array1OfReal*) NULL),
246 P,
247 V1,
248 V2,
249 V3) ;
250 }
251}
252
253//=======================================================================
254//function : DN
255//purpose :
256//=======================================================================
257
258gp_Vec Geom_BSplineCurve::DN (const Standard_Real U,
259 const Standard_Integer N ) const
260{
261 gp_Vec V;
262 if (rational) {
263 BSplCLib::DN(U,N,0,deg,periodic,POLES,
264 weights->Array1(),
265 FKNOTS,FMULTS,V);
266 }
267 else {
268 BSplCLib::DN(U,N,0,deg,periodic,POLES,
269 *((TColStd_Array1OfReal*) NULL),
270 FKNOTS,FMULTS,V);
271 }
272 return V;
273}
274
275//=======================================================================
276//function : EndPoint
277//purpose :
278//=======================================================================
279
280gp_Pnt Geom_BSplineCurve::EndPoint () const
281{
282 if (mults->Value (knots->Upper ()) == deg + 1)
283 return poles->Value (poles->Upper());
284 else
285 return Value(LastParameter());
286}
287
288//=======================================================================
289//function : FirstUKnotIndex
290//purpose :
291//=======================================================================
292
293Standard_Integer Geom_BSplineCurve::FirstUKnotIndex () const
294{
295 if (periodic) return 1;
296 else return BSplCLib::FirstUKnotIndex (deg, mults->Array1());
297}
298
299//=======================================================================
300//function : FirstParameter
301//purpose :
302//=======================================================================
303
304Standard_Real Geom_BSplineCurve::FirstParameter () const
305{
306 return flatknots->Value (deg+1);
307}
308
309//=======================================================================
310//function : Knot
311//purpose :
312//=======================================================================
313
314Standard_Real Geom_BSplineCurve::Knot (const Standard_Integer Index) const
315{
316 Standard_OutOfRange_Raise_if
317 (Index < 1 || Index > knots->Length(), "Geom_BSplineCurve::Knot");
318 return knots->Value (Index);
319}
320
321//=======================================================================
322//function : KnotDistribution
323//purpose :
324//=======================================================================
325
326GeomAbs_BSplKnotDistribution Geom_BSplineCurve::KnotDistribution () const
327{
328 return knotSet;
329}
330
331//=======================================================================
332//function : Knots
333//purpose :
334//=======================================================================
335
336void Geom_BSplineCurve::Knots (TColStd_Array1OfReal& K) const
337{
338 Standard_DimensionError_Raise_if
339 (K.Length() != knots->Length(), "Geom_BSplineCurve::Knots");
340 K = knots->Array1();
341}
342
343//=======================================================================
344//function : KnotSequence
345//purpose :
346//=======================================================================
347
348void Geom_BSplineCurve::KnotSequence (TColStd_Array1OfReal& K) const
349{
350 Standard_DimensionError_Raise_if
351 (K.Length() != flatknots->Length(), "Geom_BSplineCurve::KnotSequence");
352 K = flatknots->Array1();
353}
354
355//=======================================================================
356//function : LastUKnotIndex
357//purpose :
358//=======================================================================
359
360Standard_Integer Geom_BSplineCurve::LastUKnotIndex() const
361{
362 if (periodic) return knots->Length();
363 else return BSplCLib::LastUKnotIndex (deg, mults->Array1());
364}
365
366//=======================================================================
367//function : LastParameter
368//purpose :
369//=======================================================================
370
371Standard_Real Geom_BSplineCurve::LastParameter () const
372{
373 return flatknots->Value (flatknots->Upper()-deg);
374}
375
376//=======================================================================
377//function : LocalValue
378//purpose :
379//=======================================================================
380
381gp_Pnt Geom_BSplineCurve::LocalValue
382 (const Standard_Real U,
383 const Standard_Integer FromK1,
384 const Standard_Integer ToK2) const
385{
386 gp_Pnt P;
387 LocalD0(U,FromK1,ToK2,P);
388 return P;
389}
390
391//=======================================================================
392//function : LocalD0
393//purpose :
394//=======================================================================
395
396void Geom_BSplineCurve::LocalD0
397 (const Standard_Real U,
398 const Standard_Integer FromK1,
399 const Standard_Integer ToK2,
400 gp_Pnt& P) const
401{
402 Standard_DomainError_Raise_if (FromK1 == ToK2,
403 "Geom_BSplineCurve::LocalValue");
404
405 Standard_Real u = U;
406 Standard_Integer index = 0;
407 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic,FromK1,ToK2, index,u);
408 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
409 if (rational) {
410 BSplCLib::D0(u,index,deg,periodic,POLES,
411 weights->Array1(),
412 FKNOTS,FMULTS,P);
413 }
414 else {
415 BSplCLib::D0(u,index,deg,periodic,POLES,
416 *((TColStd_Array1OfReal*) NULL),
417 FKNOTS,FMULTS,P);
418 }
419}
420
421//=======================================================================
422//function : LocalD1
423//purpose :
424//=======================================================================
425
426void Geom_BSplineCurve::LocalD1 (const Standard_Real U,
427 const Standard_Integer FromK1,
428 const Standard_Integer ToK2,
429 gp_Pnt& P,
430 gp_Vec& V1) const
431{
432 Standard_DomainError_Raise_if (FromK1 == ToK2,
433 "Geom_BSplineCurve::LocalD1");
434
435 Standard_Real u = U;
436 Standard_Integer index = 0;
437 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
438 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
439 if (rational) {
440 BSplCLib::D1(u,index,deg,periodic,POLES,
441 weights->Array1(),
442 FKNOTS,FMULTS,P,V1);
443 }
444 else {
445 BSplCLib::D1(u,index,deg,periodic,POLES,
446 *((TColStd_Array1OfReal*) NULL),
447 FKNOTS,FMULTS,P,V1);
448 }
449}
450
451//=======================================================================
452//function : LocalD2
453//purpose :
454//=======================================================================
455
456void Geom_BSplineCurve::LocalD2
457 (const Standard_Real U,
458 const Standard_Integer FromK1,
459 const Standard_Integer ToK2,
460 gp_Pnt& P,
461 gp_Vec& V1,
462 gp_Vec& V2) const
463{
464 Standard_DomainError_Raise_if (FromK1 == ToK2,
465 "Geom_BSplineCurve::LocalD2");
466
467 Standard_Real u = U;
468 Standard_Integer index = 0;
469 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
470 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
471 if (rational) {
472 BSplCLib::D2(u,index,deg,periodic,POLES,
473 weights->Array1(),
474 FKNOTS,FMULTS,P,V1,V2);
475 }
476 else {
477 BSplCLib::D2(u,index,deg,periodic,POLES,
478 *((TColStd_Array1OfReal*) NULL),
479 FKNOTS,FMULTS,P,V1,V2);
480 }
481}
482
483//=======================================================================
484//function : LocalD3
485//purpose :
486//=======================================================================
487
488void Geom_BSplineCurve::LocalD3
489 (const Standard_Real U,
490 const Standard_Integer FromK1,
491 const Standard_Integer ToK2,
492 gp_Pnt& P,
493 gp_Vec& V1,
494 gp_Vec& V2,
495 gp_Vec& V3) const
496{
497 Standard_DomainError_Raise_if (FromK1 == ToK2,
498 "Geom_BSplineCurve::LocalD3");
499
500 Standard_Real u = U;
501 Standard_Integer index = 0;
502 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
503 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
504 if (rational) {
505 BSplCLib::D3(u,index,deg,periodic,POLES,
506 weights->Array1(),
507 FKNOTS,FMULTS,P,V1,V2,V3);
508 }
509 else {
510 BSplCLib::D3(u,index,deg,periodic,POLES,
511 *((TColStd_Array1OfReal*) NULL),
512 FKNOTS,FMULTS,P,V1,V2,V3);
513 }
514}
515
516//=======================================================================
517//function : LocalDN
518//purpose :
519//=======================================================================
520
521gp_Vec Geom_BSplineCurve::LocalDN
522 (const Standard_Real U,
523 const Standard_Integer FromK1,
524 const Standard_Integer ToK2,
525 const Standard_Integer N ) const
526{
527 Standard_DomainError_Raise_if (FromK1 == ToK2,
528 "Geom_BSplineCurve::LocalD3");
529
530 Standard_Real u = U;
531 Standard_Integer index = 0;
532 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
533 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
534
535 gp_Vec V;
536 if (rational) {
537 BSplCLib::DN(u,N,index,deg,periodic,POLES,
538 weights->Array1(),
539 FKNOTS,FMULTS,V);
540 }
541 else {
542 BSplCLib::DN(u,N,index,deg,periodic,POLES,
543 *((TColStd_Array1OfReal*) NULL),
544 FKNOTS,FMULTS,V);
545 }
546 return V;
547}
548
549//=======================================================================
550//function : Multiplicity
551//purpose :
552//=======================================================================
553
554Standard_Integer Geom_BSplineCurve::Multiplicity
555 (const Standard_Integer Index) const
556{
557 Standard_OutOfRange_Raise_if (Index < 1 || Index > mults->Length(),
558 "Geom_BSplineCurve::Multiplicity");
559 return mults->Value (Index);
560}
561
562//=======================================================================
563//function : Multiplicities
564//purpose :
565//=======================================================================
566
567void Geom_BSplineCurve::Multiplicities (TColStd_Array1OfInteger& M) const
568{
569 Standard_DimensionError_Raise_if (M.Length() != mults->Length(),
570 "Geom_BSplineCurve::Multiplicities");
571 M = mults->Array1();
572}
573
574//=======================================================================
575//function : NbKnots
576//purpose :
577//=======================================================================
578
579Standard_Integer Geom_BSplineCurve::NbKnots () const
580{ return knots->Length(); }
581
582//=======================================================================
583//function : NbPoles
584//purpose :
585//=======================================================================
586
587Standard_Integer Geom_BSplineCurve::NbPoles () const
588{ return poles->Length(); }
589
590//=======================================================================
591//function : Pole
592//purpose :
593//=======================================================================
594
595gp_Pnt Geom_BSplineCurve::Pole (const Standard_Integer Index) const
596{
597 Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
598 "Geom_BSplineCurve::Pole");
599 return poles->Value (Index);
600}
601
602//=======================================================================
603//function : Poles
604//purpose :
605//=======================================================================
606
607void Geom_BSplineCurve::Poles (TColgp_Array1OfPnt& P) const
608{
609 Standard_DimensionError_Raise_if (P.Length() != poles->Length(),
610 "Geom_BSplineCurve::Poles");
611 P = poles->Array1();
612}
613
614//=======================================================================
615//function : StartPoint
616//purpose :
617//=======================================================================
618
619gp_Pnt Geom_BSplineCurve::StartPoint () const
620{
621 if (mults->Value (1) == deg + 1)
622 return poles->Value (1);
623 else
624 return Value(FirstParameter());
625}
626
627//=======================================================================
628//function : Weight
629//purpose :
630//=======================================================================
631
632Standard_Real Geom_BSplineCurve::Weight
633 (const Standard_Integer Index) const
634{
635 Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
636 "Geom_BSplineCurve::Weight");
637 if (IsRational())
638 return weights->Value (Index);
639 else
640 return 1.;
641}
642
643//=======================================================================
644//function : Weights
645//purpose :
646//=======================================================================
647
648void Geom_BSplineCurve::Weights
649 (TColStd_Array1OfReal& W) const
650{
651 Standard_DimensionError_Raise_if (W.Length() != poles->Length(),
652 "Geom_BSplineCurve::Weights");
653 if (IsRational())
654 W = weights->Array1();
655 else {
656 Standard_Integer i;
657
658 for (i = W.Lower(); i <= W.Upper(); i++)
659 W(i) = 1.;
660 }
661}
662
663//=======================================================================
664//function : IsRational
665//purpose :
666//=======================================================================
667
668Standard_Boolean Geom_BSplineCurve::IsRational () const
669{
670 return !weights.IsNull();
671}
672
673//=======================================================================
674//function : Transform
675//purpose :
676//=======================================================================
677
678void Geom_BSplineCurve::Transform
679 (const gp_Trsf& T)
680{
681 TColgp_Array1OfPnt & CPoles = poles->ChangeArray1();
682 for (Standard_Integer I = 1; I <= CPoles.Length(); I++)
683 CPoles (I).Transform (T);
684 InvalidateCache() ;
685 maxderivinvok = 0;
686}
687
688//=======================================================================
689//function : LocateU
690//purpose :
691// pmn : 30/01/97 mise en conformite avec le cdl, lorsque U est un noeud
692// (PRO6988)
693//=======================================================================
694
695void Geom_BSplineCurve::LocateU
696 (const Standard_Real U,
697 const Standard_Real ParametricTolerance,
698 Standard_Integer& I1,
699 Standard_Integer& I2,
700 const Standard_Boolean WithKnotRepetition) const
701{
702 Standard_Real NewU = U;
703 Handle(TColStd_HArray1OfReal) TheKnots;
704 if (WithKnotRepetition) TheKnots = flatknots;
705 else TheKnots = knots;
706 const TColStd_Array1OfReal & CKnots = TheKnots->Array1();
707
708 PeriodicNormalization(NewU); //Attention a la periode
709
710 Standard_Real UFirst = CKnots (1);
711 Standard_Real ULast = CKnots (CKnots.Length());
712 if (Abs (NewU - UFirst) <= Abs(ParametricTolerance)) { I1 = I2 = 1; }
713 else if (Abs (NewU - ULast) <= Abs(ParametricTolerance)) {
714 I1 = I2 = CKnots.Length();
715 }
716 else if (NewU < UFirst - Abs(ParametricTolerance)) {
717 I2 = 1;
718 I1 = 0;
719 }
720 else if (NewU > ULast + Abs(ParametricTolerance)) {
721 I1 = CKnots.Length();
722 I2 = I1 + 1;
723 }
724 else {
725 I1 = 1;
726 BSplCLib::Hunt (CKnots, NewU, I1);
727 while ( Abs( CKnots(I1+1) - NewU) <= Abs(ParametricTolerance)) I1++;
728 if ( Abs( CKnots(I1) - NewU) <= Abs(ParametricTolerance)) {
729 I2 = I1;
730 }
731 else {
732 I2 = I1 + 1;
733 }
734 }
735}
736
737//=======================================================================
738//function : Resolution
739//purpose :
740//=======================================================================
741
742void Geom_BSplineCurve::Resolution(const Standard_Real Tolerance3D,
743 Standard_Real & UTolerance)
744{
745 Standard_Integer ii;
746 if(!maxderivinvok){
747 if ( periodic) {
748 Standard_Integer NbKnots, NbPoles;
749 BSplCLib::PrepareUnperiodize( deg,
750 mults->Array1(),
751 NbKnots,
752 NbPoles);
753 TColgp_Array1OfPnt new_poles(1,NbPoles) ;
754 TColStd_Array1OfReal new_weights(1,NbPoles) ;
755 for(ii = 1 ; ii <= NbPoles ; ii++) {
756 new_poles(ii) = poles->Array1()((ii-1) % poles->Length() + 1) ;
757 }
758 if (rational) {
759 for(ii = 1 ; ii <= NbPoles ; ii++) {
760 new_weights(ii) = weights->Array1()((ii-1) % poles->Length() + 1) ;
761 }
762 BSplCLib::Resolution(new_poles,
763 new_weights,
764 new_poles.Length(),
765 flatknots->Array1(),
766 deg,
767 1.,
768 maxderivinv) ;
769 }
770 else {
771 BSplCLib::Resolution(new_poles,
772 *((TColStd_Array1OfReal*) NULL),
773 new_poles.Length(),
774 flatknots->Array1(),
775 deg,
776 1.,
777 maxderivinv) ;
778 }
779
780 }
781 else {
782 if (rational) {
783 BSplCLib::Resolution(poles->Array1(),
784 weights->Array1(),
785 poles->Length(),
786 flatknots->Array1(),
787 deg,
788 1.,
789 maxderivinv) ;
790 }
791 else {
792 BSplCLib::Resolution(poles->Array1(),
793 *((TColStd_Array1OfReal*) NULL),
794 poles->Length(),
795 flatknots->Array1(),
796 deg,
797 1.,
798 maxderivinv) ;
799 }
800 }
801 maxderivinvok = 1;
802 }
803 UTolerance = Tolerance3D * maxderivinv;
804}