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
25 #include <BSplCLib.hxx>
26 #include <Geom2d_BSplineCurve.hxx>
27 #include <Geom2d_Geometry.hxx>
28 #include <Geom2d_UndefinedDerivative.hxx>
30 #include <gp_Pnt2d.hxx>
31 #include <gp_Trsf2d.hxx>
32 #include <gp_Vec2d.hxx>
33 #include <Precision.hxx>
34 #include <Standard_ConstructionError.hxx>
35 #include <Standard_DimensionError.hxx>
36 #include <Standard_DomainError.hxx>
37 #include <Standard_NoSuchObject.hxx>
38 #include <Standard_OutOfRange.hxx>
39 #include <Standard_RangeError.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 Geom2d_BSplineCurve::IsCN ( const Standard_Integer N) const
53 Standard_RangeError_Raise_if
54 (N < 0, "Geom2d_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;
70 //=======================================================================
73 //=======================================================================
75 Standard_Boolean Geom2d_BSplineCurve::IsG1 ( const Standard_Real theTf,
76 const Standard_Real theTl,
77 const Standard_Real theAngTol) const
85 Standard_Integer start = FirstUKnotIndex()+1,
86 finish = LastUKnotIndex()-1;
87 Standard_Integer aDeg = Degree();
88 for(Standard_Integer aNKnot = start; aNKnot <= finish; aNKnot++)
90 const Standard_Real aTpar = Knot(aNKnot);
97 Standard_Integer mult = Multiplicity(aNKnot);
103 LocalD1(aTpar, aNKnot-1, aNKnot, aP1, aV1);
104 LocalD1(aTpar, aNKnot, aNKnot+1, aP2, aV2);
106 if((aV1.SquareMagnitude() <= gp::Resolution()) ||
107 aV2.SquareMagnitude() <= gp::Resolution())
109 return Standard_False;
112 if(Abs(aV1.Angle(aV2)) > theAngTol)
113 return Standard_False;
117 return Standard_True;
119 const Standard_Real aFirstParam = FirstParameter(),
120 aLastParam = LastParameter();
122 if( ((aFirstParam - theTf)*(theTl - aFirstParam) < 0.0) &&
123 ((aLastParam - theTf)*(theTl - aLastParam) < 0.0))
125 //Range [theTf, theTl] does not intersect curve bounadries
126 return Standard_True;
129 //Curve is closed or periodic and range [theTf, theTl]
130 //intersect curve boundary. Therefore, it is necessary to
131 //check if curve is smooth in its first and last point.
135 D1(Knot(FirstUKnotIndex()), aP, aV1);
136 D1(Knot(LastUKnotIndex()), aP, aV2);
138 if((aV1.SquareMagnitude() <= gp::Resolution()) ||
139 aV2.SquareMagnitude() <= gp::Resolution())
141 return Standard_False;
144 if(Abs(aV1.Angle(aV2)) > theAngTol)
145 return Standard_False;
148 return Standard_True;
152 //=======================================================================
153 //function : IsClosed
155 //=======================================================================
157 Standard_Boolean Geom2d_BSplineCurve::IsClosed () const
158 { return (StartPoint().Distance (EndPoint())) <= gp::Resolution (); }
162 //=======================================================================
163 //function : IsPeriodic
165 //=======================================================================
167 Standard_Boolean Geom2d_BSplineCurve::IsPeriodic () const
170 //=======================================================================
171 //function : Continuity
173 //=======================================================================
175 GeomAbs_Shape Geom2d_BSplineCurve::Continuity () const
178 //=======================================================================
181 //=======================================================================
183 Standard_Integer Geom2d_BSplineCurve::Degree () const
187 //=======================================================================
190 //=======================================================================
192 void Geom2d_BSplineCurve::D0(const Standard_Real U,
195 Standard_Integer aSpanIndex = 0;
196 Standard_Real aNewU(U);
197 PeriodicNormalization(aNewU);
198 BSplCLib::LocateParameter(deg, knots->Array1(), mults->Array1(), U, periodic, aSpanIndex, aNewU);
199 if (aNewU < knots->Value(aSpanIndex))
203 BSplCLib::D0(aNewU,aSpanIndex,deg,periodic,POLES,
205 knots->Array1(), mults->Array1(),
210 BSplCLib::D0(aNewU,aSpanIndex,deg,periodic,POLES,
211 *((TColStd_Array1OfReal*) NULL),
212 knots->Array1(), mults->Array1(),
218 //=======================================================================
221 //=======================================================================
223 void Geom2d_BSplineCurve::D1(const Standard_Real U,
227 Standard_Integer aSpanIndex = 0;
228 Standard_Real aNewU(U);
229 PeriodicNormalization(aNewU);
230 BSplCLib::LocateParameter(deg, knots->Array1(), mults->Array1(), U, periodic, aSpanIndex, aNewU);
231 if (aNewU < knots->Value(aSpanIndex))
235 BSplCLib::D1(aNewU,aSpanIndex,deg,periodic,POLES,
237 knots->Array1(), mults->Array1(),
242 BSplCLib::D1(aNewU,aSpanIndex,deg,periodic,POLES,
243 *((TColStd_Array1OfReal*) NULL),
244 knots->Array1(), mults->Array1(),
249 //=======================================================================
252 //=======================================================================
254 void Geom2d_BSplineCurve::D2(const Standard_Real U,
259 Standard_Integer aSpanIndex = 0;
260 Standard_Real aNewU(U);
261 PeriodicNormalization(aNewU);
262 BSplCLib::LocateParameter(deg, knots->Array1(), mults->Array1(), U, periodic, aSpanIndex, aNewU);
263 if (aNewU < knots->Value(aSpanIndex))
267 BSplCLib::D2(aNewU,aSpanIndex,deg,periodic,POLES,
269 knots->Array1(), mults->Array1(),
274 BSplCLib::D2(aNewU,aSpanIndex,deg,periodic,POLES,
275 *((TColStd_Array1OfReal*) NULL),
276 knots->Array1(), mults->Array1(),
281 //=======================================================================
284 //=======================================================================
286 void Geom2d_BSplineCurve::D3(const Standard_Real U,
292 Standard_Integer aSpanIndex = 0;
293 Standard_Real aNewU(U);
294 PeriodicNormalization(aNewU);
295 BSplCLib::LocateParameter(deg, knots->Array1(), mults->Array1(), U, periodic, aSpanIndex, aNewU);
296 if (aNewU < knots->Value(aSpanIndex))
300 BSplCLib::D3(aNewU,aSpanIndex,deg,periodic,POLES,
302 knots->Array1(), mults->Array1(),
307 BSplCLib::D3(aNewU,aSpanIndex,deg,periodic,POLES,
308 *((TColStd_Array1OfReal*) NULL),
309 knots->Array1(), mults->Array1(),
314 //=======================================================================
317 //=======================================================================
319 gp_Vec2d Geom2d_BSplineCurve::DN(const Standard_Real U,
320 const Standard_Integer N) const
325 BSplCLib::DN(U,N,0,deg,periodic,POLES,
330 BSplCLib::DN(U,N,0,deg,periodic,POLES,
331 *((TColStd_Array1OfReal*) NULL),
337 //=======================================================================
338 //function : EndPoint
340 //=======================================================================
342 gp_Pnt2d Geom2d_BSplineCurve::EndPoint () const
344 if (mults->Value (knots->Upper ()) == deg + 1)
345 return poles->Value (poles->Upper());
347 return Value(LastParameter());
350 //=======================================================================
351 //function : FirstUKnotIndex
353 //=======================================================================
355 Standard_Integer Geom2d_BSplineCurve::FirstUKnotIndex () const
357 if (periodic) return 1;
358 else return BSplCLib::FirstUKnotIndex (deg, mults->Array1());
361 //=======================================================================
362 //function : FirstParameter
364 //=======================================================================
366 Standard_Real Geom2d_BSplineCurve::FirstParameter () const
368 return flatknots->Value (deg+1);
371 //=======================================================================
374 //=======================================================================
376 Standard_Real Geom2d_BSplineCurve::Knot (const Standard_Integer Index) const
378 Standard_OutOfRange_Raise_if
379 (Index < 1 || Index > knots->Length(), "Geom2d_BSplineCurve::Knot");
380 return knots->Value (Index);
383 //=======================================================================
384 //function : KnotDistribution
386 //=======================================================================
388 GeomAbs_BSplKnotDistribution Geom2d_BSplineCurve::KnotDistribution () const
393 //=======================================================================
396 //=======================================================================
398 void Geom2d_BSplineCurve::Knots (TColStd_Array1OfReal& K) const
400 Standard_DomainError_Raise_if (K.Lower() < knots->Lower() ||
401 K.Upper() > knots->Upper(),
402 "Geom2d_BSplineCurve::Knots");
403 for(Standard_Integer anIdx = K.Lower(); anIdx <= K.Upper(); anIdx++)
404 K(anIdx) = knots->Value(anIdx);
407 const TColStd_Array1OfReal& Geom2d_BSplineCurve::Knots() const
409 return knots->Array1();
412 //=======================================================================
413 //function : KnotSequence
415 //=======================================================================
417 void Geom2d_BSplineCurve::KnotSequence (TColStd_Array1OfReal& K) const
419 Standard_DomainError_Raise_if (K.Lower() < flatknots->Lower() ||
420 K.Upper() > flatknots->Upper(),
421 "Geom2d_BSplineCurve::KnotSequence");
422 for(Standard_Integer anIdx = K.Lower(); anIdx <= K.Upper(); anIdx++)
423 K(anIdx) = flatknots->Value(anIdx);
426 const TColStd_Array1OfReal& Geom2d_BSplineCurve::KnotSequence() const
428 return flatknots->Array1();
431 //=======================================================================
432 //function : LastUKnotIndex
434 //=======================================================================
436 Standard_Integer Geom2d_BSplineCurve::LastUKnotIndex() const
438 if (periodic) return knots->Length();
439 else return BSplCLib::LastUKnotIndex (deg, mults->Array1());
442 //=======================================================================
443 //function : LastParameter
445 //=======================================================================
447 Standard_Real Geom2d_BSplineCurve::LastParameter () const
449 return flatknots->Value (flatknots->Upper()-deg);
452 //=======================================================================
453 //function : LocalValue
455 //=======================================================================
457 gp_Pnt2d Geom2d_BSplineCurve::LocalValue
458 (const Standard_Real U,
459 const Standard_Integer FromK1,
460 const Standard_Integer ToK2) const
463 LocalD0(U,FromK1,ToK2,P);
467 //=======================================================================
470 //=======================================================================
472 void Geom2d_BSplineCurve::LocalD0
473 (const Standard_Real U,
474 const Standard_Integer FromK1,
475 const Standard_Integer ToK2,
478 Standard_DomainError_Raise_if (FromK1 == ToK2,
479 "Geom2d_BSplineCurve::LocalValue");
482 Standard_Integer index = 0;
483 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic,FromK1,ToK2, index,u);
484 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
487 BSplCLib::D0(u,index,deg,periodic,POLES,
492 BSplCLib::D0(u,index,deg,periodic,POLES,
493 *((TColStd_Array1OfReal*) NULL),
498 //=======================================================================
501 //=======================================================================
503 void Geom2d_BSplineCurve::LocalD1 (const Standard_Real U,
504 const Standard_Integer FromK1,
505 const Standard_Integer ToK2,
509 Standard_DomainError_Raise_if (FromK1 == ToK2,
510 "Geom2d_BSplineCurve::LocalD1");
513 Standard_Integer index = 0;
514 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
515 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
518 BSplCLib::D1(u,index,deg,periodic,POLES,
523 BSplCLib::D1(u,index,deg,periodic,POLES,
524 *((TColStd_Array1OfReal*) NULL),
529 //=======================================================================
532 //=======================================================================
534 void Geom2d_BSplineCurve::LocalD2
535 (const Standard_Real U,
536 const Standard_Integer FromK1,
537 const Standard_Integer ToK2,
542 Standard_DomainError_Raise_if (FromK1 == ToK2,
543 "Geom2d_BSplineCurve::LocalD2");
546 Standard_Integer index = 0;
547 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
548 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
551 BSplCLib::D2(u,index,deg,periodic,POLES,
553 FKNOTS,FMULTS,P,V1,V2);
556 BSplCLib::D2(u,index,deg,periodic,POLES,
557 *((TColStd_Array1OfReal*) NULL),
558 FKNOTS,FMULTS,P,V1,V2);
562 //=======================================================================
565 //=======================================================================
567 void Geom2d_BSplineCurve::LocalD3
568 (const Standard_Real U,
569 const Standard_Integer FromK1,
570 const Standard_Integer ToK2,
576 Standard_DomainError_Raise_if (FromK1 == ToK2,
577 "Geom2d_BSplineCurve::LocalD3");
580 Standard_Integer index = 0;
581 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
582 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
585 BSplCLib::D3(u,index,deg,periodic,POLES,
587 FKNOTS,FMULTS,P,V1,V2,V3);
590 BSplCLib::D3(u,index,deg,periodic,POLES,
591 *((TColStd_Array1OfReal*) NULL),
592 FKNOTS,FMULTS,P,V1,V2,V3);
596 //=======================================================================
599 //=======================================================================
601 gp_Vec2d Geom2d_BSplineCurve::LocalDN
602 (const Standard_Real U,
603 const Standard_Integer FromK1,
604 const Standard_Integer ToK2,
605 const Standard_Integer N ) const
607 Standard_DomainError_Raise_if (FromK1 == ToK2,
608 "Geom2d_BSplineCurve::LocalD3");
611 Standard_Integer index = 0;
612 BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
613 index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
618 BSplCLib::DN(u,N,index,deg,periodic,POLES,
623 BSplCLib::DN(u,N,index,deg,periodic,POLES,
624 *((TColStd_Array1OfReal*) NULL),
630 //=======================================================================
631 //function : Multiplicity
633 //=======================================================================
635 Standard_Integer Geom2d_BSplineCurve::Multiplicity
636 (const Standard_Integer Index) const
638 Standard_OutOfRange_Raise_if (Index < 1 || Index > mults->Length(),
639 "Geom2d_BSplineCurve::Multiplicity");
640 return mults->Value (Index);
643 //=======================================================================
644 //function : Multiplicities
646 //=======================================================================
648 void Geom2d_BSplineCurve::Multiplicities (TColStd_Array1OfInteger& M) const
650 Standard_DimensionError_Raise_if (M.Length() != mults->Length(),
651 "Geom2d_BSplineCurve::Multiplicities");
655 const TColStd_Array1OfInteger& Geom2d_BSplineCurve::Multiplicities() const
657 return mults->Array1();
660 //=======================================================================
663 //=======================================================================
665 Standard_Integer Geom2d_BSplineCurve::NbKnots () const
666 { return knots->Length(); }
668 //=======================================================================
671 //=======================================================================
673 Standard_Integer Geom2d_BSplineCurve::NbPoles () const
674 { return poles->Length(); }
676 //=======================================================================
679 //=======================================================================
681 gp_Pnt2d Geom2d_BSplineCurve::Pole (const Standard_Integer Index) const
683 Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
684 "Geom2d_BSplineCurve::Pole");
685 return poles->Value (Index);
688 //=======================================================================
691 //=======================================================================
693 void Geom2d_BSplineCurve::Poles (TColgp_Array1OfPnt2d& P) const
695 Standard_DimensionError_Raise_if (P.Length() != poles->Length(),
696 "Geom2d_BSplineCurve::Poles");
700 const TColgp_Array1OfPnt2d& Geom2d_BSplineCurve::Poles() const
702 return poles->Array1();
705 //=======================================================================
706 //function : StartPoint
708 //=======================================================================
710 gp_Pnt2d Geom2d_BSplineCurve::StartPoint () const
712 if (mults->Value (1) == deg + 1)
713 return poles->Value (1);
715 return Value(FirstParameter());
718 //=======================================================================
721 //=======================================================================
723 Standard_Real Geom2d_BSplineCurve::Weight
724 (const Standard_Integer Index) const
726 Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
727 "Geom2d_BSplineCurve::Weight");
729 return weights->Value (Index);
734 //=======================================================================
737 //=======================================================================
739 void Geom2d_BSplineCurve::Weights
740 (TColStd_Array1OfReal& W) const
742 Standard_DimensionError_Raise_if (W.Length() != poles->Length(),
743 "Geom2d_BSplineCurve::Weights");
745 W = weights->Array1();
748 for (i = W.Lower(); i <= W.Upper(); i++)
753 const TColStd_Array1OfReal& Geom2d_BSplineCurve::Weights() const
756 return weights->Array1();
757 return BSplCLib::NoWeights();
760 //=======================================================================
761 //function : IsRational
763 //=======================================================================
765 Standard_Boolean Geom2d_BSplineCurve::IsRational () const
767 return !weights.IsNull();
770 //=======================================================================
771 //function : Transform
773 //=======================================================================
775 void Geom2d_BSplineCurve::Transform
778 TColgp_Array1OfPnt2d & CPoles = poles->ChangeArray1();
779 for (Standard_Integer I = 1; I <= CPoles.Length(); I++)
780 CPoles (I).Transform (T);
782 // maxderivinvok = 0;
785 //=======================================================================
788 //=======================================================================
790 void Geom2d_BSplineCurve::LocateU
791 (const Standard_Real U,
792 const Standard_Real ParametricTolerance,
793 Standard_Integer& I1,
794 Standard_Integer& I2,
795 const Standard_Boolean WithKnotRepetition) const
797 Standard_Real NewU = U;
798 Handle(TColStd_HArray1OfReal) TheKnots;
799 if (WithKnotRepetition) TheKnots = flatknots;
800 else TheKnots = knots;
802 const TColStd_Array1OfReal & CKnots = TheKnots->Array1();
804 PeriodicNormalization(NewU); //Attention a la periode
805 Standard_Real UFirst = CKnots (1);
806 Standard_Real ULast = CKnots (CKnots.Length());
807 Standard_Real PParametricTolerance = Abs(ParametricTolerance);
808 if (Abs (NewU - UFirst) <= PParametricTolerance) { I1 = I2 = 1; }
809 else if (Abs (NewU - ULast) <= PParametricTolerance) {
810 I1 = I2 = CKnots.Length();
812 else if (NewU < UFirst) {
816 else if (NewU > ULast) {
817 I1 = CKnots.Length();
822 BSplCLib::Hunt (CKnots, NewU, I1);
823 while ( Abs( CKnots(I1+1) - NewU) <= PParametricTolerance) I1++;
824 if ( Abs( CKnots(I1) - NewU) <= PParametricTolerance) {
833 //=======================================================================
834 //function : Resolution
836 //=======================================================================
838 void Geom2d_BSplineCurve::Resolution(const Standard_Real ToleranceUV,
839 Standard_Real & UTolerance)
841 Standard_Integer ii ;
844 Standard_Integer NbKnots, NbPoles;
845 BSplCLib::PrepareUnperiodize( deg,
849 TColgp_Array1OfPnt2d new_poles(1,NbPoles) ;
850 TColStd_Array1OfReal new_weights(1,NbPoles) ;
851 for(ii = 1 ; ii <= NbPoles ; ii++) {
852 new_poles(ii) = poles->Array1()(((ii-1) % poles->Length()) + 1) ;
855 for(ii = 1 ; ii <= NbPoles ; ii++) {
856 new_weights(ii) = weights->Array1()(((ii-1) % poles->Length()) + 1) ;
858 BSplCLib::Resolution(new_poles,
867 BSplCLib::Resolution(new_poles,
868 *((TColStd_Array1OfReal*) NULL),
878 BSplCLib::Resolution(poles->Array1(),
887 BSplCLib::Resolution(poles->Array1(),
888 *((TColStd_Array1OfReal*) NULL),
898 UTolerance = ToleranceUV * maxderivinv;