1 // Created on: 1993-04-29
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 : RBV -> traitement des offset curves
21 #define No_Standard_RangeError
22 #define No_Standard_OutOfRange
25 #include <Adaptor3d_HCurve.hxx>
26 #include <BSplCLib.hxx>
27 #include <BSplCLib_Cache.hxx>
28 #include <Geom_BezierCurve.hxx>
29 #include <Geom_BSplineCurve.hxx>
30 #include <Geom_Circle.hxx>
31 #include <Geom_Curve.hxx>
32 #include <Geom_Ellipse.hxx>
33 #include <Geom_Hyperbola.hxx>
34 #include <Geom_Line.hxx>
35 #include <Geom_OffsetCurve.hxx>
36 #include <Geom_Parabola.hxx>
37 #include <Geom_TrimmedCurve.hxx>
38 #include <GeomAbs_Shape.hxx>
39 #include <GeomAdaptor_Curve.hxx>
40 #include <GeomAdaptor_HCurve.hxx>
41 #include <GeomAdaptor_Surface.hxx>
42 #include <GeomEvaluator_OffsetCurve.hxx>
43 #include <gp_Circ.hxx>
44 #include <gp_Elips.hxx>
45 #include <gp_Hypr.hxx>
47 #include <gp_Parab.hxx>
50 #include <Precision.hxx>
51 #include <Standard_ConstructionError.hxx>
52 #include <Standard_DomainError.hxx>
53 #include <Standard_NoSuchObject.hxx>
54 #include <Standard_NotImplemented.hxx>
55 #include <Standard_NullObject.hxx>
56 #include <Standard_OutOfRange.hxx>
57 #include <TColgp_Array1OfPnt.hxx>
58 #include <TColStd_Array1OfInteger.hxx>
59 #include <TColStd_Array1OfReal.hxx>
60 #include <TColStd_HArray1OfInteger.hxx>
62 //#include <GeomConvert_BSplineCurveKnotSplitting.hxx>
63 static const Standard_Real PosTol = Precision::PConfusion() / 2;
66 //=======================================================================
67 //function : LocalContinuity
68 //purpose : Computes the Continuity of a BSplineCurve
69 // between the parameters U1 and U2
70 // The continuity is C(d-m)
72 // m = max multiplicity of the Knots between U1 and U2
73 //=======================================================================
75 GeomAbs_Shape GeomAdaptor_Curve::LocalContinuity(const Standard_Real U1,
76 const Standard_Real U2)
79 Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
80 Standard_Integer Nb = myBSplineCurve->NbKnots();
81 Standard_Integer Index1 = 0;
82 Standard_Integer Index2 = 0;
83 Standard_Real newFirst, newLast;
84 TColStd_Array1OfReal TK(1,Nb);
85 TColStd_Array1OfInteger TM(1,Nb);
86 myBSplineCurve->Knots(TK);
87 myBSplineCurve->Multiplicities(TM);
88 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U1,myBSplineCurve->IsPeriodic(),
89 1,Nb,Index1,newFirst);
90 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U2,myBSplineCurve->IsPeriodic(),
92 if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) {
93 if (Index1 < Nb) Index1++;
95 if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
97 Standard_Integer MultMax;
98 // attention aux courbes peridiques.
99 if ( (myBSplineCurve->IsPeriodic()) && (Index1 == Nb) )
102 if ( Index2 - Index1 <= 0) {
103 MultMax = 100; // CN entre 2 Noeuds consecutifs
106 MultMax = TM(Index1+1);
107 for(Standard_Integer i = Index1+1;i<=Index2;i++) {
108 if ( TM(i)>MultMax) MultMax=TM(i);
110 MultMax = myBSplineCurve->Degree() - MultMax;
115 else if ( MultMax == 1) {
118 else if ( MultMax == 2) {
121 else if ( MultMax == 3) {
130 //=======================================================================
133 //=======================================================================
135 void GeomAdaptor_Curve::load(const Handle(Geom_Curve)& C,
136 const Standard_Real UFirst,
137 const Standard_Real ULast)
144 myCurveCache.Nullify();
145 myNestedEvaluator.Nullify();
146 myBSplineCurve.Nullify();
148 const Handle(Standard_Type)& TheType = C->DynamicType();
149 if ( TheType == STANDARD_TYPE(Geom_TrimmedCurve)) {
150 Load(Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve(),UFirst,ULast);
152 else if ( TheType == STANDARD_TYPE(Geom_Circle)) {
153 myTypeCurve = GeomAbs_Circle;
155 else if ( TheType ==STANDARD_TYPE(Geom_Line)) {
156 myTypeCurve = GeomAbs_Line;
158 else if ( TheType == STANDARD_TYPE(Geom_Ellipse)) {
159 myTypeCurve = GeomAbs_Ellipse;
161 else if ( TheType == STANDARD_TYPE(Geom_Parabola)) {
162 myTypeCurve = GeomAbs_Parabola;
164 else if ( TheType == STANDARD_TYPE(Geom_Hyperbola)) {
165 myTypeCurve = GeomAbs_Hyperbola;
167 else if ( TheType == STANDARD_TYPE(Geom_BezierCurve)) {
168 myTypeCurve = GeomAbs_BezierCurve;
169 // Create cache for Bezier
170 Handle(Geom_BezierCurve) aBezier = Handle(Geom_BezierCurve)::DownCast(myCurve);
171 Standard_Integer aDeg = aBezier->Degree();
172 TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
173 myCurveCache = new BSplCLib_Cache(aDeg, aBezier->IsPeriodic(), aFlatKnots,
174 aBezier->Poles(), aBezier->Weights());
176 else if ( TheType == STANDARD_TYPE(Geom_BSplineCurve)) {
177 myTypeCurve = GeomAbs_BSplineCurve;
178 // Create cache for B-spline
179 Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
180 myBSplineCurve = aBspl;
181 myCurveCache = new BSplCLib_Cache(aBspl->Degree(), aBspl->IsPeriodic(),
182 aBspl->KnotSequence(), aBspl->Poles(), aBspl->Weights());
184 else if ( TheType == STANDARD_TYPE(Geom_OffsetCurve)) {
185 myTypeCurve = GeomAbs_OffsetCurve;
186 Handle(Geom_OffsetCurve) anOffsetCurve = Handle(Geom_OffsetCurve)::DownCast(myCurve);
187 // Create nested adaptor for base curve
188 Handle(Geom_Curve) aBaseCurve = anOffsetCurve->BasisCurve();
189 Handle(GeomAdaptor_HCurve) aBaseAdaptor = new GeomAdaptor_HCurve(aBaseCurve);
190 myNestedEvaluator = new GeomEvaluator_OffsetCurve(
191 aBaseAdaptor, anOffsetCurve->Offset(), anOffsetCurve->Direction());
194 myTypeCurve = GeomAbs_OtherCurve;
197 else // rebuild cache of Bezier and B-spline curve even if the loaded curve is same
198 RebuildCache(myFirst);
202 // -- Global methods - Apply to the whole curve.
205 //=======================================================================
206 //function : Continuity
208 //=======================================================================
210 GeomAbs_Shape GeomAdaptor_Curve::Continuity() const
212 if (myTypeCurve == GeomAbs_BSplineCurve)
213 return LocalContinuity(myFirst, myLast);
215 if (myTypeCurve == GeomAbs_OffsetCurve)
217 const GeomAbs_Shape S =
218 Handle(Geom_OffsetCurve)::DownCast (myCurve)->GetBasisCurveContinuity();
221 case GeomAbs_CN: return GeomAbs_CN;
222 case GeomAbs_C3: return GeomAbs_C2;
223 case GeomAbs_C2: return GeomAbs_C1;
224 case GeomAbs_C1: return GeomAbs_C0;
225 case GeomAbs_G1: return GeomAbs_G1;
226 case GeomAbs_G2: return GeomAbs_G2;
228 Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Continuity");
231 else if (myTypeCurve == GeomAbs_OtherCurve) {
232 Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Contunuity");
238 //=======================================================================
239 //function : NbIntervals
241 //=======================================================================
243 Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
245 Standard_Integer myNbIntervals = 1;
246 Standard_Integer NbSplit;
247 if (myTypeCurve == GeomAbs_BSplineCurve) {
248 Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
249 Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
250 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
251 if ( S > Continuity()) {
252 Standard_Integer Cont;
256 Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
266 if ( S == GeomAbs_C1) Cont = 1;
267 else if ( S == GeomAbs_C2) Cont = 2;
268 else if ( S == GeomAbs_C3) Cont = 3;
269 else Cont = myBSplineCurve->Degree();
270 Standard_Integer Degree = myBSplineCurve->Degree();
271 Standard_Integer NbKnots = myBSplineCurve->NbKnots();
272 TColStd_Array1OfInteger Mults (1, NbKnots);
273 myBSplineCurve->Multiplicities (Mults);
275 Standard_Integer Index = FirstIndex;
276 Inter (NbSplit) = Index;
279 while (Index < LastIndex)
281 if (Degree - Mults (Index) < Cont)
283 Inter (NbSplit) = Index;
288 Inter (NbSplit) = Index;
290 Standard_Integer NbInt = NbSplit-1;
292 Standard_Integer Nb = myBSplineCurve->NbKnots();
293 Standard_Integer Index1 = 0;
294 Standard_Integer Index2 = 0;
295 Standard_Real newFirst, newLast;
296 TColStd_Array1OfReal TK(1,Nb);
297 TColStd_Array1OfInteger TM(1,Nb);
298 myBSplineCurve->Knots(TK);
299 myBSplineCurve->Multiplicities(TM);
300 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
301 myBSplineCurve->IsPeriodic(),
302 1,Nb,Index1,newFirst);
303 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
304 myBSplineCurve->IsPeriodic(),
305 1,Nb,Index2,newLast);
307 // On decale eventuellement les indices
308 // On utilise une "petite" tolerance, la resolution ne doit
309 // servir que pour les tres longue courbes....(PRO9248)
310 Standard_Real Eps = Min(Resolution(Precision::Confusion()),
311 Precision::PConfusion());
312 if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
313 if ( newLast-TK(Index2)> Eps) Index2++;
316 for ( Standard_Integer i=1; i<=NbInt; i++)
317 if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
324 else if (myTypeCurve == GeomAbs_OffsetCurve) {
325 GeomAbs_Shape BaseS=GeomAbs_C0;
329 Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
331 case GeomAbs_C0: BaseS = GeomAbs_C1; break;
332 case GeomAbs_C1: BaseS = GeomAbs_C2; break;
333 case GeomAbs_C2: BaseS = GeomAbs_C3; break;
334 default: BaseS = GeomAbs_CN;
337 (Handle(Geom_OffsetCurve)::DownCast (myCurve)->BasisCurve());
338 // akm 05/04/02 (OCC278) If our curve is trimmed we must recalculate
339 // the number of intervals obtained from the basis to
340 // vvv reflect parameter bounds
341 Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
344 TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
345 C.Intervals(rdfInter,BaseS);
346 for (iInt=1; iInt<=iNbBasisInt; iInt++)
347 if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
352 return myNbIntervals;
355 //=======================================================================
356 //function : Intervals
358 //=======================================================================
360 void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
361 const GeomAbs_Shape S ) const
363 Standard_Integer myNbIntervals = 1;
364 Standard_Integer NbSplit;
365 Standard_Real FirstParam = myFirst, LastParam = myLast;
367 if (myTypeCurve == GeomAbs_BSplineCurve)
369 Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
370 Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
371 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
373 if ( S > Continuity()) {
374 Standard_Integer Cont;
378 Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
388 if ( S == GeomAbs_C1) Cont = 1;
389 else if ( S == GeomAbs_C2) Cont = 2;
390 else if ( S == GeomAbs_C3) Cont = 3;
391 else Cont = myBSplineCurve->Degree();
392 Standard_Integer Degree = myBSplineCurve->Degree();
393 Standard_Integer NbKnots = myBSplineCurve->NbKnots();
394 TColStd_Array1OfInteger Mults (1, NbKnots);
395 myBSplineCurve->Multiplicities (Mults);
397 Standard_Integer Index = FirstIndex;
398 Inter (NbSplit) = Index;
401 while (Index < LastIndex)
403 if (Degree - Mults (Index) < Cont)
405 Inter (NbSplit) = Index;
410 Inter (NbSplit) = Index;
411 Standard_Integer NbInt = NbSplit-1;
412 // GeomConvert_BSplineCurveKnotSplitting Convector(myBspl, Cont);
413 // Standard_Integer NbInt = Convector.NbSplits()-1;
414 // TColStd_Array1OfInteger Inter(1,NbInt+1);
415 // Convector.Splitting( Inter);
417 Standard_Integer Nb = myBSplineCurve->NbKnots();
418 Standard_Integer Index1 = 0;
419 Standard_Integer Index2 = 0;
420 Standard_Real newFirst, newLast;
421 TColStd_Array1OfReal TK(1,Nb);
422 TColStd_Array1OfInteger TM(1,Nb);
423 myBSplineCurve->Knots(TK);
424 myBSplineCurve->Multiplicities(TM);
425 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
426 myBSplineCurve->IsPeriodic(),
427 1,Nb,Index1,newFirst);
428 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
429 myBSplineCurve->IsPeriodic(),
430 1,Nb,Index2,newLast);
431 FirstParam = newFirst;
433 // On decale eventuellement les indices
434 // On utilise une "petite" tolerance, la resolution ne doit
435 // servir que pour les tres longue courbes....(PRO9248)
436 Standard_Real Eps = Min(Resolution(Precision::Confusion()),
437 Precision::PConfusion());
438 if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
439 if ( newLast-TK(Index2)> Eps) Index2++;
443 for ( Standard_Integer i=1; i<=NbInt; i++) {
444 if (Inter(i) > Index1 && Inter(i)<Index2 ) {
446 Inter(myNbIntervals) = Inter(i);
449 Inter(myNbIntervals+1) = Index2;
451 for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
460 else if (myTypeCurve == GeomAbs_OffsetCurve){
461 GeomAbs_Shape BaseS=GeomAbs_C0;
465 Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
467 case GeomAbs_C0: BaseS = GeomAbs_C1; break;
468 case GeomAbs_C1: BaseS = GeomAbs_C2; break;
469 case GeomAbs_C2: BaseS = GeomAbs_C3; break;
470 default: BaseS = GeomAbs_CN;
473 (Handle(Geom_OffsetCurve)::DownCast (myCurve)->BasisCurve());
474 // akm 05/04/02 (OCC278) If our curve is trimmed we must recalculate
475 // the array of intervals obtained from the basis to
476 // vvv reflect parameter bounds
477 Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
480 TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
481 C.Intervals(rdfInter,BaseS);
482 for (iInt=1; iInt<=iNbBasisInt; iInt++)
483 if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
484 T(++myNbIntervals)=rdfInter(iInt);
486 // old - myNbIntervals = C.NbIntervals(BaseS);
487 // old - C.Intervals(T, BaseS);
491 T( T.Lower() ) = FirstParam;
492 T( T.Lower() + myNbIntervals ) = LastParam;
495 //=======================================================================
498 //=======================================================================
500 Handle(Adaptor3d_HCurve) GeomAdaptor_Curve::Trim(const Standard_Real First,
501 const Standard_Real Last,
502 const Standard_Real /*Tol*/) const
504 return Handle(GeomAdaptor_HCurve)(new GeomAdaptor_HCurve(myCurve,First,Last));
508 //=======================================================================
509 //function : IsClosed
511 //=======================================================================
513 Standard_Boolean GeomAdaptor_Curve::IsClosed() const
515 if (!Precision::IsPositiveInfinite(myLast) &&
516 !Precision::IsNegativeInfinite(myFirst))
518 const gp_Pnt Pd = Value(myFirst);
519 const gp_Pnt Pf = Value(myLast);
520 return (Pd.Distance(Pf) <= Precision::Confusion());
522 return Standard_False;
525 //=======================================================================
526 //function : IsPeriodic
528 //=======================================================================
530 Standard_Boolean GeomAdaptor_Curve::IsPeriodic() const
532 return (myCurve->IsPeriodic()? IsClosed() : Standard_False);
535 //=======================================================================
538 //=======================================================================
540 Standard_Real GeomAdaptor_Curve::Period() const
542 return myCurve->LastParameter() - myCurve->FirstParameter();
545 //=======================================================================
546 //function : RebuildCache
548 //=======================================================================
549 void GeomAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
551 if (myTypeCurve == GeomAbs_BezierCurve)
553 Handle(Geom_BezierCurve) aBezier = Handle(Geom_BezierCurve)::DownCast(myCurve);
554 Standard_Integer aDeg = aBezier->Degree();
555 TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
556 myCurveCache->BuildCache(theParameter, aDeg, aBezier->IsPeriodic(), aFlatKnots,
557 aBezier->Poles(), aBezier->Weights());
559 else if (myTypeCurve == GeomAbs_BSplineCurve)
561 myCurveCache->BuildCache(theParameter, myBSplineCurve->Degree(),
562 myBSplineCurve->IsPeriodic(), myBSplineCurve->KnotSequence(),
563 myBSplineCurve->Poles(), myBSplineCurve->Weights());
567 //=======================================================================
568 //function : IsBoundary
570 //=======================================================================
571 Standard_Boolean GeomAdaptor_Curve::IsBoundary(const Standard_Real theU,
572 Standard_Integer& theSpanStart,
573 Standard_Integer& theSpanFinish) const
575 if (!myBSplineCurve.IsNull() && (theU == myFirst || theU == myLast))
579 myBSplineCurve->LocateU(myFirst, PosTol, theSpanStart, theSpanFinish);
580 if (theSpanStart < 1)
582 if (theSpanStart >= theSpanFinish)
583 theSpanFinish = theSpanStart + 1;
585 else if (theU == myLast)
587 myBSplineCurve->LocateU(myLast, PosTol, theSpanStart, theSpanFinish);
588 if (theSpanFinish > myBSplineCurve->NbKnots())
589 theSpanFinish = myBSplineCurve->NbKnots();
590 if (theSpanStart >= theSpanFinish)
591 theSpanStart = theSpanFinish - 1;
593 return Standard_True;
595 return Standard_False;
598 //=======================================================================
601 //=======================================================================
603 gp_Pnt GeomAdaptor_Curve::Value(const Standard_Real U) const
610 //=======================================================================
613 //=======================================================================
615 void GeomAdaptor_Curve::D0(const Standard_Real U, gp_Pnt& P) const
619 case GeomAbs_BezierCurve:
620 case GeomAbs_BSplineCurve:
622 Standard_Integer aStart = 0, aFinish = 0;
623 if (IsBoundary(U, aStart, aFinish))
625 myBSplineCurve->LocalD0(U, aStart, aFinish, P);
627 else if (!myCurveCache.IsNull()) // use cached data
629 if (!myCurveCache->IsCacheValid(U))
631 myCurveCache->D0(U, P);
638 case GeomAbs_OffsetCurve:
639 myNestedEvaluator->D0(U, P);
647 //=======================================================================
650 //=======================================================================
652 void GeomAdaptor_Curve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V) const
656 case GeomAbs_BezierCurve:
657 case GeomAbs_BSplineCurve:
659 Standard_Integer aStart = 0, aFinish = 0;
660 if (IsBoundary(U, aStart, aFinish))
662 myBSplineCurve->LocalD1(U, aStart, aFinish, P, V);
664 else if (!myCurveCache.IsNull()) // use cached data
666 if (!myCurveCache->IsCacheValid(U))
668 myCurveCache->D1(U, P, V);
671 myCurve->D1(U, P, V);
675 case GeomAbs_OffsetCurve:
676 myNestedEvaluator->D1(U, P, V);
680 myCurve->D1(U, P, V);
684 //=======================================================================
687 //=======================================================================
689 void GeomAdaptor_Curve::D2(const Standard_Real U,
690 gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) const
694 case GeomAbs_BezierCurve:
695 case GeomAbs_BSplineCurve:
697 Standard_Integer aStart = 0, aFinish = 0;
698 if (IsBoundary(U, aStart, aFinish))
700 myBSplineCurve->LocalD2(U, aStart, aFinish, P, V1, V2);
702 else if (!myCurveCache.IsNull()) // use cached data
704 if (!myCurveCache->IsCacheValid(U))
706 myCurveCache->D2(U, P, V1, V2);
709 myCurve->D2(U, P, V1, V2);
713 case GeomAbs_OffsetCurve:
714 myNestedEvaluator->D2(U, P, V1, V2);
718 myCurve->D2(U, P, V1, V2);
722 //=======================================================================
725 //=======================================================================
727 void GeomAdaptor_Curve::D3(const Standard_Real U,
728 gp_Pnt& P, gp_Vec& V1,
729 gp_Vec& V2, gp_Vec& V3) const
733 case GeomAbs_BezierCurve:
734 case GeomAbs_BSplineCurve:
736 Standard_Integer aStart = 0, aFinish = 0;
737 if (IsBoundary(U, aStart, aFinish))
739 myBSplineCurve->LocalD3(U, aStart, aFinish, P, V1, V2, V3);
741 else if (!myCurveCache.IsNull()) // use cached data
743 if (!myCurveCache->IsCacheValid(U))
745 myCurveCache->D3(U, P, V1, V2, V3);
748 myCurve->D3(U, P, V1, V2, V3);
752 case GeomAbs_OffsetCurve:
753 myNestedEvaluator->D3(U, P, V1, V2, V3);
757 myCurve->D3(U, P, V1, V2, V3);
761 //=======================================================================
764 //=======================================================================
766 gp_Vec GeomAdaptor_Curve::DN(const Standard_Real U,
767 const Standard_Integer N) const
771 case GeomAbs_BezierCurve:
772 case GeomAbs_BSplineCurve:
774 Standard_Integer aStart = 0, aFinish = 0;
775 if (IsBoundary(U, aStart, aFinish))
777 return myBSplineCurve->LocalDN(U, aStart, aFinish, N);
780 return myCurve->DN(U, N);
784 case GeomAbs_OffsetCurve:
785 return myNestedEvaluator->DN(U, N);
788 default: // to eliminate gcc warning
791 return myCurve->DN(U, N);
794 //=======================================================================
795 //function : Resolution
797 //=======================================================================
799 Standard_Real GeomAdaptor_Curve::Resolution(const Standard_Real R3D) const
801 switch ( myTypeCurve) {
804 case GeomAbs_Circle: {
805 Standard_Real R = Handle(Geom_Circle)::DownCast (myCurve)->Circ().Radius();
807 return 2*ASin(R3D/(2*R));
811 case GeomAbs_Ellipse: {
812 return R3D / Handle(Geom_Ellipse)::DownCast (myCurve)->MajorRadius();
814 case GeomAbs_BezierCurve: {
816 Handle(Geom_BezierCurve)::DownCast (myCurve)->Resolution(R3D,res);
819 case GeomAbs_BSplineCurve: {
821 myBSplineCurve->Resolution(R3D,res);
825 return Precision::Parametric(R3D);
831 // -- The following methods must be called when GetType returned
832 // -- the corresponding type.
835 //=======================================================================
838 //=======================================================================
840 gp_Lin GeomAdaptor_Curve::Line() const
842 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
843 return Handle(Geom_Line)::DownCast (myCurve)->Lin();
846 //=======================================================================
849 //=======================================================================
851 gp_Circ GeomAdaptor_Curve::Circle() const
853 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
854 return Handle(Geom_Circle)::DownCast (myCurve)->Circ();
857 //=======================================================================
860 //=======================================================================
862 gp_Elips GeomAdaptor_Curve::Ellipse() const
864 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Ellipse, "");
865 return Handle(Geom_Ellipse)::DownCast (myCurve)->Elips();
868 //=======================================================================
869 //function : Hyperbola
871 //=======================================================================
873 gp_Hypr GeomAdaptor_Curve::Hyperbola() const
875 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
876 return Handle(Geom_Hyperbola)::DownCast (myCurve)->Hypr();
879 //=======================================================================
880 //function : Parabola
882 //=======================================================================
884 gp_Parab GeomAdaptor_Curve::Parabola() const
886 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
887 return Handle(Geom_Parabola)::DownCast (myCurve)->Parab();
890 //=======================================================================
893 //=======================================================================
895 Standard_Integer GeomAdaptor_Curve::Degree() const
897 if (myTypeCurve == GeomAbs_BezierCurve)
898 return Handle(Geom_BezierCurve)::DownCast (myCurve)->Degree();
899 else if (myTypeCurve == GeomAbs_BSplineCurve)
900 return myBSplineCurve->Degree();
902 Standard_NoSuchObject::Raise();
907 //=======================================================================
908 //function : IsRational
910 //=======================================================================
912 Standard_Boolean GeomAdaptor_Curve::IsRational() const {
913 switch( myTypeCurve) {
914 case GeomAbs_BSplineCurve:
915 return myBSplineCurve->IsRational();
916 case GeomAbs_BezierCurve:
917 return Handle(Geom_BezierCurve)::DownCast (myCurve)->IsRational();
919 return Standard_False;
923 //=======================================================================
926 //=======================================================================
928 Standard_Integer GeomAdaptor_Curve::NbPoles() const
930 if (myTypeCurve == GeomAbs_BezierCurve)
931 return Handle(Geom_BezierCurve)::DownCast (myCurve)->NbPoles();
932 else if (myTypeCurve == GeomAbs_BSplineCurve)
933 return myBSplineCurve->NbPoles();
935 Standard_NoSuchObject::Raise();
940 //=======================================================================
943 //=======================================================================
945 Standard_Integer GeomAdaptor_Curve::NbKnots() const
947 if ( myTypeCurve != GeomAbs_BSplineCurve)
948 Standard_NoSuchObject::Raise("GeomAdaptor_Curve::NbKnots");
949 return myBSplineCurve->NbKnots();
952 //=======================================================================
955 //=======================================================================
957 Handle(Geom_BezierCurve) GeomAdaptor_Curve::Bezier() const
959 if ( myTypeCurve != GeomAbs_BezierCurve)
960 Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Bezier");
961 return Handle(Geom_BezierCurve)::DownCast (myCurve);
964 //=======================================================================
967 //=======================================================================
969 Handle(Geom_BSplineCurve) GeomAdaptor_Curve::BSpline() const
971 if ( myTypeCurve != GeomAbs_BSplineCurve)
972 Standard_NoSuchObject::Raise("GeomAdaptor_Curve::BSpline");
974 return myBSplineCurve;