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