0028724: Extrema between circle and plane cannot be found
[occt.git] / src / Geom2dAdaptor / Geom2dAdaptor_Curve.cxx
CommitLineData
b311480e 1// Created on: 1993-06-04
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.
b311480e 16
7fd59977 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
20
21#define No_Standard_RangeError
22#define No_Standard_OutOfRange
23
42cf5bc1 24
7fd59977 25#include <Adaptor2d_HCurve2d.hxx>
26#include <BSplCLib.hxx>
94f71cad 27#include <BSplCLib_Cache.hxx>
7fd59977 28#include <Geom2d_BezierCurve.hxx>
29#include <Geom2d_BSplineCurve.hxx>
42cf5bc1 30#include <Geom2d_Circle.hxx>
31#include <Geom2d_Curve.hxx>
7fd59977 32#include <Geom2d_Ellipse.hxx>
7fd59977 33#include <Geom2d_Hyperbola.hxx>
42cf5bc1 34#include <Geom2d_Line.hxx>
35#include <Geom2d_OffsetCurve.hxx>
36#include <Geom2d_Parabola.hxx>
37#include <Geom2d_TrimmedCurve.hxx>
94f71cad 38#include <Geom2d_UndefinedDerivative.hxx>
42cf5bc1 39#include <Geom2d_UndefinedValue.hxx>
40#include <Geom2dAdaptor_Curve.hxx>
41#include <Geom2dAdaptor_HCurve.hxx>
d660a72a 42#include <Geom2dEvaluator_OffsetCurve.hxx>
42cf5bc1 43#include <GeomAbs_Shape.hxx>
44#include <gp.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>
7fd59977 55#include <Standard_NoSuchObject.hxx>
56#include <Standard_NotImplemented.hxx>
42cf5bc1 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>
7fd59977 63
42cf5bc1 64//#include <Geom2dConvert_BSplineCurveKnotSplitting.hxx>
c8b5b3d8 65static const Standard_Real PosTol = Precision::PConfusion() / 2;
7fd59977 66
94f71cad 67
7fd59977 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)
73// with d = degree,
74// m = max multiplicity of the Knots between U1 and U2
75//=======================================================================
76
77GeomAbs_Shape Geom2dAdaptor_Curve::LocalContinuity(const Standard_Real U1,
3b25c0e8
IC
78 const Standard_Real U2) const
79{
7fd59977 80 Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
3b25c0e8 81 Standard_Integer Nb = myBSplineCurve->NbKnots();
7fd59977 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);
3b25c0e8
IC
87 myBSplineCurve->Knots(TK);
88 myBSplineCurve->Multiplicities(TM);
89 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U1,myBSplineCurve->IsPeriodic(),
7fd59977 90 1,Nb,Index1,newFirst);
3b25c0e8 91 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U2,myBSplineCurve->IsPeriodic(),
7fd59977 92 1,Nb,Index2,newLast);
93 if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) {
94 if (Index1 < Nb)Index1++;
95 }
96 if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
97 Index2--;
98 Standard_Integer MultMax;
99 // attention aux courbes peridiques.
3b25c0e8 100 if ( myBSplineCurve->IsPeriodic() && Index1 == Nb )
7fd59977 101 Index1 = 1;
102
103 if ( Index2 - Index1 <= 0) {
104 MultMax = 100; // CN entre 2 Noeuds consecutifs
105 }
106 else {
107 MultMax = TM(Index1+1);
108 for(Standard_Integer i = Index1+1;i<=Index2;i++) {
109 if ( TM(i)>MultMax) MultMax=TM(i);
110 }
3b25c0e8 111 MultMax = myBSplineCurve->Degree() - MultMax;
7fd59977 112 }
113 if ( MultMax <= 0) {
114 return GeomAbs_C0;
115 }
116 else if ( MultMax == 1) {
117 return GeomAbs_C1;
118 }
119 else if ( MultMax == 2) {
120 return GeomAbs_C2;
121 }
122 else if ( MultMax == 3) {
123 return GeomAbs_C3;
124 }
125 else {
126 return GeomAbs_CN;
127 }
3b25c0e8 128}
7fd59977 129
130
131//=======================================================================
132//function : Geom2dAdaptor_Curve
133//purpose :
134//=======================================================================
135
136Geom2dAdaptor_Curve::Geom2dAdaptor_Curve()
cbff1e55 137: myTypeCurve(GeomAbs_OtherCurve),
138 myFirst (0.0),
139 myLast (0.0)
7fd59977 140{
141}
142
143//=======================================================================
144//function : Geom2dAdaptor_Curve
145//purpose :
146//=======================================================================
147
cbff1e55 148Geom2dAdaptor_Curve::Geom2dAdaptor_Curve(const Handle(Geom2d_Curve)& theCrv)
149: myTypeCurve(GeomAbs_OtherCurve),
150 myFirst (0.0),
151 myLast (0.0)
041bfce9 152{
cbff1e55 153 Load(theCrv);
7fd59977 154}
155
156//=======================================================================
157//function : Geom2dAdaptor_Curve
158//purpose :
159//=======================================================================
160
cbff1e55 161Geom2dAdaptor_Curve::Geom2dAdaptor_Curve(const Handle(Geom2d_Curve)& theCrv,
162 const Standard_Real theUFirst,
163 const Standard_Real theULast)
164: myTypeCurve(GeomAbs_OtherCurve),
165 myFirst (theUFirst),
166 myLast (theULast)
041bfce9 167{
cbff1e55 168 Load(theCrv, theUFirst, theULast);
7fd59977 169}
170
7fd59977 171
172//=======================================================================
173//function : Load
174//purpose :
175//=======================================================================
176
041bfce9 177void Geom2dAdaptor_Curve::load(const Handle(Geom2d_Curve)& C,
178 const Standard_Real UFirst,
179 const Standard_Real ULast)
180{
7fd59977 181 myFirst = UFirst;
182 myLast = ULast;
81093856 183 myCurveCache.Nullify();
7fd59977 184
185 if ( myCurve != C) {
186 myCurve = C;
3b25c0e8
IC
187 myNestedEvaluator.Nullify();
188 myBSplineCurve.Nullify();
7fd59977 189
190 Handle(Standard_Type) TheType = C->DynamicType();
191 if ( TheType == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
c5f3a425 192 Load(Handle(Geom2d_TrimmedCurve)::DownCast (C)->BasisCurve(),
7fd59977 193 UFirst,ULast);
194 }
195 else if ( TheType == STANDARD_TYPE(Geom2d_Circle)) {
196 myTypeCurve = GeomAbs_Circle;
197 }
198 else if ( TheType ==STANDARD_TYPE(Geom2d_Line)) {
199 myTypeCurve = GeomAbs_Line;
200 }
201 else if ( TheType == STANDARD_TYPE(Geom2d_Ellipse)) {
202 myTypeCurve = GeomAbs_Ellipse;
203 }
204 else if ( TheType == STANDARD_TYPE(Geom2d_Parabola)) {
205 myTypeCurve = GeomAbs_Parabola;
206 }
207 else if ( TheType == STANDARD_TYPE(Geom2d_Hyperbola)) {
208 myTypeCurve = GeomAbs_Hyperbola;
209 }
210 else if ( TheType == STANDARD_TYPE(Geom2d_BezierCurve)) {
211 myTypeCurve = GeomAbs_BezierCurve;
212 }
213 else if ( TheType == STANDARD_TYPE(Geom2d_BSplineCurve)) {
214 myTypeCurve = GeomAbs_BSplineCurve;
81093856 215 myBSplineCurve = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
94f71cad 216 }
217 else if ( TheType == STANDARD_TYPE(Geom2d_OffsetCurve))
218 {
1aec3320 219 myTypeCurve = GeomAbs_OffsetCurve;
d660a72a 220 Handle(Geom2d_OffsetCurve) anOffsetCurve = Handle(Geom2d_OffsetCurve)::DownCast(myCurve);
94f71cad 221 // Create nested adaptor for base curve
d660a72a 222 Handle(Geom2d_Curve) aBaseCurve = anOffsetCurve->BasisCurve();
223 Handle(Geom2dAdaptor_HCurve) aBaseAdaptor = new Geom2dAdaptor_HCurve(aBaseCurve);
224 myNestedEvaluator = new Geom2dEvaluator_OffsetCurve(aBaseAdaptor, anOffsetCurve->Offset());
7fd59977 225 }
226 else {
227 myTypeCurve = GeomAbs_OtherCurve;
228 }
229 }
230}
231
232// --
233// -- Global methods - Apply to the whole curve.
234// --
235
236//=======================================================================
237//function : Continuity
238//purpose :
239//=======================================================================
240
241GeomAbs_Shape Geom2dAdaptor_Curve::Continuity() const
242{
243 if (myTypeCurve == GeomAbs_BSplineCurve) {
244 return LocalContinuity(myFirst, myLast);
245 }
1aec3320 246 else if (myTypeCurve == GeomAbs_OffsetCurve){
7fd59977 247 GeomAbs_Shape S =
c5f3a425 248 Handle(Geom2d_OffsetCurve)::DownCast (myCurve)->GetBasisCurveContinuity();
7fd59977 249 switch(S){
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;
3d58dc49 254 case GeomAbs_G1: return GeomAbs_G1;
255 case GeomAbs_G2: return GeomAbs_G2;
256
7fd59977 257 default:
9775fa61 258 throw Standard_NoSuchObject("Geom2dAdaptor_Curve::Continuity");
7fd59977 259 }
260 }
261
262 else if (myTypeCurve == GeomAbs_OtherCurve) {
9775fa61 263 throw Standard_NoSuchObject("Geom2dAdaptor_Curve::Continuity");
7fd59977 264 }
265 else {
266 return GeomAbs_CN;
267 }
7fd59977 268}
269
270//=======================================================================
271//function : NbIntervals
272//purpose :
273//=======================================================================
274
275Standard_Integer Geom2dAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
276{
277 Standard_Integer myNbIntervals = 1;
278 Standard_Integer NbSplit;
279 if (myTypeCurve == GeomAbs_BSplineCurve) {
3b25c0e8
IC
280 Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
281 Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
7fd59977 282 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
283 if ( S > Continuity()) {
284 Standard_Integer Cont;
285 switch ( S) {
286 case GeomAbs_G1:
287 case GeomAbs_G2:
9775fa61 288 throw Standard_DomainError("Geom2dAdaptor_Curve::NbIntervals");
7fd59977 289 break;
290 case GeomAbs_C0:
291 myNbIntervals = 1;
292 break;
293 case GeomAbs_C1:
294 case GeomAbs_C2:
295 case GeomAbs_C3:
296 case GeomAbs_CN:
297 {
298 if ( S == GeomAbs_C1) Cont = 1;
299 else if ( S == GeomAbs_C2) Cont = 2;
300 else if ( S == GeomAbs_C3) Cont = 3;
3b25c0e8
IC
301 else Cont = myBSplineCurve->Degree();
302 Standard_Integer Degree = myBSplineCurve->Degree();
303 Standard_Integer NbKnots = myBSplineCurve->NbKnots();
7fd59977 304 TColStd_Array1OfInteger Mults (1, NbKnots);
3b25c0e8 305 myBSplineCurve->Multiplicities (Mults);
7fd59977 306 NbSplit = 1;
307 Standard_Integer Index = FirstIndex;
308 Inter (NbSplit) = Index;
309 Index++;
310 NbSplit++;
311 while (Index < LastIndex)
312 {
313 if (Degree - Mults (Index) < Cont)
314 {
315 Inter (NbSplit) = Index;
316 NbSplit++;
317 }
318 Index++;
319 }
320 Inter (NbSplit) = Index;
321
322 Standard_Integer NbInt = NbSplit-1;
323
3b25c0e8 324 Standard_Integer Nb = myBSplineCurve->NbKnots();
7fd59977 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);
3b25c0e8
IC
330 myBSplineCurve->Knots(TK);
331 myBSplineCurve->Multiplicities(TM);
332 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
333 myBSplineCurve->IsPeriodic(),
7fd59977 334 1,Nb,Index1,newFirst);
3b25c0e8
IC
335 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
336 myBSplineCurve->IsPeriodic(),
7fd59977 337 1,Nb,Index2,newLast);
338
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++;
346
347 myNbIntervals = 1;
348 for ( Standard_Integer i=1; i<=NbInt; i++)
349 if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
350 }
351 break;
352 }
353 }
354 }
1aec3320 355 else if (myTypeCurve == GeomAbs_OffsetCurve){
7fd59977 356 GeomAbs_Shape BaseS=GeomAbs_C0;
357 switch(S){
358 case GeomAbs_G1:
359 case GeomAbs_G2:
9775fa61 360 throw Standard_DomainError("GeomAdaptor_Curve::NbIntervals");
7fd59977 361 break;
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;
366 }
d660a72a 367 Geom2dAdaptor_Curve anAdaptor( Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->BasisCurve() );
368 myNbIntervals = anAdaptor.NbIntervals(BaseS);
7fd59977 369 }
370
371 return myNbIntervals;
372}
373
374//=======================================================================
375//function : Intervals
376//purpose :
377//=======================================================================
378
379void Geom2dAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
380 const GeomAbs_Shape S ) const
381{
382 Standard_Integer myNbIntervals = 1;
383 Standard_Integer NbSplit;
384 if (myTypeCurve == GeomAbs_BSplineCurve) {
3b25c0e8
IC
385 Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
386 Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
7fd59977 387 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
388 if ( S > Continuity()) {
389 Standard_Integer Cont;
390 switch ( S) {
391 case GeomAbs_G1:
392 case GeomAbs_G2:
9775fa61 393 throw Standard_DomainError("Geom2dAdaptor_Curve::NbIntervals");
7fd59977 394 break;
395 case GeomAbs_C0:
396 myNbIntervals = 1;
397 break;
398 case GeomAbs_C1:
399 case GeomAbs_C2:
400 case GeomAbs_C3:
401 case GeomAbs_CN:
402 {
403 if ( S == GeomAbs_C1) Cont = 1;
404 else if ( S == GeomAbs_C2) Cont = 2;
405 else if ( S == GeomAbs_C3) Cont = 3;
3b25c0e8
IC
406 else Cont = myBSplineCurve->Degree();
407 Standard_Integer Degree = myBSplineCurve->Degree();
408 Standard_Integer NbKnots = myBSplineCurve->NbKnots();
7fd59977 409 TColStd_Array1OfInteger Mults (1, NbKnots);
3b25c0e8 410 myBSplineCurve->Multiplicities (Mults);
7fd59977 411 NbSplit = 1;
412 Standard_Integer Index = FirstIndex;
413 Inter (NbSplit) = Index;
414 Index++;
415 NbSplit++;
416 while (Index < LastIndex)
417 {
418 if (Degree - Mults (Index) < Cont)
419 {
420 Inter (NbSplit) = Index;
421 NbSplit++;
422 }
423 Index++;
424 }
425 Inter (NbSplit) = Index;
426 Standard_Integer NbInt = NbSplit-1;
427
3b25c0e8 428 Standard_Integer Nb = myBSplineCurve->NbKnots();
7fd59977 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);
3b25c0e8
IC
434 myBSplineCurve->Knots(TK);
435 myBSplineCurve->Multiplicities(TM);
436 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
437 myBSplineCurve->IsPeriodic(),
7fd59977 438 1,Nb,Index1,newFirst);
3b25c0e8
IC
439 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
440 myBSplineCurve->IsPeriodic(),
7fd59977 441 1,Nb,Index2,newLast);
442
443
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++;
451
452 Inter( 1) = Index1;
453 myNbIntervals = 1;
454 for ( Standard_Integer i=1; i<=NbInt; i++) {
455 if (Inter(i) > Index1 && Inter(i)<Index2 ) {
456 myNbIntervals++;
457 Inter(myNbIntervals) = Inter(i);
458 }
459 }
460 Inter(myNbIntervals+1) = Index2;
461
462 Standard_Integer ii = T.Lower() - 1;
463 for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
464 T(ii + I) = TK(Inter(I));
465 }
466 }
467 break;
468 }
469 }
470 }
1aec3320 471 else if (myTypeCurve == GeomAbs_OffsetCurve){
7fd59977 472 GeomAbs_Shape BaseS=GeomAbs_C0;
473 switch(S){
474 case GeomAbs_G1:
475 case GeomAbs_G2:
9775fa61 476 throw Standard_DomainError("GeomAdaptor_Curve::NbIntervals");
7fd59977 477 break;
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;
482 }
d660a72a 483
484 Geom2dAdaptor_Curve anAdaptor( Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->BasisCurve() );
485 myNbIntervals = anAdaptor.NbIntervals(BaseS);
486 anAdaptor.Intervals(T, BaseS);
7fd59977 487 }
488
489 T( T.Lower() ) = myFirst;
490 T( T.Lower() + myNbIntervals ) = myLast;
491}
492
493//=======================================================================
494//function : Trim
495//purpose :
496//=======================================================================
497
498Handle(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
503{
504 Handle(Geom2dAdaptor_HCurve) HE = new Geom2dAdaptor_HCurve(myCurve,First,Last);
505 return HE;
506}
507
508
509//=======================================================================
510//function : IsClosed
511//purpose :
512//=======================================================================
513
514Standard_Boolean Geom2dAdaptor_Curve::IsClosed() const
515{
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());
521 }
522 else
523 return Standard_False;
524}
525
526//=======================================================================
527//function : IsPeriodic
528//purpose :
529//=======================================================================
530
531Standard_Boolean Geom2dAdaptor_Curve::IsPeriodic() const
532{
ff3f0387 533 return myCurve->IsPeriodic();
7fd59977 534}
535
536//=======================================================================
537//function : Period
538//purpose :
539//=======================================================================
540
541Standard_Real Geom2dAdaptor_Curve::Period() const
542{
543 return myCurve->LastParameter() - myCurve->FirstParameter();
544}
545
546//=======================================================================
94f71cad 547//function : RebuildCache
548//purpose :
549//=======================================================================
550void Geom2dAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
551{
c8b5b3d8 552 if (myTypeCurve == GeomAbs_BezierCurve)
553 {
81093856 554 // Create cache for Bezier
c8b5b3d8 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));
81093856 558 if (myCurveCache.IsNull())
559 myCurveCache = new BSplCLib_Cache(aDeg, aBezier->IsPeriodic(), aFlatKnots,
560 aBezier->Poles(), aBezier->Weights());
c8b5b3d8 561 myCurveCache->BuildCache(theParameter, aDeg, aBezier->IsPeriodic(), aFlatKnots,
562 aBezier->Poles(), aBezier->Weights());
563 }
564 else if (myTypeCurve == GeomAbs_BSplineCurve)
565 {
81093856 566 // Create cache for B-spline
567 if (myCurveCache.IsNull())
568 myCurveCache = new BSplCLib_Cache(myBSplineCurve->Degree(), myBSplineCurve->IsPeriodic(),
569 myBSplineCurve->KnotSequence(), myBSplineCurve->Poles(), myBSplineCurve->Weights());
3b25c0e8
IC
570 myCurveCache->BuildCache(theParameter, myBSplineCurve->Degree(),
571 myBSplineCurve->IsPeriodic(), myBSplineCurve->KnotSequence(),
572 myBSplineCurve->Poles(), myBSplineCurve->Weights());
c8b5b3d8 573 }
94f71cad 574}
575
576//=======================================================================
d660a72a 577//function : IsBoundary
7fd59977 578//purpose :
579//=======================================================================
d660a72a 580Standard_Boolean Geom2dAdaptor_Curve::IsBoundary(const Standard_Real theU,
581 Standard_Integer& theSpanStart,
582 Standard_Integer& theSpanFinish) const
7fd59977 583{
3b25c0e8 584 if (!myBSplineCurve.IsNull() && (theU == myFirst || theU == myLast))
94f71cad 585 {
94f71cad 586 if (theU == myFirst)
587 {
3b25c0e8 588 myBSplineCurve->LocateU(myFirst, PosTol, theSpanStart, theSpanFinish);
d660a72a 589 if (theSpanStart < 1)
590 theSpanStart = 1;
591 if (theSpanStart >= theSpanFinish)
592 theSpanFinish = theSpanStart + 1;
7fd59977 593 }
d660a72a 594 else if (theU == myLast)
94f71cad 595 {
3b25c0e8
IC
596 myBSplineCurve->LocateU(myLast, PosTol, theSpanStart, theSpanFinish);
597 if (theSpanFinish > myBSplineCurve->NbKnots())
598 theSpanFinish = myBSplineCurve->NbKnots();
d660a72a 599 if (theSpanStart >= theSpanFinish)
600 theSpanStart = theSpanFinish - 1;
7fd59977 601 }
d660a72a 602 return Standard_True;
7fd59977 603 }
d660a72a 604 return Standard_False;
94f71cad 605}
606
607//=======================================================================
d660a72a 608//function : Value
609//purpose :
94f71cad 610//=======================================================================
d660a72a 611
612gp_Pnt2d Geom2dAdaptor_Curve::Value(const Standard_Real U) const
94f71cad 613{
d660a72a 614 gp_Pnt2d aRes;
615 D0(U, aRes);
616 return aRes;
7fd59977 617}
618
619//=======================================================================
620//function : D0
621//purpose :
622//=======================================================================
623
624void Geom2dAdaptor_Curve::D0(const Standard_Real U, gp_Pnt2d& P) const
625{
d660a72a 626 switch (myTypeCurve)
94f71cad 627 {
d660a72a 628 case GeomAbs_BezierCurve:
629 case GeomAbs_BSplineCurve:
630 {
631 Standard_Integer aStart = 0, aFinish = 0;
632 if (IsBoundary(U, aStart, aFinish))
633 {
3b25c0e8 634 myBSplineCurve->LocalD0(U, aStart, aFinish, P);
7fd59977 635 }
81093856 636 else
d660a72a 637 {
81093856 638 // use cached data
639 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
d660a72a 640 RebuildCache(U);
641 myCurveCache->D0(U, P);
7fd59977 642 }
d660a72a 643 break;
94f71cad 644 }
94f71cad 645
d660a72a 646 case GeomAbs_OffsetCurve:
647 myNestedEvaluator->D0(U, P);
648 break;
649
650 default:
651 myCurve->D0(U, P);
652 }
7fd59977 653}
654
655//=======================================================================
656//function : D1
657//purpose :
658//=======================================================================
659
94f71cad 660void Geom2dAdaptor_Curve::D1(const Standard_Real U,
661 gp_Pnt2d& P, gp_Vec2d& V) const
662{
d660a72a 663 switch (myTypeCurve)
94f71cad 664 {
d660a72a 665 case GeomAbs_BezierCurve:
666 case GeomAbs_BSplineCurve:
667 {
668 Standard_Integer aStart = 0, aFinish = 0;
669 if (IsBoundary(U, aStart, aFinish))
670 {
3b25c0e8 671 myBSplineCurve->LocalD1(U, aStart, aFinish, P, V);
7fd59977 672 }
81093856 673 else
d660a72a 674 {
81093856 675 // use cached data
676 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
d660a72a 677 RebuildCache(U);
678 myCurveCache->D1(U, P, V);
7fd59977 679 }
d660a72a 680 break;
94f71cad 681 }
94f71cad 682
d660a72a 683 case GeomAbs_OffsetCurve:
684 myNestedEvaluator->D1(U, P, V);
685 break;
94f71cad 686
d660a72a 687 default:
688 myCurve->D1(U, P, V);
689 }
7fd59977 690}
691
692//=======================================================================
693//function : D2
694//purpose :
695//=======================================================================
696
697void Geom2dAdaptor_Curve::D2(const Standard_Real U,
94f71cad 698 gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const
7fd59977 699{
d660a72a 700 switch (myTypeCurve)
94f71cad 701 {
d660a72a 702 case GeomAbs_BezierCurve:
703 case GeomAbs_BSplineCurve:
704 {
705 Standard_Integer aStart = 0, aFinish = 0;
706 if (IsBoundary(U, aStart, aFinish))
707 {
3b25c0e8 708 myBSplineCurve->LocalD2(U, aStart, aFinish, P, V1, V2);
7fd59977 709 }
81093856 710 else
d660a72a 711 {
81093856 712 // use cached data
713 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
d660a72a 714 RebuildCache(U);
715 myCurveCache->D2(U, P, V1, V2);
7fd59977 716 }
d660a72a 717 break;
7fd59977 718 }
94f71cad 719
d660a72a 720 case GeomAbs_OffsetCurve:
721 myNestedEvaluator->D2(U, P, V1, V2);
722 break;
94f71cad 723
d660a72a 724 default:
725 myCurve->D2(U, P, V1, V2);
726 }
7fd59977 727}
728
729//=======================================================================
730//function : D3
731//purpose :
732//=======================================================================
733
734void Geom2dAdaptor_Curve::D3(const Standard_Real U,
94f71cad 735 gp_Pnt2d& P, gp_Vec2d& V1,
736 gp_Vec2d& V2, gp_Vec2d& V3) const
7fd59977 737{
d660a72a 738 switch (myTypeCurve)
94f71cad 739 {
d660a72a 740 case GeomAbs_BezierCurve:
741 case GeomAbs_BSplineCurve:
742 {
743 Standard_Integer aStart = 0, aFinish = 0;
744 if (IsBoundary(U, aStart, aFinish))
745 {
3b25c0e8 746 myBSplineCurve->LocalD3(U, aStart, aFinish, P, V1, V2, V3);
7fd59977 747 }
81093856 748 else
d660a72a 749 {
81093856 750 // use cached data
751 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
d660a72a 752 RebuildCache(U);
753 myCurveCache->D3(U, P, V1, V2, V3);
7fd59977 754 }
d660a72a 755 break;
7fd59977 756 }
94f71cad 757
d660a72a 758 case GeomAbs_OffsetCurve:
759 myNestedEvaluator->D3(U, P, V1, V2, V3);
760 break;
94f71cad 761
d660a72a 762 default:
763 myCurve->D3(U, P, V1, V2, V3);
764 }
7fd59977 765}
766
767//=======================================================================
768//function : DN
769//purpose :
770//=======================================================================
771
772gp_Vec2d Geom2dAdaptor_Curve::DN(const Standard_Real U,
94f71cad 773 const Standard_Integer N) const
7fd59977 774{
d660a72a 775 switch (myTypeCurve)
94f71cad 776 {
d660a72a 777 case GeomAbs_BezierCurve:
778 case GeomAbs_BSplineCurve:
779 {
780 Standard_Integer aStart = 0, aFinish = 0;
781 if (IsBoundary(U, aStart, aFinish))
782 {
3b25c0e8 783 myBSplineCurve->LocalDN(U, aStart, aFinish, N);
7fd59977 784 }
d660a72a 785 else
786 return myCurve->DN(U, N);
787 break;
7fd59977 788 }
94f71cad 789
d660a72a 790 case GeomAbs_OffsetCurve:
791 return myNestedEvaluator->DN(U, N);
94f71cad 792 break;
d660a72a 793
794 default: // to eliminate gcc warning
94f71cad 795 break;
94f71cad 796 }
d660a72a 797 return myCurve->DN(U, N);
7fd59977 798}
799
800//=======================================================================
801//function : Resolution
802//purpose :
803//=======================================================================
804
805Standard_Real Geom2dAdaptor_Curve::Resolution(const Standard_Real Ruv) const {
806 switch ( myTypeCurve) {
807 case GeomAbs_Line :
808 return Ruv;
809 case GeomAbs_Circle: {
c5f3a425 810 Standard_Real R = Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d().Radius();
7fd59977 811 if ( R > Ruv/2.)
812 return 2*ASin(Ruv/(2*R));
813 else
c6541a0c 814 return 2*M_PI;
7fd59977 815 }
816 case GeomAbs_Ellipse: {
c5f3a425 817 return Ruv / Handle(Geom2d_Ellipse)::DownCast (myCurve)->MajorRadius();
7fd59977 818 }
819 case GeomAbs_BezierCurve: {
820 Standard_Real res;
c5f3a425 821 Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Resolution(Ruv,res);
7fd59977 822 return res;
823 }
824 case GeomAbs_BSplineCurve: {
825 Standard_Real res;
c5f3a425 826 Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->Resolution(Ruv,res);
7fd59977 827 return res;
828 }
829 default:
830 return Precision::Parametric(Ruv);
831 }
832}
833
834
835// --
836// -- The following methods must be called when GetType returned
837// -- the corresponding type.
838// --
839
840//=======================================================================
841//function : Line
842//purpose :
843//=======================================================================
844
845gp_Lin2d Geom2dAdaptor_Curve::Line() const
846{
2d2b3d53 847 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Line,
848 "Geom2dAdaptor_Curve::Line() - curve is not a Line");
c5f3a425 849 return Handle(Geom2d_Line)::DownCast (myCurve)->Lin2d();
7fd59977 850}
851
852//=======================================================================
853//function : Circle
854//purpose :
855//=======================================================================
856
857gp_Circ2d Geom2dAdaptor_Curve::Circle() const
858{
2d2b3d53 859 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Circle,
860 "Geom2dAdaptor_Curve::Circle() - curve is not a Circle");
c5f3a425 861 return Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d();
7fd59977 862}
863
864//=======================================================================
865//function : Ellipse
866//purpose :
867//=======================================================================
868
869gp_Elips2d Geom2dAdaptor_Curve::Ellipse() const
870{
2d2b3d53 871 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Ellipse,
872 "Geom2dAdaptor_Curve::Ellipse() - curve is not an Ellipse");
c5f3a425 873 return Handle(Geom2d_Ellipse)::DownCast (myCurve)->Elips2d();
7fd59977 874}
875
876//=======================================================================
877//function : Hyperbola
878//purpose :
879//=======================================================================
880
881gp_Hypr2d Geom2dAdaptor_Curve::Hyperbola() const
882{
2d2b3d53 883 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Hyperbola,
884 "Geom2dAdaptor_Curve::Hyperbola() - curve is not a Hyperbola");
c5f3a425 885 return Handle(Geom2d_Hyperbola)::DownCast (myCurve)->Hypr2d();
7fd59977 886}
887
888//=======================================================================
889//function : Parabola
890//purpose :
891//=======================================================================
892
893gp_Parab2d Geom2dAdaptor_Curve::Parabola() const
894{
2d2b3d53 895 Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Parabola,
896 "Geom2dAdaptor_Curve::Parabola() - curve is not a Parabola");
c5f3a425 897 return Handle(Geom2d_Parabola)::DownCast (myCurve)->Parab2d();
7fd59977 898}
899
900//=======================================================================
901//function : Degree
902//purpose :
903//=======================================================================
904
905Standard_Integer Geom2dAdaptor_Curve::Degree() const
906{
907 if (myTypeCurve == GeomAbs_BezierCurve)
c5f3a425 908 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Degree();
7fd59977 909 else if (myTypeCurve == GeomAbs_BSplineCurve)
3b25c0e8 910 return myBSplineCurve->Degree();
7fd59977 911 else
9775fa61 912 throw Standard_NoSuchObject();
7fd59977 913}
914
915//=======================================================================
916//function : IsRational
917//purpose :
918//=======================================================================
919
920Standard_Boolean Geom2dAdaptor_Curve::IsRational() const {
921 switch( myTypeCurve) {
922 case GeomAbs_BSplineCurve:
3b25c0e8 923 return myBSplineCurve->IsRational();
7fd59977 924 case GeomAbs_BezierCurve:
c5f3a425 925 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->IsRational();
7fd59977 926 default:
927 return Standard_False;
928 }
929}
930
931//=======================================================================
932//function : NbPoles
933//purpose :
934//=======================================================================
935
936Standard_Integer Geom2dAdaptor_Curve::NbPoles() const
937{
938 if (myTypeCurve == GeomAbs_BezierCurve)
c5f3a425 939 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->NbPoles();
7fd59977 940 else if (myTypeCurve == GeomAbs_BSplineCurve)
3b25c0e8 941 return myBSplineCurve->NbPoles();
7fd59977 942 else
9775fa61 943 throw Standard_NoSuchObject();
7fd59977 944}
945
946//=======================================================================
947//function : NbKnots
948//purpose :
949//=======================================================================
950
3b25c0e8
IC
951Standard_Integer Geom2dAdaptor_Curve::NbKnots() const
952{
7fd59977 953 if ( myTypeCurve != GeomAbs_BSplineCurve)
9775fa61 954 throw Standard_NoSuchObject("Geom2dAdaptor_Curve::NbKnots");
3b25c0e8 955 return myBSplineCurve->NbKnots();
7fd59977 956}
957
958//=======================================================================
959//function : Bezier
960//purpose :
961//=======================================================================
962
963Handle(Geom2d_BezierCurve) Geom2dAdaptor_Curve::Bezier() const
964{
c5f3a425 965 return Handle(Geom2d_BezierCurve)::DownCast (myCurve);
7fd59977 966}
967
968//=======================================================================
969//function : BSpline
970//purpose :
971//=======================================================================
972
973Handle(Geom2d_BSplineCurve) Geom2dAdaptor_Curve::BSpline() const
974{
3b25c0e8 975 return myBSplineCurve;
7fd59977 976}
977
a874a4a0 978static Standard_Integer nbPoints(const Handle(Geom2d_Curve)& theCurve)
979{
980
5ae6e53d 981 Standard_Integer nbs = 20;
a874a4a0 982
983 if(theCurve->IsKind(STANDARD_TYPE( Geom2d_Line)) )
984 nbs = 2;
985 else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BezierCurve)))
986 {
c5f3a425 987 nbs = 3 + Handle(Geom2d_BezierCurve)::DownCast (theCurve)->NbPoles();
a874a4a0 988 }
989 else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BSplineCurve))) {
c5f3a425 990 nbs = Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->NbKnots();
991 nbs*= Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->Degree();
a874a4a0 992 if(nbs < 2.0) nbs=2;
993 }
994 else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
995 {
c5f3a425 996 Handle(Geom2d_Curve) aCurve = Handle(Geom2d_OffsetCurve)::DownCast (theCurve)->BasisCurve();
a874a4a0 997 return Max(nbs, nbPoints(aCurve));
998 }
999
1000 else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
1001 {
c5f3a425 1002 Handle(Geom2d_Curve) aCurve = Handle(Geom2d_TrimmedCurve)::DownCast (theCurve)->BasisCurve();
a874a4a0 1003 return Max(nbs, nbPoints(aCurve));
1004 }
1005 if(nbs>300)
1006 nbs = 300;
1007 return nbs;
3b25c0e8 1008
a874a4a0 1009}
1010
1011Standard_Integer Geom2dAdaptor_Curve::NbSamples() const
1012{
1013 return nbPoints(myCurve);
1014}