1 // Created on: 1993-06-04
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1993-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 // 20/02/97 : PMN -> Positionement local sur BSpline (PRO6902)
18 // 10/07/97 : PMN -> Pas de calcul de resolution dans Nb(Intervals) (PRO9248)
19 // 20/10/97 : JPI -> traitement des offset curves
21 #define No_Standard_RangeError
22 #define No_Standard_OutOfRange
25 #include <Adaptor2d_HCurve2d.hxx>
26 #include <BSplCLib.hxx>
27 #include <BSplCLib_Cache.hxx>
28 #include <Geom2d_BezierCurve.hxx>
29 #include <Geom2d_BSplineCurve.hxx>
30 #include <Geom2d_Circle.hxx>
31 #include <Geom2d_Curve.hxx>
32 #include <Geom2d_Ellipse.hxx>
33 #include <Geom2d_Hyperbola.hxx>
34 #include <Geom2d_Line.hxx>
35 #include <Geom2d_OffsetCurve.hxx>
36 #include <Geom2d_Parabola.hxx>
37 #include <Geom2d_TrimmedCurve.hxx>
38 #include <Geom2d_UndefinedDerivative.hxx>
39 #include <Geom2d_UndefinedValue.hxx>
40 #include <Geom2dAdaptor_Curve.hxx>
41 #include <Geom2dAdaptor_HCurve.hxx>
42 #include <Geom2dEvaluator_OffsetCurve.hxx>
43 #include <GeomAbs_Shape.hxx>
45 #include <gp_Circ2d.hxx>
46 #include <gp_Elips2d.hxx>
47 #include <gp_Hypr2d.hxx>
48 #include <gp_Lin2d.hxx>
49 #include <gp_Parab2d.hxx>
50 #include <gp_Pnt2d.hxx>
51 #include <gp_Vec2d.hxx>
52 #include <Precision.hxx>
53 #include <Standard_ConstructionError.hxx>
54 #include <Standard_DomainError.hxx>
55 #include <Standard_NoSuchObject.hxx>
56 #include <Standard_NotImplemented.hxx>
57 #include <Standard_NullObject.hxx>
58 #include <Standard_OutOfRange.hxx>
59 #include <TColgp_Array1OfPnt2d.hxx>
60 #include <TColStd_Array1OfInteger.hxx>
61 #include <TColStd_Array1OfReal.hxx>
62 #include <TColStd_HArray1OfInteger.hxx>
64 //#include <Geom2dConvert_BSplineCurveKnotSplitting.hxx>
65 static const Standard_Real PosTol = Precision::PConfusion() / 2;
68 //=======================================================================
69 //function : LocalContinuity
70 //purpose : Computes the Continuity of a BSplineCurve
71 // between the parameters U1 and U2
72 // The continuity is C(d-m)
74 // m = max multiplicity of the Knots between U1 and U2
75 //=======================================================================
77 GeomAbs_Shape Geom2dAdaptor_Curve::LocalContinuity(const Standard_Real U1,
78 const Standard_Real U2) const
80 Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
81 Standard_Integer Nb = myBSplineCurve->NbKnots();
82 Standard_Integer Index1 = 0;
83 Standard_Integer Index2 = 0;
84 Standard_Real newFirst, newLast;
85 TColStd_Array1OfReal TK(1,Nb);
86 TColStd_Array1OfInteger TM(1,Nb);
87 myBSplineCurve->Knots(TK);
88 myBSplineCurve->Multiplicities(TM);
89 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U1,myBSplineCurve->IsPeriodic(),
90 1,Nb,Index1,newFirst);
91 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U2,myBSplineCurve->IsPeriodic(),
93 if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) {
94 if (Index1 < Nb)Index1++;
96 if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
98 Standard_Integer MultMax;
99 // attention aux courbes peridiques.
100 if ( myBSplineCurve->IsPeriodic() && Index1 == Nb )
103 if ( Index2 - Index1 <= 0) {
104 MultMax = 100; // CN entre 2 Noeuds consecutifs
107 MultMax = TM(Index1+1);
108 for(Standard_Integer i = Index1+1;i<=Index2;i++) {
109 if ( TM(i)>MultMax) MultMax=TM(i);
111 MultMax = myBSplineCurve->Degree() - MultMax;
116 else if ( MultMax == 1) {
119 else if ( MultMax == 2) {
122 else if ( MultMax == 3) {
131 //=======================================================================
132 //function : Geom2dAdaptor_Curve
134 //=======================================================================
136 Geom2dAdaptor_Curve::Geom2dAdaptor_Curve()
137 : myTypeCurve(GeomAbs_OtherCurve),
143 //=======================================================================
144 //function : Geom2dAdaptor_Curve
146 //=======================================================================
148 Geom2dAdaptor_Curve::Geom2dAdaptor_Curve(const Handle(Geom2d_Curve)& theCrv)
149 : myTypeCurve(GeomAbs_OtherCurve),
156 //=======================================================================
157 //function : Geom2dAdaptor_Curve
159 //=======================================================================
161 Geom2dAdaptor_Curve::Geom2dAdaptor_Curve(const Handle(Geom2d_Curve)& theCrv,
162 const Standard_Real theUFirst,
163 const Standard_Real theULast)
164 : myTypeCurve(GeomAbs_OtherCurve),
168 Load(theCrv, theUFirst, theULast);
172 //=======================================================================
175 //=======================================================================
177 void Geom2dAdaptor_Curve::load(const Handle(Geom2d_Curve)& C,
178 const Standard_Real UFirst,
179 const Standard_Real ULast)
183 myCurveCache.Nullify();
187 myNestedEvaluator.Nullify();
188 myBSplineCurve.Nullify();
190 Handle(Standard_Type) TheType = C->DynamicType();
191 if ( TheType == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
192 Load(Handle(Geom2d_TrimmedCurve)::DownCast (C)->BasisCurve(),
195 else if ( TheType == STANDARD_TYPE(Geom2d_Circle)) {
196 myTypeCurve = GeomAbs_Circle;
198 else if ( TheType ==STANDARD_TYPE(Geom2d_Line)) {
199 myTypeCurve = GeomAbs_Line;
201 else if ( TheType == STANDARD_TYPE(Geom2d_Ellipse)) {
202 myTypeCurve = GeomAbs_Ellipse;
204 else if ( TheType == STANDARD_TYPE(Geom2d_Parabola)) {
205 myTypeCurve = GeomAbs_Parabola;
207 else if ( TheType == STANDARD_TYPE(Geom2d_Hyperbola)) {
208 myTypeCurve = GeomAbs_Hyperbola;
210 else if ( TheType == STANDARD_TYPE(Geom2d_BezierCurve)) {
211 myTypeCurve = GeomAbs_BezierCurve;
213 else if ( TheType == STANDARD_TYPE(Geom2d_BSplineCurve)) {
214 myTypeCurve = GeomAbs_BSplineCurve;
215 myBSplineCurve = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
217 else if ( TheType == STANDARD_TYPE(Geom2d_OffsetCurve))
219 myTypeCurve = GeomAbs_OffsetCurve;
220 Handle(Geom2d_OffsetCurve) anOffsetCurve = Handle(Geom2d_OffsetCurve)::DownCast(myCurve);
221 // Create nested adaptor for base curve
222 Handle(Geom2d_Curve) aBaseCurve = anOffsetCurve->BasisCurve();
223 Handle(Geom2dAdaptor_HCurve) aBaseAdaptor = new Geom2dAdaptor_HCurve(aBaseCurve);
224 myNestedEvaluator = new Geom2dEvaluator_OffsetCurve(aBaseAdaptor, anOffsetCurve->Offset());
227 myTypeCurve = GeomAbs_OtherCurve;
233 // -- Global methods - Apply to the whole curve.
236 //=======================================================================
237 //function : Continuity
239 //=======================================================================
241 GeomAbs_Shape Geom2dAdaptor_Curve::Continuity() const
243 if (myTypeCurve == GeomAbs_BSplineCurve) {
244 return LocalContinuity(myFirst, myLast);
246 else if (myTypeCurve == GeomAbs_OffsetCurve){
248 Handle(Geom2d_OffsetCurve)::DownCast (myCurve)->GetBasisCurveContinuity();
250 case GeomAbs_CN: return GeomAbs_CN;
251 case GeomAbs_C3: return GeomAbs_C2;
252 case GeomAbs_C2: return GeomAbs_C1;
253 case GeomAbs_C1: return GeomAbs_C0;
254 case GeomAbs_G1: return GeomAbs_G1;
255 case GeomAbs_G2: return GeomAbs_G2;
258 throw Standard_NoSuchObject("Geom2dAdaptor_Curve::Continuity");
262 else if (myTypeCurve == GeomAbs_OtherCurve) {
263 throw Standard_NoSuchObject("Geom2dAdaptor_Curve::Continuity");
270 //=======================================================================
271 //function : NbIntervals
273 //=======================================================================
275 Standard_Integer Geom2dAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
277 Standard_Integer myNbIntervals = 1;
278 Standard_Integer NbSplit;
279 if (myTypeCurve == GeomAbs_BSplineCurve) {
280 Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
281 Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
282 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
283 if ( S > Continuity()) {
284 Standard_Integer Cont;
288 throw Standard_DomainError("Geom2dAdaptor_Curve::NbIntervals");
298 if ( S == GeomAbs_C1) Cont = 1;
299 else if ( S == GeomAbs_C2) Cont = 2;
300 else if ( S == GeomAbs_C3) Cont = 3;
301 else Cont = myBSplineCurve->Degree();
302 Standard_Integer Degree = myBSplineCurve->Degree();
303 Standard_Integer NbKnots = myBSplineCurve->NbKnots();
304 TColStd_Array1OfInteger Mults (1, NbKnots);
305 myBSplineCurve->Multiplicities (Mults);
307 Standard_Integer Index = FirstIndex;
308 Inter (NbSplit) = Index;
311 while (Index < LastIndex)
313 if (Degree - Mults (Index) < Cont)
315 Inter (NbSplit) = Index;
320 Inter (NbSplit) = Index;
322 Standard_Integer NbInt = NbSplit-1;
324 Standard_Integer Nb = myBSplineCurve->NbKnots();
325 Standard_Integer Index1 = 0;
326 Standard_Integer Index2 = 0;
327 Standard_Real newFirst, newLast;
328 TColStd_Array1OfReal TK(1,Nb);
329 TColStd_Array1OfInteger TM(1,Nb);
330 myBSplineCurve->Knots(TK);
331 myBSplineCurve->Multiplicities(TM);
332 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
333 myBSplineCurve->IsPeriodic(),
334 1,Nb,Index1,newFirst);
335 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
336 myBSplineCurve->IsPeriodic(),
337 1,Nb,Index2,newLast);
339 // On decale eventuellement les indices
340 // On utilise une "petite" tolerance, la resolution ne doit
341 // servir que pour les tres longue courbes....(PRO9248)
342 Standard_Real Eps = Min(Resolution(Precision::Confusion()),
343 Precision::PConfusion());
344 if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
345 if ( newLast-TK(Index2)> Eps) Index2++;
348 for ( Standard_Integer i=1; i<=NbInt; i++)
349 if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
355 else if (myTypeCurve == GeomAbs_OffsetCurve){
356 GeomAbs_Shape BaseS=GeomAbs_C0;
360 throw Standard_DomainError("GeomAdaptor_Curve::NbIntervals");
362 case GeomAbs_C0: BaseS = GeomAbs_C1; break;
363 case GeomAbs_C1: BaseS = GeomAbs_C2; break;
364 case GeomAbs_C2: BaseS = GeomAbs_C3; break;
365 default: BaseS = GeomAbs_CN;
367 Geom2dAdaptor_Curve anAdaptor( Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->BasisCurve() );
368 myNbIntervals = anAdaptor.NbIntervals(BaseS);
371 return myNbIntervals;
374 //=======================================================================
375 //function : Intervals
377 //=======================================================================
379 void Geom2dAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
380 const GeomAbs_Shape S ) const
382 Standard_Integer myNbIntervals = 1;
383 Standard_Integer NbSplit;
384 if (myTypeCurve == GeomAbs_BSplineCurve) {
385 Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
386 Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
387 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
388 if ( S > Continuity()) {
389 Standard_Integer Cont;
393 throw Standard_DomainError("Geom2dAdaptor_Curve::NbIntervals");
403 if ( S == GeomAbs_C1) Cont = 1;
404 else if ( S == GeomAbs_C2) Cont = 2;
405 else if ( S == GeomAbs_C3) Cont = 3;
406 else Cont = myBSplineCurve->Degree();
407 Standard_Integer Degree = myBSplineCurve->Degree();
408 Standard_Integer NbKnots = myBSplineCurve->NbKnots();
409 TColStd_Array1OfInteger Mults (1, NbKnots);
410 myBSplineCurve->Multiplicities (Mults);
412 Standard_Integer Index = FirstIndex;
413 Inter (NbSplit) = Index;
416 while (Index < LastIndex)
418 if (Degree - Mults (Index) < Cont)
420 Inter (NbSplit) = Index;
425 Inter (NbSplit) = Index;
426 Standard_Integer NbInt = NbSplit-1;
428 Standard_Integer Nb = myBSplineCurve->NbKnots();
429 Standard_Integer Index1 = 0;
430 Standard_Integer Index2 = 0;
431 Standard_Real newFirst, newLast;
432 TColStd_Array1OfReal TK(1,Nb);
433 TColStd_Array1OfInteger TM(1,Nb);
434 myBSplineCurve->Knots(TK);
435 myBSplineCurve->Multiplicities(TM);
436 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
437 myBSplineCurve->IsPeriodic(),
438 1,Nb,Index1,newFirst);
439 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
440 myBSplineCurve->IsPeriodic(),
441 1,Nb,Index2,newLast);
444 // On decale eventuellement les indices
445 // On utilise une "petite" tolerance, la resolution ne doit
446 // servir que pour les tres longue courbes....(PRO9248)
447 Standard_Real Eps = Min(Resolution(Precision::Confusion()),
448 Precision::PConfusion());
449 if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
450 if ( newLast-TK(Index2)> Eps) Index2++;
454 for ( Standard_Integer i=1; i<=NbInt; i++) {
455 if (Inter(i) > Index1 && Inter(i)<Index2 ) {
457 Inter(myNbIntervals) = Inter(i);
460 Inter(myNbIntervals+1) = Index2;
462 Standard_Integer ii = T.Lower() - 1;
463 for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
464 T(ii + I) = TK(Inter(I));
471 else if (myTypeCurve == GeomAbs_OffsetCurve){
472 GeomAbs_Shape BaseS=GeomAbs_C0;
476 throw Standard_DomainError("GeomAdaptor_Curve::NbIntervals");
478 case GeomAbs_C0: BaseS = GeomAbs_C1; break;
479 case GeomAbs_C1: BaseS = GeomAbs_C2; break;
480 case GeomAbs_C2: BaseS = GeomAbs_C3; break;
481 default: BaseS = GeomAbs_CN;
484 Geom2dAdaptor_Curve anAdaptor( Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->BasisCurve() );
485 myNbIntervals = anAdaptor.NbIntervals(BaseS);
486 anAdaptor.Intervals(T, BaseS);
489 T( T.Lower() ) = myFirst;
490 T( T.Lower() + myNbIntervals ) = myLast;
493 //=======================================================================
496 //=======================================================================
498 Handle(Adaptor2d_HCurve2d) Geom2dAdaptor_Curve::Trim
499 (const Standard_Real First,
500 const Standard_Real Last,
501 // const Standard_Real Tol) const
502 const Standard_Real ) const
504 Handle(Geom2dAdaptor_HCurve) HE = new Geom2dAdaptor_HCurve(myCurve,First,Last);
509 //=======================================================================
510 //function : IsClosed
512 //=======================================================================
514 Standard_Boolean Geom2dAdaptor_Curve::IsClosed() const
516 if (!Precision::IsPositiveInfinite(myLast) &&
517 !Precision::IsNegativeInfinite(myFirst)) {
518 gp_Pnt2d Pd = Value(myFirst);
519 gp_Pnt2d Pf = Value(myLast);
520 return ( Pd.Distance(Pf) <= Precision::Confusion());
523 return Standard_False;
526 //=======================================================================
527 //function : IsPeriodic
529 //=======================================================================
531 Standard_Boolean Geom2dAdaptor_Curve::IsPeriodic() const
533 return myCurve->IsPeriodic();
536 //=======================================================================
539 //=======================================================================
541 Standard_Real Geom2dAdaptor_Curve::Period() const
543 return myCurve->LastParameter() - myCurve->FirstParameter();
546 //=======================================================================
547 //function : RebuildCache
549 //=======================================================================
550 void Geom2dAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
552 if (myTypeCurve == GeomAbs_BezierCurve)
554 // Create cache for Bezier
555 Handle(Geom2d_BezierCurve) aBezier = Handle(Geom2d_BezierCurve)::DownCast(myCurve);
556 Standard_Integer aDeg = aBezier->Degree();
557 TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
558 if (myCurveCache.IsNull())
559 myCurveCache = new BSplCLib_Cache (aDeg, aBezier->IsPeriodic(), aFlatKnots,
560 aBezier->Poles(), aBezier->Weights());
561 myCurveCache->BuildCache (theParameter, aFlatKnots, aBezier->Poles(), aBezier->Weights());
563 else if (myTypeCurve == GeomAbs_BSplineCurve)
565 // Create cache for B-spline
566 if (myCurveCache.IsNull())
567 myCurveCache = new BSplCLib_Cache (myBSplineCurve->Degree(), myBSplineCurve->IsPeriodic(),
568 myBSplineCurve->KnotSequence(), myBSplineCurve->Poles(), myBSplineCurve->Weights());
569 myCurveCache->BuildCache (theParameter, myBSplineCurve->KnotSequence(),
570 myBSplineCurve->Poles(), myBSplineCurve->Weights());
574 //=======================================================================
575 //function : IsBoundary
577 //=======================================================================
578 Standard_Boolean Geom2dAdaptor_Curve::IsBoundary(const Standard_Real theU,
579 Standard_Integer& theSpanStart,
580 Standard_Integer& theSpanFinish) const
582 if (!myBSplineCurve.IsNull() && (theU == myFirst || theU == myLast))
586 myBSplineCurve->LocateU(myFirst, PosTol, theSpanStart, theSpanFinish);
587 if (theSpanStart < 1)
589 if (theSpanStart >= theSpanFinish)
590 theSpanFinish = theSpanStart + 1;
592 else if (theU == myLast)
594 myBSplineCurve->LocateU(myLast, PosTol, theSpanStart, theSpanFinish);
595 if (theSpanFinish > myBSplineCurve->NbKnots())
596 theSpanFinish = myBSplineCurve->NbKnots();
597 if (theSpanStart >= theSpanFinish)
598 theSpanStart = theSpanFinish - 1;
600 return Standard_True;
602 return Standard_False;
605 //=======================================================================
608 //=======================================================================
610 gp_Pnt2d Geom2dAdaptor_Curve::Value(const Standard_Real U) const
617 //=======================================================================
620 //=======================================================================
622 void Geom2dAdaptor_Curve::D0(const Standard_Real U, gp_Pnt2d& P) const
626 case GeomAbs_BezierCurve:
627 case GeomAbs_BSplineCurve:
629 Standard_Integer aStart = 0, aFinish = 0;
630 if (IsBoundary(U, aStart, aFinish))
632 myBSplineCurve->LocalD0(U, aStart, aFinish, P);
637 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
639 myCurveCache->D0(U, P);
644 case GeomAbs_OffsetCurve:
645 myNestedEvaluator->D0(U, P);
653 //=======================================================================
656 //=======================================================================
658 void Geom2dAdaptor_Curve::D1(const Standard_Real U,
659 gp_Pnt2d& P, gp_Vec2d& V) const
663 case GeomAbs_BezierCurve:
664 case GeomAbs_BSplineCurve:
666 Standard_Integer aStart = 0, aFinish = 0;
667 if (IsBoundary(U, aStart, aFinish))
669 myBSplineCurve->LocalD1(U, aStart, aFinish, P, V);
674 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
676 myCurveCache->D1(U, P, V);
681 case GeomAbs_OffsetCurve:
682 myNestedEvaluator->D1(U, P, V);
686 myCurve->D1(U, P, V);
690 //=======================================================================
693 //=======================================================================
695 void Geom2dAdaptor_Curve::D2(const Standard_Real U,
696 gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const
700 case GeomAbs_BezierCurve:
701 case GeomAbs_BSplineCurve:
703 Standard_Integer aStart = 0, aFinish = 0;
704 if (IsBoundary(U, aStart, aFinish))
706 myBSplineCurve->LocalD2(U, aStart, aFinish, P, V1, V2);
711 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
713 myCurveCache->D2(U, P, V1, V2);
718 case GeomAbs_OffsetCurve:
719 myNestedEvaluator->D2(U, P, V1, V2);
723 myCurve->D2(U, P, V1, V2);
727 //=======================================================================
730 //=======================================================================
732 void Geom2dAdaptor_Curve::D3(const Standard_Real U,
733 gp_Pnt2d& P, gp_Vec2d& V1,
734 gp_Vec2d& V2, gp_Vec2d& V3) const
738 case GeomAbs_BezierCurve:
739 case GeomAbs_BSplineCurve:
741 Standard_Integer aStart = 0, aFinish = 0;
742 if (IsBoundary(U, aStart, aFinish))
744 myBSplineCurve->LocalD3(U, aStart, aFinish, P, V1, V2, V3);
749 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
751 myCurveCache->D3(U, P, V1, V2, V3);
756 case GeomAbs_OffsetCurve:
757 myNestedEvaluator->D3(U, P, V1, V2, V3);
761 myCurve->D3(U, P, V1, V2, V3);
765 //=======================================================================
768 //=======================================================================
770 gp_Vec2d Geom2dAdaptor_Curve::DN(const Standard_Real U,
771 const Standard_Integer N) const
775 case GeomAbs_BezierCurve:
776 case GeomAbs_BSplineCurve:
778 Standard_Integer aStart = 0, aFinish = 0;
779 if (IsBoundary(U, aStart, aFinish))
781 myBSplineCurve->LocalDN(U, aStart, aFinish, N);
784 return myCurve->DN(U, N);
788 case GeomAbs_OffsetCurve:
789 return myNestedEvaluator->DN(U, N);
792 default: // to eliminate gcc warning
795 return myCurve->DN(U, N);
798 //=======================================================================
799 //function : Resolution
801 //=======================================================================
803 Standard_Real Geom2dAdaptor_Curve::Resolution(const Standard_Real Ruv) const {
804 switch ( myTypeCurve) {
807 case GeomAbs_Circle: {
808 Standard_Real R = Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d().Radius();
810 return 2*ASin(Ruv/(2*R));
814 case GeomAbs_Ellipse: {
815 return Ruv / Handle(Geom2d_Ellipse)::DownCast (myCurve)->MajorRadius();
817 case GeomAbs_BezierCurve: {
819 Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Resolution(Ruv,res);
822 case GeomAbs_BSplineCurve: {
824 Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->Resolution(Ruv,res);
828 return Precision::Parametric(Ruv);
834 // -- The following methods must be called when GetType returned
835 // -- the corresponding type.
838 //=======================================================================
841 //=======================================================================
843 gp_Lin2d Geom2dAdaptor_Curve::Line() const
845 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Line,
846 "Geom2dAdaptor_Curve::Line() - curve is not a Line");
847 return Handle(Geom2d_Line)::DownCast (myCurve)->Lin2d();
850 //=======================================================================
853 //=======================================================================
855 gp_Circ2d Geom2dAdaptor_Curve::Circle() const
857 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Circle,
858 "Geom2dAdaptor_Curve::Circle() - curve is not a Circle");
859 return Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d();
862 //=======================================================================
865 //=======================================================================
867 gp_Elips2d Geom2dAdaptor_Curve::Ellipse() const
869 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Ellipse,
870 "Geom2dAdaptor_Curve::Ellipse() - curve is not an Ellipse");
871 return Handle(Geom2d_Ellipse)::DownCast (myCurve)->Elips2d();
874 //=======================================================================
875 //function : Hyperbola
877 //=======================================================================
879 gp_Hypr2d Geom2dAdaptor_Curve::Hyperbola() const
881 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Hyperbola,
882 "Geom2dAdaptor_Curve::Hyperbola() - curve is not a Hyperbola");
883 return Handle(Geom2d_Hyperbola)::DownCast (myCurve)->Hypr2d();
886 //=======================================================================
887 //function : Parabola
889 //=======================================================================
891 gp_Parab2d Geom2dAdaptor_Curve::Parabola() const
893 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Parabola,
894 "Geom2dAdaptor_Curve::Parabola() - curve is not a Parabola");
895 return Handle(Geom2d_Parabola)::DownCast (myCurve)->Parab2d();
898 //=======================================================================
901 //=======================================================================
903 Standard_Integer Geom2dAdaptor_Curve::Degree() const
905 if (myTypeCurve == GeomAbs_BezierCurve)
906 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Degree();
907 else if (myTypeCurve == GeomAbs_BSplineCurve)
908 return myBSplineCurve->Degree();
910 throw Standard_NoSuchObject();
913 //=======================================================================
914 //function : IsRational
916 //=======================================================================
918 Standard_Boolean Geom2dAdaptor_Curve::IsRational() const {
919 switch( myTypeCurve) {
920 case GeomAbs_BSplineCurve:
921 return myBSplineCurve->IsRational();
922 case GeomAbs_BezierCurve:
923 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->IsRational();
925 return Standard_False;
929 //=======================================================================
932 //=======================================================================
934 Standard_Integer Geom2dAdaptor_Curve::NbPoles() const
936 if (myTypeCurve == GeomAbs_BezierCurve)
937 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->NbPoles();
938 else if (myTypeCurve == GeomAbs_BSplineCurve)
939 return myBSplineCurve->NbPoles();
941 throw Standard_NoSuchObject();
944 //=======================================================================
947 //=======================================================================
949 Standard_Integer Geom2dAdaptor_Curve::NbKnots() const
951 if ( myTypeCurve != GeomAbs_BSplineCurve)
952 throw Standard_NoSuchObject("Geom2dAdaptor_Curve::NbKnots");
953 return myBSplineCurve->NbKnots();
956 //=======================================================================
959 //=======================================================================
961 Handle(Geom2d_BezierCurve) Geom2dAdaptor_Curve::Bezier() const
963 return Handle(Geom2d_BezierCurve)::DownCast (myCurve);
966 //=======================================================================
969 //=======================================================================
971 Handle(Geom2d_BSplineCurve) Geom2dAdaptor_Curve::BSpline() const
973 return myBSplineCurve;
976 static Standard_Integer nbPoints(const Handle(Geom2d_Curve)& theCurve)
979 Standard_Integer nbs = 20;
981 if(theCurve->IsKind(STANDARD_TYPE( Geom2d_Line)) )
983 else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BezierCurve)))
985 nbs = 3 + Handle(Geom2d_BezierCurve)::DownCast (theCurve)->NbPoles();
987 else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BSplineCurve))) {
988 nbs = Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->NbKnots();
989 nbs*= Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->Degree();
992 else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
994 Handle(Geom2d_Curve) aCurve = Handle(Geom2d_OffsetCurve)::DownCast (theCurve)->BasisCurve();
995 return Max(nbs, nbPoints(aCurve));
998 else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
1000 Handle(Geom2d_Curve) aCurve = Handle(Geom2d_TrimmedCurve)::DownCast (theCurve)->BasisCurve();
1001 return Max(nbs, nbPoints(aCurve));
1009 Standard_Integer Geom2dAdaptor_Curve::NbSamples() const
1011 return nbPoints(myCurve);