0023620: Follow up of 0022939 - make Bezier curve/surface evaluation thread-safe
[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>
42cf5bc1 28#include <CSLib_Offset.hxx>
7fd59977 29#include <Geom2d_BezierCurve.hxx>
30#include <Geom2d_BSplineCurve.hxx>
42cf5bc1 31#include <Geom2d_Circle.hxx>
32#include <Geom2d_Curve.hxx>
7fd59977 33#include <Geom2d_Ellipse.hxx>
7fd59977 34#include <Geom2d_Hyperbola.hxx>
42cf5bc1 35#include <Geom2d_Line.hxx>
36#include <Geom2d_OffsetCurve.hxx>
37#include <Geom2d_Parabola.hxx>
38#include <Geom2d_TrimmedCurve.hxx>
94f71cad 39#include <Geom2d_UndefinedDerivative.hxx>
42cf5bc1 40#include <Geom2d_UndefinedValue.hxx>
41#include <Geom2dAdaptor_Curve.hxx>
42#include <Geom2dAdaptor_HCurve.hxx>
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
c8b5b3d8 67static const Standard_Integer maxDerivOrder = 3;
94f71cad 68static const Standard_Real MinStep = 1e-7;
69
70static gp_Vec2d dummyDerivative; // used as empty value for unused derivatives in AdjustDerivative
71
72// Recalculate derivatives in the singular point
73// Returns true is the direction of derivatives is changed
74static Standard_Boolean AdjustDerivative(const Handle(Adaptor2d_HCurve2d)& theAdaptor, Standard_Integer theMaxDerivative,
75 Standard_Real theU, gp_Vec2d& theD1, gp_Vec2d& theD2 = dummyDerivative,
76 gp_Vec2d& theD3 = dummyDerivative, gp_Vec2d& theD4 = dummyDerivative);
77
7fd59977 78//=======================================================================
79//function : LocalContinuity
80//purpose : Computes the Continuity of a BSplineCurve
81// between the parameters U1 and U2
82// The continuity is C(d-m)
83// with d = degree,
84// m = max multiplicity of the Knots between U1 and U2
85//=======================================================================
86
87GeomAbs_Shape Geom2dAdaptor_Curve::LocalContinuity(const Standard_Real U1,
88 const Standard_Real U2)
89 const {
90
91 Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
c8b5b3d8 92 Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
93 Standard_Integer Nb = aBspl->NbKnots();
7fd59977 94 Standard_Integer Index1 = 0;
95 Standard_Integer Index2 = 0;
96 Standard_Real newFirst, newLast;
97 TColStd_Array1OfReal TK(1,Nb);
98 TColStd_Array1OfInteger TM(1,Nb);
c8b5b3d8 99 aBspl->Knots(TK);
100 aBspl->Multiplicities(TM);
101 BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,U1,aBspl->IsPeriodic(),
7fd59977 102 1,Nb,Index1,newFirst);
c8b5b3d8 103 BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,U2,aBspl->IsPeriodic(),
7fd59977 104 1,Nb,Index2,newLast);
105 if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) {
106 if (Index1 < Nb)Index1++;
107 }
108 if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
109 Index2--;
110 Standard_Integer MultMax;
111 // attention aux courbes peridiques.
c8b5b3d8 112 if ( (aBspl->IsPeriodic()) && (Index1 == Nb) )
7fd59977 113 Index1 = 1;
114
115 if ( Index2 - Index1 <= 0) {
116 MultMax = 100; // CN entre 2 Noeuds consecutifs
117 }
118 else {
119 MultMax = TM(Index1+1);
120 for(Standard_Integer i = Index1+1;i<=Index2;i++) {
121 if ( TM(i)>MultMax) MultMax=TM(i);
122 }
c8b5b3d8 123 MultMax = aBspl->Degree() - MultMax;
7fd59977 124 }
125 if ( MultMax <= 0) {
126 return GeomAbs_C0;
127 }
128 else if ( MultMax == 1) {
129 return GeomAbs_C1;
130 }
131 else if ( MultMax == 2) {
132 return GeomAbs_C2;
133 }
134 else if ( MultMax == 3) {
135 return GeomAbs_C3;
136 }
137 else {
138 return GeomAbs_CN;
139 }
140 }
141
142
143//=======================================================================
144//function : Geom2dAdaptor_Curve
145//purpose :
146//=======================================================================
147
148Geom2dAdaptor_Curve::Geom2dAdaptor_Curve()
cbff1e55 149: myTypeCurve(GeomAbs_OtherCurve),
150 myFirst (0.0),
151 myLast (0.0)
7fd59977 152{
153}
154
155//=======================================================================
156//function : Geom2dAdaptor_Curve
157//purpose :
158//=======================================================================
159
cbff1e55 160Geom2dAdaptor_Curve::Geom2dAdaptor_Curve(const Handle(Geom2d_Curve)& theCrv)
161: myTypeCurve(GeomAbs_OtherCurve),
162 myFirst (0.0),
163 myLast (0.0)
041bfce9 164{
cbff1e55 165 Load(theCrv);
7fd59977 166}
167
168//=======================================================================
169//function : Geom2dAdaptor_Curve
170//purpose :
171//=======================================================================
172
cbff1e55 173Geom2dAdaptor_Curve::Geom2dAdaptor_Curve(const Handle(Geom2d_Curve)& theCrv,
174 const Standard_Real theUFirst,
175 const Standard_Real theULast)
176: myTypeCurve(GeomAbs_OtherCurve),
177 myFirst (theUFirst),
178 myLast (theULast)
041bfce9 179{
cbff1e55 180 Load(theCrv, theUFirst, theULast);
7fd59977 181}
182
7fd59977 183
184//=======================================================================
185//function : Load
186//purpose :
187//=======================================================================
188
041bfce9 189void Geom2dAdaptor_Curve::load(const Handle(Geom2d_Curve)& C,
190 const Standard_Real UFirst,
191 const Standard_Real ULast)
192{
7fd59977 193 myFirst = UFirst;
194 myLast = ULast;
195
196 if ( myCurve != C) {
197 myCurve = C;
c8b5b3d8 198 myCurveCache = Handle(BSplCLib_Cache)();
7fd59977 199
200 Handle(Standard_Type) TheType = C->DynamicType();
201 if ( TheType == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
c5f3a425 202 Load(Handle(Geom2d_TrimmedCurve)::DownCast (C)->BasisCurve(),
7fd59977 203 UFirst,ULast);
204 }
205 else if ( TheType == STANDARD_TYPE(Geom2d_Circle)) {
206 myTypeCurve = GeomAbs_Circle;
207 }
208 else if ( TheType ==STANDARD_TYPE(Geom2d_Line)) {
209 myTypeCurve = GeomAbs_Line;
210 }
211 else if ( TheType == STANDARD_TYPE(Geom2d_Ellipse)) {
212 myTypeCurve = GeomAbs_Ellipse;
213 }
214 else if ( TheType == STANDARD_TYPE(Geom2d_Parabola)) {
215 myTypeCurve = GeomAbs_Parabola;
216 }
217 else if ( TheType == STANDARD_TYPE(Geom2d_Hyperbola)) {
218 myTypeCurve = GeomAbs_Hyperbola;
219 }
220 else if ( TheType == STANDARD_TYPE(Geom2d_BezierCurve)) {
221 myTypeCurve = GeomAbs_BezierCurve;
c8b5b3d8 222 // Create cache for Bezier
223 Handle(Geom2d_BezierCurve) aBezier = Handle(Geom2d_BezierCurve)::DownCast(myCurve);
224 Standard_Integer aDeg = aBezier->Degree();
225 TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
226 myCurveCache = new BSplCLib_Cache(aDeg, aBezier->IsPeriodic(), aFlatKnots,
227 aBezier->Poles(), aBezier->Weights());
7fd59977 228 }
229 else if ( TheType == STANDARD_TYPE(Geom2d_BSplineCurve)) {
230 myTypeCurve = GeomAbs_BSplineCurve;
94f71cad 231 // Create cache for B-spline
c8b5b3d8 232 Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
233 myCurveCache = new BSplCLib_Cache(aBspl->Degree(), aBspl->IsPeriodic(),
234 aBspl->KnotSequence(), aBspl->Poles(), aBspl->Weights());
94f71cad 235 }
236 else if ( TheType == STANDARD_TYPE(Geom2d_OffsetCurve))
237 {
1aec3320 238 myTypeCurve = GeomAbs_OffsetCurve;
94f71cad 239 // Create nested adaptor for base curve
240 Handle(Geom2d_Curve) aBase = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->BasisCurve();
241 myOffsetBaseCurveAdaptor = new Geom2dAdaptor_HCurve(aBase);
7fd59977 242 }
243 else {
244 myTypeCurve = GeomAbs_OtherCurve;
245 }
246 }
247}
248
249// --
250// -- Global methods - Apply to the whole curve.
251// --
252
253//=======================================================================
254//function : Continuity
255//purpose :
256//=======================================================================
257
258GeomAbs_Shape Geom2dAdaptor_Curve::Continuity() const
259{
260 if (myTypeCurve == GeomAbs_BSplineCurve) {
261 return LocalContinuity(myFirst, myLast);
262 }
1aec3320 263 else if (myTypeCurve == GeomAbs_OffsetCurve){
7fd59977 264 GeomAbs_Shape S =
c5f3a425 265 Handle(Geom2d_OffsetCurve)::DownCast (myCurve)->GetBasisCurveContinuity();
7fd59977 266 switch(S){
267 case GeomAbs_CN: return GeomAbs_CN;
268 case GeomAbs_C3: return GeomAbs_C2;
269 case GeomAbs_C2: return GeomAbs_C1;
270 case GeomAbs_C1: return GeomAbs_C0;
3d58dc49 271 case GeomAbs_G1: return GeomAbs_G1;
272 case GeomAbs_G2: return GeomAbs_G2;
273
7fd59977 274 default:
275 Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::Continuity");
276 }
277 }
278
279 else if (myTypeCurve == GeomAbs_OtherCurve) {
280 Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::Continuity");
281 }
282 else {
283 return GeomAbs_CN;
284 }
285
286 // portage WNT
287 return GeomAbs_CN;
288}
289
290//=======================================================================
291//function : NbIntervals
292//purpose :
293//=======================================================================
294
295Standard_Integer Geom2dAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
296{
297 Standard_Integer myNbIntervals = 1;
298 Standard_Integer NbSplit;
299 if (myTypeCurve == GeomAbs_BSplineCurve) {
c8b5b3d8 300 Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
301 Standard_Integer FirstIndex = aBspl->FirstUKnotIndex();
302 Standard_Integer LastIndex = aBspl->LastUKnotIndex();
7fd59977 303 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
304 if ( S > Continuity()) {
305 Standard_Integer Cont;
306 switch ( S) {
307 case GeomAbs_G1:
308 case GeomAbs_G2:
309 Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
310 break;
311 case GeomAbs_C0:
312 myNbIntervals = 1;
313 break;
314 case GeomAbs_C1:
315 case GeomAbs_C2:
316 case GeomAbs_C3:
317 case GeomAbs_CN:
318 {
319 if ( S == GeomAbs_C1) Cont = 1;
320 else if ( S == GeomAbs_C2) Cont = 2;
321 else if ( S == GeomAbs_C3) Cont = 3;
c8b5b3d8 322 else Cont = aBspl->Degree();
323 Standard_Integer Degree = aBspl->Degree();
324 Standard_Integer NbKnots = aBspl->NbKnots();
7fd59977 325 TColStd_Array1OfInteger Mults (1, NbKnots);
c8b5b3d8 326 aBspl->Multiplicities (Mults);
7fd59977 327 NbSplit = 1;
328 Standard_Integer Index = FirstIndex;
329 Inter (NbSplit) = Index;
330 Index++;
331 NbSplit++;
332 while (Index < LastIndex)
333 {
334 if (Degree - Mults (Index) < Cont)
335 {
336 Inter (NbSplit) = Index;
337 NbSplit++;
338 }
339 Index++;
340 }
341 Inter (NbSplit) = Index;
342
343 Standard_Integer NbInt = NbSplit-1;
344
c8b5b3d8 345 Standard_Integer Nb = aBspl->NbKnots();
7fd59977 346 Standard_Integer Index1 = 0;
347 Standard_Integer Index2 = 0;
348 Standard_Real newFirst, newLast;
349 TColStd_Array1OfReal TK(1,Nb);
350 TColStd_Array1OfInteger TM(1,Nb);
c8b5b3d8 351 aBspl->Knots(TK);
352 aBspl->Multiplicities(TM);
353 BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,myFirst,
354 aBspl->IsPeriodic(),
7fd59977 355 1,Nb,Index1,newFirst);
c8b5b3d8 356 BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,myLast,
357 aBspl->IsPeriodic(),
7fd59977 358 1,Nb,Index2,newLast);
359
360 // On decale eventuellement les indices
361 // On utilise une "petite" tolerance, la resolution ne doit
362 // servir que pour les tres longue courbes....(PRO9248)
363 Standard_Real Eps = Min(Resolution(Precision::Confusion()),
364 Precision::PConfusion());
365 if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
366 if ( newLast-TK(Index2)> Eps) Index2++;
367
368 myNbIntervals = 1;
369 for ( Standard_Integer i=1; i<=NbInt; i++)
370 if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
371 }
372 break;
373 }
374 }
375 }
1aec3320 376 else if (myTypeCurve == GeomAbs_OffsetCurve){
7fd59977 377 GeomAbs_Shape BaseS=GeomAbs_C0;
378 switch(S){
379 case GeomAbs_G1:
380 case GeomAbs_G2:
381 Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
382 break;
383 case GeomAbs_C0: BaseS = GeomAbs_C1; break;
384 case GeomAbs_C1: BaseS = GeomAbs_C2; break;
385 case GeomAbs_C2: BaseS = GeomAbs_C3; break;
386 default: BaseS = GeomAbs_CN;
387 }
94f71cad 388 myNbIntervals = myOffsetBaseCurveAdaptor->NbIntervals(BaseS);
7fd59977 389 }
390
391 return myNbIntervals;
392}
393
394//=======================================================================
395//function : Intervals
396//purpose :
397//=======================================================================
398
399void Geom2dAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
400 const GeomAbs_Shape S ) const
401{
402 Standard_Integer myNbIntervals = 1;
403 Standard_Integer NbSplit;
404 if (myTypeCurve == GeomAbs_BSplineCurve) {
c8b5b3d8 405 Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
406 Standard_Integer FirstIndex = aBspl->FirstUKnotIndex();
407 Standard_Integer LastIndex = aBspl->LastUKnotIndex();
7fd59977 408 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
409 if ( S > Continuity()) {
410 Standard_Integer Cont;
411 switch ( S) {
412 case GeomAbs_G1:
413 case GeomAbs_G2:
414 Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
415 break;
416 case GeomAbs_C0:
417 myNbIntervals = 1;
418 break;
419 case GeomAbs_C1:
420 case GeomAbs_C2:
421 case GeomAbs_C3:
422 case GeomAbs_CN:
423 {
424 if ( S == GeomAbs_C1) Cont = 1;
425 else if ( S == GeomAbs_C2) Cont = 2;
426 else if ( S == GeomAbs_C3) Cont = 3;
c8b5b3d8 427 else Cont = aBspl->Degree();
428 Standard_Integer Degree = aBspl->Degree();
429 Standard_Integer NbKnots = aBspl->NbKnots();
7fd59977 430 TColStd_Array1OfInteger Mults (1, NbKnots);
c8b5b3d8 431 aBspl->Multiplicities (Mults);
7fd59977 432 NbSplit = 1;
433 Standard_Integer Index = FirstIndex;
434 Inter (NbSplit) = Index;
435 Index++;
436 NbSplit++;
437 while (Index < LastIndex)
438 {
439 if (Degree - Mults (Index) < Cont)
440 {
441 Inter (NbSplit) = Index;
442 NbSplit++;
443 }
444 Index++;
445 }
446 Inter (NbSplit) = Index;
447 Standard_Integer NbInt = NbSplit-1;
448
c8b5b3d8 449 Standard_Integer Nb = aBspl->NbKnots();
7fd59977 450 Standard_Integer Index1 = 0;
451 Standard_Integer Index2 = 0;
452 Standard_Real newFirst, newLast;
453 TColStd_Array1OfReal TK(1,Nb);
454 TColStd_Array1OfInteger TM(1,Nb);
c8b5b3d8 455 aBspl->Knots(TK);
456 aBspl->Multiplicities(TM);
457 BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,myFirst,
458 aBspl->IsPeriodic(),
7fd59977 459 1,Nb,Index1,newFirst);
c8b5b3d8 460 BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,myLast,
461 aBspl->IsPeriodic(),
7fd59977 462 1,Nb,Index2,newLast);
463
464
465 // On decale eventuellement les indices
466 // On utilise une "petite" tolerance, la resolution ne doit
467 // servir que pour les tres longue courbes....(PRO9248)
468 Standard_Real Eps = Min(Resolution(Precision::Confusion()),
469 Precision::PConfusion());
470 if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
471 if ( newLast-TK(Index2)> Eps) Index2++;
472
473 Inter( 1) = Index1;
474 myNbIntervals = 1;
475 for ( Standard_Integer i=1; i<=NbInt; i++) {
476 if (Inter(i) > Index1 && Inter(i)<Index2 ) {
477 myNbIntervals++;
478 Inter(myNbIntervals) = Inter(i);
479 }
480 }
481 Inter(myNbIntervals+1) = Index2;
482
483 Standard_Integer ii = T.Lower() - 1;
484 for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
485 T(ii + I) = TK(Inter(I));
486 }
487 }
488 break;
489 }
490 }
491 }
1aec3320 492 else if (myTypeCurve == GeomAbs_OffsetCurve){
7fd59977 493 GeomAbs_Shape BaseS=GeomAbs_C0;
494 switch(S){
495 case GeomAbs_G1:
496 case GeomAbs_G2:
497 Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
498 break;
499 case GeomAbs_C0: BaseS = GeomAbs_C1; break;
500 case GeomAbs_C1: BaseS = GeomAbs_C2; break;
501 case GeomAbs_C2: BaseS = GeomAbs_C3; break;
502 default: BaseS = GeomAbs_CN;
503 }
94f71cad 504 myNbIntervals = myOffsetBaseCurveAdaptor->NbIntervals(BaseS);
505 myOffsetBaseCurveAdaptor->Intervals(T, BaseS);
7fd59977 506 }
507
508 T( T.Lower() ) = myFirst;
509 T( T.Lower() + myNbIntervals ) = myLast;
510}
511
512//=======================================================================
513//function : Trim
514//purpose :
515//=======================================================================
516
517Handle(Adaptor2d_HCurve2d) Geom2dAdaptor_Curve::Trim
518(const Standard_Real First,
519 const Standard_Real Last,
520// const Standard_Real Tol) const
521 const Standard_Real ) const
522{
523 Handle(Geom2dAdaptor_HCurve) HE = new Geom2dAdaptor_HCurve(myCurve,First,Last);
524 return HE;
525}
526
527
528//=======================================================================
529//function : IsClosed
530//purpose :
531//=======================================================================
532
533Standard_Boolean Geom2dAdaptor_Curve::IsClosed() const
534{
535 if (!Precision::IsPositiveInfinite(myLast) &&
536 !Precision::IsNegativeInfinite(myFirst)) {
537 gp_Pnt2d Pd = Value(myFirst);
538 gp_Pnt2d Pf = Value(myLast);
539 return ( Pd.Distance(Pf) <= Precision::Confusion());
540 }
541 else
542 return Standard_False;
543}
544
545//=======================================================================
546//function : IsPeriodic
547//purpose :
548//=======================================================================
549
550Standard_Boolean Geom2dAdaptor_Curve::IsPeriodic() const
551{
552 if (myCurve->IsPeriodic())
553 return IsClosed();
554 else
555 return Standard_False;
556}
557
558//=======================================================================
559//function : Period
560//purpose :
561//=======================================================================
562
563Standard_Real Geom2dAdaptor_Curve::Period() const
564{
565 return myCurve->LastParameter() - myCurve->FirstParameter();
566}
567
568//=======================================================================
94f71cad 569//function : RebuildCache
570//purpose :
571//=======================================================================
572void Geom2dAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
573{
c8b5b3d8 574 if (myTypeCurve == GeomAbs_BezierCurve)
575 {
576 Handle(Geom2d_BezierCurve) aBezier = Handle(Geom2d_BezierCurve)::DownCast(myCurve);
577 Standard_Integer aDeg = aBezier->Degree();
578 TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
579 myCurveCache->BuildCache(theParameter, aDeg, aBezier->IsPeriodic(), aFlatKnots,
580 aBezier->Poles(), aBezier->Weights());
581 }
582 else if (myTypeCurve == GeomAbs_BSplineCurve)
583 {
584 Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
585 myCurveCache->BuildCache(theParameter, aBspl->Degree(),
586 aBspl->IsPeriodic(), aBspl->KnotSequence(),
587 aBspl->Poles(), aBspl->Weights());
588 }
94f71cad 589}
590
591//=======================================================================
7fd59977 592//function : Value
593//purpose :
594//=======================================================================
595
596gp_Pnt2d Geom2dAdaptor_Curve::Value(const Standard_Real U) const
597{
94f71cad 598 if (myTypeCurve == GeomAbs_BSplineCurve)
599 return ValueBSpline(U);
1aec3320 600 else if (myTypeCurve == GeomAbs_OffsetCurve)
94f71cad 601 return ValueOffset(U);
c8b5b3d8 602 else if (myTypeCurve == GeomAbs_BezierCurve)
603 { // use cached data
604 gp_Pnt2d aRes;
605 myCurveCache->D0(U, aRes);
606 return aRes;
607 }
94f71cad 608
609 return myCurve->Value(U);
610}
611
612//=======================================================================
613//function : ValueBSpline
614//purpose : Computes the point of parameter U on the B-spline curve
615//=======================================================================
616gp_Pnt2d Geom2dAdaptor_Curve::ValueBSpline(const Standard_Real theU) const
617{
618 if (theU == myFirst || theU == myLast)
619 {
c8b5b3d8 620 Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
1d47d8d0 621 Standard_Integer Ideb = 0, Ifin = 0;
94f71cad 622 if (theU == myFirst)
623 {
c8b5b3d8 624 aBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
7fd59977 625 if (Ideb<1) Ideb=1;
626 if (Ideb>=Ifin) Ifin = Ideb+1;
627 }
94f71cad 628 if (theU == myLast)
629 {
c8b5b3d8 630 aBspl->LocateU(myLast, PosTol, Ideb, Ifin);
631 if (Ifin > aBspl->NbKnots()) Ifin = aBspl->NbKnots();
7fd59977 632 if (Ideb>=Ifin) Ideb = Ifin-1;
633 }
c8b5b3d8 634 return aBspl->LocalValue(theU, Ideb, Ifin);
7fd59977 635 }
94f71cad 636 else if (!myCurveCache.IsNull()) // use cached B-spline data
637 {
638 if (!myCurveCache->IsCacheValid(theU))
639 RebuildCache(theU);
640 gp_Pnt2d aRes;
641 myCurveCache->D0(theU, aRes);
642 return aRes;
7fd59977 643 }
94f71cad 644 return myCurve->Value(theU);
645}
646
647//=======================================================================
648//function : ValueOffset
649//purpose : Computes the point of parameter U on the offset curve
650//=======================================================================
651gp_Pnt2d Geom2dAdaptor_Curve::ValueOffset(const Standard_Real theU) const
652{
653 gp_Pnt2d aP;
654 gp_Vec2d aD1;
655 myOffsetBaseCurveAdaptor->D1(theU, aP, aD1);
656 Standard_Boolean isDirectionChange = Standard_False;
657 const Standard_Real aTol = gp::Resolution();
658 if(aD1.SquareMagnitude() <= aTol)
659 isDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 1, theU, aD1);
660
661 Standard_Real anOffset = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->Offset();
662 CSLib_Offset::D0(aP, aD1, anOffset, isDirectionChange, aP);
663 return aP;
7fd59977 664}
665
666//=======================================================================
667//function : D0
668//purpose :
669//=======================================================================
670
671void Geom2dAdaptor_Curve::D0(const Standard_Real U, gp_Pnt2d& P) const
672{
94f71cad 673 if (myTypeCurve == GeomAbs_BSplineCurve)
94f71cad 674 D0BSpline(U, P);
1aec3320 675 else if (myTypeCurve == GeomAbs_OffsetCurve)
94f71cad 676 D0Offset(U, P);
c8b5b3d8 677 else if (myTypeCurve == GeomAbs_BezierCurve) // use cached data
678 myCurveCache->D0(U, P);
679 else
680 myCurve->D0(U, P);
94f71cad 681}
682
683//=======================================================================
684//function : D0BSpline
685//purpose : Computes the point of parameter theU on the B-spline curve
686//=======================================================================
687void Geom2dAdaptor_Curve::D0BSpline(const Standard_Real theU, gp_Pnt2d& theP) const
688{
689 if (theU == myFirst || theU == myLast)
690 {
c8b5b3d8 691 Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
1d47d8d0 692 Standard_Integer Ideb = 0, Ifin = 0;
94f71cad 693 if (theU == myFirst) {
c8b5b3d8 694 aBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
7fd59977 695 if (Ideb<1) Ideb=1;
696 if (Ideb>=Ifin) Ifin = Ideb+1;
697 }
94f71cad 698 if (theU == myLast) {
c8b5b3d8 699 aBspl->LocateU(myLast, PosTol, Ideb, Ifin);
700 if (Ifin > aBspl->NbKnots()) Ifin = aBspl->NbKnots();
7fd59977 701 if (Ideb>=Ifin) Ideb = Ifin-1;
702 }
c8b5b3d8 703 aBspl->LocalD0(theU, Ideb, Ifin, theP);
94f71cad 704 return;
7fd59977 705 }
94f71cad 706 else if (!myCurveCache.IsNull()) // use cached B-spline data
707 {
708 if (!myCurveCache->IsCacheValid(theU))
709 RebuildCache(theU);
710 myCurveCache->D0(theU, theP);
711 return;
712 }
713 myCurve->D0(theU, theP);
714}
715
716//=======================================================================
717//function : D0Offset
718//purpose : Computes the point of parameter theU on the offset curve
719//=======================================================================
720void Geom2dAdaptor_Curve::D0Offset(const Standard_Real theU, gp_Pnt2d& theP) const
721{
722 theP = ValueOffset(theU);
7fd59977 723}
724
725//=======================================================================
726//function : D1
727//purpose :
728//=======================================================================
729
94f71cad 730void Geom2dAdaptor_Curve::D1(const Standard_Real U,
731 gp_Pnt2d& P, gp_Vec2d& V) const
732{
733 if (myTypeCurve == GeomAbs_BSplineCurve)
94f71cad 734 D1BSpline(U, P, V);
1aec3320 735 else if (myTypeCurve == GeomAbs_OffsetCurve)
94f71cad 736 D1Offset(U, P, V);
c8b5b3d8 737 else if (myTypeCurve == GeomAbs_BezierCurve) // use cached data
738 myCurveCache->D1(U, P, V);
739 else
740 myCurve->D1(U, P, V);
94f71cad 741}
742
743//=======================================================================
744//function : D1BSpline
745//purpose : Computes the point of parameter theU on the B-spline curve and its derivative
746//=======================================================================
747void Geom2dAdaptor_Curve::D1BSpline(const Standard_Real theU, gp_Pnt2d& theP, gp_Vec2d& theV) const
7fd59977 748{
94f71cad 749 if (theU == myFirst || theU == myLast)
750 {
c8b5b3d8 751 Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
1d47d8d0 752 Standard_Integer Ideb = 0, Ifin = 0;
94f71cad 753 if (theU == myFirst) {
c8b5b3d8 754 aBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
7fd59977 755 if (Ideb<1) Ideb=1;
756 if (Ideb>=Ifin) Ifin = Ideb+1;
757 }
94f71cad 758 if (theU == myLast) {
c8b5b3d8 759 aBspl->LocateU(myLast, PosTol, Ideb, Ifin);
760 if (Ifin > aBspl->NbKnots()) Ifin = aBspl->NbKnots();
7fd59977 761 if (Ideb>=Ifin) Ideb = Ifin-1;
762 }
c8b5b3d8 763 aBspl->LocalD1(theU, Ideb, Ifin, theP, theV);
94f71cad 764 return;
7fd59977 765 }
94f71cad 766 else if (!myCurveCache.IsNull()) // use cached B-spline data
767 {
768 if (!myCurveCache->IsCacheValid(theU))
769 RebuildCache(theU);
770 myCurveCache->D1(theU, theP, theV);
771 return;
772 }
773 myCurve->D1(theU, theP, theV);
774}
775
776//=======================================================================
777//function : D1Offset
778//purpose : Computes the point of parameter theU on the offset curve and its derivative
779//=======================================================================
780void Geom2dAdaptor_Curve::D1Offset(const Standard_Real theU, gp_Pnt2d& theP, gp_Vec2d& theV) const
781{
782 // P(u) = p(u) + Offset * Ndir / R
783 // with R = || p' ^ Z|| and Ndir = P' ^ Z
784
785 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
786
787 gp_Vec2d V2;
788 myOffsetBaseCurveAdaptor->D2 (theU, theP, theV, V2);
789
790 Standard_Boolean IsDirectionChange = Standard_False;
791 if(theV.SquareMagnitude() <= gp::Resolution())
792 IsDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 2, theU, theV, V2);
793
794 Standard_Real anOffset = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->Offset();
795 CSLib_Offset::D1(theP, theV, V2, anOffset, IsDirectionChange, theP, theV);
7fd59977 796}
797
798//=======================================================================
799//function : D2
800//purpose :
801//=======================================================================
802
803void Geom2dAdaptor_Curve::D2(const Standard_Real U,
94f71cad 804 gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const
7fd59977 805{
94f71cad 806 if (myTypeCurve == GeomAbs_BSplineCurve)
94f71cad 807 D2BSpline(U, P, V1, V2);
1aec3320 808 else if (myTypeCurve == GeomAbs_OffsetCurve)
94f71cad 809 D2Offset(U, P, V1, V2);
c8b5b3d8 810 else if (myTypeCurve == GeomAbs_BezierCurve) // use cached data
811 myCurveCache->D2(U, P, V1, V2);
812 else
813 myCurve->D2(U, P, V1, V2);
94f71cad 814}
815
816//=======================================================================
817//function : D2BSpline
818//purpose : Computes the point of parameter theU on the B-spline curve and its first and second derivatives
819//=======================================================================
820void Geom2dAdaptor_Curve::D2BSpline(const Standard_Real theU, gp_Pnt2d& theP,
821 gp_Vec2d& theV1, gp_Vec2d& theV2) const
822{
823 if (theU == myFirst || theU == myLast)
824 {
c8b5b3d8 825 Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
1d47d8d0 826 Standard_Integer Ideb = 0, Ifin = 0;
94f71cad 827 if (theU == myFirst) {
c8b5b3d8 828 aBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
7fd59977 829 if (Ideb<1) Ideb=1;
830 if (Ideb>=Ifin) Ifin = Ideb+1;
831 }
94f71cad 832 if (theU == myLast) {
c8b5b3d8 833 aBspl->LocateU(myLast, PosTol, Ideb, Ifin);
834 if (Ifin > aBspl->NbKnots()) Ifin = aBspl->NbKnots();
7fd59977 835 if (Ideb>=Ifin) Ideb = Ifin-1;
836 }
c8b5b3d8 837 aBspl->LocalD2(theU, Ideb, Ifin, theP, theV1, theV2);
94f71cad 838 return;
7fd59977 839 }
94f71cad 840 else if (!myCurveCache.IsNull()) // use cached B-spline data
841 {
842 if (!myCurveCache->IsCacheValid(theU))
843 RebuildCache(theU);
844 myCurveCache->D2(theU, theP, theV1, theV2);
845 return;
7fd59977 846 }
94f71cad 847 myCurve->D2(theU, theP, theV1, theV2);
848}
849//=======================================================================
850//function : D2Offset
851//purpose : Computes the point of parameter theU on the offset curve and its first and second derivatives
852//=======================================================================
853void Geom2dAdaptor_Curve::D2Offset(const Standard_Real theU, gp_Pnt2d& theP,
854 gp_Vec2d& theV1, gp_Vec2d& theV2) const
855{
856 // P(u) = p(u) + Offset * Ndir / R
857 // with R = || p' ^ Z|| and Ndir = P' ^ Z
858
859 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
860
861 // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
862 // Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
863
864 gp_Vec2d V3;
865 myOffsetBaseCurveAdaptor->D3 (theU, theP, theV1, theV2, V3);
866
867 Standard_Boolean IsDirectionChange = Standard_False;
868 if(theV1.SquareMagnitude() <= gp::Resolution())
869 IsDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 3, theU, theV1, theV2, V3);
870
871 Standard_Real anOffset = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->Offset();
872 CSLib_Offset::D2(theP, theV1, theV2, V3, anOffset, IsDirectionChange, theP, theV1, theV2);
7fd59977 873}
874
875//=======================================================================
876//function : D3
877//purpose :
878//=======================================================================
879
880void Geom2dAdaptor_Curve::D3(const Standard_Real U,
94f71cad 881 gp_Pnt2d& P, gp_Vec2d& V1,
882 gp_Vec2d& V2, gp_Vec2d& V3) const
7fd59977 883{
94f71cad 884 if (myTypeCurve == GeomAbs_BSplineCurve)
94f71cad 885 D3BSpline(U, P, V1, V2, V3);
1aec3320 886 else if (myTypeCurve == GeomAbs_OffsetCurve)
94f71cad 887 D3Offset(U, P, V1, V2, V3);
c8b5b3d8 888 else if (myTypeCurve == GeomAbs_BezierCurve) // use cached data
889 myCurveCache->D3(U, P, V1, V2, V3);
890 else
891 myCurve->D3(U, P, V1, V2, V3);
94f71cad 892}
893
894//=======================================================================
895//function : D3BSpline
896//purpose : Computes the point of parameter theU on the B-spline curve and its 1st - 3rd derivatives
897//=======================================================================
898void Geom2dAdaptor_Curve::D3BSpline(const Standard_Real theU, gp_Pnt2d& theP,
899 gp_Vec2d& theV1, gp_Vec2d& theV2, gp_Vec2d& theV3) const
900{
901 if (theU == myFirst || theU == myLast)
902 {
c8b5b3d8 903 Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
1d47d8d0 904 Standard_Integer Ideb = 0, Ifin = 0;
94f71cad 905 if (theU == myFirst) {
c8b5b3d8 906 aBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
7fd59977 907 if (Ideb<1) Ideb=1;
908 if (Ideb>=Ifin) Ifin = Ideb+1;
909 }
94f71cad 910 if (theU == myLast) {
c8b5b3d8 911 aBspl->LocateU(myLast, PosTol, Ideb, Ifin);
912 if (Ifin > aBspl->NbKnots()) Ifin = aBspl->NbKnots();
7fd59977 913 if (Ideb>=Ifin) Ideb = Ifin-1;
914 }
c8b5b3d8 915 aBspl->LocalD3(theU, Ideb, Ifin, theP, theV1, theV2, theV3);
94f71cad 916 return;
7fd59977 917 }
94f71cad 918 else if (!myCurveCache.IsNull()) // use cached B-spline data
919 {
920 if (!myCurveCache->IsCacheValid(theU))
921 RebuildCache(theU);
922 myCurveCache->D3(theU, theP, theV1, theV2, theV3);
923 return;
7fd59977 924 }
94f71cad 925 myCurve->D3(theU, theP, theV1, theV2, theV3);
926}
927//=======================================================================
928//function : D3Offset
929//purpose : Computes the point of parameter theU on the offset curve and its 1st - 3rd derivatives
930//=======================================================================
931void Geom2dAdaptor_Curve::D3Offset(const Standard_Real theU, gp_Pnt2d& theP,
932 gp_Vec2d& theV1, gp_Vec2d& theV2, gp_Vec2d& theV3) const
933{
934 // P(u) = p(u) + Offset * Ndir / R
935 // with R = || p' ^ Z|| and Ndir = P' ^ Z
936
937 // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R - Ndir * (DR/R))
938
939 // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
940 // Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
941
942 //P"'(u) = p"'(u) + (Offset / R) * (D3Ndir - (3.0 * Dr/R**2 ) * D2Ndir -
943 // (3.0 * D2r / R2) * DNdir) + (3.0 * Dr * Dr / R4) * DNdir -
944 // (D3r/R2) * Ndir + (6.0 * Dr * Dr / R4) * Ndir +
945 // (6.0 * Dr * D2r / R4) * Ndir - (15.0 * Dr* Dr* Dr /R6) * Ndir
946
947 Standard_Boolean IsDirectionChange = Standard_False;
948
949 myOffsetBaseCurveAdaptor->D3 (theU, theP, theV1, theV2, theV3);
950 gp_Vec2d V4 = myOffsetBaseCurveAdaptor->DN (theU, 4);
951
952 if(theV1.SquareMagnitude() <= gp::Resolution())
953 IsDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 4, theU, theV1, theV2, theV3, V4);
954
955 Standard_Real anOffset = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->Offset();
956 CSLib_Offset::D3(theP, theV1, theV2, theV3, V4, anOffset, IsDirectionChange,
957 theP, theV1, theV2, theV3);
7fd59977 958}
959
960//=======================================================================
961//function : DN
962//purpose :
963//=======================================================================
964
965gp_Vec2d Geom2dAdaptor_Curve::DN(const Standard_Real U,
94f71cad 966 const Standard_Integer N) const
7fd59977 967{
94f71cad 968 if (myTypeCurve == GeomAbs_BSplineCurve)
969 return DNBSpline(U, N);
1aec3320 970 else if (myTypeCurve == GeomAbs_OffsetCurve)
94f71cad 971 return DNOffset(U, N);
972
973 return myCurve->DN(U, N);
974}
975
976gp_Vec2d Geom2dAdaptor_Curve::DNBSpline(const Standard_Real U,
977 const Standard_Integer N) const
978{
979 if (U==myFirst || U==myLast)
980 {
c8b5b3d8 981 Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
1d47d8d0 982 Standard_Integer Ideb = 0, Ifin = 0;
7fd59977 983 if (U==myFirst) {
c8b5b3d8 984 aBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
7fd59977 985 if (Ideb<1) Ideb=1;
986 if (Ideb>=Ifin) Ifin = Ideb+1;
987 }
988 if (U==myLast) {
c8b5b3d8 989 aBspl->LocateU(myLast, PosTol, Ideb, Ifin);
990 if (Ifin > aBspl->NbKnots()) Ifin = aBspl->NbKnots();
7fd59977 991 if (Ideb>=Ifin) Ideb = Ifin-1;
992 }
c8b5b3d8 993 return aBspl->LocalDN( U, Ideb, Ifin, N);
7fd59977 994 }
94f71cad 995
996 return myCurve->DN( U, N);
997}
998
999gp_Vec2d Geom2dAdaptor_Curve::DNOffset(const Standard_Real U,
1000 const Standard_Integer N) const
1001{
1002 gp_Pnt2d aPnt;
1003 gp_Vec2d aVec, aVN;
1004
1005 switch (N)
1006 {
1007 case 1:
1008 D1Offset(U, aPnt, aVN);
1009 break;
1010 case 2:
1011 D2Offset(U, aPnt, aVec, aVN);
1012 break;
1013 case 3:
1014 D3Offset(U, aPnt, aVec, aVec, aVN);
1015 break;
1016 default:
1017 aVN = myCurve->DN(U, N);
1018 }
1019 return aVN;
7fd59977 1020}
1021
1022//=======================================================================
1023//function : Resolution
1024//purpose :
1025//=======================================================================
1026
1027Standard_Real Geom2dAdaptor_Curve::Resolution(const Standard_Real Ruv) const {
1028 switch ( myTypeCurve) {
1029 case GeomAbs_Line :
1030 return Ruv;
1031 case GeomAbs_Circle: {
c5f3a425 1032 Standard_Real R = Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d().Radius();
7fd59977 1033 if ( R > Ruv/2.)
1034 return 2*ASin(Ruv/(2*R));
1035 else
c6541a0c 1036 return 2*M_PI;
7fd59977 1037 }
1038 case GeomAbs_Ellipse: {
c5f3a425 1039 return Ruv / Handle(Geom2d_Ellipse)::DownCast (myCurve)->MajorRadius();
7fd59977 1040 }
1041 case GeomAbs_BezierCurve: {
1042 Standard_Real res;
c5f3a425 1043 Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Resolution(Ruv,res);
7fd59977 1044 return res;
1045 }
1046 case GeomAbs_BSplineCurve: {
1047 Standard_Real res;
c5f3a425 1048 Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->Resolution(Ruv,res);
7fd59977 1049 return res;
1050 }
1051 default:
1052 return Precision::Parametric(Ruv);
1053 }
1054}
1055
1056
1057// --
1058// -- The following methods must be called when GetType returned
1059// -- the corresponding type.
1060// --
1061
1062//=======================================================================
1063//function : Line
1064//purpose :
1065//=======================================================================
1066
1067gp_Lin2d Geom2dAdaptor_Curve::Line() const
1068{
1069 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
c5f3a425 1070 return Handle(Geom2d_Line)::DownCast (myCurve)->Lin2d();
7fd59977 1071}
1072
1073//=======================================================================
1074//function : Circle
1075//purpose :
1076//=======================================================================
1077
1078gp_Circ2d Geom2dAdaptor_Curve::Circle() const
1079{
1080 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
c5f3a425 1081 return Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d();
7fd59977 1082}
1083
1084//=======================================================================
1085//function : Ellipse
1086//purpose :
1087//=======================================================================
1088
1089gp_Elips2d Geom2dAdaptor_Curve::Ellipse() const
1090{
1091 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Ellipse, "");
c5f3a425 1092 return Handle(Geom2d_Ellipse)::DownCast (myCurve)->Elips2d();
7fd59977 1093}
1094
1095//=======================================================================
1096//function : Hyperbola
1097//purpose :
1098//=======================================================================
1099
1100gp_Hypr2d Geom2dAdaptor_Curve::Hyperbola() const
1101{
1102 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
c5f3a425 1103 return Handle(Geom2d_Hyperbola)::DownCast (myCurve)->Hypr2d();
7fd59977 1104}
1105
1106//=======================================================================
1107//function : Parabola
1108//purpose :
1109//=======================================================================
1110
1111gp_Parab2d Geom2dAdaptor_Curve::Parabola() const
1112{
1113 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
c5f3a425 1114 return Handle(Geom2d_Parabola)::DownCast (myCurve)->Parab2d();
7fd59977 1115}
1116
1117//=======================================================================
1118//function : Degree
1119//purpose :
1120//=======================================================================
1121
1122Standard_Integer Geom2dAdaptor_Curve::Degree() const
1123{
1124 if (myTypeCurve == GeomAbs_BezierCurve)
c5f3a425 1125 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Degree();
7fd59977 1126 else if (myTypeCurve == GeomAbs_BSplineCurve)
c5f3a425 1127 return Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->Degree();
7fd59977 1128 else
1129 Standard_NoSuchObject::Raise();
1130 // portage WNT
1131 return 0;
1132}
1133
1134//=======================================================================
1135//function : IsRational
1136//purpose :
1137//=======================================================================
1138
1139Standard_Boolean Geom2dAdaptor_Curve::IsRational() const {
1140 switch( myTypeCurve) {
1141 case GeomAbs_BSplineCurve:
c5f3a425 1142 return Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->IsRational();
7fd59977 1143 case GeomAbs_BezierCurve:
c5f3a425 1144 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->IsRational();
7fd59977 1145 default:
1146 return Standard_False;
1147 }
1148}
1149
1150//=======================================================================
1151//function : NbPoles
1152//purpose :
1153//=======================================================================
1154
1155Standard_Integer Geom2dAdaptor_Curve::NbPoles() const
1156{
1157 if (myTypeCurve == GeomAbs_BezierCurve)
c5f3a425 1158 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->NbPoles();
7fd59977 1159 else if (myTypeCurve == GeomAbs_BSplineCurve)
c5f3a425 1160 return Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->NbPoles();
7fd59977 1161 else
1162 Standard_NoSuchObject::Raise();
1163 // portage WNT
1164 return 0;
1165}
1166
1167//=======================================================================
1168//function : NbKnots
1169//purpose :
1170//=======================================================================
1171
1172Standard_Integer Geom2dAdaptor_Curve::NbKnots() const {
1173 if ( myTypeCurve != GeomAbs_BSplineCurve)
1174 Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::NbKnots");
c5f3a425 1175 return Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->NbKnots();
7fd59977 1176
1177}
1178
1179//=======================================================================
1180//function : Bezier
1181//purpose :
1182//=======================================================================
1183
1184Handle(Geom2d_BezierCurve) Geom2dAdaptor_Curve::Bezier() const
1185{
c5f3a425 1186 return Handle(Geom2d_BezierCurve)::DownCast (myCurve);
7fd59977 1187}
1188
1189//=======================================================================
1190//function : BSpline
1191//purpose :
1192//=======================================================================
1193
1194Handle(Geom2d_BSplineCurve) Geom2dAdaptor_Curve::BSpline() const
1195{
c5f3a425 1196 return Handle(Geom2d_BSplineCurve)::DownCast (myCurve);
7fd59977 1197}
1198
a874a4a0 1199static Standard_Integer nbPoints(const Handle(Geom2d_Curve)& theCurve)
1200{
1201
1202 Standard_Integer nbs = 10;
1203
1204 if(theCurve->IsKind(STANDARD_TYPE( Geom2d_Line)) )
1205 nbs = 2;
1206 else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BezierCurve)))
1207 {
c5f3a425 1208 nbs = 3 + Handle(Geom2d_BezierCurve)::DownCast (theCurve)->NbPoles();
a874a4a0 1209 }
1210 else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BSplineCurve))) {
c5f3a425 1211 nbs = Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->NbKnots();
1212 nbs*= Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->Degree();
a874a4a0 1213 if(nbs < 2.0) nbs=2;
1214 }
1215 else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
1216 {
c5f3a425 1217 Handle(Geom2d_Curve) aCurve = Handle(Geom2d_OffsetCurve)::DownCast (theCurve)->BasisCurve();
a874a4a0 1218 return Max(nbs, nbPoints(aCurve));
1219 }
1220
1221 else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
1222 {
c5f3a425 1223 Handle(Geom2d_Curve) aCurve = Handle(Geom2d_TrimmedCurve)::DownCast (theCurve)->BasisCurve();
a874a4a0 1224 return Max(nbs, nbPoints(aCurve));
1225 }
1226 if(nbs>300)
1227 nbs = 300;
1228 return nbs;
1229
1230}
1231
1232Standard_Integer Geom2dAdaptor_Curve::NbSamples() const
1233{
1234 return nbPoints(myCurve);
1235}
94f71cad 1236
1237
1238// ============= Auxiliary functions ===================
1239Standard_Boolean AdjustDerivative(const Handle(Adaptor2d_HCurve2d)& theAdaptor, Standard_Integer theMaxDerivative,
1240 Standard_Real theU, gp_Vec2d& theD1, gp_Vec2d& theD2,
1241 gp_Vec2d& theD3, gp_Vec2d& theD4)
1242{
1243 static const Standard_Real aTol = gp::Resolution();
1244
1245 Standard_Boolean IsDirectionChange = Standard_False;
1246 const Standard_Real anUinfium = theAdaptor->FirstParameter();
1247 const Standard_Real anUsupremum = theAdaptor->LastParameter();
1248
1249 const Standard_Real DivisionFactor = 1.e-3;
1250 Standard_Real du;
1251 if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
1252 du = 0.0;
1253 else
1254 du = anUsupremum - anUinfium;
1255
1256 const Standard_Real aDelta = Max(du * DivisionFactor, MinStep);
1257
1258 //Derivative is approximated by Taylor-series
1259 Standard_Integer anIndex = 1; //Derivative order
1260 gp_Vec2d V;
1261
1262 do
1263 {
1264 V = theAdaptor->DN(theU, ++anIndex);
1265 }
1266 while((V.Magnitude() <= aTol) && anIndex < maxDerivOrder);
1267
1268 Standard_Real u;
1269
1270 if(theU-anUinfium < aDelta)
1271 u = theU+aDelta;
1272 else
1273 u = theU-aDelta;
1274
1275 gp_Pnt2d P1, P2;
1276 theAdaptor->D0(Min(theU, u),P1);
1277 theAdaptor->D0(Max(theU, u),P2);
1278
1279 gp_Vec2d V1(P1, P2);
1280 IsDirectionChange = V.Dot(V1) < 0.0;
1281 Standard_Real aSign = IsDirectionChange ? -1.0 : 1.0;
1282
1283 theD1 = V * aSign;
1284 gp_Vec2d* aDeriv[3] = {&theD2, &theD3, &theD4};
1285 for (Standard_Integer i = 1; i < theMaxDerivative; i++)
1286 *(aDeriv[i-1]) = theAdaptor->DN(theU, anIndex + i) * aSign;
1287
1288 return IsDirectionChange;
1289}