1 // Created on: 1991-07-05
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // 03-02-97 : pmn ->LocateU sur Periodic (PRO6963),
18 // bon appel a LocateParameter (PRO6973) et mise en conformite avec
19 // le cdl de LocateU, lorsque U est un noeud (PRO6988)
21 #define No_Standard_OutOfRange
22 #define No_Standard_DimensionError
24 #include <Geom2d_BSplineCurve.jxx>
25 #include <BSplCLib.hxx>
28 #include <Geom2d_UndefinedDerivative.hxx>
29 #include <Standard_DimensionError.hxx>
30 #include <Standard_OutOfRange.hxx>
31 #include <Standard_DomainError.hxx>
32 #include <Standard_RangeError.hxx>
33 #include <Standard_Mutex.hxx>
35 #define POLES (poles->Array1())
36 #define KNOTS (knots->Array1())
37 #define FKNOTS (flatknots->Array1())
38 #define FMULTS (BSplCLib::NoMults())
40 //=======================================================================
43 //=======================================================================
45 Standard_Boolean Geom2d_BSplineCurve::IsCN ( const Standard_Integer N) const
47 Standard_RangeError_Raise_if
48 (N < 0, "Geom2d_BSplineCurve::IsCN");
51 case GeomAbs_CN : return Standard_True;
52 case GeomAbs_C0 : return N <= 0;
53 case GeomAbs_G1 : return N <= 0;
54 case GeomAbs_C1 : return N <= 1;
55 case GeomAbs_G2 : return N <= 1;
56 case GeomAbs_C2 : return N <= 2;
58 return N <= 3 ? Standard_True :
59 N <= deg - BSplCLib::MaxKnotMult (mults->Array1(), mults->Lower() + 1, mults->Upper() - 1);
61 return Standard_False;
65 //=======================================================================
68 //=======================================================================
70 Standard_Boolean Geom2d_BSplineCurve::IsClosed () const
71 { return (StartPoint().Distance (EndPoint())) <= gp::Resolution (); }
75 //=======================================================================
76 //function : IsPeriodic
78 //=======================================================================
80 Standard_Boolean Geom2d_BSplineCurve::IsPeriodic () const
83 //=======================================================================
84 //function : Continuity
86 //=======================================================================
88 GeomAbs_Shape Geom2d_BSplineCurve::Continuity () const
91 //=======================================================================
94 //=======================================================================
96 Standard_Integer Geom2d_BSplineCurve::Degree () const
100 //=======================================================================
103 //=======================================================================
105 void Geom2d_BSplineCurve::D0 ( const Standard_Real U,
108 Standard_Real NewU(U);
109 PeriodicNormalization(NewU);
111 Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
112 Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
114 if (!IsCacheValid(NewU))
115 MyCurve->ValidateCache(NewU);
119 BSplCLib::CacheD0(NewU,
123 (cachepoles->Array1()),
124 cacheweights->Array1(),
128 BSplCLib::CacheD0(NewU,
132 (cachepoles->Array1()),
133 BSplCLib::NoWeights(),
139 //=======================================================================
142 //=======================================================================
144 void Geom2d_BSplineCurve::D1 (const Standard_Real U,
148 Standard_Real NewU(U);
149 PeriodicNormalization(NewU);
151 Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
152 Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
154 if (!IsCacheValid(NewU))
155 MyCurve->ValidateCache(NewU);
159 BSplCLib::CacheD1(NewU,
163 (cachepoles->Array1()),
164 cacheweights->Array1(),
169 BSplCLib::CacheD1(NewU,
173 (cachepoles->Array1()),
174 BSplCLib::NoWeights(),
180 //=======================================================================
183 //=======================================================================
185 void Geom2d_BSplineCurve::D2 (const Standard_Real U ,
190 Standard_Real NewU(U);
191 PeriodicNormalization(NewU);
193 Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
194 Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
196 if (!IsCacheValid(NewU))
197 MyCurve->ValidateCache(NewU);
201 BSplCLib::CacheD2(NewU,
205 (cachepoles->Array1()),
206 cacheweights->Array1(),
212 BSplCLib::CacheD2(NewU,
216 (cachepoles->Array1()),
217 BSplCLib::NoWeights(),
224 //=======================================================================
227 //=======================================================================
229 void Geom2d_BSplineCurve::D3 (const Standard_Real U ,
235 Standard_Real NewU(U);
236 PeriodicNormalization(NewU);
238 Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
239 Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
241 if (!IsCacheValid(NewU))
242 MyCurve->ValidateCache(NewU);
246 BSplCLib::CacheD3(NewU,
250 (cachepoles->Array1()),
251 cacheweights->Array1(),
258 BSplCLib::CacheD3(NewU,
262 (cachepoles->Array1()),
263 BSplCLib::NoWeights(),
271 //=======================================================================
274 //=======================================================================
276 gp_Vec2d Geom2d_BSplineCurve::DN (const Standard_Real U,
277 const Standard_Integer N ) const
282 BSplCLib::DN(U,N,0,deg,periodic,POLES,
287 BSplCLib::DN(U,N,0,deg,periodic,POLES,
288 *((TColStd_Array1OfReal*) NULL),
294 //=======================================================================
295 //function : EndPoint
297 //=======================================================================
299 gp_Pnt2d Geom2d_BSplineCurve::EndPoint () const
301 if (mults->Value (knots->Upper ()) == deg + 1)
302 return poles->Value (poles->Upper());
304 return Value(LastParameter());
307 //=======================================================================
308 //function : FirstUKnotIndex
310 //=======================================================================
312 Standard_Integer Geom2d_BSplineCurve::FirstUKnotIndex () const
314 if (periodic) return 1;
315 else return BSplCLib::FirstUKnotIndex (deg, mults->Array1());
318 //=======================================================================
319 //function : FirstParameter
321 //=======================================================================
323 Standard_Real Geom2d_BSplineCurve::FirstParameter () const
325 return flatknots->Value (deg+1);
328 //=======================================================================
331 //=======================================================================
333 Standard_Real Geom2d_BSplineCurve::Knot (const Standard_Integer Index) const
335 Standard_OutOfRange_Raise_if
336 (Index < 1 || Index > knots->Length(), "Geom2d_BSplineCurve::Knot");
337 return knots->Value (Index);
340 //=======================================================================
341 //function : KnotDistribution
343 //=======================================================================
345 GeomAbs_BSplKnotDistribution Geom2d_BSplineCurve::KnotDistribution () const
350 //=======================================================================
353 //=======================================================================
355 void Geom2d_BSplineCurve::Knots (TColStd_Array1OfReal& K) const
357 Standard_DimensionError_Raise_if
358 (K.Length() != knots->Length(), "Geom2d_BSplineCurve::Knots");
362 //=======================================================================
363 //function : KnotSequence
365 //=======================================================================
367 void Geom2d_BSplineCurve::KnotSequence (TColStd_Array1OfReal& K) const
369 Standard_DimensionError_Raise_if
370 (K.Length() != flatknots->Length(), "Geom2d_BSplineCurve::KnotSequence");
371 K = flatknots->Array1();
374 //=======================================================================
375 //function : LastUKnotIndex
377 //=======================================================================
379 Standard_Integer Geom2d_BSplineCurve::LastUKnotIndex() const
381 if (periodic) return knots->Length();
382 else return BSplCLib::LastUKnotIndex (deg, mults->Array1());
385 //=======================================================================
386 //function : LastParameter
388 //=======================================================================
390 Standard_Real Geom2d_BSplineCurve::LastParameter () const
392 return flatknots->Value (flatknots->Upper()-deg);
395 //=======================================================================
396 //function : LocalValue
398 //=======================================================================
400 gp_Pnt2d Geom2d_BSplineCurve::LocalValue
401 (const Standard_Real U,
402 const Standard_Integer FromK1,
403 const Standard_Integer ToK2) const
406 LocalD0(U,FromK1,ToK2,P);
410 //=======================================================================
413 //=======================================================================
415 void Geom2d_BSplineCurve::LocalD0
416 (const Standard_Real U,
417 const Standard_Integer FromK1,
418 const Standard_Integer ToK2,
421 Standard_DomainError_Raise_if (FromK1 == ToK2,
422 "Geom2d_BSplineCurve::LocalValue");
425 Standard_Integer index = 0;
426 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic,FromK1,ToK2, index,u);
427 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
430 BSplCLib::D0(u,index,deg,periodic,POLES,
435 BSplCLib::D0(u,index,deg,periodic,POLES,
436 *((TColStd_Array1OfReal*) NULL),
441 //=======================================================================
444 //=======================================================================
446 void Geom2d_BSplineCurve::LocalD1 (const Standard_Real U,
447 const Standard_Integer FromK1,
448 const Standard_Integer ToK2,
452 Standard_DomainError_Raise_if (FromK1 == ToK2,
453 "Geom2d_BSplineCurve::LocalD1");
456 Standard_Integer index = 0;
457 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
458 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
461 BSplCLib::D1(u,index,deg,periodic,POLES,
466 BSplCLib::D1(u,index,deg,periodic,POLES,
467 *((TColStd_Array1OfReal*) NULL),
472 //=======================================================================
475 //=======================================================================
477 void Geom2d_BSplineCurve::LocalD2
478 (const Standard_Real U,
479 const Standard_Integer FromK1,
480 const Standard_Integer ToK2,
485 Standard_DomainError_Raise_if (FromK1 == ToK2,
486 "Geom2d_BSplineCurve::LocalD2");
489 Standard_Integer index = 0;
490 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
491 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
494 BSplCLib::D2(u,index,deg,periodic,POLES,
496 FKNOTS,FMULTS,P,V1,V2);
499 BSplCLib::D2(u,index,deg,periodic,POLES,
500 *((TColStd_Array1OfReal*) NULL),
501 FKNOTS,FMULTS,P,V1,V2);
505 //=======================================================================
508 //=======================================================================
510 void Geom2d_BSplineCurve::LocalD3
511 (const Standard_Real U,
512 const Standard_Integer FromK1,
513 const Standard_Integer ToK2,
519 Standard_DomainError_Raise_if (FromK1 == ToK2,
520 "Geom2d_BSplineCurve::LocalD3");
523 Standard_Integer index = 0;
524 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
525 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
528 BSplCLib::D3(u,index,deg,periodic,POLES,
530 FKNOTS,FMULTS,P,V1,V2,V3);
533 BSplCLib::D3(u,index,deg,periodic,POLES,
534 *((TColStd_Array1OfReal*) NULL),
535 FKNOTS,FMULTS,P,V1,V2,V3);
539 //=======================================================================
542 //=======================================================================
544 gp_Vec2d Geom2d_BSplineCurve::LocalDN
545 (const Standard_Real U,
546 const Standard_Integer FromK1,
547 const Standard_Integer ToK2,
548 const Standard_Integer N ) const
550 Standard_DomainError_Raise_if (FromK1 == ToK2,
551 "Geom2d_BSplineCurve::LocalD3");
554 Standard_Integer index = 0;
555 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
556 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 Geom2d_BSplineCurve::Multiplicity
579 (const Standard_Integer Index) const
581 Standard_OutOfRange_Raise_if (Index < 1 || Index > mults->Length(),
582 "Geom2d_BSplineCurve::Multiplicity");
583 return mults->Value (Index);
586 //=======================================================================
587 //function : Multiplicities
589 //=======================================================================
591 void Geom2d_BSplineCurve::Multiplicities (TColStd_Array1OfInteger& M) const
593 Standard_DimensionError_Raise_if (M.Length() != mults->Length(),
594 "Geom2d_BSplineCurve::Multiplicities");
598 //=======================================================================
601 //=======================================================================
603 Standard_Integer Geom2d_BSplineCurve::NbKnots () const
604 { return knots->Length(); }
606 //=======================================================================
609 //=======================================================================
611 Standard_Integer Geom2d_BSplineCurve::NbPoles () const
612 { return poles->Length(); }
614 //=======================================================================
617 //=======================================================================
619 gp_Pnt2d Geom2d_BSplineCurve::Pole (const Standard_Integer Index) const
621 Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
622 "Geom2d_BSplineCurve::Pole");
623 return poles->Value (Index);
626 //=======================================================================
629 //=======================================================================
631 void Geom2d_BSplineCurve::Poles (TColgp_Array1OfPnt2d& P) const
633 Standard_DimensionError_Raise_if (P.Length() != poles->Length(),
634 "Geom2d_BSplineCurve::Poles");
638 //=======================================================================
639 //function : StartPoint
641 //=======================================================================
643 gp_Pnt2d Geom2d_BSplineCurve::StartPoint () const
645 if (mults->Value (1) == deg + 1)
646 return poles->Value (1);
648 return Value(FirstParameter());
651 //=======================================================================
654 //=======================================================================
656 Standard_Real Geom2d_BSplineCurve::Weight
657 (const Standard_Integer Index) const
659 Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
660 "Geom2d_BSplineCurve::Weight");
662 return weights->Value (Index);
667 //=======================================================================
670 //=======================================================================
672 void Geom2d_BSplineCurve::Weights
673 (TColStd_Array1OfReal& W) const
675 Standard_DimensionError_Raise_if (W.Length() != poles->Length(),
676 "Geom2d_BSplineCurve::Weights");
678 W = weights->Array1();
681 for (i = W.Lower(); i <= W.Upper(); i++)
686 //=======================================================================
687 //function : IsRational
689 //=======================================================================
691 Standard_Boolean Geom2d_BSplineCurve::IsRational () const
693 return !weights.IsNull();
696 //=======================================================================
697 //function : Transform
699 //=======================================================================
701 void Geom2d_BSplineCurve::Transform
704 TColgp_Array1OfPnt2d & CPoles = poles->ChangeArray1();
705 for (Standard_Integer I = 1; I <= CPoles.Length(); I++)
706 CPoles (I).Transform (T);
709 // maxderivinvok = 0;
712 //=======================================================================
715 //=======================================================================
717 void Geom2d_BSplineCurve::LocateU
718 (const Standard_Real U,
719 const Standard_Real ParametricTolerance,
720 Standard_Integer& I1,
721 Standard_Integer& I2,
722 const Standard_Boolean WithKnotRepetition) const
724 Standard_Real NewU = U;
725 Handle(TColStd_HArray1OfReal) TheKnots;
726 if (WithKnotRepetition) TheKnots = flatknots;
727 else TheKnots = knots;
729 const TColStd_Array1OfReal & CKnots = TheKnots->Array1();
731 PeriodicNormalization(NewU); //Attention a la periode
732 Standard_Real UFirst = CKnots (1);
733 Standard_Real ULast = CKnots (CKnots.Length());
734 Standard_Real PParametricTolerance = Abs(ParametricTolerance);
735 if (Abs (NewU - UFirst) <= PParametricTolerance) { I1 = I2 = 1; }
736 else if (Abs (NewU - ULast) <= PParametricTolerance) {
737 I1 = I2 = CKnots.Length();
739 else if (NewU < UFirst) {
743 else if (NewU > ULast) {
744 I1 = CKnots.Length();
749 BSplCLib::Hunt (CKnots, NewU, I1);
750 while ( Abs( CKnots(I1+1) - NewU) <= PParametricTolerance) I1++;
751 if ( Abs( CKnots(I1) - NewU) <= PParametricTolerance) {
760 //=======================================================================
761 //function : Resolution
763 //=======================================================================
765 void Geom2d_BSplineCurve::Resolution(const Standard_Real ToleranceUV,
766 Standard_Real & UTolerance)
768 Standard_Integer ii ;
771 Standard_Integer NbKnots, NbPoles;
772 BSplCLib::PrepareUnperiodize( deg,
776 TColgp_Array1OfPnt2d new_poles(1,NbPoles) ;
777 TColStd_Array1OfReal new_weights(1,NbPoles) ;
778 for(ii = 1 ; ii <= NbPoles ; ii++) {
779 new_poles(ii) = poles->Array1()(((ii-1) % poles->Length()) + 1) ;
782 for(ii = 1 ; ii <= NbPoles ; ii++) {
783 new_weights(ii) = weights->Array1()(((ii-1) % poles->Length()) + 1) ;
785 BSplCLib::Resolution(new_poles,
794 BSplCLib::Resolution(new_poles,
795 *((TColStd_Array1OfReal*) NULL),
805 BSplCLib::Resolution(poles->Array1(),
814 BSplCLib::Resolution(poles->Array1(),
815 *((TColStd_Array1OfReal*) NULL),
825 UTolerance = ToleranceUV * maxderivinv;