0028724: Extrema between circle and plane cannot be found
[occt.git] / src / GeomAdaptor / GeomAdaptor_Curve.cxx
CommitLineData
b311480e 1// Created on: 1993-04-29
2// Created by: Bruno DUMORTIER
3// Copyright (c) 1993-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
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
20
21#define No_Standard_RangeError
22#define No_Standard_OutOfRange
23
7fd59977 24
7fd59977 25#include <Adaptor3d_HCurve.hxx>
26#include <BSplCLib.hxx>
94f71cad 27#include <BSplCLib_Cache.hxx>
7fd59977 28#include <Geom_BezierCurve.hxx>
29#include <Geom_BSplineCurve.hxx>
42cf5bc1 30#include <Geom_Circle.hxx>
31#include <Geom_Curve.hxx>
7fd59977 32#include <Geom_Ellipse.hxx>
7fd59977 33#include <Geom_Hyperbola.hxx>
42cf5bc1 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>
d660a72a 42#include <GeomEvaluator_OffsetCurve.hxx>
42cf5bc1 43#include <gp_Circ.hxx>
44#include <gp_Elips.hxx>
45#include <gp_Hypr.hxx>
46#include <gp_Lin.hxx>
47#include <gp_Parab.hxx>
48#include <gp_Pnt.hxx>
49#include <gp_Vec.hxx>
50#include <Precision.hxx>
51#include <Standard_ConstructionError.hxx>
52#include <Standard_DomainError.hxx>
7fd59977 53#include <Standard_NoSuchObject.hxx>
54#include <Standard_NotImplemented.hxx>
42cf5bc1 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>
7fd59977 61
42cf5bc1 62//#include <GeomConvert_BSplineCurveKnotSplitting.hxx>
c8b5b3d8 63static const Standard_Real PosTol = Precision::PConfusion() / 2;
7fd59977 64
94f71cad 65
7fd59977 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)
71// with d = degree,
72// m = max multiplicity of the Knots between U1 and U2
73//=======================================================================
74
75GeomAbs_Shape GeomAdaptor_Curve::LocalContinuity(const Standard_Real U1,
76 const Standard_Real U2)
77 const
78{
79 Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
3b25c0e8 80 Standard_Integer Nb = myBSplineCurve->NbKnots();
7fd59977 81 Standard_Integer Index1 = 0;
82 Standard_Integer Index2 = 0;
83 Standard_Real newFirst, newLast;
e1c1b6b9 84 const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
85 const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
3b25c0e8 86 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U1,myBSplineCurve->IsPeriodic(),
7fd59977 87 1,Nb,Index1,newFirst);
3b25c0e8 88 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U2,myBSplineCurve->IsPeriodic(),
7fd59977 89 1,Nb,Index2,newLast);
90 if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) {
91 if (Index1 < Nb) Index1++;
92 }
93 if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
94 Index2--;
95 Standard_Integer MultMax;
96 // attention aux courbes peridiques.
3b25c0e8 97 if ( (myBSplineCurve->IsPeriodic()) && (Index1 == Nb) )
7fd59977 98 Index1 = 1;
99
100 if ( Index2 - Index1 <= 0) {
101 MultMax = 100; // CN entre 2 Noeuds consecutifs
102 }
103 else {
104 MultMax = TM(Index1+1);
105 for(Standard_Integer i = Index1+1;i<=Index2;i++) {
106 if ( TM(i)>MultMax) MultMax=TM(i);
107 }
3b25c0e8 108 MultMax = myBSplineCurve->Degree() - MultMax;
7fd59977 109 }
110 if ( MultMax <= 0) {
111 return GeomAbs_C0;
112 }
113 else if ( MultMax == 1) {
114 return GeomAbs_C1;
115 }
116 else if ( MultMax == 2) {
117 return GeomAbs_C2;
118 }
119 else if ( MultMax == 3) {
120 return GeomAbs_C3;
121 }
122 else {
123 return GeomAbs_CN;
124 }
125}
126
127
128//=======================================================================
129//function : Load
130//purpose :
131//=======================================================================
132
041bfce9 133void GeomAdaptor_Curve::load(const Handle(Geom_Curve)& C,
7fd59977 134 const Standard_Real UFirst,
135 const Standard_Real ULast)
136{
7fd59977 137 myFirst = UFirst;
138 myLast = ULast;
81093856 139 myCurveCache.Nullify();
7fd59977 140
141 if ( myCurve != C) {
142 myCurve = C;
3b25c0e8
IC
143 myNestedEvaluator.Nullify();
144 myBSplineCurve.Nullify();
f4dee9bb 145
7fd59977 146 const Handle(Standard_Type)& TheType = C->DynamicType();
147 if ( TheType == STANDARD_TYPE(Geom_TrimmedCurve)) {
c5f3a425 148 Load(Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve(),UFirst,ULast);
7fd59977 149 }
150 else if ( TheType == STANDARD_TYPE(Geom_Circle)) {
151 myTypeCurve = GeomAbs_Circle;
152 }
153 else if ( TheType ==STANDARD_TYPE(Geom_Line)) {
154 myTypeCurve = GeomAbs_Line;
155 }
156 else if ( TheType == STANDARD_TYPE(Geom_Ellipse)) {
157 myTypeCurve = GeomAbs_Ellipse;
158 }
159 else if ( TheType == STANDARD_TYPE(Geom_Parabola)) {
160 myTypeCurve = GeomAbs_Parabola;
161 }
162 else if ( TheType == STANDARD_TYPE(Geom_Hyperbola)) {
163 myTypeCurve = GeomAbs_Hyperbola;
164 }
165 else if ( TheType == STANDARD_TYPE(Geom_BezierCurve)) {
166 myTypeCurve = GeomAbs_BezierCurve;
167 }
168 else if ( TheType == STANDARD_TYPE(Geom_BSplineCurve)) {
169 myTypeCurve = GeomAbs_BSplineCurve;
81093856 170 myBSplineCurve = Handle(Geom_BSplineCurve)::DownCast(myCurve);
94f71cad 171 }
172 else if ( TheType == STANDARD_TYPE(Geom_OffsetCurve)) {
1aec3320 173 myTypeCurve = GeomAbs_OffsetCurve;
d660a72a 174 Handle(Geom_OffsetCurve) anOffsetCurve = Handle(Geom_OffsetCurve)::DownCast(myCurve);
94f71cad 175 // Create nested adaptor for base curve
d660a72a 176 Handle(Geom_Curve) aBaseCurve = anOffsetCurve->BasisCurve();
177 Handle(GeomAdaptor_HCurve) aBaseAdaptor = new GeomAdaptor_HCurve(aBaseCurve);
178 myNestedEvaluator = new GeomEvaluator_OffsetCurve(
179 aBaseAdaptor, anOffsetCurve->Offset(), anOffsetCurve->Direction());
7fd59977 180 }
181 else {
182 myTypeCurve = GeomAbs_OtherCurve;
183 }
184 }
f3a1c0cb 185}
7fd59977 186
187// --
188// -- Global methods - Apply to the whole curve.
189// --
190
191//=======================================================================
192//function : Continuity
193//purpose :
194//=======================================================================
195
196GeomAbs_Shape GeomAdaptor_Curve::Continuity() const
197{
198 if (myTypeCurve == GeomAbs_BSplineCurve)
199 return LocalContinuity(myFirst, myLast);
200
1aec3320 201 if (myTypeCurve == GeomAbs_OffsetCurve)
7fd59977 202 {
203 const GeomAbs_Shape S =
c5f3a425 204 Handle(Geom_OffsetCurve)::DownCast (myCurve)->GetBasisCurveContinuity();
7fd59977 205 switch(S)
206 {
207 case GeomAbs_CN: return GeomAbs_CN;
208 case GeomAbs_C3: return GeomAbs_C2;
209 case GeomAbs_C2: return GeomAbs_C1;
3d58dc49 210 case GeomAbs_C1: return GeomAbs_C0;
211 case GeomAbs_G1: return GeomAbs_G1;
212 case GeomAbs_G2: return GeomAbs_G2;
7fd59977 213 default:
9775fa61 214 throw Standard_NoSuchObject("GeomAdaptor_Curve::Continuity");
7fd59977 215 }
216 }
217 else if (myTypeCurve == GeomAbs_OtherCurve) {
9775fa61 218 throw Standard_NoSuchObject("GeomAdaptor_Curve::Contunuity");
7fd59977 219 }
220
221 return GeomAbs_CN;
222}
223
224//=======================================================================
225//function : NbIntervals
226//purpose :
227//=======================================================================
228
31b1749c 229Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
7fd59977 230{
231 Standard_Integer myNbIntervals = 1;
232 Standard_Integer NbSplit;
233 if (myTypeCurve == GeomAbs_BSplineCurve) {
3b25c0e8
IC
234 Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
235 Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
7fd59977 236 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
237 if ( S > Continuity()) {
238 Standard_Integer Cont;
239 switch ( S) {
240 case GeomAbs_G1:
241 case GeomAbs_G2:
9775fa61 242 throw Standard_DomainError("GeomAdaptor_Curve::NbIntervals");
7fd59977 243 break;
244 case GeomAbs_C0:
245 myNbIntervals = 1;
246 break;
247 case GeomAbs_C1:
248 case GeomAbs_C2:
249 case GeomAbs_C3:
250 case GeomAbs_CN:
251 {
252 if ( S == GeomAbs_C1) Cont = 1;
253 else if ( S == GeomAbs_C2) Cont = 2;
254 else if ( S == GeomAbs_C3) Cont = 3;
3b25c0e8
IC
255 else Cont = myBSplineCurve->Degree();
256 Standard_Integer Degree = myBSplineCurve->Degree();
257 Standard_Integer NbKnots = myBSplineCurve->NbKnots();
7fd59977 258 TColStd_Array1OfInteger Mults (1, NbKnots);
3b25c0e8 259 myBSplineCurve->Multiplicities (Mults);
7fd59977 260 NbSplit = 1;
261 Standard_Integer Index = FirstIndex;
262 Inter (NbSplit) = Index;
263 Index++;
264 NbSplit++;
265 while (Index < LastIndex)
266 {
267 if (Degree - Mults (Index) < Cont)
268 {
269 Inter (NbSplit) = Index;
270 NbSplit++;
271 }
272 Index++;
273 }
274 Inter (NbSplit) = Index;
275
276 Standard_Integer NbInt = NbSplit-1;
277
3b25c0e8 278 Standard_Integer Nb = myBSplineCurve->NbKnots();
7fd59977 279 Standard_Integer Index1 = 0;
280 Standard_Integer Index2 = 0;
281 Standard_Real newFirst, newLast;
e1c1b6b9 282 const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
283 const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
3b25c0e8
IC
284 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
285 myBSplineCurve->IsPeriodic(),
7fd59977 286 1,Nb,Index1,newFirst);
3b25c0e8
IC
287 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
288 myBSplineCurve->IsPeriodic(),
7fd59977 289 1,Nb,Index2,newLast);
290
291 // On decale eventuellement les indices
292 // On utilise une "petite" tolerance, la resolution ne doit
293 // servir que pour les tres longue courbes....(PRO9248)
294 Standard_Real Eps = Min(Resolution(Precision::Confusion()),
295 Precision::PConfusion());
296 if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
297 if ( newLast-TK(Index2)> Eps) Index2++;
298
299 myNbIntervals = 1;
300 for ( Standard_Integer i=1; i<=NbInt; i++)
301 if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
302 }
303 break;
304 }
305 }
306 }
307
1aec3320 308 else if (myTypeCurve == GeomAbs_OffsetCurve) {
7fd59977 309 GeomAbs_Shape BaseS=GeomAbs_C0;
310 switch(S){
311 case GeomAbs_G1:
312 case GeomAbs_G2:
9775fa61 313 throw Standard_DomainError("GeomAdaptor_Curve::NbIntervals");
7fd59977 314 break;
315 case GeomAbs_C0: BaseS = GeomAbs_C1; break;
316 case GeomAbs_C1: BaseS = GeomAbs_C2; break;
317 case GeomAbs_C2: BaseS = GeomAbs_C3; break;
318 default: BaseS = GeomAbs_CN;
319 }
320 GeomAdaptor_Curve C
c5f3a425 321 (Handle(Geom_OffsetCurve)::DownCast (myCurve)->BasisCurve());
7fd59977 322 // akm 05/04/02 (OCC278) If our curve is trimmed we must recalculate
323 // the number of intervals obtained from the basis to
324 // vvv reflect parameter bounds
325 Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
326 if (iNbBasisInt>1)
327 {
328 TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
329 C.Intervals(rdfInter,BaseS);
330 for (iInt=1; iInt<=iNbBasisInt; iInt++)
331 if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
332 myNbIntervals++;
333 }
334 // akm 05/04/02 ^^^
335 }
336 return myNbIntervals;
337}
338
339//=======================================================================
340//function : Intervals
341//purpose :
342//=======================================================================
343
344void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
31b1749c 345 const GeomAbs_Shape S ) const
7fd59977 346{
347 Standard_Integer myNbIntervals = 1;
348 Standard_Integer NbSplit;
f34eec8f 349 Standard_Real FirstParam = myFirst, LastParam = myLast;
7fd59977 350
351 if (myTypeCurve == GeomAbs_BSplineCurve)
352 {
3b25c0e8
IC
353 Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
354 Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
7fd59977 355 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
356
357 if ( S > Continuity()) {
358 Standard_Integer Cont;
359 switch ( S) {
360 case GeomAbs_G1:
361 case GeomAbs_G2:
9775fa61 362 throw Standard_DomainError("Geom2dAdaptor_Curve::NbIntervals");
7fd59977 363 break;
364 case GeomAbs_C0:
365 myNbIntervals = 1;
366 break;
367 case GeomAbs_C1:
368 case GeomAbs_C2:
369 case GeomAbs_C3:
370 case GeomAbs_CN:
371 {
372 if ( S == GeomAbs_C1) Cont = 1;
373 else if ( S == GeomAbs_C2) Cont = 2;
374 else if ( S == GeomAbs_C3) Cont = 3;
3b25c0e8
IC
375 else Cont = myBSplineCurve->Degree();
376 Standard_Integer Degree = myBSplineCurve->Degree();
377 Standard_Integer NbKnots = myBSplineCurve->NbKnots();
7fd59977 378 TColStd_Array1OfInteger Mults (1, NbKnots);
3b25c0e8 379 myBSplineCurve->Multiplicities (Mults);
7fd59977 380 NbSplit = 1;
381 Standard_Integer Index = FirstIndex;
382 Inter (NbSplit) = Index;
383 Index++;
384 NbSplit++;
385 while (Index < LastIndex)
386 {
387 if (Degree - Mults (Index) < Cont)
388 {
389 Inter (NbSplit) = Index;
390 NbSplit++;
391 }
392 Index++;
393 }
394 Inter (NbSplit) = Index;
395 Standard_Integer NbInt = NbSplit-1;
396 // GeomConvert_BSplineCurveKnotSplitting Convector(myBspl, Cont);
397 // Standard_Integer NbInt = Convector.NbSplits()-1;
398 // TColStd_Array1OfInteger Inter(1,NbInt+1);
399 // Convector.Splitting( Inter);
400
3b25c0e8 401 Standard_Integer Nb = myBSplineCurve->NbKnots();
7fd59977 402 Standard_Integer Index1 = 0;
403 Standard_Integer Index2 = 0;
404 Standard_Real newFirst, newLast;
e1c1b6b9 405 const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
406 const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
3b25c0e8
IC
407 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
408 myBSplineCurve->IsPeriodic(),
7fd59977 409 1,Nb,Index1,newFirst);
3b25c0e8
IC
410 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
411 myBSplineCurve->IsPeriodic(),
7fd59977 412 1,Nb,Index2,newLast);
f34eec8f 413 FirstParam = newFirst;
414 LastParam = newLast;
7fd59977 415 // On decale eventuellement les indices
416 // On utilise une "petite" tolerance, la resolution ne doit
417 // servir que pour les tres longue courbes....(PRO9248)
418 Standard_Real Eps = Min(Resolution(Precision::Confusion()),
419 Precision::PConfusion());
420 if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
421 if ( newLast-TK(Index2)> Eps) Index2++;
422
423 Inter( 1) = Index1;
424 myNbIntervals = 1;
425 for ( Standard_Integer i=1; i<=NbInt; i++) {
426 if (Inter(i) > Index1 && Inter(i)<Index2 ) {
427 myNbIntervals++;
428 Inter(myNbIntervals) = Inter(i);
429 }
430 }
431 Inter(myNbIntervals+1) = Index2;
432
433 for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
434 T(I) = TK(Inter(I));
435 }
436 }
437 break;
438 }
439 }
440 }
441
1aec3320 442 else if (myTypeCurve == GeomAbs_OffsetCurve){
7fd59977 443 GeomAbs_Shape BaseS=GeomAbs_C0;
444 switch(S){
445 case GeomAbs_G1:
446 case GeomAbs_G2:
9775fa61 447 throw Standard_DomainError("GeomAdaptor_Curve::NbIntervals");
7fd59977 448 break;
449 case GeomAbs_C0: BaseS = GeomAbs_C1; break;
450 case GeomAbs_C1: BaseS = GeomAbs_C2; break;
451 case GeomAbs_C2: BaseS = GeomAbs_C3; break;
452 default: BaseS = GeomAbs_CN;
453 }
454 GeomAdaptor_Curve C
c5f3a425 455 (Handle(Geom_OffsetCurve)::DownCast (myCurve)->BasisCurve());
7fd59977 456 // akm 05/04/02 (OCC278) If our curve is trimmed we must recalculate
457 // the array of intervals obtained from the basis to
458 // vvv reflect parameter bounds
459 Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
460 if (iNbBasisInt>1)
461 {
462 TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
463 C.Intervals(rdfInter,BaseS);
464 for (iInt=1; iInt<=iNbBasisInt; iInt++)
465 if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
466 T(++myNbIntervals)=rdfInter(iInt);
467 }
468 // old - myNbIntervals = C.NbIntervals(BaseS);
469 // old - C.Intervals(T, BaseS);
470 // akm 05/04/02 ^^^
471 }
472
f34eec8f 473 T( T.Lower() ) = FirstParam;
474 T( T.Lower() + myNbIntervals ) = LastParam;
7fd59977 475}
476
477//=======================================================================
478//function : Trim
479//purpose :
480//=======================================================================
481
482Handle(Adaptor3d_HCurve) GeomAdaptor_Curve::Trim(const Standard_Real First,
483 const Standard_Real Last,
484 const Standard_Real /*Tol*/) const
485{
486 return Handle(GeomAdaptor_HCurve)(new GeomAdaptor_HCurve(myCurve,First,Last));
487}
488
489
490//=======================================================================
491//function : IsClosed
492//purpose :
493//=======================================================================
494
495Standard_Boolean GeomAdaptor_Curve::IsClosed() const
496{
497 if (!Precision::IsPositiveInfinite(myLast) &&
498 !Precision::IsNegativeInfinite(myFirst))
499 {
500 const gp_Pnt Pd = Value(myFirst);
501 const gp_Pnt Pf = Value(myLast);
502 return (Pd.Distance(Pf) <= Precision::Confusion());
503 }
504 return Standard_False;
505}
506
507//=======================================================================
508//function : IsPeriodic
509//purpose :
510//=======================================================================
511
512Standard_Boolean GeomAdaptor_Curve::IsPeriodic() const
513{
ff3f0387 514 return myCurve->IsPeriodic();
7fd59977 515}
516
517//=======================================================================
518//function : Period
519//purpose :
520//=======================================================================
521
522Standard_Real GeomAdaptor_Curve::Period() const
523{
524 return myCurve->LastParameter() - myCurve->FirstParameter();
525}
526
94f71cad 527//=======================================================================
528//function : RebuildCache
529//purpose :
530//=======================================================================
531void GeomAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
532{
c8b5b3d8 533 if (myTypeCurve == GeomAbs_BezierCurve)
534 {
81093856 535 // Create cache for Bezier
c8b5b3d8 536 Handle(Geom_BezierCurve) aBezier = Handle(Geom_BezierCurve)::DownCast(myCurve);
537 Standard_Integer aDeg = aBezier->Degree();
538 TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
81093856 539 if (myCurveCache.IsNull())
540 myCurveCache = new BSplCLib_Cache(aDeg, aBezier->IsPeriodic(), aFlatKnots,
c8b5b3d8 541 aBezier->Poles(), aBezier->Weights());
81093856 542 myCurveCache->BuildCache(theParameter, aDeg, aBezier->IsPeriodic(), aFlatKnots,
f4dee9bb 543 aBezier->Poles(), aBezier->Weights());
544}
c8b5b3d8 545 else if (myTypeCurve == GeomAbs_BSplineCurve)
f4dee9bb 546{
81093856 547 // Create cache for B-spline
548 if (myCurveCache.IsNull())
549 myCurveCache = new BSplCLib_Cache(myBSplineCurve->Degree(), myBSplineCurve->IsPeriodic(),
550 myBSplineCurve->KnotSequence(), myBSplineCurve->Poles(), myBSplineCurve->Weights());
3b25c0e8
IC
551 myCurveCache->BuildCache(theParameter, myBSplineCurve->Degree(),
552 myBSplineCurve->IsPeriodic(), myBSplineCurve->KnotSequence(),
553 myBSplineCurve->Poles(), myBSplineCurve->Weights());
f4dee9bb 554}
94f71cad 555}
556
7fd59977 557//=======================================================================
d660a72a 558//function : IsBoundary
94f71cad 559//purpose :
560//=======================================================================
d660a72a 561Standard_Boolean GeomAdaptor_Curve::IsBoundary(const Standard_Real theU,
562 Standard_Integer& theSpanStart,
563 Standard_Integer& theSpanFinish) const
94f71cad 564{
3b25c0e8 565 if (!myBSplineCurve.IsNull() && (theU == myFirst || theU == myLast))
94f71cad 566 {
d660a72a 567 if (theU == myFirst)
568 {
3b25c0e8 569 myBSplineCurve->LocateU(myFirst, PosTol, theSpanStart, theSpanFinish);
d660a72a 570 if (theSpanStart < 1)
571 theSpanStart = 1;
572 if (theSpanStart >= theSpanFinish)
573 theSpanFinish = theSpanStart + 1;
7fd59977 574 }
d660a72a 575 else if (theU == myLast)
576 {
3b25c0e8
IC
577 myBSplineCurve->LocateU(myLast, PosTol, theSpanStart, theSpanFinish);
578 if (theSpanFinish > myBSplineCurve->NbKnots())
579 theSpanFinish = myBSplineCurve->NbKnots();
d660a72a 580 if (theSpanStart >= theSpanFinish)
581 theSpanStart = theSpanFinish - 1;
7fd59977 582 }
d660a72a 583 return Standard_True;
94f71cad 584 }
d660a72a 585 return Standard_False;
f4dee9bb 586 }
94f71cad 587
588//=======================================================================
d660a72a 589//function : Value
94f71cad 590//purpose :
591//=======================================================================
d660a72a 592
593gp_Pnt GeomAdaptor_Curve::Value(const Standard_Real U) const
94f71cad 594{
d660a72a 595 gp_Pnt aValue;
596 D0(U, aValue);
597 return aValue;
7fd59977 598}
599
600//=======================================================================
601//function : D0
602//purpose :
603//=======================================================================
604
605void GeomAdaptor_Curve::D0(const Standard_Real U, gp_Pnt& P) const
606{
d660a72a 607 switch (myTypeCurve)
f4dee9bb 608{
d660a72a 609 case GeomAbs_BezierCurve:
610 case GeomAbs_BSplineCurve:
611 {
612 Standard_Integer aStart = 0, aFinish = 0;
613 if (IsBoundary(U, aStart, aFinish))
614 {
3b25c0e8 615 myBSplineCurve->LocalD0(U, aStart, aFinish, P);
7fd59977 616 }
81093856 617 else
f4dee9bb 618 {
81093856 619 // use cached data
620 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
d660a72a 621 RebuildCache(U);
622 myCurveCache->D0(U, P);
94f71cad 623 }
f4dee9bb 624 break;
625}
94f71cad 626
d660a72a 627 case GeomAbs_OffsetCurve:
628 myNestedEvaluator->D0(U, P);
629 break;
630
631 default:
632 myCurve->D0(U, P);
f4dee9bb 633}
7fd59977 634}
635
636//=======================================================================
637//function : D1
638//purpose :
639//=======================================================================
640
641void GeomAdaptor_Curve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V) const
642{
d660a72a 643 switch (myTypeCurve)
f4dee9bb 644{
d660a72a 645 case GeomAbs_BezierCurve:
646 case GeomAbs_BSplineCurve:
647 {
648 Standard_Integer aStart = 0, aFinish = 0;
649 if (IsBoundary(U, aStart, aFinish))
650 {
3b25c0e8 651 myBSplineCurve->LocalD1(U, aStart, aFinish, P, V);
7fd59977 652 }
81093856 653 else
f4dee9bb 654 {
81093856 655 // use cached data
656 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
d660a72a 657 RebuildCache(U);
658 myCurveCache->D1(U, P, V);
94f71cad 659 }
f4dee9bb 660 break;
661}
94f71cad 662
d660a72a 663 case GeomAbs_OffsetCurve:
664 myNestedEvaluator->D1(U, P, V);
665 break;
94f71cad 666
d660a72a 667 default:
668 myCurve->D1(U, P, V);
f4dee9bb 669}
94f71cad 670}
671
7fd59977 672//=======================================================================
673//function : D2
674//purpose :
675//=======================================================================
676
677void GeomAdaptor_Curve::D2(const Standard_Real U,
94f71cad 678 gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) const
679{
d660a72a 680 switch (myTypeCurve)
f4dee9bb 681{
d660a72a 682 case GeomAbs_BezierCurve:
683 case GeomAbs_BSplineCurve:
684 {
685 Standard_Integer aStart = 0, aFinish = 0;
686 if (IsBoundary(U, aStart, aFinish))
687 {
3b25c0e8 688 myBSplineCurve->LocalD2(U, aStart, aFinish, P, V1, V2);
7fd59977 689 }
81093856 690 else
f4dee9bb 691 {
81093856 692 // use cached data
693 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
d660a72a 694 RebuildCache(U);
695 myCurveCache->D2(U, P, V1, V2);
7fd59977 696 }
f4dee9bb 697 break;
698}
94f71cad 699
d660a72a 700 case GeomAbs_OffsetCurve:
701 myNestedEvaluator->D2(U, P, V1, V2);
702 break;
94f71cad 703
d660a72a 704 default:
705 myCurve->D2(U, P, V1, V2);
f4dee9bb 706}
7fd59977 707}
708
709//=======================================================================
710//function : D3
711//purpose :
712//=======================================================================
713
714void GeomAdaptor_Curve::D3(const Standard_Real U,
94f71cad 715 gp_Pnt& P, gp_Vec& V1,
716 gp_Vec& V2, gp_Vec& V3) const
7fd59977 717{
d660a72a 718 switch (myTypeCurve)
f4dee9bb 719{
d660a72a 720 case GeomAbs_BezierCurve:
721 case GeomAbs_BSplineCurve:
722 {
723 Standard_Integer aStart = 0, aFinish = 0;
724 if (IsBoundary(U, aStart, aFinish))
725 {
3b25c0e8 726 myBSplineCurve->LocalD3(U, aStart, aFinish, P, V1, V2, V3);
7fd59977 727 }
81093856 728 else
f4dee9bb 729 {
81093856 730 // use cached data
731 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
d660a72a 732 RebuildCache(U);
733 myCurveCache->D3(U, P, V1, V2, V3);
7fd59977 734 }
f4dee9bb 735 break;
736}
94f71cad 737
d660a72a 738 case GeomAbs_OffsetCurve:
739 myNestedEvaluator->D3(U, P, V1, V2, V3);
740 break;
741
742 default:
743 myCurve->D3(U, P, V1, V2, V3);
f4dee9bb 744}
7fd59977 745}
746
747//=======================================================================
748//function : DN
749//purpose :
750//=======================================================================
751
752gp_Vec GeomAdaptor_Curve::DN(const Standard_Real U,
94f71cad 753 const Standard_Integer N) const
754{
d660a72a 755 switch (myTypeCurve)
f4dee9bb 756{
d660a72a 757 case GeomAbs_BezierCurve:
758 case GeomAbs_BSplineCurve:
759 {
760 Standard_Integer aStart = 0, aFinish = 0;
761 if (IsBoundary(U, aStart, aFinish))
762 {
3b25c0e8 763 return myBSplineCurve->LocalDN(U, aStart, aFinish, N);
7fd59977 764 }
d660a72a 765 else
f4dee9bb 766 return myCurve->DN( U, N);
d660a72a 767 break;
f4dee9bb 768}
94f71cad 769
d660a72a 770 case GeomAbs_OffsetCurve:
771 return myNestedEvaluator->DN(U, N);
94f71cad 772 break;
d660a72a 773
774 default: // to eliminate gcc warning
94f71cad 775 break;
94f71cad 776 }
d660a72a 777 return myCurve->DN(U, N);
7fd59977 778}
779
780//=======================================================================
781//function : Resolution
782//purpose :
783//=======================================================================
784
785Standard_Real GeomAdaptor_Curve::Resolution(const Standard_Real R3D) const
786{
787 switch ( myTypeCurve) {
788 case GeomAbs_Line :
789 return R3D;
790 case GeomAbs_Circle: {
c5f3a425 791 Standard_Real R = Handle(Geom_Circle)::DownCast (myCurve)->Circ().Radius();
7fd59977 792 if ( R > R3D/2. )
793 return 2*ASin(R3D/(2*R));
794 else
c6541a0c 795 return 2*M_PI;
7fd59977 796 }
797 case GeomAbs_Ellipse: {
c5f3a425 798 return R3D / Handle(Geom_Ellipse)::DownCast (myCurve)->MajorRadius();
7fd59977 799 }
800 case GeomAbs_BezierCurve: {
801 Standard_Real res;
c5f3a425 802 Handle(Geom_BezierCurve)::DownCast (myCurve)->Resolution(R3D,res);
7fd59977 803 return res;
804 }
805 case GeomAbs_BSplineCurve: {
806 Standard_Real res;
3b25c0e8 807 myBSplineCurve->Resolution(R3D,res);
7fd59977 808 return res;
809 }
810 default:
811 return Precision::Parametric(R3D);
812 }
813}
814
815
816// --
817// -- The following methods must be called when GetType returned
818// -- the corresponding type.
819// --
820
821//=======================================================================
822//function : Line
823//purpose :
824//=======================================================================
825
826gp_Lin GeomAdaptor_Curve::Line() const
827{
2d2b3d53 828 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Line,
829 "GeomAdaptor_Curve::Line() - curve is not a Line");
c5f3a425 830 return Handle(Geom_Line)::DownCast (myCurve)->Lin();
7fd59977 831}
832
833//=======================================================================
834//function : Circle
835//purpose :
836//=======================================================================
837
838gp_Circ GeomAdaptor_Curve::Circle() const
839{
2d2b3d53 840 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Circle,
841 "GeomAdaptor_Curve::Circle() - curve is not a Circle");
c5f3a425 842 return Handle(Geom_Circle)::DownCast (myCurve)->Circ();
7fd59977 843}
844
845//=======================================================================
846//function : Ellipse
847//purpose :
848//=======================================================================
849
850gp_Elips GeomAdaptor_Curve::Ellipse() const
851{
2d2b3d53 852 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Ellipse,
853 "GeomAdaptor_Curve::Ellipse() - curve is not an Ellipse");
c5f3a425 854 return Handle(Geom_Ellipse)::DownCast (myCurve)->Elips();
7fd59977 855}
856
857//=======================================================================
858//function : Hyperbola
859//purpose :
860//=======================================================================
861
862gp_Hypr GeomAdaptor_Curve::Hyperbola() const
863{
2d2b3d53 864 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Hyperbola,
865 "GeomAdaptor_Curve::Hyperbola() - curve is not a Hyperbola");
c5f3a425 866 return Handle(Geom_Hyperbola)::DownCast (myCurve)->Hypr();
7fd59977 867}
868
869//=======================================================================
870//function : Parabola
871//purpose :
872//=======================================================================
873
874gp_Parab GeomAdaptor_Curve::Parabola() const
875{
2d2b3d53 876 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Parabola,
877 "GeomAdaptor_Curve::Parabola() - curve is not a Parabola");
c5f3a425 878 return Handle(Geom_Parabola)::DownCast (myCurve)->Parab();
7fd59977 879}
880
881//=======================================================================
882//function : Degree
883//purpose :
884//=======================================================================
885
886Standard_Integer GeomAdaptor_Curve::Degree() const
887{
888 if (myTypeCurve == GeomAbs_BezierCurve)
c5f3a425 889 return Handle(Geom_BezierCurve)::DownCast (myCurve)->Degree();
7fd59977 890 else if (myTypeCurve == GeomAbs_BSplineCurve)
3b25c0e8 891 return myBSplineCurve->Degree();
7fd59977 892 else
9775fa61 893 throw Standard_NoSuchObject();
7fd59977 894}
895
896//=======================================================================
897//function : IsRational
898//purpose :
899//=======================================================================
900
901Standard_Boolean GeomAdaptor_Curve::IsRational() const {
902 switch( myTypeCurve) {
903 case GeomAbs_BSplineCurve:
3b25c0e8 904 return myBSplineCurve->IsRational();
7fd59977 905 case GeomAbs_BezierCurve:
c5f3a425 906 return Handle(Geom_BezierCurve)::DownCast (myCurve)->IsRational();
7fd59977 907 default:
908 return Standard_False;
909 }
910}
911
912//=======================================================================
913//function : NbPoles
914//purpose :
915//=======================================================================
916
917Standard_Integer GeomAdaptor_Curve::NbPoles() const
918{
919 if (myTypeCurve == GeomAbs_BezierCurve)
c5f3a425 920 return Handle(Geom_BezierCurve)::DownCast (myCurve)->NbPoles();
7fd59977 921 else if (myTypeCurve == GeomAbs_BSplineCurve)
3b25c0e8 922 return myBSplineCurve->NbPoles();
7fd59977 923 else
9775fa61 924 throw Standard_NoSuchObject();
7fd59977 925}
926
927//=======================================================================
928//function : NbKnots
929//purpose :
930//=======================================================================
931
932Standard_Integer GeomAdaptor_Curve::NbKnots() const
933{
934 if ( myTypeCurve != GeomAbs_BSplineCurve)
9775fa61 935 throw Standard_NoSuchObject("GeomAdaptor_Curve::NbKnots");
3b25c0e8 936 return myBSplineCurve->NbKnots();
7fd59977 937}
938
939//=======================================================================
940//function : Bezier
941//purpose :
942//=======================================================================
943
944Handle(Geom_BezierCurve) GeomAdaptor_Curve::Bezier() const
945{
946 if ( myTypeCurve != GeomAbs_BezierCurve)
9775fa61 947 throw Standard_NoSuchObject("GeomAdaptor_Curve::Bezier");
c5f3a425 948 return Handle(Geom_BezierCurve)::DownCast (myCurve);
7fd59977 949}
950
951//=======================================================================
952//function : BSpline
953//purpose :
954//=======================================================================
955
956Handle(Geom_BSplineCurve) GeomAdaptor_Curve::BSpline() const
957{
958 if ( myTypeCurve != GeomAbs_BSplineCurve)
9775fa61 959 throw Standard_NoSuchObject("GeomAdaptor_Curve::BSpline");
7fd59977 960
3b25c0e8 961 return myBSplineCurve;
7fd59977 962}
f4dee9bb 963
964//=======================================================================
965//function : BasisCurve
966//purpose :
967//=======================================================================
968
969Handle(Geom_OffsetCurve) GeomAdaptor_Curve::OffsetCurve() const
970{
971 if ( myTypeCurve != GeomAbs_OffsetCurve)
9775fa61 972 throw Standard_NoSuchObject("GeomAdaptor_Curve::OffsetCurve");
f4dee9bb 973 return Handle(Geom_OffsetCurve)::DownCast(myCurve);
974}