0027490: BRepMesh: Reduce number of memory allocations
[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>
7fd59977 28#include <Geom_BezierCurve.hxx>
29#include <Geom_BSplineCurve.hxx>
42cf5bc1 30#include <Geom_Circle.hxx>
31#include <Geom_Curve.hxx>
7fd59977 32#include <Geom_Ellipse.hxx>
7fd59977 33#include <Geom_Hyperbola.hxx>
42cf5bc1 34#include <Geom_Line.hxx>
35#include <Geom_OffsetCurve.hxx>
36#include <Geom_Parabola.hxx>
37#include <Geom_TrimmedCurve.hxx>
38#include <GeomAbs_Shape.hxx>
39#include <GeomAdaptor_Curve.hxx>
40#include <GeomAdaptor_HCurve.hxx>
41#include <GeomAdaptor_Surface.hxx>
d660a72a 42#include <GeomEvaluator_OffsetCurve.hxx>
42cf5bc1 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
94f71cad 65
7fd59977 66//=======================================================================
67//function : LocalContinuity
68//purpose : Computes the Continuity of a BSplineCurve
69// between the parameters U1 and U2
70// The continuity is C(d-m)
71// with d = degree,
72// m = max multiplicity of the Knots between U1 and U2
73//=======================================================================
74
75GeomAbs_Shape GeomAdaptor_Curve::LocalContinuity(const Standard_Real U1,
76 const Standard_Real U2)
77 const
78{
79 Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
3b25c0e8 80 Standard_Integer Nb = myBSplineCurve->NbKnots();
7fd59977 81 Standard_Integer Index1 = 0;
82 Standard_Integer Index2 = 0;
83 Standard_Real newFirst, newLast;
e1c1b6b9 84 const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
85 const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
3b25c0e8 86 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U1,myBSplineCurve->IsPeriodic(),
7fd59977 87 1,Nb,Index1,newFirst);
3b25c0e8 88 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U2,myBSplineCurve->IsPeriodic(),
7fd59977 89 1,Nb,Index2,newLast);
90 if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) {
91 if (Index1 < Nb) Index1++;
92 }
93 if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
94 Index2--;
95 Standard_Integer MultMax;
96 // attention aux courbes peridiques.
3b25c0e8 97 if ( (myBSplineCurve->IsPeriodic()) && (Index1 == Nb) )
7fd59977 98 Index1 = 1;
99
100 if ( Index2 - Index1 <= 0) {
101 MultMax = 100; // CN entre 2 Noeuds consecutifs
102 }
103 else {
104 MultMax = TM(Index1+1);
105 for(Standard_Integer i = Index1+1;i<=Index2;i++) {
106 if ( TM(i)>MultMax) MultMax=TM(i);
107 }
3b25c0e8 108 MultMax = myBSplineCurve->Degree() - MultMax;
7fd59977 109 }
110 if ( MultMax <= 0) {
111 return GeomAbs_C0;
112 }
113 else if ( MultMax == 1) {
114 return GeomAbs_C1;
115 }
116 else if ( MultMax == 2) {
117 return GeomAbs_C2;
118 }
119 else if ( MultMax == 3) {
120 return GeomAbs_C3;
121 }
122 else {
123 return GeomAbs_CN;
124 }
125}
126
127
128//=======================================================================
129//function : Load
130//purpose :
131//=======================================================================
132
041bfce9 133void GeomAdaptor_Curve::load(const Handle(Geom_Curve)& C,
7fd59977 134 const Standard_Real UFirst,
135 const Standard_Real ULast)
136{
7fd59977 137 myFirst = UFirst;
138 myLast = ULast;
139
140 if ( myCurve != C) {
141 myCurve = C;
3b25c0e8
IC
142 myCurveCache.Nullify();
143 myNestedEvaluator.Nullify();
144 myBSplineCurve.Nullify();
c8b5b3d8 145
7fd59977 146 const Handle(Standard_Type)& TheType = C->DynamicType();
147 if ( TheType == STANDARD_TYPE(Geom_TrimmedCurve)) {
c5f3a425 148 Load(Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve(),UFirst,ULast);
7fd59977 149 }
150 else if ( TheType == STANDARD_TYPE(Geom_Circle)) {
151 myTypeCurve = GeomAbs_Circle;
152 }
153 else if ( TheType ==STANDARD_TYPE(Geom_Line)) {
154 myTypeCurve = GeomAbs_Line;
155 }
156 else if ( TheType == STANDARD_TYPE(Geom_Ellipse)) {
157 myTypeCurve = GeomAbs_Ellipse;
158 }
159 else if ( TheType == STANDARD_TYPE(Geom_Parabola)) {
160 myTypeCurve = GeomAbs_Parabola;
161 }
162 else if ( TheType == STANDARD_TYPE(Geom_Hyperbola)) {
163 myTypeCurve = GeomAbs_Hyperbola;
164 }
165 else if ( TheType == STANDARD_TYPE(Geom_BezierCurve)) {
166 myTypeCurve = GeomAbs_BezierCurve;
c8b5b3d8 167 // Create cache for Bezier
168 Handle(Geom_BezierCurve) aBezier = Handle(Geom_BezierCurve)::DownCast(myCurve);
169 Standard_Integer aDeg = aBezier->Degree();
170 TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
171 myCurveCache = new BSplCLib_Cache(aDeg, aBezier->IsPeriodic(), aFlatKnots,
172 aBezier->Poles(), aBezier->Weights());
7fd59977 173 }
174 else if ( TheType == STANDARD_TYPE(Geom_BSplineCurve)) {
175 myTypeCurve = GeomAbs_BSplineCurve;
94f71cad 176 // Create cache for B-spline
c8b5b3d8 177 Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
3b25c0e8 178 myBSplineCurve = aBspl;
c8b5b3d8 179 myCurveCache = new BSplCLib_Cache(aBspl->Degree(), aBspl->IsPeriodic(),
180 aBspl->KnotSequence(), aBspl->Poles(), aBspl->Weights());
94f71cad 181 }
182 else if ( TheType == STANDARD_TYPE(Geom_OffsetCurve)) {
1aec3320 183 myTypeCurve = GeomAbs_OffsetCurve;
d660a72a 184 Handle(Geom_OffsetCurve) anOffsetCurve = Handle(Geom_OffsetCurve)::DownCast(myCurve);
94f71cad 185 // Create nested adaptor for base curve
d660a72a 186 Handle(Geom_Curve) aBaseCurve = anOffsetCurve->BasisCurve();
187 Handle(GeomAdaptor_HCurve) aBaseAdaptor = new GeomAdaptor_HCurve(aBaseCurve);
188 myNestedEvaluator = new GeomEvaluator_OffsetCurve(
189 aBaseAdaptor, anOffsetCurve->Offset(), anOffsetCurve->Direction());
7fd59977 190 }
191 else {
192 myTypeCurve = GeomAbs_OtherCurve;
193 }
194 }
f3a1c0cb 195 else // rebuild cache of Bezier and B-spline curve even if the loaded curve is same
196 RebuildCache(myFirst);
197}
7fd59977 198
199// --
200// -- Global methods - Apply to the whole curve.
201// --
202
203//=======================================================================
204//function : Continuity
205//purpose :
206//=======================================================================
207
208GeomAbs_Shape GeomAdaptor_Curve::Continuity() const
209{
210 if (myTypeCurve == GeomAbs_BSplineCurve)
211 return LocalContinuity(myFirst, myLast);
212
1aec3320 213 if (myTypeCurve == GeomAbs_OffsetCurve)
7fd59977 214 {
215 const GeomAbs_Shape S =
c5f3a425 216 Handle(Geom_OffsetCurve)::DownCast (myCurve)->GetBasisCurveContinuity();
7fd59977 217 switch(S)
218 {
219 case GeomAbs_CN: return GeomAbs_CN;
220 case GeomAbs_C3: return GeomAbs_C2;
221 case GeomAbs_C2: return GeomAbs_C1;
3d58dc49 222 case GeomAbs_C1: return GeomAbs_C0;
223 case GeomAbs_G1: return GeomAbs_G1;
224 case GeomAbs_G2: return GeomAbs_G2;
7fd59977 225 default:
3d58dc49 226 Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Continuity");
7fd59977 227 }
228 }
229 else if (myTypeCurve == GeomAbs_OtherCurve) {
230 Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Contunuity");
231 }
232
233 return GeomAbs_CN;
234}
235
236//=======================================================================
237//function : NbIntervals
238//purpose :
239//=======================================================================
240
31b1749c 241Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
7fd59977 242{
243 Standard_Integer myNbIntervals = 1;
244 Standard_Integer NbSplit;
245 if (myTypeCurve == GeomAbs_BSplineCurve) {
3b25c0e8
IC
246 Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
247 Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
7fd59977 248 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
249 if ( S > Continuity()) {
250 Standard_Integer Cont;
251 switch ( S) {
252 case GeomAbs_G1:
253 case GeomAbs_G2:
254 Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
255 break;
256 case GeomAbs_C0:
257 myNbIntervals = 1;
258 break;
259 case GeomAbs_C1:
260 case GeomAbs_C2:
261 case GeomAbs_C3:
262 case GeomAbs_CN:
263 {
264 if ( S == GeomAbs_C1) Cont = 1;
265 else if ( S == GeomAbs_C2) Cont = 2;
266 else if ( S == GeomAbs_C3) Cont = 3;
3b25c0e8
IC
267 else Cont = myBSplineCurve->Degree();
268 Standard_Integer Degree = myBSplineCurve->Degree();
269 Standard_Integer NbKnots = myBSplineCurve->NbKnots();
7fd59977 270 TColStd_Array1OfInteger Mults (1, NbKnots);
3b25c0e8 271 myBSplineCurve->Multiplicities (Mults);
7fd59977 272 NbSplit = 1;
273 Standard_Integer Index = FirstIndex;
274 Inter (NbSplit) = Index;
275 Index++;
276 NbSplit++;
277 while (Index < LastIndex)
278 {
279 if (Degree - Mults (Index) < Cont)
280 {
281 Inter (NbSplit) = Index;
282 NbSplit++;
283 }
284 Index++;
285 }
286 Inter (NbSplit) = Index;
287
288 Standard_Integer NbInt = NbSplit-1;
289
3b25c0e8 290 Standard_Integer Nb = myBSplineCurve->NbKnots();
7fd59977 291 Standard_Integer Index1 = 0;
292 Standard_Integer Index2 = 0;
293 Standard_Real newFirst, newLast;
e1c1b6b9 294 const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
295 const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
3b25c0e8
IC
296 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
297 myBSplineCurve->IsPeriodic(),
7fd59977 298 1,Nb,Index1,newFirst);
3b25c0e8
IC
299 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
300 myBSplineCurve->IsPeriodic(),
7fd59977 301 1,Nb,Index2,newLast);
302
303 // On decale eventuellement les indices
304 // On utilise une "petite" tolerance, la resolution ne doit
305 // servir que pour les tres longue courbes....(PRO9248)
306 Standard_Real Eps = Min(Resolution(Precision::Confusion()),
307 Precision::PConfusion());
308 if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
309 if ( newLast-TK(Index2)> Eps) Index2++;
310
311 myNbIntervals = 1;
312 for ( Standard_Integer i=1; i<=NbInt; i++)
313 if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
314 }
315 break;
316 }
317 }
318 }
319
1aec3320 320 else if (myTypeCurve == GeomAbs_OffsetCurve) {
7fd59977 321 GeomAbs_Shape BaseS=GeomAbs_C0;
322 switch(S){
323 case GeomAbs_G1:
324 case GeomAbs_G2:
325 Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
326 break;
327 case GeomAbs_C0: BaseS = GeomAbs_C1; break;
328 case GeomAbs_C1: BaseS = GeomAbs_C2; break;
329 case GeomAbs_C2: BaseS = GeomAbs_C3; break;
330 default: BaseS = GeomAbs_CN;
331 }
332 GeomAdaptor_Curve C
c5f3a425 333 (Handle(Geom_OffsetCurve)::DownCast (myCurve)->BasisCurve());
7fd59977 334 // akm 05/04/02 (OCC278) If our curve is trimmed we must recalculate
335 // the number of intervals obtained from the basis to
336 // vvv reflect parameter bounds
337 Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
338 if (iNbBasisInt>1)
339 {
340 TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
341 C.Intervals(rdfInter,BaseS);
342 for (iInt=1; iInt<=iNbBasisInt; iInt++)
343 if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
344 myNbIntervals++;
345 }
346 // akm 05/04/02 ^^^
347 }
348 return myNbIntervals;
349}
350
351//=======================================================================
352//function : Intervals
353//purpose :
354//=======================================================================
355
356void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
31b1749c 357 const GeomAbs_Shape S ) const
7fd59977 358{
359 Standard_Integer myNbIntervals = 1;
360 Standard_Integer NbSplit;
f34eec8f 361 Standard_Real FirstParam = myFirst, LastParam = myLast;
7fd59977 362
363 if (myTypeCurve == GeomAbs_BSplineCurve)
364 {
3b25c0e8
IC
365 Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
366 Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
7fd59977 367 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
368
369 if ( S > Continuity()) {
370 Standard_Integer Cont;
371 switch ( S) {
372 case GeomAbs_G1:
373 case GeomAbs_G2:
374 Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
375 break;
376 case GeomAbs_C0:
377 myNbIntervals = 1;
378 break;
379 case GeomAbs_C1:
380 case GeomAbs_C2:
381 case GeomAbs_C3:
382 case GeomAbs_CN:
383 {
384 if ( S == GeomAbs_C1) Cont = 1;
385 else if ( S == GeomAbs_C2) Cont = 2;
386 else if ( S == GeomAbs_C3) Cont = 3;
3b25c0e8
IC
387 else Cont = myBSplineCurve->Degree();
388 Standard_Integer Degree = myBSplineCurve->Degree();
389 Standard_Integer NbKnots = myBSplineCurve->NbKnots();
7fd59977 390 TColStd_Array1OfInteger Mults (1, NbKnots);
3b25c0e8 391 myBSplineCurve->Multiplicities (Mults);
7fd59977 392 NbSplit = 1;
393 Standard_Integer Index = FirstIndex;
394 Inter (NbSplit) = Index;
395 Index++;
396 NbSplit++;
397 while (Index < LastIndex)
398 {
399 if (Degree - Mults (Index) < Cont)
400 {
401 Inter (NbSplit) = Index;
402 NbSplit++;
403 }
404 Index++;
405 }
406 Inter (NbSplit) = Index;
407 Standard_Integer NbInt = NbSplit-1;
408 // GeomConvert_BSplineCurveKnotSplitting Convector(myBspl, Cont);
409 // Standard_Integer NbInt = Convector.NbSplits()-1;
410 // TColStd_Array1OfInteger Inter(1,NbInt+1);
411 // Convector.Splitting( Inter);
412
3b25c0e8 413 Standard_Integer Nb = myBSplineCurve->NbKnots();
7fd59977 414 Standard_Integer Index1 = 0;
415 Standard_Integer Index2 = 0;
416 Standard_Real newFirst, newLast;
e1c1b6b9 417 const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
418 const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
3b25c0e8
IC
419 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
420 myBSplineCurve->IsPeriodic(),
7fd59977 421 1,Nb,Index1,newFirst);
3b25c0e8
IC
422 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
423 myBSplineCurve->IsPeriodic(),
7fd59977 424 1,Nb,Index2,newLast);
f34eec8f 425 FirstParam = newFirst;
426 LastParam = newLast;
7fd59977 427 // On decale eventuellement les indices
428 // On utilise une "petite" tolerance, la resolution ne doit
429 // servir que pour les tres longue courbes....(PRO9248)
430 Standard_Real Eps = Min(Resolution(Precision::Confusion()),
431 Precision::PConfusion());
432 if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
433 if ( newLast-TK(Index2)> Eps) Index2++;
434
435 Inter( 1) = Index1;
436 myNbIntervals = 1;
437 for ( Standard_Integer i=1; i<=NbInt; i++) {
438 if (Inter(i) > Index1 && Inter(i)<Index2 ) {
439 myNbIntervals++;
440 Inter(myNbIntervals) = Inter(i);
441 }
442 }
443 Inter(myNbIntervals+1) = Index2;
444
445 for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
446 T(I) = TK(Inter(I));
447 }
448 }
449 break;
450 }
451 }
452 }
453
1aec3320 454 else if (myTypeCurve == GeomAbs_OffsetCurve){
7fd59977 455 GeomAbs_Shape BaseS=GeomAbs_C0;
456 switch(S){
457 case GeomAbs_G1:
458 case GeomAbs_G2:
459 Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
460 break;
461 case GeomAbs_C0: BaseS = GeomAbs_C1; break;
462 case GeomAbs_C1: BaseS = GeomAbs_C2; break;
463 case GeomAbs_C2: BaseS = GeomAbs_C3; break;
464 default: BaseS = GeomAbs_CN;
465 }
466 GeomAdaptor_Curve C
c5f3a425 467 (Handle(Geom_OffsetCurve)::DownCast (myCurve)->BasisCurve());
7fd59977 468 // akm 05/04/02 (OCC278) If our curve is trimmed we must recalculate
469 // the array of intervals obtained from the basis to
470 // vvv reflect parameter bounds
471 Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
472 if (iNbBasisInt>1)
473 {
474 TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
475 C.Intervals(rdfInter,BaseS);
476 for (iInt=1; iInt<=iNbBasisInt; iInt++)
477 if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
478 T(++myNbIntervals)=rdfInter(iInt);
479 }
480 // old - myNbIntervals = C.NbIntervals(BaseS);
481 // old - C.Intervals(T, BaseS);
482 // akm 05/04/02 ^^^
483 }
484
f34eec8f 485 T( T.Lower() ) = FirstParam;
486 T( T.Lower() + myNbIntervals ) = LastParam;
7fd59977 487}
488
489//=======================================================================
490//function : Trim
491//purpose :
492//=======================================================================
493
494Handle(Adaptor3d_HCurve) GeomAdaptor_Curve::Trim(const Standard_Real First,
495 const Standard_Real Last,
496 const Standard_Real /*Tol*/) const
497{
498 return Handle(GeomAdaptor_HCurve)(new GeomAdaptor_HCurve(myCurve,First,Last));
499}
500
501
502//=======================================================================
503//function : IsClosed
504//purpose :
505//=======================================================================
506
507Standard_Boolean GeomAdaptor_Curve::IsClosed() const
508{
509 if (!Precision::IsPositiveInfinite(myLast) &&
510 !Precision::IsNegativeInfinite(myFirst))
511 {
512 const gp_Pnt Pd = Value(myFirst);
513 const gp_Pnt Pf = Value(myLast);
514 return (Pd.Distance(Pf) <= Precision::Confusion());
515 }
516 return Standard_False;
517}
518
519//=======================================================================
520//function : IsPeriodic
521//purpose :
522//=======================================================================
523
524Standard_Boolean GeomAdaptor_Curve::IsPeriodic() const
525{
526 return (myCurve->IsPeriodic()? IsClosed() : Standard_False);
527}
528
529//=======================================================================
530//function : Period
531//purpose :
532//=======================================================================
533
534Standard_Real GeomAdaptor_Curve::Period() const
535{
536 return myCurve->LastParameter() - myCurve->FirstParameter();
537}
538
94f71cad 539//=======================================================================
540//function : RebuildCache
541//purpose :
542//=======================================================================
543void GeomAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
544{
c8b5b3d8 545 if (myTypeCurve == GeomAbs_BezierCurve)
546 {
547 Handle(Geom_BezierCurve) aBezier = Handle(Geom_BezierCurve)::DownCast(myCurve);
548 Standard_Integer aDeg = aBezier->Degree();
549 TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
550 myCurveCache->BuildCache(theParameter, aDeg, aBezier->IsPeriodic(), aFlatKnots,
551 aBezier->Poles(), aBezier->Weights());
552 }
553 else if (myTypeCurve == GeomAbs_BSplineCurve)
554 {
3b25c0e8
IC
555 myCurveCache->BuildCache(theParameter, myBSplineCurve->Degree(),
556 myBSplineCurve->IsPeriodic(), myBSplineCurve->KnotSequence(),
557 myBSplineCurve->Poles(), myBSplineCurve->Weights());
c8b5b3d8 558 }
94f71cad 559}
560
7fd59977 561//=======================================================================
d660a72a 562//function : IsBoundary
94f71cad 563//purpose :
564//=======================================================================
d660a72a 565Standard_Boolean GeomAdaptor_Curve::IsBoundary(const Standard_Real theU,
566 Standard_Integer& theSpanStart,
567 Standard_Integer& theSpanFinish) const
94f71cad 568{
3b25c0e8 569 if (!myBSplineCurve.IsNull() && (theU == myFirst || theU == myLast))
94f71cad 570 {
d660a72a 571 if (theU == myFirst)
572 {
3b25c0e8 573 myBSplineCurve->LocateU(myFirst, PosTol, theSpanStart, theSpanFinish);
d660a72a 574 if (theSpanStart < 1)
575 theSpanStart = 1;
576 if (theSpanStart >= theSpanFinish)
577 theSpanFinish = theSpanStart + 1;
7fd59977 578 }
d660a72a 579 else if (theU == myLast)
580 {
3b25c0e8
IC
581 myBSplineCurve->LocateU(myLast, PosTol, theSpanStart, theSpanFinish);
582 if (theSpanFinish > myBSplineCurve->NbKnots())
583 theSpanFinish = myBSplineCurve->NbKnots();
d660a72a 584 if (theSpanStart >= theSpanFinish)
585 theSpanStart = theSpanFinish - 1;
7fd59977 586 }
d660a72a 587 return Standard_True;
94f71cad 588 }
d660a72a 589 return Standard_False;
94f71cad 590}
591
592//=======================================================================
d660a72a 593//function : Value
94f71cad 594//purpose :
595//=======================================================================
d660a72a 596
597gp_Pnt GeomAdaptor_Curve::Value(const Standard_Real U) const
94f71cad 598{
d660a72a 599 gp_Pnt aValue;
600 D0(U, aValue);
601 return aValue;
7fd59977 602}
603
604//=======================================================================
605//function : D0
606//purpose :
607//=======================================================================
608
609void GeomAdaptor_Curve::D0(const Standard_Real U, gp_Pnt& P) const
610{
d660a72a 611 switch (myTypeCurve)
94f71cad 612 {
d660a72a 613 case GeomAbs_BezierCurve:
614 case GeomAbs_BSplineCurve:
615 {
616 Standard_Integer aStart = 0, aFinish = 0;
617 if (IsBoundary(U, aStart, aFinish))
618 {
3b25c0e8 619 myBSplineCurve->LocalD0(U, aStart, aFinish, P);
7fd59977 620 }
d660a72a 621 else if (!myCurveCache.IsNull()) // use cached data
622 {
623 if (!myCurveCache->IsCacheValid(U))
624 RebuildCache(U);
625 myCurveCache->D0(U, P);
7fd59977 626 }
d660a72a 627 else
628 myCurve->D0(U, P);
629 break;
94f71cad 630 }
94f71cad 631
d660a72a 632 case GeomAbs_OffsetCurve:
633 myNestedEvaluator->D0(U, P);
634 break;
635
636 default:
637 myCurve->D0(U, P);
638 }
7fd59977 639}
640
641//=======================================================================
642//function : D1
643//purpose :
644//=======================================================================
645
646void GeomAdaptor_Curve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V) const
647{
d660a72a 648 switch (myTypeCurve)
94f71cad 649 {
d660a72a 650 case GeomAbs_BezierCurve:
651 case GeomAbs_BSplineCurve:
652 {
653 Standard_Integer aStart = 0, aFinish = 0;
654 if (IsBoundary(U, aStart, aFinish))
655 {
3b25c0e8 656 myBSplineCurve->LocalD1(U, aStart, aFinish, P, V);
7fd59977 657 }
d660a72a 658 else if (!myCurveCache.IsNull()) // use cached data
659 {
660 if (!myCurveCache->IsCacheValid(U))
661 RebuildCache(U);
662 myCurveCache->D1(U, P, V);
7fd59977 663 }
d660a72a 664 else
665 myCurve->D1(U, P, V);
666 break;
94f71cad 667 }
94f71cad 668
d660a72a 669 case GeomAbs_OffsetCurve:
670 myNestedEvaluator->D1(U, P, V);
671 break;
94f71cad 672
d660a72a 673 default:
674 myCurve->D1(U, P, V);
675 }
94f71cad 676}
677
7fd59977 678//=======================================================================
679//function : D2
680//purpose :
681//=======================================================================
682
683void GeomAdaptor_Curve::D2(const Standard_Real U,
94f71cad 684 gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) const
685{
d660a72a 686 switch (myTypeCurve)
94f71cad 687 {
d660a72a 688 case GeomAbs_BezierCurve:
689 case GeomAbs_BSplineCurve:
690 {
691 Standard_Integer aStart = 0, aFinish = 0;
692 if (IsBoundary(U, aStart, aFinish))
693 {
3b25c0e8 694 myBSplineCurve->LocalD2(U, aStart, aFinish, P, V1, V2);
7fd59977 695 }
d660a72a 696 else if (!myCurveCache.IsNull()) // use cached data
697 {
698 if (!myCurveCache->IsCacheValid(U))
699 RebuildCache(U);
700 myCurveCache->D2(U, P, V1, V2);
7fd59977 701 }
d660a72a 702 else
703 myCurve->D2(U, P, V1, V2);
704 break;
7fd59977 705 }
94f71cad 706
d660a72a 707 case GeomAbs_OffsetCurve:
708 myNestedEvaluator->D2(U, P, V1, V2);
709 break;
94f71cad 710
d660a72a 711 default:
712 myCurve->D2(U, P, V1, V2);
713 }
7fd59977 714}
715
716//=======================================================================
717//function : D3
718//purpose :
719//=======================================================================
720
721void GeomAdaptor_Curve::D3(const Standard_Real U,
94f71cad 722 gp_Pnt& P, gp_Vec& V1,
723 gp_Vec& V2, gp_Vec& V3) const
7fd59977 724{
d660a72a 725 switch (myTypeCurve)
94f71cad 726 {
d660a72a 727 case GeomAbs_BezierCurve:
728 case GeomAbs_BSplineCurve:
729 {
730 Standard_Integer aStart = 0, aFinish = 0;
731 if (IsBoundary(U, aStart, aFinish))
732 {
3b25c0e8 733 myBSplineCurve->LocalD3(U, aStart, aFinish, P, V1, V2, V3);
7fd59977 734 }
d660a72a 735 else if (!myCurveCache.IsNull()) // use cached data
736 {
737 if (!myCurveCache->IsCacheValid(U))
738 RebuildCache(U);
739 myCurveCache->D3(U, P, V1, V2, V3);
7fd59977 740 }
d660a72a 741 else
742 myCurve->D3(U, P, V1, V2, V3);
743 break;
7fd59977 744 }
94f71cad 745
d660a72a 746 case GeomAbs_OffsetCurve:
747 myNestedEvaluator->D3(U, P, V1, V2, V3);
748 break;
749
750 default:
751 myCurve->D3(U, P, V1, V2, V3);
752 }
7fd59977 753}
754
755//=======================================================================
756//function : DN
757//purpose :
758//=======================================================================
759
760gp_Vec GeomAdaptor_Curve::DN(const Standard_Real U,
94f71cad 761 const Standard_Integer N) const
762{
d660a72a 763 switch (myTypeCurve)
94f71cad 764 {
d660a72a 765 case GeomAbs_BezierCurve:
766 case GeomAbs_BSplineCurve:
767 {
768 Standard_Integer aStart = 0, aFinish = 0;
769 if (IsBoundary(U, aStart, aFinish))
770 {
3b25c0e8 771 return myBSplineCurve->LocalDN(U, aStart, aFinish, N);
7fd59977 772 }
d660a72a 773 else
774 return myCurve->DN(U, N);
775 break;
7fd59977 776 }
94f71cad 777
d660a72a 778 case GeomAbs_OffsetCurve:
779 return myNestedEvaluator->DN(U, N);
94f71cad 780 break;
d660a72a 781
782 default: // to eliminate gcc warning
94f71cad 783 break;
94f71cad 784 }
d660a72a 785 return myCurve->DN(U, N);
7fd59977 786}
787
788//=======================================================================
789//function : Resolution
790//purpose :
791//=======================================================================
792
793Standard_Real GeomAdaptor_Curve::Resolution(const Standard_Real R3D) const
794{
795 switch ( myTypeCurve) {
796 case GeomAbs_Line :
797 return R3D;
798 case GeomAbs_Circle: {
c5f3a425 799 Standard_Real R = Handle(Geom_Circle)::DownCast (myCurve)->Circ().Radius();
7fd59977 800 if ( R > R3D/2. )
801 return 2*ASin(R3D/(2*R));
802 else
c6541a0c 803 return 2*M_PI;
7fd59977 804 }
805 case GeomAbs_Ellipse: {
c5f3a425 806 return R3D / Handle(Geom_Ellipse)::DownCast (myCurve)->MajorRadius();
7fd59977 807 }
808 case GeomAbs_BezierCurve: {
809 Standard_Real res;
c5f3a425 810 Handle(Geom_BezierCurve)::DownCast (myCurve)->Resolution(R3D,res);
7fd59977 811 return res;
812 }
813 case GeomAbs_BSplineCurve: {
814 Standard_Real res;
3b25c0e8 815 myBSplineCurve->Resolution(R3D,res);
7fd59977 816 return res;
817 }
818 default:
819 return Precision::Parametric(R3D);
820 }
821}
822
823
824// --
825// -- The following methods must be called when GetType returned
826// -- the corresponding type.
827// --
828
829//=======================================================================
830//function : Line
831//purpose :
832//=======================================================================
833
834gp_Lin GeomAdaptor_Curve::Line() const
835{
836 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
c5f3a425 837 return Handle(Geom_Line)::DownCast (myCurve)->Lin();
7fd59977 838}
839
840//=======================================================================
841//function : Circle
842//purpose :
843//=======================================================================
844
845gp_Circ GeomAdaptor_Curve::Circle() const
846{
847 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
c5f3a425 848 return Handle(Geom_Circle)::DownCast (myCurve)->Circ();
7fd59977 849}
850
851//=======================================================================
852//function : Ellipse
853//purpose :
854//=======================================================================
855
856gp_Elips GeomAdaptor_Curve::Ellipse() const
857{
858 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Ellipse, "");
c5f3a425 859 return Handle(Geom_Ellipse)::DownCast (myCurve)->Elips();
7fd59977 860}
861
862//=======================================================================
863//function : Hyperbola
864//purpose :
865//=======================================================================
866
867gp_Hypr GeomAdaptor_Curve::Hyperbola() const
868{
869 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
c5f3a425 870 return Handle(Geom_Hyperbola)::DownCast (myCurve)->Hypr();
7fd59977 871}
872
873//=======================================================================
874//function : Parabola
875//purpose :
876//=======================================================================
877
878gp_Parab GeomAdaptor_Curve::Parabola() const
879{
880 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
c5f3a425 881 return Handle(Geom_Parabola)::DownCast (myCurve)->Parab();
7fd59977 882}
883
884//=======================================================================
885//function : Degree
886//purpose :
887//=======================================================================
888
889Standard_Integer GeomAdaptor_Curve::Degree() const
890{
891 if (myTypeCurve == GeomAbs_BezierCurve)
c5f3a425 892 return Handle(Geom_BezierCurve)::DownCast (myCurve)->Degree();
7fd59977 893 else if (myTypeCurve == GeomAbs_BSplineCurve)
3b25c0e8 894 return myBSplineCurve->Degree();
7fd59977 895 else
896 Standard_NoSuchObject::Raise();
897 // portage WNT
898 return 0;
899}
900
901//=======================================================================
902//function : IsRational
903//purpose :
904//=======================================================================
905
906Standard_Boolean GeomAdaptor_Curve::IsRational() const {
907 switch( myTypeCurve) {
908 case GeomAbs_BSplineCurve:
3b25c0e8 909 return myBSplineCurve->IsRational();
7fd59977 910 case GeomAbs_BezierCurve:
c5f3a425 911 return Handle(Geom_BezierCurve)::DownCast (myCurve)->IsRational();
7fd59977 912 default:
913 return Standard_False;
914 }
915}
916
917//=======================================================================
918//function : NbPoles
919//purpose :
920//=======================================================================
921
922Standard_Integer GeomAdaptor_Curve::NbPoles() const
923{
924 if (myTypeCurve == GeomAbs_BezierCurve)
c5f3a425 925 return Handle(Geom_BezierCurve)::DownCast (myCurve)->NbPoles();
7fd59977 926 else if (myTypeCurve == GeomAbs_BSplineCurve)
3b25c0e8 927 return myBSplineCurve->NbPoles();
7fd59977 928 else
929 Standard_NoSuchObject::Raise();
930 // portage WNT
931 return 0;
932}
933
934//=======================================================================
935//function : NbKnots
936//purpose :
937//=======================================================================
938
939Standard_Integer GeomAdaptor_Curve::NbKnots() const
940{
941 if ( myTypeCurve != GeomAbs_BSplineCurve)
942 Standard_NoSuchObject::Raise("GeomAdaptor_Curve::NbKnots");
3b25c0e8 943 return myBSplineCurve->NbKnots();
7fd59977 944}
945
946//=======================================================================
947//function : Bezier
948//purpose :
949//=======================================================================
950
951Handle(Geom_BezierCurve) GeomAdaptor_Curve::Bezier() const
952{
953 if ( myTypeCurve != GeomAbs_BezierCurve)
954 Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Bezier");
c5f3a425 955 return Handle(Geom_BezierCurve)::DownCast (myCurve);
7fd59977 956}
957
958//=======================================================================
959//function : BSpline
960//purpose :
961//=======================================================================
962
963Handle(Geom_BSplineCurve) GeomAdaptor_Curve::BSpline() const
964{
965 if ( myTypeCurve != GeomAbs_BSplineCurve)
966 Standard_NoSuchObject::Raise("GeomAdaptor_Curve::BSpline");
967
3b25c0e8 968 return myBSplineCurve;
7fd59977 969}