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;
64 //=======================================================================
67 //=======================================================================
69 Standard_Boolean Geom2d_BSplineCurve::IsG1 ( const Standard_Real theTf,
70 const Standard_Real theTl,
71 const Standard_Real theAngTol) const
79 Standard_Integer start = FirstUKnotIndex()+1,
80 finish = LastUKnotIndex()-1;
81 Standard_Integer aDeg = Degree();
82 for(Standard_Integer aNKnot = start; aNKnot <= finish; aNKnot++)
84 const Standard_Real aTpar = Knot(aNKnot);
91 Standard_Integer mult = Multiplicity(aNKnot);
97 LocalD1(aTpar, aNKnot-1, aNKnot, aP1, aV1);
98 LocalD1(aTpar, aNKnot, aNKnot+1, aP2, aV2);
100 if((aV1.SquareMagnitude() <= gp::Resolution()) ||
101 aV2.SquareMagnitude() <= gp::Resolution())
103 return Standard_False;
106 if(Abs(aV1.Angle(aV2)) > theAngTol)
107 return Standard_False;
111 return Standard_True;
113 const Standard_Real aFirstParam = FirstParameter(),
114 aLastParam = LastParameter();
116 if( ((aFirstParam - theTf)*(theTl - aFirstParam) < 0.0) &&
117 ((aLastParam - theTf)*(theTl - aLastParam) < 0.0))
119 //Range [theTf, theTl] does not intersect curve bounadries
120 return Standard_True;
123 //Curve is closed or periodic and range [theTf, theTl]
124 //intersect curve boundary. Therefore, it is necessary to
125 //check if curve is smooth in its first and last point.
129 D1(Knot(FirstUKnotIndex()), aP, aV1);
130 D1(Knot(LastUKnotIndex()), aP, aV2);
132 if((aV1.SquareMagnitude() <= gp::Resolution()) ||
133 aV2.SquareMagnitude() <= gp::Resolution())
135 return Standard_False;
138 if(Abs(aV1.Angle(aV2)) > theAngTol)
139 return Standard_False;
142 return Standard_True;
146 //=======================================================================
147 //function : IsClosed
149 //=======================================================================
151 Standard_Boolean Geom2d_BSplineCurve::IsClosed () const
152 { return (StartPoint().Distance (EndPoint())) <= gp::Resolution (); }
156 //=======================================================================
157 //function : IsPeriodic
159 //=======================================================================
161 Standard_Boolean Geom2d_BSplineCurve::IsPeriodic () const
164 //=======================================================================
165 //function : Continuity
167 //=======================================================================
169 GeomAbs_Shape Geom2d_BSplineCurve::Continuity () const
172 //=======================================================================
175 //=======================================================================
177 Standard_Integer Geom2d_BSplineCurve::Degree () const
181 //=======================================================================
184 //=======================================================================
186 void Geom2d_BSplineCurve::D0 ( const Standard_Real U,
189 Standard_Real NewU(U);
190 PeriodicNormalization(NewU);
192 Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
193 Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
195 if (!IsCacheValid(NewU))
196 MyCurve->ValidateCache(NewU);
200 BSplCLib::CacheD0(NewU,
204 (cachepoles->Array1()),
205 cacheweights->Array1(),
209 BSplCLib::CacheD0(NewU,
213 (cachepoles->Array1()),
214 BSplCLib::NoWeights(),
220 //=======================================================================
223 //=======================================================================
225 void Geom2d_BSplineCurve::D1 (const Standard_Real U,
229 Standard_Real NewU(U);
230 PeriodicNormalization(NewU);
232 Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
233 Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
235 if (!IsCacheValid(NewU))
236 MyCurve->ValidateCache(NewU);
240 BSplCLib::CacheD1(NewU,
244 (cachepoles->Array1()),
245 cacheweights->Array1(),
250 BSplCLib::CacheD1(NewU,
254 (cachepoles->Array1()),
255 BSplCLib::NoWeights(),
261 //=======================================================================
264 //=======================================================================
266 void Geom2d_BSplineCurve::D2 (const Standard_Real U ,
271 Standard_Real NewU(U);
272 PeriodicNormalization(NewU);
274 Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
275 Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
277 if (!IsCacheValid(NewU))
278 MyCurve->ValidateCache(NewU);
282 BSplCLib::CacheD2(NewU,
286 (cachepoles->Array1()),
287 cacheweights->Array1(),
293 BSplCLib::CacheD2(NewU,
297 (cachepoles->Array1()),
298 BSplCLib::NoWeights(),
305 //=======================================================================
308 //=======================================================================
310 void Geom2d_BSplineCurve::D3 (const Standard_Real U ,
316 Standard_Real NewU(U);
317 PeriodicNormalization(NewU);
319 Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
320 Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
322 if (!IsCacheValid(NewU))
323 MyCurve->ValidateCache(NewU);
327 BSplCLib::CacheD3(NewU,
331 (cachepoles->Array1()),
332 cacheweights->Array1(),
339 BSplCLib::CacheD3(NewU,
343 (cachepoles->Array1()),
344 BSplCLib::NoWeights(),
352 //=======================================================================
355 //=======================================================================
357 gp_Vec2d Geom2d_BSplineCurve::DN (const Standard_Real U,
358 const Standard_Integer N ) const
363 BSplCLib::DN(U,N,0,deg,periodic,POLES,
368 BSplCLib::DN(U,N,0,deg,periodic,POLES,
369 *((TColStd_Array1OfReal*) NULL),
375 //=======================================================================
376 //function : EndPoint
378 //=======================================================================
380 gp_Pnt2d Geom2d_BSplineCurve::EndPoint () const
382 if (mults->Value (knots->Upper ()) == deg + 1)
383 return poles->Value (poles->Upper());
385 return Value(LastParameter());
388 //=======================================================================
389 //function : FirstUKnotIndex
391 //=======================================================================
393 Standard_Integer Geom2d_BSplineCurve::FirstUKnotIndex () const
395 if (periodic) return 1;
396 else return BSplCLib::FirstUKnotIndex (deg, mults->Array1());
399 //=======================================================================
400 //function : FirstParameter
402 //=======================================================================
404 Standard_Real Geom2d_BSplineCurve::FirstParameter () const
406 return flatknots->Value (deg+1);
409 //=======================================================================
412 //=======================================================================
414 Standard_Real Geom2d_BSplineCurve::Knot (const Standard_Integer Index) const
416 Standard_OutOfRange_Raise_if
417 (Index < 1 || Index > knots->Length(), "Geom2d_BSplineCurve::Knot");
418 return knots->Value (Index);
421 //=======================================================================
422 //function : KnotDistribution
424 //=======================================================================
426 GeomAbs_BSplKnotDistribution Geom2d_BSplineCurve::KnotDistribution () const
431 //=======================================================================
434 //=======================================================================
436 void Geom2d_BSplineCurve::Knots (TColStd_Array1OfReal& K) const
438 Standard_DimensionError_Raise_if
439 (K.Length() != knots->Length(), "Geom2d_BSplineCurve::Knots");
443 //=======================================================================
444 //function : KnotSequence
446 //=======================================================================
448 void Geom2d_BSplineCurve::KnotSequence (TColStd_Array1OfReal& K) const
450 Standard_DimensionError_Raise_if
451 (K.Length() != flatknots->Length(), "Geom2d_BSplineCurve::KnotSequence");
452 K = flatknots->Array1();
455 //=======================================================================
456 //function : LastUKnotIndex
458 //=======================================================================
460 Standard_Integer Geom2d_BSplineCurve::LastUKnotIndex() const
462 if (periodic) return knots->Length();
463 else return BSplCLib::LastUKnotIndex (deg, mults->Array1());
466 //=======================================================================
467 //function : LastParameter
469 //=======================================================================
471 Standard_Real Geom2d_BSplineCurve::LastParameter () const
473 return flatknots->Value (flatknots->Upper()-deg);
476 //=======================================================================
477 //function : LocalValue
479 //=======================================================================
481 gp_Pnt2d Geom2d_BSplineCurve::LocalValue
482 (const Standard_Real U,
483 const Standard_Integer FromK1,
484 const Standard_Integer ToK2) const
487 LocalD0(U,FromK1,ToK2,P);
491 //=======================================================================
494 //=======================================================================
496 void Geom2d_BSplineCurve::LocalD0
497 (const Standard_Real U,
498 const Standard_Integer FromK1,
499 const Standard_Integer ToK2,
502 Standard_DomainError_Raise_if (FromK1 == ToK2,
503 "Geom2d_BSplineCurve::LocalValue");
506 Standard_Integer index = 0;
507 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic,FromK1,ToK2, index,u);
508 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
511 BSplCLib::D0(u,index,deg,periodic,POLES,
516 BSplCLib::D0(u,index,deg,periodic,POLES,
517 *((TColStd_Array1OfReal*) NULL),
522 //=======================================================================
525 //=======================================================================
527 void Geom2d_BSplineCurve::LocalD1 (const Standard_Real U,
528 const Standard_Integer FromK1,
529 const Standard_Integer ToK2,
533 Standard_DomainError_Raise_if (FromK1 == ToK2,
534 "Geom2d_BSplineCurve::LocalD1");
537 Standard_Integer index = 0;
538 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
539 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
542 BSplCLib::D1(u,index,deg,periodic,POLES,
547 BSplCLib::D1(u,index,deg,periodic,POLES,
548 *((TColStd_Array1OfReal*) NULL),
553 //=======================================================================
556 //=======================================================================
558 void Geom2d_BSplineCurve::LocalD2
559 (const Standard_Real U,
560 const Standard_Integer FromK1,
561 const Standard_Integer ToK2,
566 Standard_DomainError_Raise_if (FromK1 == ToK2,
567 "Geom2d_BSplineCurve::LocalD2");
570 Standard_Integer index = 0;
571 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
572 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
575 BSplCLib::D2(u,index,deg,periodic,POLES,
577 FKNOTS,FMULTS,P,V1,V2);
580 BSplCLib::D2(u,index,deg,periodic,POLES,
581 *((TColStd_Array1OfReal*) NULL),
582 FKNOTS,FMULTS,P,V1,V2);
586 //=======================================================================
589 //=======================================================================
591 void Geom2d_BSplineCurve::LocalD3
592 (const Standard_Real U,
593 const Standard_Integer FromK1,
594 const Standard_Integer ToK2,
600 Standard_DomainError_Raise_if (FromK1 == ToK2,
601 "Geom2d_BSplineCurve::LocalD3");
604 Standard_Integer index = 0;
605 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
606 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
609 BSplCLib::D3(u,index,deg,periodic,POLES,
611 FKNOTS,FMULTS,P,V1,V2,V3);
614 BSplCLib::D3(u,index,deg,periodic,POLES,
615 *((TColStd_Array1OfReal*) NULL),
616 FKNOTS,FMULTS,P,V1,V2,V3);
620 //=======================================================================
623 //=======================================================================
625 gp_Vec2d Geom2d_BSplineCurve::LocalDN
626 (const Standard_Real U,
627 const Standard_Integer FromK1,
628 const Standard_Integer ToK2,
629 const Standard_Integer N ) const
631 Standard_DomainError_Raise_if (FromK1 == ToK2,
632 "Geom2d_BSplineCurve::LocalD3");
635 Standard_Integer index = 0;
636 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
637 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
642 BSplCLib::DN(u,N,index,deg,periodic,POLES,
647 BSplCLib::DN(u,N,index,deg,periodic,POLES,
648 *((TColStd_Array1OfReal*) NULL),
654 //=======================================================================
655 //function : Multiplicity
657 //=======================================================================
659 Standard_Integer Geom2d_BSplineCurve::Multiplicity
660 (const Standard_Integer Index) const
662 Standard_OutOfRange_Raise_if (Index < 1 || Index > mults->Length(),
663 "Geom2d_BSplineCurve::Multiplicity");
664 return mults->Value (Index);
667 //=======================================================================
668 //function : Multiplicities
670 //=======================================================================
672 void Geom2d_BSplineCurve::Multiplicities (TColStd_Array1OfInteger& M) const
674 Standard_DimensionError_Raise_if (M.Length() != mults->Length(),
675 "Geom2d_BSplineCurve::Multiplicities");
679 //=======================================================================
682 //=======================================================================
684 Standard_Integer Geom2d_BSplineCurve::NbKnots () const
685 { return knots->Length(); }
687 //=======================================================================
690 //=======================================================================
692 Standard_Integer Geom2d_BSplineCurve::NbPoles () const
693 { return poles->Length(); }
695 //=======================================================================
698 //=======================================================================
700 gp_Pnt2d Geom2d_BSplineCurve::Pole (const Standard_Integer Index) const
702 Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
703 "Geom2d_BSplineCurve::Pole");
704 return poles->Value (Index);
707 //=======================================================================
710 //=======================================================================
712 void Geom2d_BSplineCurve::Poles (TColgp_Array1OfPnt2d& P) const
714 Standard_DimensionError_Raise_if (P.Length() != poles->Length(),
715 "Geom2d_BSplineCurve::Poles");
719 //=======================================================================
720 //function : StartPoint
722 //=======================================================================
724 gp_Pnt2d Geom2d_BSplineCurve::StartPoint () const
726 if (mults->Value (1) == deg + 1)
727 return poles->Value (1);
729 return Value(FirstParameter());
732 //=======================================================================
735 //=======================================================================
737 Standard_Real Geom2d_BSplineCurve::Weight
738 (const Standard_Integer Index) const
740 Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
741 "Geom2d_BSplineCurve::Weight");
743 return weights->Value (Index);
748 //=======================================================================
751 //=======================================================================
753 void Geom2d_BSplineCurve::Weights
754 (TColStd_Array1OfReal& W) const
756 Standard_DimensionError_Raise_if (W.Length() != poles->Length(),
757 "Geom2d_BSplineCurve::Weights");
759 W = weights->Array1();
762 for (i = W.Lower(); i <= W.Upper(); i++)
767 //=======================================================================
768 //function : IsRational
770 //=======================================================================
772 Standard_Boolean Geom2d_BSplineCurve::IsRational () const
774 return !weights.IsNull();
777 //=======================================================================
778 //function : Transform
780 //=======================================================================
782 void Geom2d_BSplineCurve::Transform
785 TColgp_Array1OfPnt2d & CPoles = poles->ChangeArray1();
786 for (Standard_Integer I = 1; I <= CPoles.Length(); I++)
787 CPoles (I).Transform (T);
790 // maxderivinvok = 0;
793 //=======================================================================
796 //=======================================================================
798 void Geom2d_BSplineCurve::LocateU
799 (const Standard_Real U,
800 const Standard_Real ParametricTolerance,
801 Standard_Integer& I1,
802 Standard_Integer& I2,
803 const Standard_Boolean WithKnotRepetition) const
805 Standard_Real NewU = U;
806 Handle(TColStd_HArray1OfReal) TheKnots;
807 if (WithKnotRepetition) TheKnots = flatknots;
808 else TheKnots = knots;
810 const TColStd_Array1OfReal & CKnots = TheKnots->Array1();
812 PeriodicNormalization(NewU); //Attention a la periode
813 Standard_Real UFirst = CKnots (1);
814 Standard_Real ULast = CKnots (CKnots.Length());
815 Standard_Real PParametricTolerance = Abs(ParametricTolerance);
816 if (Abs (NewU - UFirst) <= PParametricTolerance) { I1 = I2 = 1; }
817 else if (Abs (NewU - ULast) <= PParametricTolerance) {
818 I1 = I2 = CKnots.Length();
820 else if (NewU < UFirst) {
824 else if (NewU > ULast) {
825 I1 = CKnots.Length();
830 BSplCLib::Hunt (CKnots, NewU, I1);
831 while ( Abs( CKnots(I1+1) - NewU) <= PParametricTolerance) I1++;
832 if ( Abs( CKnots(I1) - NewU) <= PParametricTolerance) {
841 //=======================================================================
842 //function : Resolution
844 //=======================================================================
846 void Geom2d_BSplineCurve::Resolution(const Standard_Real ToleranceUV,
847 Standard_Real & UTolerance)
849 Standard_Integer ii ;
852 Standard_Integer NbKnots, NbPoles;
853 BSplCLib::PrepareUnperiodize( deg,
857 TColgp_Array1OfPnt2d new_poles(1,NbPoles) ;
858 TColStd_Array1OfReal new_weights(1,NbPoles) ;
859 for(ii = 1 ; ii <= NbPoles ; ii++) {
860 new_poles(ii) = poles->Array1()(((ii-1) % poles->Length()) + 1) ;
863 for(ii = 1 ; ii <= NbPoles ; ii++) {
864 new_weights(ii) = weights->Array1()(((ii-1) % poles->Length()) + 1) ;
866 BSplCLib::Resolution(new_poles,
875 BSplCLib::Resolution(new_poles,
876 *((TColStd_Array1OfReal*) NULL),
886 BSplCLib::Resolution(poles->Array1(),
895 BSplCLib::Resolution(poles->Array1(),
896 *((TColStd_Array1OfReal*) NULL),
906 UTolerance = ToleranceUV * maxderivinv;