0026937: Eliminate NO_CXX_EXCEPTION macro support
[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{
533 if (myCurve->IsPeriodic())
534 return IsClosed();
535 else
536 return Standard_False;
537}
538
539//=======================================================================
540//function : Period
541//purpose :
542//=======================================================================
543
544Standard_Real Geom2dAdaptor_Curve::Period() const
545{
546 return myCurve->LastParameter() - myCurve->FirstParameter();
547}
548
94f71cad 549//=======================================================================
550//function : RebuildCache
551//purpose :
552//=======================================================================
553void Geom2dAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
554{
c8b5b3d8 555 if (myTypeCurve == GeomAbs_BezierCurve)
556 {
81093856 557 // Create cache for Bezier
c8b5b3d8 558 Handle(Geom2d_BezierCurve) aBezier = Handle(Geom2d_BezierCurve)::DownCast(myCurve);
559 Standard_Integer aDeg = aBezier->Degree();
560 TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
81093856 561 if (myCurveCache.IsNull())
562 myCurveCache = new BSplCLib_Cache(aDeg, aBezier->IsPeriodic(), aFlatKnots,
563 aBezier->Poles(), aBezier->Weights());
c8b5b3d8 564 myCurveCache->BuildCache(theParameter, aDeg, aBezier->IsPeriodic(), aFlatKnots,
565 aBezier->Poles(), aBezier->Weights());
566 }
567 else if (myTypeCurve == GeomAbs_BSplineCurve)
568 {
81093856 569 // Create cache for B-spline
570 if (myCurveCache.IsNull())
571 myCurveCache = new BSplCLib_Cache(myBSplineCurve->Degree(), myBSplineCurve->IsPeriodic(),
572 myBSplineCurve->KnotSequence(), myBSplineCurve->Poles(), myBSplineCurve->Weights());
3b25c0e8
IC
573 myCurveCache->BuildCache(theParameter, myBSplineCurve->Degree(),
574 myBSplineCurve->IsPeriodic(), myBSplineCurve->KnotSequence(),
575 myBSplineCurve->Poles(), myBSplineCurve->Weights());
c8b5b3d8 576 }
94f71cad 577}
578
7fd59977 579//=======================================================================
d660a72a 580//function : IsBoundary
7fd59977 581//purpose :
582//=======================================================================
d660a72a 583Standard_Boolean Geom2dAdaptor_Curve::IsBoundary(const Standard_Real theU,
584 Standard_Integer& theSpanStart,
585 Standard_Integer& theSpanFinish) const
7fd59977 586{
3b25c0e8 587 if (!myBSplineCurve.IsNull() && (theU == myFirst || theU == myLast))
94f71cad 588 {
94f71cad 589 if (theU == myFirst)
590 {
3b25c0e8 591 myBSplineCurve->LocateU(myFirst, PosTol, theSpanStart, theSpanFinish);
d660a72a 592 if (theSpanStart < 1)
593 theSpanStart = 1;
594 if (theSpanStart >= theSpanFinish)
595 theSpanFinish = theSpanStart + 1;
7fd59977 596 }
d660a72a 597 else if (theU == myLast)
94f71cad 598 {
3b25c0e8
IC
599 myBSplineCurve->LocateU(myLast, PosTol, theSpanStart, theSpanFinish);
600 if (theSpanFinish > myBSplineCurve->NbKnots())
601 theSpanFinish = myBSplineCurve->NbKnots();
d660a72a 602 if (theSpanStart >= theSpanFinish)
603 theSpanStart = theSpanFinish - 1;
7fd59977 604 }
d660a72a 605 return Standard_True;
7fd59977 606 }
d660a72a 607 return Standard_False;
94f71cad 608}
609
610//=======================================================================
d660a72a 611//function : Value
612//purpose :
94f71cad 613//=======================================================================
d660a72a 614
615gp_Pnt2d Geom2dAdaptor_Curve::Value(const Standard_Real U) const
94f71cad 616{
d660a72a 617 gp_Pnt2d aRes;
618 D0(U, aRes);
619 return aRes;
7fd59977 620}
621
622//=======================================================================
623//function : D0
624//purpose :
625//=======================================================================
626
627void Geom2dAdaptor_Curve::D0(const Standard_Real U, gp_Pnt2d& P) const
628{
d660a72a 629 switch (myTypeCurve)
94f71cad 630 {
d660a72a 631 case GeomAbs_BezierCurve:
632 case GeomAbs_BSplineCurve:
633 {
634 Standard_Integer aStart = 0, aFinish = 0;
635 if (IsBoundary(U, aStart, aFinish))
636 {
3b25c0e8 637 myBSplineCurve->LocalD0(U, aStart, aFinish, P);
7fd59977 638 }
81093856 639 else
d660a72a 640 {
81093856 641 // use cached data
642 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
d660a72a 643 RebuildCache(U);
644 myCurveCache->D0(U, P);
7fd59977 645 }
d660a72a 646 break;
94f71cad 647 }
94f71cad 648
d660a72a 649 case GeomAbs_OffsetCurve:
650 myNestedEvaluator->D0(U, P);
651 break;
652
653 default:
654 myCurve->D0(U, P);
655 }
7fd59977 656}
657
658//=======================================================================
659//function : D1
660//purpose :
661//=======================================================================
662
94f71cad 663void Geom2dAdaptor_Curve::D1(const Standard_Real U,
664 gp_Pnt2d& P, gp_Vec2d& V) const
665{
d660a72a 666 switch (myTypeCurve)
94f71cad 667 {
d660a72a 668 case GeomAbs_BezierCurve:
669 case GeomAbs_BSplineCurve:
670 {
671 Standard_Integer aStart = 0, aFinish = 0;
672 if (IsBoundary(U, aStart, aFinish))
673 {
3b25c0e8 674 myBSplineCurve->LocalD1(U, aStart, aFinish, P, V);
7fd59977 675 }
81093856 676 else
d660a72a 677 {
81093856 678 // use cached data
679 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
d660a72a 680 RebuildCache(U);
681 myCurveCache->D1(U, P, V);
7fd59977 682 }
d660a72a 683 break;
94f71cad 684 }
94f71cad 685
d660a72a 686 case GeomAbs_OffsetCurve:
687 myNestedEvaluator->D1(U, P, V);
688 break;
94f71cad 689
d660a72a 690 default:
691 myCurve->D1(U, P, V);
692 }
7fd59977 693}
694
695//=======================================================================
696//function : D2
697//purpose :
698//=======================================================================
699
700void Geom2dAdaptor_Curve::D2(const Standard_Real U,
94f71cad 701 gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const
7fd59977 702{
d660a72a 703 switch (myTypeCurve)
94f71cad 704 {
d660a72a 705 case GeomAbs_BezierCurve:
706 case GeomAbs_BSplineCurve:
707 {
708 Standard_Integer aStart = 0, aFinish = 0;
709 if (IsBoundary(U, aStart, aFinish))
710 {
3b25c0e8 711 myBSplineCurve->LocalD2(U, aStart, aFinish, P, V1, V2);
7fd59977 712 }
81093856 713 else
d660a72a 714 {
81093856 715 // use cached data
716 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
d660a72a 717 RebuildCache(U);
718 myCurveCache->D2(U, P, V1, V2);
7fd59977 719 }
d660a72a 720 break;
7fd59977 721 }
94f71cad 722
d660a72a 723 case GeomAbs_OffsetCurve:
724 myNestedEvaluator->D2(U, P, V1, V2);
725 break;
94f71cad 726
d660a72a 727 default:
728 myCurve->D2(U, P, V1, V2);
729 }
7fd59977 730}
731
732//=======================================================================
733//function : D3
734//purpose :
735//=======================================================================
736
737void Geom2dAdaptor_Curve::D3(const Standard_Real U,
94f71cad 738 gp_Pnt2d& P, gp_Vec2d& V1,
739 gp_Vec2d& V2, gp_Vec2d& V3) const
7fd59977 740{
d660a72a 741 switch (myTypeCurve)
94f71cad 742 {
d660a72a 743 case GeomAbs_BezierCurve:
744 case GeomAbs_BSplineCurve:
745 {
746 Standard_Integer aStart = 0, aFinish = 0;
747 if (IsBoundary(U, aStart, aFinish))
748 {
3b25c0e8 749 myBSplineCurve->LocalD3(U, aStart, aFinish, P, V1, V2, V3);
7fd59977 750 }
81093856 751 else
d660a72a 752 {
81093856 753 // use cached data
754 if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
d660a72a 755 RebuildCache(U);
756 myCurveCache->D3(U, P, V1, V2, V3);
7fd59977 757 }
d660a72a 758 break;
7fd59977 759 }
94f71cad 760
d660a72a 761 case GeomAbs_OffsetCurve:
762 myNestedEvaluator->D3(U, P, V1, V2, V3);
763 break;
94f71cad 764
d660a72a 765 default:
766 myCurve->D3(U, P, V1, V2, V3);
767 }
7fd59977 768}
769
770//=======================================================================
771//function : DN
772//purpose :
773//=======================================================================
774
775gp_Vec2d Geom2dAdaptor_Curve::DN(const Standard_Real U,
94f71cad 776 const Standard_Integer N) const
7fd59977 777{
d660a72a 778 switch (myTypeCurve)
94f71cad 779 {
d660a72a 780 case GeomAbs_BezierCurve:
781 case GeomAbs_BSplineCurve:
782 {
783 Standard_Integer aStart = 0, aFinish = 0;
784 if (IsBoundary(U, aStart, aFinish))
785 {
3b25c0e8 786 myBSplineCurve->LocalDN(U, aStart, aFinish, N);
7fd59977 787 }
d660a72a 788 else
789 return myCurve->DN(U, N);
790 break;
7fd59977 791 }
94f71cad 792
d660a72a 793 case GeomAbs_OffsetCurve:
794 return myNestedEvaluator->DN(U, N);
94f71cad 795 break;
d660a72a 796
797 default: // to eliminate gcc warning
94f71cad 798 break;
94f71cad 799 }
d660a72a 800 return myCurve->DN(U, N);
7fd59977 801}
802
803//=======================================================================
804//function : Resolution
805//purpose :
806//=======================================================================
807
808Standard_Real Geom2dAdaptor_Curve::Resolution(const Standard_Real Ruv) const {
809 switch ( myTypeCurve) {
810 case GeomAbs_Line :
811 return Ruv;
812 case GeomAbs_Circle: {
c5f3a425 813 Standard_Real R = Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d().Radius();
7fd59977 814 if ( R > Ruv/2.)
815 return 2*ASin(Ruv/(2*R));
816 else
c6541a0c 817 return 2*M_PI;
7fd59977 818 }
819 case GeomAbs_Ellipse: {
c5f3a425 820 return Ruv / Handle(Geom2d_Ellipse)::DownCast (myCurve)->MajorRadius();
7fd59977 821 }
822 case GeomAbs_BezierCurve: {
823 Standard_Real res;
c5f3a425 824 Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Resolution(Ruv,res);
7fd59977 825 return res;
826 }
827 case GeomAbs_BSplineCurve: {
828 Standard_Real res;
c5f3a425 829 Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->Resolution(Ruv,res);
7fd59977 830 return res;
831 }
832 default:
833 return Precision::Parametric(Ruv);
834 }
835}
836
837
838// --
839// -- The following methods must be called when GetType returned
840// -- the corresponding type.
841// --
842
843//=======================================================================
844//function : Line
845//purpose :
846//=======================================================================
847
848gp_Lin2d Geom2dAdaptor_Curve::Line() const
849{
850 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
c5f3a425 851 return Handle(Geom2d_Line)::DownCast (myCurve)->Lin2d();
7fd59977 852}
853
854//=======================================================================
855//function : Circle
856//purpose :
857//=======================================================================
858
859gp_Circ2d Geom2dAdaptor_Curve::Circle() const
860{
861 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
c5f3a425 862 return Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d();
7fd59977 863}
864
865//=======================================================================
866//function : Ellipse
867//purpose :
868//=======================================================================
869
870gp_Elips2d Geom2dAdaptor_Curve::Ellipse() const
871{
872 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_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{
883 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
c5f3a425 884 return Handle(Geom2d_Hyperbola)::DownCast (myCurve)->Hypr2d();
7fd59977 885}
886
887//=======================================================================
888//function : Parabola
889//purpose :
890//=======================================================================
891
892gp_Parab2d Geom2dAdaptor_Curve::Parabola() const
893{
894 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
c5f3a425 895 return Handle(Geom2d_Parabola)::DownCast (myCurve)->Parab2d();
7fd59977 896}
897
898//=======================================================================
899//function : Degree
900//purpose :
901//=======================================================================
902
903Standard_Integer Geom2dAdaptor_Curve::Degree() const
904{
905 if (myTypeCurve == GeomAbs_BezierCurve)
c5f3a425 906 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Degree();
7fd59977 907 else if (myTypeCurve == GeomAbs_BSplineCurve)
3b25c0e8 908 return myBSplineCurve->Degree();
7fd59977 909 else
9775fa61 910 throw Standard_NoSuchObject();
7fd59977 911}
912
913//=======================================================================
914//function : IsRational
915//purpose :
916//=======================================================================
917
918Standard_Boolean Geom2dAdaptor_Curve::IsRational() const {
919 switch( myTypeCurve) {
920 case GeomAbs_BSplineCurve:
3b25c0e8 921 return myBSplineCurve->IsRational();
7fd59977 922 case GeomAbs_BezierCurve:
c5f3a425 923 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->IsRational();
7fd59977 924 default:
925 return Standard_False;
926 }
927}
928
929//=======================================================================
930//function : NbPoles
931//purpose :
932//=======================================================================
933
934Standard_Integer Geom2dAdaptor_Curve::NbPoles() const
935{
936 if (myTypeCurve == GeomAbs_BezierCurve)
c5f3a425 937 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->NbPoles();
7fd59977 938 else if (myTypeCurve == GeomAbs_BSplineCurve)
3b25c0e8 939 return myBSplineCurve->NbPoles();
7fd59977 940 else
9775fa61 941 throw Standard_NoSuchObject();
7fd59977 942}
943
944//=======================================================================
945//function : NbKnots
946//purpose :
947//=======================================================================
948
3b25c0e8
IC
949Standard_Integer Geom2dAdaptor_Curve::NbKnots() const
950{
7fd59977 951 if ( myTypeCurve != GeomAbs_BSplineCurve)
9775fa61 952 throw Standard_NoSuchObject("Geom2dAdaptor_Curve::NbKnots");
3b25c0e8 953 return myBSplineCurve->NbKnots();
7fd59977 954}
955
956//=======================================================================
957//function : Bezier
958//purpose :
959//=======================================================================
960
961Handle(Geom2d_BezierCurve) Geom2dAdaptor_Curve::Bezier() const
962{
c5f3a425 963 return Handle(Geom2d_BezierCurve)::DownCast (myCurve);
7fd59977 964}
965
966//=======================================================================
967//function : BSpline
968//purpose :
969//=======================================================================
970
971Handle(Geom2d_BSplineCurve) Geom2dAdaptor_Curve::BSpline() const
972{
3b25c0e8 973 return myBSplineCurve;
7fd59977 974}
975
a874a4a0 976static Standard_Integer nbPoints(const Handle(Geom2d_Curve)& theCurve)
977{
978
5ae6e53d 979 Standard_Integer nbs = 20;
a874a4a0 980
981 if(theCurve->IsKind(STANDARD_TYPE( Geom2d_Line)) )
982 nbs = 2;
983 else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BezierCurve)))
984 {
c5f3a425 985 nbs = 3 + Handle(Geom2d_BezierCurve)::DownCast (theCurve)->NbPoles();
a874a4a0 986 }
987 else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BSplineCurve))) {
c5f3a425 988 nbs = Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->NbKnots();
989 nbs*= Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->Degree();
a874a4a0 990 if(nbs < 2.0) nbs=2;
991 }
992 else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
993 {
c5f3a425 994 Handle(Geom2d_Curve) aCurve = Handle(Geom2d_OffsetCurve)::DownCast (theCurve)->BasisCurve();
a874a4a0 995 return Max(nbs, nbPoints(aCurve));
996 }
997
998 else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
999 {
c5f3a425 1000 Handle(Geom2d_Curve) aCurve = Handle(Geom2d_TrimmedCurve)::DownCast (theCurve)->BasisCurve();
a874a4a0 1001 return Max(nbs, nbPoints(aCurve));
1002 }
1003 if(nbs>300)
1004 nbs = 300;
1005 return nbs;
3b25c0e8 1006
a874a4a0 1007}
1008
1009Standard_Integer Geom2dAdaptor_Curve::NbSamples() const
1010{
1011 return nbPoints(myCurve);
1012}