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