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