1 // Created on: 1991-07-05
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
23 // 03-02-97 : pmn ->LocateU sur Periodic (PRO6963),
24 // bon appel a LocateParameter (PRO6973) et mise en conformite avec
25 // le cdl de LocateU, lorsque U est un noeud (PRO6988)
27 #define No_Standard_OutOfRange
28 #define No_Standard_DimensionError
30 #include <Geom_BSplineCurve.jxx>
31 #include <BSplCLib.hxx>
34 #include <Geom_UndefinedDerivative.hxx>
35 #include <Standard_DimensionError.hxx>
36 #include <Standard_OutOfRange.hxx>
37 #include <Standard_DomainError.hxx>
38 #include <Standard_RangeError.hxx>
39 #include <Standard_Mutex.hxx>
41 #define POLES (poles->Array1())
42 #define KNOTS (knots->Array1())
43 #define FKNOTS (flatknots->Array1())
44 #define FMULTS (BSplCLib::NoMults())
46 //=======================================================================
49 //=======================================================================
51 Standard_Boolean Geom_BSplineCurve::IsCN ( const Standard_Integer N) const
53 Standard_RangeError_Raise_if
54 (N < 0, "Geom_BSplineCurve::IsCN");
57 case GeomAbs_CN : return Standard_True;
58 case GeomAbs_C0 : return N <= 0;
59 case GeomAbs_G1 : return N <= 0;
60 case GeomAbs_C1 : return N <= 1;
61 case GeomAbs_G2 : return N <= 1;
62 case GeomAbs_C2 : return N <= 2;
64 return N <= 3 ? Standard_True :
65 N <= deg - BSplCLib::MaxKnotMult (mults->Array1(), mults->Lower() + 1, mults->Upper() - 1);
67 return Standard_False;
71 //=======================================================================
74 //=======================================================================
76 Standard_Boolean Geom_BSplineCurve::IsClosed () const
77 //-- { return (StartPoint().Distance (EndPoint())) <= gp::Resolution (); }
78 { return (StartPoint().SquareDistance(EndPoint())) <= 1e-16; }
80 //=======================================================================
81 //function : IsPeriodic
83 //=======================================================================
85 Standard_Boolean Geom_BSplineCurve::IsPeriodic () const
88 //=======================================================================
89 //function : Continuity
91 //=======================================================================
93 GeomAbs_Shape Geom_BSplineCurve::Continuity () const
96 //=======================================================================
99 //=======================================================================
101 Standard_Integer Geom_BSplineCurve::Degree () const
104 //=======================================================================
107 //=======================================================================
109 void Geom_BSplineCurve::D0(const Standard_Real U, gp_Pnt& P) const
111 Standard_Real NewU(U);
112 PeriodicNormalization(NewU);
114 Geom_BSplineCurve* MyCurve = (Geom_BSplineCurve *) this;
115 Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
117 if(!IsCacheValid(NewU))
118 MyCurve->ValidateCache(NewU);
122 BSplCLib::CacheD0(NewU,
126 cachepoles->Array1(),
127 cacheweights->Array1(),
132 BSplCLib::CacheD0(NewU,
136 cachepoles->Array1(),
137 *((TColStd_Array1OfReal*) NULL),
142 //=======================================================================
145 //=======================================================================
147 void Geom_BSplineCurve::D1 (const Standard_Real U,
151 Standard_Real NewU(U);
152 PeriodicNormalization(NewU);
154 Geom_BSplineCurve* MyCurve = (Geom_BSplineCurve *) this;
155 Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
157 if(!IsCacheValid(NewU))
158 MyCurve->ValidateCache(NewU);
162 BSplCLib::CacheD1(NewU,
166 cachepoles->Array1(),
167 cacheweights->Array1(),
173 BSplCLib::CacheD1(NewU,
177 cachepoles->Array1(),
178 *((TColStd_Array1OfReal*) NULL),
184 //=======================================================================
187 //=======================================================================
189 void Geom_BSplineCurve::D2(const Standard_Real U,
194 Standard_Real NewU(U);
195 PeriodicNormalization(NewU);
197 Geom_BSplineCurve* MyCurve = (Geom_BSplineCurve *) this;
198 Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
200 if(!IsCacheValid(NewU))
201 MyCurve->ValidateCache(NewU);
205 BSplCLib::CacheD2(NewU,
209 (cachepoles->Array1()),
210 cacheweights->Array1(),
216 BSplCLib::CacheD2(NewU,
220 (cachepoles->Array1()),
221 *((TColStd_Array1OfReal*) NULL),
228 //=======================================================================
231 //=======================================================================
233 void Geom_BSplineCurve::D3(const Standard_Real U,
240 Standard_Real NewU(U);
241 PeriodicNormalization(NewU);
243 Geom_BSplineCurve* MyCurve = (Geom_BSplineCurve *) this;
244 Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
246 if(!IsCacheValid(NewU))
247 MyCurve->ValidateCache(NewU);
251 BSplCLib::CacheD3(NewU,
255 (cachepoles->Array1()),
256 cacheweights->Array1(),
264 BSplCLib::CacheD3(NewU,
268 cachepoles->Array1(),
269 *((TColStd_Array1OfReal*) NULL),
277 //=======================================================================
280 //=======================================================================
282 gp_Vec Geom_BSplineCurve::DN (const Standard_Real U,
283 const Standard_Integer N ) const
287 BSplCLib::DN(U,N,0,deg,periodic,POLES,
292 BSplCLib::DN(U,N,0,deg,periodic,POLES,
293 *((TColStd_Array1OfReal*) NULL),
299 //=======================================================================
300 //function : EndPoint
302 //=======================================================================
304 gp_Pnt Geom_BSplineCurve::EndPoint () const
306 if (mults->Value (knots->Upper ()) == deg + 1)
307 return poles->Value (poles->Upper());
309 return Value(LastParameter());
312 //=======================================================================
313 //function : FirstUKnotIndex
315 //=======================================================================
317 Standard_Integer Geom_BSplineCurve::FirstUKnotIndex () const
319 if (periodic) return 1;
320 else return BSplCLib::FirstUKnotIndex (deg, mults->Array1());
323 //=======================================================================
324 //function : FirstParameter
326 //=======================================================================
328 Standard_Real Geom_BSplineCurve::FirstParameter () const
330 return flatknots->Value (deg+1);
333 //=======================================================================
336 //=======================================================================
338 Standard_Real Geom_BSplineCurve::Knot (const Standard_Integer Index) const
340 Standard_OutOfRange_Raise_if
341 (Index < 1 || Index > knots->Length(), "Geom_BSplineCurve::Knot");
342 return knots->Value (Index);
345 //=======================================================================
346 //function : KnotDistribution
348 //=======================================================================
350 GeomAbs_BSplKnotDistribution Geom_BSplineCurve::KnotDistribution () const
355 //=======================================================================
358 //=======================================================================
360 void Geom_BSplineCurve::Knots (TColStd_Array1OfReal& K) const
362 Standard_DimensionError_Raise_if
363 (K.Length() != knots->Length(), "Geom_BSplineCurve::Knots");
367 //=======================================================================
368 //function : KnotSequence
370 //=======================================================================
372 void Geom_BSplineCurve::KnotSequence (TColStd_Array1OfReal& K) const
374 Standard_DimensionError_Raise_if
375 (K.Length() != flatknots->Length(), "Geom_BSplineCurve::KnotSequence");
376 K = flatknots->Array1();
379 //=======================================================================
380 //function : LastUKnotIndex
382 //=======================================================================
384 Standard_Integer Geom_BSplineCurve::LastUKnotIndex() const
386 if (periodic) return knots->Length();
387 else return BSplCLib::LastUKnotIndex (deg, mults->Array1());
390 //=======================================================================
391 //function : LastParameter
393 //=======================================================================
395 Standard_Real Geom_BSplineCurve::LastParameter () const
397 return flatknots->Value (flatknots->Upper()-deg);
400 //=======================================================================
401 //function : LocalValue
403 //=======================================================================
405 gp_Pnt Geom_BSplineCurve::LocalValue
406 (const Standard_Real U,
407 const Standard_Integer FromK1,
408 const Standard_Integer ToK2) const
411 LocalD0(U,FromK1,ToK2,P);
415 //=======================================================================
418 //=======================================================================
420 void Geom_BSplineCurve::LocalD0
421 (const Standard_Real U,
422 const Standard_Integer FromK1,
423 const Standard_Integer ToK2,
426 Standard_DomainError_Raise_if (FromK1 == ToK2,
427 "Geom_BSplineCurve::LocalValue");
430 Standard_Integer index = 0;
431 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic,FromK1,ToK2, index,u);
432 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
434 BSplCLib::D0(u,index,deg,periodic,POLES,
439 BSplCLib::D0(u,index,deg,periodic,POLES,
440 *((TColStd_Array1OfReal*) NULL),
445 //=======================================================================
448 //=======================================================================
450 void Geom_BSplineCurve::LocalD1 (const Standard_Real U,
451 const Standard_Integer FromK1,
452 const Standard_Integer ToK2,
456 Standard_DomainError_Raise_if (FromK1 == ToK2,
457 "Geom_BSplineCurve::LocalD1");
460 Standard_Integer index = 0;
461 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
462 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
464 BSplCLib::D1(u,index,deg,periodic,POLES,
469 BSplCLib::D1(u,index,deg,periodic,POLES,
470 *((TColStd_Array1OfReal*) NULL),
475 //=======================================================================
478 //=======================================================================
480 void Geom_BSplineCurve::LocalD2
481 (const Standard_Real U,
482 const Standard_Integer FromK1,
483 const Standard_Integer ToK2,
488 Standard_DomainError_Raise_if (FromK1 == ToK2,
489 "Geom_BSplineCurve::LocalD2");
492 Standard_Integer index = 0;
493 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
494 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
496 BSplCLib::D2(u,index,deg,periodic,POLES,
498 FKNOTS,FMULTS,P,V1,V2);
501 BSplCLib::D2(u,index,deg,periodic,POLES,
502 *((TColStd_Array1OfReal*) NULL),
503 FKNOTS,FMULTS,P,V1,V2);
507 //=======================================================================
510 //=======================================================================
512 void Geom_BSplineCurve::LocalD3
513 (const Standard_Real U,
514 const Standard_Integer FromK1,
515 const Standard_Integer ToK2,
521 Standard_DomainError_Raise_if (FromK1 == ToK2,
522 "Geom_BSplineCurve::LocalD3");
525 Standard_Integer index = 0;
526 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
527 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
529 BSplCLib::D3(u,index,deg,periodic,POLES,
531 FKNOTS,FMULTS,P,V1,V2,V3);
534 BSplCLib::D3(u,index,deg,periodic,POLES,
535 *((TColStd_Array1OfReal*) NULL),
536 FKNOTS,FMULTS,P,V1,V2,V3);
540 //=======================================================================
543 //=======================================================================
545 gp_Vec Geom_BSplineCurve::LocalDN
546 (const Standard_Real U,
547 const Standard_Integer FromK1,
548 const Standard_Integer ToK2,
549 const Standard_Integer N ) const
551 Standard_DomainError_Raise_if (FromK1 == ToK2,
552 "Geom_BSplineCurve::LocalD3");
555 Standard_Integer index = 0;
556 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
557 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
561 BSplCLib::DN(u,N,index,deg,periodic,POLES,
566 BSplCLib::DN(u,N,index,deg,periodic,POLES,
567 *((TColStd_Array1OfReal*) NULL),
573 //=======================================================================
574 //function : Multiplicity
576 //=======================================================================
578 Standard_Integer Geom_BSplineCurve::Multiplicity
579 (const Standard_Integer Index) const
581 Standard_OutOfRange_Raise_if (Index < 1 || Index > mults->Length(),
582 "Geom_BSplineCurve::Multiplicity");
583 return mults->Value (Index);
586 //=======================================================================
587 //function : Multiplicities
589 //=======================================================================
591 void Geom_BSplineCurve::Multiplicities (TColStd_Array1OfInteger& M) const
593 Standard_DimensionError_Raise_if (M.Length() != mults->Length(),
594 "Geom_BSplineCurve::Multiplicities");
598 //=======================================================================
601 //=======================================================================
603 Standard_Integer Geom_BSplineCurve::NbKnots () const
604 { return knots->Length(); }
606 //=======================================================================
609 //=======================================================================
611 Standard_Integer Geom_BSplineCurve::NbPoles () const
612 { return poles->Length(); }
614 //=======================================================================
617 //=======================================================================
619 gp_Pnt Geom_BSplineCurve::Pole (const Standard_Integer Index) const
621 Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
622 "Geom_BSplineCurve::Pole");
623 return poles->Value (Index);
626 //=======================================================================
629 //=======================================================================
631 void Geom_BSplineCurve::Poles (TColgp_Array1OfPnt& P) const
633 Standard_DimensionError_Raise_if (P.Length() != poles->Length(),
634 "Geom_BSplineCurve::Poles");
638 //=======================================================================
639 //function : StartPoint
641 //=======================================================================
643 gp_Pnt Geom_BSplineCurve::StartPoint () const
645 if (mults->Value (1) == deg + 1)
646 return poles->Value (1);
648 return Value(FirstParameter());
651 //=======================================================================
654 //=======================================================================
656 Standard_Real Geom_BSplineCurve::Weight
657 (const Standard_Integer Index) const
659 Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
660 "Geom_BSplineCurve::Weight");
662 return weights->Value (Index);
667 //=======================================================================
670 //=======================================================================
672 void Geom_BSplineCurve::Weights
673 (TColStd_Array1OfReal& W) const
675 Standard_DimensionError_Raise_if (W.Length() != poles->Length(),
676 "Geom_BSplineCurve::Weights");
678 W = weights->Array1();
682 for (i = W.Lower(); i <= W.Upper(); i++)
687 //=======================================================================
688 //function : IsRational
690 //=======================================================================
692 Standard_Boolean Geom_BSplineCurve::IsRational () const
694 return !weights.IsNull();
697 //=======================================================================
698 //function : Transform
700 //=======================================================================
702 void Geom_BSplineCurve::Transform
705 TColgp_Array1OfPnt & CPoles = poles->ChangeArray1();
706 for (Standard_Integer I = 1; I <= CPoles.Length(); I++)
707 CPoles (I).Transform (T);
712 //=======================================================================
715 // pmn : 30/01/97 mise en conformite avec le cdl, lorsque U est un noeud
717 //=======================================================================
719 void Geom_BSplineCurve::LocateU
720 (const Standard_Real U,
721 const Standard_Real ParametricTolerance,
722 Standard_Integer& I1,
723 Standard_Integer& I2,
724 const Standard_Boolean WithKnotRepetition) const
726 Standard_Real NewU = U;
727 Handle(TColStd_HArray1OfReal) TheKnots;
728 if (WithKnotRepetition) TheKnots = flatknots;
729 else TheKnots = knots;
730 const TColStd_Array1OfReal & CKnots = TheKnots->Array1();
732 PeriodicNormalization(NewU); //Attention a la periode
734 Standard_Real UFirst = CKnots (1);
735 Standard_Real ULast = CKnots (CKnots.Length());
736 Standard_Real PParametricTolerance = Abs(ParametricTolerance);
737 if (Abs (NewU - UFirst) <= PParametricTolerance) { I1 = I2 = 1; }
738 else if (Abs (NewU - ULast) <= PParametricTolerance) {
739 I1 = I2 = CKnots.Length();
741 else if (NewU < UFirst) {
745 else if (NewU > ULast) {
746 I1 = CKnots.Length();
751 BSplCLib::Hunt (CKnots, NewU, I1);
752 while ( Abs( CKnots(I1+1) - NewU) <= PParametricTolerance) I1++;
753 if ( Abs( CKnots(I1) - NewU) <= PParametricTolerance) {
762 //=======================================================================
763 //function : Resolution
765 //=======================================================================
767 void Geom_BSplineCurve::Resolution(const Standard_Real Tolerance3D,
768 Standard_Real & UTolerance)
773 Standard_Integer NbKnots, NbPoles;
774 BSplCLib::PrepareUnperiodize( deg,
778 TColgp_Array1OfPnt new_poles(1,NbPoles) ;
779 TColStd_Array1OfReal new_weights(1,NbPoles) ;
780 for(ii = 1 ; ii <= NbPoles ; ii++) {
781 new_poles(ii) = poles->Array1()((ii-1) % poles->Length() + 1) ;
784 for(ii = 1 ; ii <= NbPoles ; ii++) {
785 new_weights(ii) = weights->Array1()((ii-1) % poles->Length() + 1) ;
787 BSplCLib::Resolution(new_poles,
796 BSplCLib::Resolution(new_poles,
797 *((TColStd_Array1OfReal*) NULL),
808 BSplCLib::Resolution(poles->Array1(),
817 BSplCLib::Resolution(poles->Array1(),
818 *((TColStd_Array1OfReal*) NULL),
828 UTolerance = Tolerance3D * maxderivinv;