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