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