0027341: Incorrect exact HLR results
[occt.git] / src / Geom2dAdaptor / Geom2dAdaptor_Curve.cxx
CommitLineData
b311480e 1// Created on: 1993-06-04
2// Created by: Bruno DUMORTIER
3// Copyright (c) 1993-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
b311480e 16
7fd59977 17// 20/02/97 : PMN -> Positionement local sur BSpline (PRO6902)
18// 10/07/97 : PMN -> Pas de calcul de resolution dans Nb(Intervals) (PRO9248)
19// 20/10/97 : JPI -> traitement des offset curves
20
21#define No_Standard_RangeError
22#define No_Standard_OutOfRange
23
42cf5bc1 24
7fd59977 25#include <Adaptor2d_HCurve2d.hxx>
26#include <BSplCLib.hxx>
94f71cad 27#include <BSplCLib_Cache.hxx>
7fd59977 28#include <Geom2d_BezierCurve.hxx>
29#include <Geom2d_BSplineCurve.hxx>
42cf5bc1 30#include <Geom2d_Circle.hxx>
31#include <Geom2d_Curve.hxx>
7fd59977 32#include <Geom2d_Ellipse.hxx>
7fd59977 33#include <Geom2d_Hyperbola.hxx>
42cf5bc1 34#include <Geom2d_Line.hxx>
35#include <Geom2d_OffsetCurve.hxx>
36#include <Geom2d_Parabola.hxx>
37#include <Geom2d_TrimmedCurve.hxx>
94f71cad 38#include <Geom2d_UndefinedDerivative.hxx>
42cf5bc1 39#include <Geom2d_UndefinedValue.hxx>
40#include <Geom2dAdaptor_Curve.hxx>
41#include <Geom2dAdaptor_HCurve.hxx>
d660a72a 42#include <Geom2dEvaluator_OffsetCurve.hxx>
42cf5bc1 43#include <GeomAbs_Shape.hxx>
44#include <gp.hxx>
45#include <gp_Circ2d.hxx>
46#include <gp_Elips2d.hxx>
47#include <gp_Hypr2d.hxx>
48#include <gp_Lin2d.hxx>
49#include <gp_Parab2d.hxx>
50#include <gp_Pnt2d.hxx>
51#include <gp_Vec2d.hxx>
52#include <Precision.hxx>
53#include <Standard_ConstructionError.hxx>
54#include <Standard_DomainError.hxx>
7fd59977 55#include <Standard_NoSuchObject.hxx>
56#include <Standard_NotImplemented.hxx>
42cf5bc1 57#include <Standard_NullObject.hxx>
58#include <Standard_OutOfRange.hxx>
59#include <TColgp_Array1OfPnt2d.hxx>
60#include <TColStd_Array1OfInteger.hxx>
61#include <TColStd_Array1OfReal.hxx>
62#include <TColStd_HArray1OfInteger.hxx>
7fd59977 63
42cf5bc1 64//#include <Geom2dConvert_BSplineCurveKnotSplitting.hxx>
c8b5b3d8 65static const Standard_Real PosTol = Precision::PConfusion() / 2;
7fd59977 66
94f71cad 67
7fd59977 68//=======================================================================
69//function : LocalContinuity
70//purpose : Computes the Continuity of a BSplineCurve
71// between the parameters U1 and U2
72// The continuity is C(d-m)
73// with d = degree,
74// m = max multiplicity of the Knots between U1 and U2
75//=======================================================================
76
77GeomAbs_Shape Geom2dAdaptor_Curve::LocalContinuity(const Standard_Real U1,
3b25c0e8
IC
78 const Standard_Real U2) const
79{
7fd59977 80 Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
3b25c0e8 81 Standard_Integer Nb = myBSplineCurve->NbKnots();
7fd59977 82 Standard_Integer Index1 = 0;
83 Standard_Integer Index2 = 0;
84 Standard_Real newFirst, newLast;
85 TColStd_Array1OfReal TK(1,Nb);
86 TColStd_Array1OfInteger TM(1,Nb);
3b25c0e8
IC
87 myBSplineCurve->Knots(TK);
88 myBSplineCurve->Multiplicities(TM);
89 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U1,myBSplineCurve->IsPeriodic(),
7fd59977 90 1,Nb,Index1,newFirst);
3b25c0e8 91 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U2,myBSplineCurve->IsPeriodic(),
7fd59977 92 1,Nb,Index2,newLast);
93 if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) {
94 if (Index1 < Nb)Index1++;
95 }
96 if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
97 Index2--;
98 Standard_Integer MultMax;
99 // attention aux courbes peridiques.
3b25c0e8 100 if ( myBSplineCurve->IsPeriodic() && Index1 == Nb )
7fd59977 101 Index1 = 1;
102
103 if ( Index2 - Index1 <= 0) {
104 MultMax = 100; // CN entre 2 Noeuds consecutifs
105 }
106 else {
107 MultMax = TM(Index1+1);
108 for(Standard_Integer i = Index1+1;i<=Index2;i++) {
109 if ( TM(i)>MultMax) MultMax=TM(i);
110 }
3b25c0e8 111 MultMax = myBSplineCurve->Degree() - MultMax;
7fd59977 112 }
113 if ( MultMax <= 0) {
114 return GeomAbs_C0;
115 }
116 else if ( MultMax == 1) {
117 return GeomAbs_C1;
118 }
119 else if ( MultMax == 2) {
120 return GeomAbs_C2;
121 }
122 else if ( MultMax == 3) {
123 return GeomAbs_C3;
124 }
125 else {
126 return GeomAbs_CN;
127 }
3b25c0e8 128}
7fd59977 129
130
131//=======================================================================
132//function : Geom2dAdaptor_Curve
133//purpose :
134//=======================================================================
135
136Geom2dAdaptor_Curve::Geom2dAdaptor_Curve()
cbff1e55 137: myTypeCurve(GeomAbs_OtherCurve),
138 myFirst (0.0),
139 myLast (0.0)
7fd59977 140{
141}
142
143//=======================================================================
144//function : Geom2dAdaptor_Curve
145//purpose :
146//=======================================================================
147
cbff1e55 148Geom2dAdaptor_Curve::Geom2dAdaptor_Curve(const Handle(Geom2d_Curve)& theCrv)
149: myTypeCurve(GeomAbs_OtherCurve),
150 myFirst (0.0),
151 myLast (0.0)
041bfce9 152{
cbff1e55 153 Load(theCrv);
7fd59977 154}
155
156//=======================================================================
157//function : Geom2dAdaptor_Curve
158//purpose :
159//=======================================================================
160
cbff1e55 161Geom2dAdaptor_Curve::Geom2dAdaptor_Curve(const Handle(Geom2d_Curve)& theCrv,
162 const Standard_Real theUFirst,
163 const Standard_Real theULast)
164: myTypeCurve(GeomAbs_OtherCurve),
165 myFirst (theUFirst),
166 myLast (theULast)
041bfce9 167{
cbff1e55 168 Load(theCrv, theUFirst, theULast);
7fd59977 169}
170
7fd59977 171
172//=======================================================================
173//function : Load
174//purpose :
175//=======================================================================
176
041bfce9 177void Geom2dAdaptor_Curve::load(const Handle(Geom2d_Curve)& C,
178 const Standard_Real UFirst,
179 const Standard_Real ULast)
180{
7fd59977 181 myFirst = UFirst;
182 myLast = ULast;
183
184 if ( myCurve != C) {
185 myCurve = C;
3b25c0e8
IC
186 myCurveCache.Nullify();
187 myNestedEvaluator.Nullify();
188 myBSplineCurve.Nullify();
7fd59977 189
190 Handle(Standard_Type) TheType = C->DynamicType();
191 if ( TheType == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
c5f3a425 192 Load(Handle(Geom2d_TrimmedCurve)::DownCast (C)->BasisCurve(),
7fd59977 193 UFirst,ULast);
194 }
195 else if ( TheType == STANDARD_TYPE(Geom2d_Circle)) {
196 myTypeCurve = GeomAbs_Circle;
197 }
198 else if ( TheType ==STANDARD_TYPE(Geom2d_Line)) {
199 myTypeCurve = GeomAbs_Line;
200 }
201 else if ( TheType == STANDARD_TYPE(Geom2d_Ellipse)) {
202 myTypeCurve = GeomAbs_Ellipse;
203 }
204 else if ( TheType == STANDARD_TYPE(Geom2d_Parabola)) {
205 myTypeCurve = GeomAbs_Parabola;
206 }
207 else if ( TheType == STANDARD_TYPE(Geom2d_Hyperbola)) {
208 myTypeCurve = GeomAbs_Hyperbola;
209 }
210 else if ( TheType == STANDARD_TYPE(Geom2d_BezierCurve)) {
211 myTypeCurve = GeomAbs_BezierCurve;
c8b5b3d8 212 // Create cache for Bezier
213 Handle(Geom2d_BezierCurve) aBezier = Handle(Geom2d_BezierCurve)::DownCast(myCurve);
214 Standard_Integer aDeg = aBezier->Degree();
215 TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
216 myCurveCache = new BSplCLib_Cache(aDeg, aBezier->IsPeriodic(), aFlatKnots,
217 aBezier->Poles(), aBezier->Weights());
7fd59977 218 }
219 else if ( TheType == STANDARD_TYPE(Geom2d_BSplineCurve)) {
220 myTypeCurve = GeomAbs_BSplineCurve;
94f71cad 221 // Create cache for B-spline
c8b5b3d8 222 Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(myCurve);
3b25c0e8 223 myBSplineCurve = aBspl;
c8b5b3d8 224 myCurveCache = new BSplCLib_Cache(aBspl->Degree(), aBspl->IsPeriodic(),
225 aBspl->KnotSequence(), aBspl->Poles(), aBspl->Weights());
94f71cad 226 }
227 else if ( TheType == STANDARD_TYPE(Geom2d_OffsetCurve))
228 {
1aec3320 229 myTypeCurve = GeomAbs_OffsetCurve;
d660a72a 230 Handle(Geom2d_OffsetCurve) anOffsetCurve = Handle(Geom2d_OffsetCurve)::DownCast(myCurve);
94f71cad 231 // Create nested adaptor for base curve
d660a72a 232 Handle(Geom2d_Curve) aBaseCurve = anOffsetCurve->BasisCurve();
233 Handle(Geom2dAdaptor_HCurve) aBaseAdaptor = new Geom2dAdaptor_HCurve(aBaseCurve);
234 myNestedEvaluator = new Geom2dEvaluator_OffsetCurve(aBaseAdaptor, anOffsetCurve->Offset());
7fd59977 235 }
236 else {
237 myTypeCurve = GeomAbs_OtherCurve;
238 }
239 }
f3a1c0cb 240 else // rebuild cache of Bezier and B-spline curve even if the loaded curve is same
241 RebuildCache(myFirst);
7fd59977 242}
243
244// --
245// -- Global methods - Apply to the whole curve.
246// --
247
248//=======================================================================
249//function : Continuity
250//purpose :
251//=======================================================================
252
253GeomAbs_Shape Geom2dAdaptor_Curve::Continuity() const
254{
255 if (myTypeCurve == GeomAbs_BSplineCurve) {
256 return LocalContinuity(myFirst, myLast);
257 }
1aec3320 258 else if (myTypeCurve == GeomAbs_OffsetCurve){
7fd59977 259 GeomAbs_Shape S =
c5f3a425 260 Handle(Geom2d_OffsetCurve)::DownCast (myCurve)->GetBasisCurveContinuity();
7fd59977 261 switch(S){
262 case GeomAbs_CN: return GeomAbs_CN;
263 case GeomAbs_C3: return GeomAbs_C2;
264 case GeomAbs_C2: return GeomAbs_C1;
265 case GeomAbs_C1: return GeomAbs_C0;
3d58dc49 266 case GeomAbs_G1: return GeomAbs_G1;
267 case GeomAbs_G2: return GeomAbs_G2;
268
7fd59977 269 default:
270 Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::Continuity");
271 }
272 }
273
274 else if (myTypeCurve == GeomAbs_OtherCurve) {
275 Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::Continuity");
276 }
277 else {
278 return GeomAbs_CN;
279 }
280
281 // portage WNT
282 return GeomAbs_CN;
283}
284
285//=======================================================================
286//function : NbIntervals
287//purpose :
288//=======================================================================
289
290Standard_Integer Geom2dAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
291{
292 Standard_Integer myNbIntervals = 1;
293 Standard_Integer NbSplit;
294 if (myTypeCurve == GeomAbs_BSplineCurve) {
3b25c0e8
IC
295 Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
296 Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
7fd59977 297 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
298 if ( S > Continuity()) {
299 Standard_Integer Cont;
300 switch ( S) {
301 case GeomAbs_G1:
302 case GeomAbs_G2:
303 Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
304 break;
305 case GeomAbs_C0:
306 myNbIntervals = 1;
307 break;
308 case GeomAbs_C1:
309 case GeomAbs_C2:
310 case GeomAbs_C3:
311 case GeomAbs_CN:
312 {
313 if ( S == GeomAbs_C1) Cont = 1;
314 else if ( S == GeomAbs_C2) Cont = 2;
315 else if ( S == GeomAbs_C3) Cont = 3;
3b25c0e8
IC
316 else Cont = myBSplineCurve->Degree();
317 Standard_Integer Degree = myBSplineCurve->Degree();
318 Standard_Integer NbKnots = myBSplineCurve->NbKnots();
7fd59977 319 TColStd_Array1OfInteger Mults (1, NbKnots);
3b25c0e8 320 myBSplineCurve->Multiplicities (Mults);
7fd59977 321 NbSplit = 1;
322 Standard_Integer Index = FirstIndex;
323 Inter (NbSplit) = Index;
324 Index++;
325 NbSplit++;
326 while (Index < LastIndex)
327 {
328 if (Degree - Mults (Index) < Cont)
329 {
330 Inter (NbSplit) = Index;
331 NbSplit++;
332 }
333 Index++;
334 }
335 Inter (NbSplit) = Index;
336
337 Standard_Integer NbInt = NbSplit-1;
338
3b25c0e8 339 Standard_Integer Nb = myBSplineCurve->NbKnots();
7fd59977 340 Standard_Integer Index1 = 0;
341 Standard_Integer Index2 = 0;
342 Standard_Real newFirst, newLast;
343 TColStd_Array1OfReal TK(1,Nb);
344 TColStd_Array1OfInteger TM(1,Nb);
3b25c0e8
IC
345 myBSplineCurve->Knots(TK);
346 myBSplineCurve->Multiplicities(TM);
347 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
348 myBSplineCurve->IsPeriodic(),
7fd59977 349 1,Nb,Index1,newFirst);
3b25c0e8
IC
350 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
351 myBSplineCurve->IsPeriodic(),
7fd59977 352 1,Nb,Index2,newLast);
353
354 // On decale eventuellement les indices
355 // On utilise une "petite" tolerance, la resolution ne doit
356 // servir que pour les tres longue courbes....(PRO9248)
357 Standard_Real Eps = Min(Resolution(Precision::Confusion()),
358 Precision::PConfusion());
359 if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
360 if ( newLast-TK(Index2)> Eps) Index2++;
361
362 myNbIntervals = 1;
363 for ( Standard_Integer i=1; i<=NbInt; i++)
364 if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
365 }
366 break;
367 }
368 }
369 }
1aec3320 370 else if (myTypeCurve == GeomAbs_OffsetCurve){
7fd59977 371 GeomAbs_Shape BaseS=GeomAbs_C0;
372 switch(S){
373 case GeomAbs_G1:
374 case GeomAbs_G2:
375 Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
376 break;
377 case GeomAbs_C0: BaseS = GeomAbs_C1; break;
378 case GeomAbs_C1: BaseS = GeomAbs_C2; break;
379 case GeomAbs_C2: BaseS = GeomAbs_C3; break;
380 default: BaseS = GeomAbs_CN;
381 }
d660a72a 382 Geom2dAdaptor_Curve anAdaptor( Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->BasisCurve() );
383 myNbIntervals = anAdaptor.NbIntervals(BaseS);
7fd59977 384 }
385
386 return myNbIntervals;
387}
388
389//=======================================================================
390//function : Intervals
391//purpose :
392//=======================================================================
393
394void Geom2dAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
395 const GeomAbs_Shape S ) const
396{
397 Standard_Integer myNbIntervals = 1;
398 Standard_Integer NbSplit;
399 if (myTypeCurve == GeomAbs_BSplineCurve) {
3b25c0e8
IC
400 Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
401 Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
7fd59977 402 TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
403 if ( S > Continuity()) {
404 Standard_Integer Cont;
405 switch ( S) {
406 case GeomAbs_G1:
407 case GeomAbs_G2:
408 Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
409 break;
410 case GeomAbs_C0:
411 myNbIntervals = 1;
412 break;
413 case GeomAbs_C1:
414 case GeomAbs_C2:
415 case GeomAbs_C3:
416 case GeomAbs_CN:
417 {
418 if ( S == GeomAbs_C1) Cont = 1;
419 else if ( S == GeomAbs_C2) Cont = 2;
420 else if ( S == GeomAbs_C3) Cont = 3;
3b25c0e8
IC
421 else Cont = myBSplineCurve->Degree();
422 Standard_Integer Degree = myBSplineCurve->Degree();
423 Standard_Integer NbKnots = myBSplineCurve->NbKnots();
7fd59977 424 TColStd_Array1OfInteger Mults (1, NbKnots);
3b25c0e8 425 myBSplineCurve->Multiplicities (Mults);
7fd59977 426 NbSplit = 1;
427 Standard_Integer Index = FirstIndex;
428 Inter (NbSplit) = Index;
429 Index++;
430 NbSplit++;
431 while (Index < LastIndex)
432 {
433 if (Degree - Mults (Index) < Cont)
434 {
435 Inter (NbSplit) = Index;
436 NbSplit++;
437 }
438 Index++;
439 }
440 Inter (NbSplit) = Index;
441 Standard_Integer NbInt = NbSplit-1;
442
3b25c0e8 443 Standard_Integer Nb = myBSplineCurve->NbKnots();
7fd59977 444 Standard_Integer Index1 = 0;
445 Standard_Integer Index2 = 0;
446 Standard_Real newFirst, newLast;
447 TColStd_Array1OfReal TK(1,Nb);
448 TColStd_Array1OfInteger TM(1,Nb);
3b25c0e8
IC
449 myBSplineCurve->Knots(TK);
450 myBSplineCurve->Multiplicities(TM);
451 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
452 myBSplineCurve->IsPeriodic(),
7fd59977 453 1,Nb,Index1,newFirst);
3b25c0e8
IC
454 BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
455 myBSplineCurve->IsPeriodic(),
7fd59977 456 1,Nb,Index2,newLast);
457
458
459 // On decale eventuellement les indices
460 // On utilise une "petite" tolerance, la resolution ne doit
461 // servir que pour les tres longue courbes....(PRO9248)
462 Standard_Real Eps = Min(Resolution(Precision::Confusion()),
463 Precision::PConfusion());
464 if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
465 if ( newLast-TK(Index2)> Eps) Index2++;
466
467 Inter( 1) = Index1;
468 myNbIntervals = 1;
469 for ( Standard_Integer i=1; i<=NbInt; i++) {
470 if (Inter(i) > Index1 && Inter(i)<Index2 ) {
471 myNbIntervals++;
472 Inter(myNbIntervals) = Inter(i);
473 }
474 }
475 Inter(myNbIntervals+1) = Index2;
476
477 Standard_Integer ii = T.Lower() - 1;
478 for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
479 T(ii + I) = TK(Inter(I));
480 }
481 }
482 break;
483 }
484 }
485 }
1aec3320 486 else if (myTypeCurve == GeomAbs_OffsetCurve){
7fd59977 487 GeomAbs_Shape BaseS=GeomAbs_C0;
488 switch(S){
489 case GeomAbs_G1:
490 case GeomAbs_G2:
491 Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
492 break;
493 case GeomAbs_C0: BaseS = GeomAbs_C1; break;
494 case GeomAbs_C1: BaseS = GeomAbs_C2; break;
495 case GeomAbs_C2: BaseS = GeomAbs_C3; break;
496 default: BaseS = GeomAbs_CN;
497 }
d660a72a 498
499 Geom2dAdaptor_Curve anAdaptor( Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->BasisCurve() );
500 myNbIntervals = anAdaptor.NbIntervals(BaseS);
501 anAdaptor.Intervals(T, BaseS);
7fd59977 502 }
503
504 T( T.Lower() ) = myFirst;
505 T( T.Lower() + myNbIntervals ) = myLast;
506}
507
508//=======================================================================
509//function : Trim
510//purpose :
511//=======================================================================
512
513Handle(Adaptor2d_HCurve2d) Geom2dAdaptor_Curve::Trim
514(const Standard_Real First,
515 const Standard_Real Last,
516// const Standard_Real Tol) const
517 const Standard_Real ) const
518{
519 Handle(Geom2dAdaptor_HCurve) HE = new Geom2dAdaptor_HCurve(myCurve,First,Last);
520 return HE;
521}
522
523
524//=======================================================================
525//function : IsClosed
526//purpose :
527//=======================================================================
528
529Standard_Boolean Geom2dAdaptor_Curve::IsClosed() const
530{
531 if (!Precision::IsPositiveInfinite(myLast) &&
532 !Precision::IsNegativeInfinite(myFirst)) {
533 gp_Pnt2d Pd = Value(myFirst);
534 gp_Pnt2d Pf = Value(myLast);
535 return ( Pd.Distance(Pf) <= Precision::Confusion());
536 }
537 else
538 return Standard_False;
539}
540
541//=======================================================================
542//function : IsPeriodic
543//purpose :
544//=======================================================================
545
546Standard_Boolean Geom2dAdaptor_Curve::IsPeriodic() const
547{
548 if (myCurve->IsPeriodic())
549 return IsClosed();
550 else
551 return Standard_False;
552}
553
554//=======================================================================
555//function : Period
556//purpose :
557//=======================================================================
558
559Standard_Real Geom2dAdaptor_Curve::Period() const
560{
561 return myCurve->LastParameter() - myCurve->FirstParameter();
562}
563
564//=======================================================================
94f71cad 565//function : RebuildCache
566//purpose :
567//=======================================================================
568void Geom2dAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
569{
c8b5b3d8 570 if (myTypeCurve == GeomAbs_BezierCurve)
571 {
572 Handle(Geom2d_BezierCurve) aBezier = Handle(Geom2d_BezierCurve)::DownCast(myCurve);
573 Standard_Integer aDeg = aBezier->Degree();
574 TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
575 myCurveCache->BuildCache(theParameter, aDeg, aBezier->IsPeriodic(), aFlatKnots,
576 aBezier->Poles(), aBezier->Weights());
577 }
578 else if (myTypeCurve == GeomAbs_BSplineCurve)
579 {
3b25c0e8
IC
580 myCurveCache->BuildCache(theParameter, myBSplineCurve->Degree(),
581 myBSplineCurve->IsPeriodic(), myBSplineCurve->KnotSequence(),
582 myBSplineCurve->Poles(), myBSplineCurve->Weights());
c8b5b3d8 583 }
94f71cad 584}
585
586//=======================================================================
d660a72a 587//function : IsBoundary
7fd59977 588//purpose :
589//=======================================================================
d660a72a 590Standard_Boolean Geom2dAdaptor_Curve::IsBoundary(const Standard_Real theU,
591 Standard_Integer& theSpanStart,
592 Standard_Integer& theSpanFinish) const
7fd59977 593{
3b25c0e8 594 if (!myBSplineCurve.IsNull() && (theU == myFirst || theU == myLast))
94f71cad 595 {
94f71cad 596 if (theU == myFirst)
597 {
3b25c0e8 598 myBSplineCurve->LocateU(myFirst, PosTol, theSpanStart, theSpanFinish);
d660a72a 599 if (theSpanStart < 1)
600 theSpanStart = 1;
601 if (theSpanStart >= theSpanFinish)
602 theSpanFinish = theSpanStart + 1;
7fd59977 603 }
d660a72a 604 else if (theU == myLast)
94f71cad 605 {
3b25c0e8
IC
606 myBSplineCurve->LocateU(myLast, PosTol, theSpanStart, theSpanFinish);
607 if (theSpanFinish > myBSplineCurve->NbKnots())
608 theSpanFinish = myBSplineCurve->NbKnots();
d660a72a 609 if (theSpanStart >= theSpanFinish)
610 theSpanStart = theSpanFinish - 1;
7fd59977 611 }
d660a72a 612 return Standard_True;
7fd59977 613 }
d660a72a 614 return Standard_False;
94f71cad 615}
616
617//=======================================================================
d660a72a 618//function : Value
619//purpose :
94f71cad 620//=======================================================================
d660a72a 621
622gp_Pnt2d Geom2dAdaptor_Curve::Value(const Standard_Real U) const
94f71cad 623{
d660a72a 624 gp_Pnt2d aRes;
625 D0(U, aRes);
626 return aRes;
7fd59977 627}
628
629//=======================================================================
630//function : D0
631//purpose :
632//=======================================================================
633
634void Geom2dAdaptor_Curve::D0(const Standard_Real U, gp_Pnt2d& P) const
635{
d660a72a 636 switch (myTypeCurve)
94f71cad 637 {
d660a72a 638 case GeomAbs_BezierCurve:
639 case GeomAbs_BSplineCurve:
640 {
641 Standard_Integer aStart = 0, aFinish = 0;
642 if (IsBoundary(U, aStart, aFinish))
643 {
3b25c0e8 644 myBSplineCurve->LocalD0(U, aStart, aFinish, P);
7fd59977 645 }
d660a72a 646 else if (!myCurveCache.IsNull()) // use cached data
647 {
648 if (!myCurveCache->IsCacheValid(U))
649 RebuildCache(U);
650 myCurveCache->D0(U, P);
7fd59977 651 }
d660a72a 652 else
653 myCurve->D0(U, P);
654 break;
94f71cad 655 }
94f71cad 656
d660a72a 657 case GeomAbs_OffsetCurve:
658 myNestedEvaluator->D0(U, P);
659 break;
660
661 default:
662 myCurve->D0(U, P);
663 }
7fd59977 664}
665
666//=======================================================================
667//function : D1
668//purpose :
669//=======================================================================
670
94f71cad 671void Geom2dAdaptor_Curve::D1(const Standard_Real U,
672 gp_Pnt2d& P, gp_Vec2d& V) const
673{
d660a72a 674 switch (myTypeCurve)
94f71cad 675 {
d660a72a 676 case GeomAbs_BezierCurve:
677 case GeomAbs_BSplineCurve:
678 {
679 Standard_Integer aStart = 0, aFinish = 0;
680 if (IsBoundary(U, aStart, aFinish))
681 {
3b25c0e8 682 myBSplineCurve->LocalD1(U, aStart, aFinish, P, V);
7fd59977 683 }
d660a72a 684 else if (!myCurveCache.IsNull()) // use cached data
685 {
686 if (!myCurveCache->IsCacheValid(U))
687 RebuildCache(U);
688 myCurveCache->D1(U, P, V);
7fd59977 689 }
d660a72a 690 else
691 myCurve->D1(U, P, V);
692 break;
94f71cad 693 }
94f71cad 694
d660a72a 695 case GeomAbs_OffsetCurve:
696 myNestedEvaluator->D1(U, P, V);
697 break;
94f71cad 698
d660a72a 699 default:
700 myCurve->D1(U, P, V);
701 }
7fd59977 702}
703
704//=======================================================================
705//function : D2
706//purpose :
707//=======================================================================
708
709void Geom2dAdaptor_Curve::D2(const Standard_Real U,
94f71cad 710 gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const
7fd59977 711{
d660a72a 712 switch (myTypeCurve)
94f71cad 713 {
d660a72a 714 case GeomAbs_BezierCurve:
715 case GeomAbs_BSplineCurve:
716 {
717 Standard_Integer aStart = 0, aFinish = 0;
718 if (IsBoundary(U, aStart, aFinish))
719 {
3b25c0e8 720 myBSplineCurve->LocalD2(U, aStart, aFinish, P, V1, V2);
7fd59977 721 }
d660a72a 722 else if (!myCurveCache.IsNull()) // use cached data
723 {
724 if (!myCurveCache->IsCacheValid(U))
725 RebuildCache(U);
726 myCurveCache->D2(U, P, V1, V2);
7fd59977 727 }
d660a72a 728 else
729 myCurve->D2(U, P, V1, V2);
730 break;
7fd59977 731 }
94f71cad 732
d660a72a 733 case GeomAbs_OffsetCurve:
734 myNestedEvaluator->D2(U, P, V1, V2);
735 break;
94f71cad 736
d660a72a 737 default:
738 myCurve->D2(U, P, V1, V2);
739 }
7fd59977 740}
741
742//=======================================================================
743//function : D3
744//purpose :
745//=======================================================================
746
747void Geom2dAdaptor_Curve::D3(const Standard_Real U,
94f71cad 748 gp_Pnt2d& P, gp_Vec2d& V1,
749 gp_Vec2d& V2, gp_Vec2d& V3) const
7fd59977 750{
d660a72a 751 switch (myTypeCurve)
94f71cad 752 {
d660a72a 753 case GeomAbs_BezierCurve:
754 case GeomAbs_BSplineCurve:
755 {
756 Standard_Integer aStart = 0, aFinish = 0;
757 if (IsBoundary(U, aStart, aFinish))
758 {
3b25c0e8 759 myBSplineCurve->LocalD3(U, aStart, aFinish, P, V1, V2, V3);
7fd59977 760 }
d660a72a 761 else if (!myCurveCache.IsNull()) // use cached data
762 {
763 if (!myCurveCache->IsCacheValid(U))
764 RebuildCache(U);
765 myCurveCache->D3(U, P, V1, V2, V3);
7fd59977 766 }
d660a72a 767 else
768 myCurve->D3(U, P, V1, V2, V3);
769 break;
7fd59977 770 }
94f71cad 771
d660a72a 772 case GeomAbs_OffsetCurve:
773 myNestedEvaluator->D3(U, P, V1, V2, V3);
774 break;
94f71cad 775
d660a72a 776 default:
777 myCurve->D3(U, P, V1, V2, V3);
778 }
7fd59977 779}
780
781//=======================================================================
782//function : DN
783//purpose :
784//=======================================================================
785
786gp_Vec2d Geom2dAdaptor_Curve::DN(const Standard_Real U,
94f71cad 787 const Standard_Integer N) const
7fd59977 788{
d660a72a 789 switch (myTypeCurve)
94f71cad 790 {
d660a72a 791 case GeomAbs_BezierCurve:
792 case GeomAbs_BSplineCurve:
793 {
794 Standard_Integer aStart = 0, aFinish = 0;
795 if (IsBoundary(U, aStart, aFinish))
796 {
3b25c0e8 797 myBSplineCurve->LocalDN(U, aStart, aFinish, N);
7fd59977 798 }
d660a72a 799 else
800 return myCurve->DN(U, N);
801 break;
7fd59977 802 }
94f71cad 803
d660a72a 804 case GeomAbs_OffsetCurve:
805 return myNestedEvaluator->DN(U, N);
94f71cad 806 break;
d660a72a 807
808 default: // to eliminate gcc warning
94f71cad 809 break;
94f71cad 810 }
d660a72a 811 return myCurve->DN(U, N);
7fd59977 812}
813
814//=======================================================================
815//function : Resolution
816//purpose :
817//=======================================================================
818
819Standard_Real Geom2dAdaptor_Curve::Resolution(const Standard_Real Ruv) const {
820 switch ( myTypeCurve) {
821 case GeomAbs_Line :
822 return Ruv;
823 case GeomAbs_Circle: {
c5f3a425 824 Standard_Real R = Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d().Radius();
7fd59977 825 if ( R > Ruv/2.)
826 return 2*ASin(Ruv/(2*R));
827 else
c6541a0c 828 return 2*M_PI;
7fd59977 829 }
830 case GeomAbs_Ellipse: {
c5f3a425 831 return Ruv / Handle(Geom2d_Ellipse)::DownCast (myCurve)->MajorRadius();
7fd59977 832 }
833 case GeomAbs_BezierCurve: {
834 Standard_Real res;
c5f3a425 835 Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Resolution(Ruv,res);
7fd59977 836 return res;
837 }
838 case GeomAbs_BSplineCurve: {
839 Standard_Real res;
c5f3a425 840 Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->Resolution(Ruv,res);
7fd59977 841 return res;
842 }
843 default:
844 return Precision::Parametric(Ruv);
845 }
846}
847
848
849// --
850// -- The following methods must be called when GetType returned
851// -- the corresponding type.
852// --
853
854//=======================================================================
855//function : Line
856//purpose :
857//=======================================================================
858
859gp_Lin2d Geom2dAdaptor_Curve::Line() const
860{
861 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
c5f3a425 862 return Handle(Geom2d_Line)::DownCast (myCurve)->Lin2d();
7fd59977 863}
864
865//=======================================================================
866//function : Circle
867//purpose :
868//=======================================================================
869
870gp_Circ2d Geom2dAdaptor_Curve::Circle() const
871{
872 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
c5f3a425 873 return Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d();
7fd59977 874}
875
876//=======================================================================
877//function : Ellipse
878//purpose :
879//=======================================================================
880
881gp_Elips2d Geom2dAdaptor_Curve::Ellipse() const
882{
883 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Ellipse, "");
c5f3a425 884 return Handle(Geom2d_Ellipse)::DownCast (myCurve)->Elips2d();
7fd59977 885}
886
887//=======================================================================
888//function : Hyperbola
889//purpose :
890//=======================================================================
891
892gp_Hypr2d Geom2dAdaptor_Curve::Hyperbola() const
893{
894 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
c5f3a425 895 return Handle(Geom2d_Hyperbola)::DownCast (myCurve)->Hypr2d();
7fd59977 896}
897
898//=======================================================================
899//function : Parabola
900//purpose :
901//=======================================================================
902
903gp_Parab2d Geom2dAdaptor_Curve::Parabola() const
904{
905 Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
c5f3a425 906 return Handle(Geom2d_Parabola)::DownCast (myCurve)->Parab2d();
7fd59977 907}
908
909//=======================================================================
910//function : Degree
911//purpose :
912//=======================================================================
913
914Standard_Integer Geom2dAdaptor_Curve::Degree() const
915{
916 if (myTypeCurve == GeomAbs_BezierCurve)
c5f3a425 917 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Degree();
7fd59977 918 else if (myTypeCurve == GeomAbs_BSplineCurve)
3b25c0e8 919 return myBSplineCurve->Degree();
7fd59977 920 else
921 Standard_NoSuchObject::Raise();
922 // portage WNT
923 return 0;
924}
925
926//=======================================================================
927//function : IsRational
928//purpose :
929//=======================================================================
930
931Standard_Boolean Geom2dAdaptor_Curve::IsRational() const {
932 switch( myTypeCurve) {
933 case GeomAbs_BSplineCurve:
3b25c0e8 934 return myBSplineCurve->IsRational();
7fd59977 935 case GeomAbs_BezierCurve:
c5f3a425 936 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->IsRational();
7fd59977 937 default:
938 return Standard_False;
939 }
940}
941
942//=======================================================================
943//function : NbPoles
944//purpose :
945//=======================================================================
946
947Standard_Integer Geom2dAdaptor_Curve::NbPoles() const
948{
949 if (myTypeCurve == GeomAbs_BezierCurve)
c5f3a425 950 return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->NbPoles();
7fd59977 951 else if (myTypeCurve == GeomAbs_BSplineCurve)
3b25c0e8 952 return myBSplineCurve->NbPoles();
7fd59977 953 else
954 Standard_NoSuchObject::Raise();
955 // portage WNT
956 return 0;
957}
958
959//=======================================================================
960//function : NbKnots
961//purpose :
962//=======================================================================
963
3b25c0e8
IC
964Standard_Integer Geom2dAdaptor_Curve::NbKnots() const
965{
7fd59977 966 if ( myTypeCurve != GeomAbs_BSplineCurve)
967 Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::NbKnots");
3b25c0e8 968 return myBSplineCurve->NbKnots();
7fd59977 969}
970
971//=======================================================================
972//function : Bezier
973//purpose :
974//=======================================================================
975
976Handle(Geom2d_BezierCurve) Geom2dAdaptor_Curve::Bezier() const
977{
c5f3a425 978 return Handle(Geom2d_BezierCurve)::DownCast (myCurve);
7fd59977 979}
980
981//=======================================================================
982//function : BSpline
983//purpose :
984//=======================================================================
985
986Handle(Geom2d_BSplineCurve) Geom2dAdaptor_Curve::BSpline() const
987{
3b25c0e8 988 return myBSplineCurve;
7fd59977 989}
990
a874a4a0 991static Standard_Integer nbPoints(const Handle(Geom2d_Curve)& theCurve)
992{
993
5ae6e53d 994 Standard_Integer nbs = 20;
a874a4a0 995
996 if(theCurve->IsKind(STANDARD_TYPE( Geom2d_Line)) )
997 nbs = 2;
998 else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BezierCurve)))
999 {
c5f3a425 1000 nbs = 3 + Handle(Geom2d_BezierCurve)::DownCast (theCurve)->NbPoles();
a874a4a0 1001 }
1002 else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BSplineCurve))) {
c5f3a425 1003 nbs = Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->NbKnots();
1004 nbs*= Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->Degree();
a874a4a0 1005 if(nbs < 2.0) nbs=2;
1006 }
1007 else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
1008 {
c5f3a425 1009 Handle(Geom2d_Curve) aCurve = Handle(Geom2d_OffsetCurve)::DownCast (theCurve)->BasisCurve();
a874a4a0 1010 return Max(nbs, nbPoints(aCurve));
1011 }
1012
1013 else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
1014 {
c5f3a425 1015 Handle(Geom2d_Curve) aCurve = Handle(Geom2d_TrimmedCurve)::DownCast (theCurve)->BasisCurve();
a874a4a0 1016 return Max(nbs, nbPoints(aCurve));
1017 }
1018 if(nbs>300)
1019 nbs = 300;
1020 return nbs;
3b25c0e8 1021
a874a4a0 1022}
1023
1024Standard_Integer Geom2dAdaptor_Curve::NbSamples() const
1025{
1026 return nbPoints(myCurve);
1027}