b311480e |
1 | // Created on: 1991-07-05 |
2 | // Created by: JCV |
3 | // Copyright (c) 1991-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 | // 03-02-97 : pmn ->LocateU sur Periodic (PRO6963), |
18 | // bon appel a LocateParameter (PRO6973) et mise en conformite avec |
19 | // le cdl de LocateU, lorsque U est un noeud (PRO6988) |
20 | |
21 | #define No_Standard_OutOfRange |
22 | #define No_Standard_DimensionError |
23 | |
7fd59977 |
24 | |
42cf5bc1 |
25 | #include <BSplCLib.hxx> |
26 | #include <Geom_BSplineCurve.hxx> |
27 | #include <Geom_Geometry.hxx> |
7fd59977 |
28 | #include <Geom_UndefinedDerivative.hxx> |
42cf5bc1 |
29 | #include <gp.hxx> |
30 | #include <gp_Pnt.hxx> |
31 | #include <gp_Trsf.hxx> |
32 | #include <gp_Vec.hxx> |
33 | #include <Precision.hxx> |
34 | #include <Standard_ConstructionError.hxx> |
7fd59977 |
35 | #include <Standard_DimensionError.hxx> |
7fd59977 |
36 | #include <Standard_DomainError.hxx> |
42cf5bc1 |
37 | #include <Standard_NoSuchObject.hxx> |
38 | #include <Standard_OutOfRange.hxx> |
7fd59977 |
39 | #include <Standard_RangeError.hxx> |
40 | |
41 | #define POLES (poles->Array1()) |
42 | #define KNOTS (knots->Array1()) |
43 | #define FKNOTS (flatknots->Array1()) |
44 | #define FMULTS (BSplCLib::NoMults()) |
45 | |
46 | //======================================================================= |
47 | //function : IsCN |
48 | //purpose : |
49 | //======================================================================= |
50 | |
51 | Standard_Boolean Geom_BSplineCurve::IsCN ( const Standard_Integer N) const |
52 | { |
53 | Standard_RangeError_Raise_if |
54 | (N < 0, "Geom_BSplineCurve::IsCN"); |
55 | |
56 | switch (smooth) { |
57 | case GeomAbs_CN : return Standard_True; |
58 | case GeomAbs_C0 : return N <= 0; |
59 | case GeomAbs_G1 : return N <= 0; |
60 | case GeomAbs_C1 : return N <= 1; |
61 | case GeomAbs_G2 : return N <= 1; |
62 | case GeomAbs_C2 : return N <= 2; |
63 | case GeomAbs_C3 : |
64 | return N <= 3 ? Standard_True : |
65 | N <= deg - BSplCLib::MaxKnotMult (mults->Array1(), mults->Lower() + 1, mults->Upper() - 1); |
66 | default: |
67 | return Standard_False; |
68 | } |
69 | } |
3d58dc49 |
70 | //======================================================================= |
71 | //function : IsG1 |
72 | //purpose : |
73 | //======================================================================= |
74 | |
75 | Standard_Boolean Geom_BSplineCurve::IsG1 ( const Standard_Real theTf, |
76 | const Standard_Real theTl, |
77 | const Standard_Real theAngTol) const |
78 | { |
79 | if(IsCN(1)) |
80 | { |
81 | return Standard_True; |
82 | } |
83 | |
84 | Standard_Integer start = FirstUKnotIndex()+1, |
85 | finish = LastUKnotIndex()-1; |
86 | Standard_Integer aDeg = Degree(); |
87 | for(Standard_Integer aNKnot = start; aNKnot <= finish; aNKnot++) |
88 | { |
89 | const Standard_Real aTpar = Knot(aNKnot); |
90 | |
91 | if(aTpar < theTf) |
92 | continue; |
93 | if(aTpar > theTl) |
94 | break; |
95 | |
96 | Standard_Integer mult = Multiplicity(aNKnot); |
97 | if (mult < aDeg) |
98 | continue; |
99 | |
100 | gp_Pnt aP1, aP2; |
101 | gp_Vec aV1, aV2; |
102 | LocalD1(aTpar, aNKnot-1, aNKnot, aP1, aV1); |
103 | LocalD1(aTpar, aNKnot, aNKnot+1, aP2, aV2); |
104 | |
105 | if((aV1.SquareMagnitude() <= gp::Resolution()) || |
106 | aV2.SquareMagnitude() <= gp::Resolution()) |
107 | { |
108 | return Standard_False; |
109 | } |
110 | |
111 | if(Abs(aV1.Angle(aV2)) > theAngTol) |
112 | return Standard_False; |
113 | } |
114 | |
115 | if(!IsPeriodic()) |
116 | return Standard_True; |
117 | |
118 | const Standard_Real aFirstParam = FirstParameter(), |
119 | aLastParam = LastParameter(); |
120 | |
121 | if( ((aFirstParam - theTf)*(theTl - aFirstParam) < 0.0) && |
122 | ((aLastParam - theTf)*(theTl - aLastParam) < 0.0)) |
123 | { |
124 | //Range [theTf, theTl] does not intersect curve bounadries |
125 | return Standard_True; |
126 | } |
127 | |
128 | //Curve is closed or periodic and range [theTf, theTl] |
129 | //intersect curve boundary. Therefore, it is necessary to |
130 | //check if curve is smooth in its first and last point. |
131 | |
132 | gp_Pnt aP; |
133 | gp_Vec aV1, aV2; |
134 | D1(Knot(FirstUKnotIndex()), aP, aV1); |
135 | D1(Knot(LastUKnotIndex()), aP, aV2); |
136 | |
137 | if((aV1.SquareMagnitude() <= gp::Resolution()) || |
138 | aV2.SquareMagnitude() <= gp::Resolution()) |
139 | { |
140 | return Standard_False; |
141 | } |
142 | |
143 | if(Abs(aV1.Angle(aV2)) > theAngTol) |
144 | return Standard_False; |
145 | |
146 | return Standard_True; |
147 | } |
7fd59977 |
148 | |
149 | //======================================================================= |
150 | //function : IsClosed |
151 | //purpose : |
152 | //======================================================================= |
153 | |
154 | Standard_Boolean Geom_BSplineCurve::IsClosed () const |
155 | //-- { return (StartPoint().Distance (EndPoint())) <= gp::Resolution (); } |
156 | { return (StartPoint().SquareDistance(EndPoint())) <= 1e-16; } |
157 | |
158 | //======================================================================= |
159 | //function : IsPeriodic |
160 | //purpose : |
161 | //======================================================================= |
162 | |
163 | Standard_Boolean Geom_BSplineCurve::IsPeriodic () const |
164 | { return periodic; } |
165 | |
166 | //======================================================================= |
167 | //function : Continuity |
168 | //purpose : |
169 | //======================================================================= |
170 | |
171 | GeomAbs_Shape Geom_BSplineCurve::Continuity () const |
172 | { return smooth; } |
173 | |
174 | //======================================================================= |
175 | //function : Degree |
176 | //purpose : |
177 | //======================================================================= |
178 | |
179 | Standard_Integer Geom_BSplineCurve::Degree () const |
180 | { return deg; } |
181 | |
182 | //======================================================================= |
183 | //function : D0 |
184 | //purpose : |
185 | //======================================================================= |
186 | |
83ada95b |
187 | void Geom_BSplineCurve::D0(const Standard_Real U, gp_Pnt& P) const |
7fd59977 |
188 | { |
94f71cad |
189 | Standard_Integer aSpanIndex = 0; |
190 | Standard_Real aNewU(U); |
191 | PeriodicNormalization(aNewU); |
0e14656b |
192 | BSplCLib::LocateParameter(deg, knots->Array1(), &mults->Array1(), U, periodic, aSpanIndex, aNewU); |
94f71cad |
193 | if (aNewU < knots->Value(aSpanIndex)) |
194 | aSpanIndex--; |
195 | if (rational) |
83ada95b |
196 | { |
94f71cad |
197 | BSplCLib::D0(aNewU,aSpanIndex,deg,periodic,POLES, |
0e14656b |
198 | &weights->Array1(), |
199 | knots->Array1(), &mults->Array1(), |
83ada95b |
200 | P); |
7fd59977 |
201 | } |
94f71cad |
202 | else |
83ada95b |
203 | { |
94f71cad |
204 | BSplCLib::D0(aNewU,aSpanIndex,deg,periodic,POLES, |
0e14656b |
205 | BSplCLib::NoWeights(), |
206 | knots->Array1(), &mults->Array1(), |
83ada95b |
207 | P); |
7fd59977 |
208 | } |
209 | } |
210 | |
211 | //======================================================================= |
212 | //function : D1 |
213 | //purpose : |
214 | //======================================================================= |
215 | |
216 | void Geom_BSplineCurve::D1 (const Standard_Real U, |
217 | gp_Pnt& P, |
218 | gp_Vec& V1) const |
219 | { |
94f71cad |
220 | Standard_Integer aSpanIndex = 0; |
221 | Standard_Real aNewU(U); |
222 | PeriodicNormalization(aNewU); |
0e14656b |
223 | BSplCLib::LocateParameter(deg, knots->Array1(), &mults->Array1(), U, periodic, aSpanIndex, aNewU); |
94f71cad |
224 | if (aNewU < knots->Value(aSpanIndex)) |
225 | aSpanIndex--; |
226 | if (rational) |
83ada95b |
227 | { |
94f71cad |
228 | BSplCLib::D1(aNewU,aSpanIndex,deg,periodic,POLES, |
0e14656b |
229 | &weights->Array1(), |
230 | knots->Array1(), &mults->Array1(), |
94f71cad |
231 | P, V1); |
7fd59977 |
232 | } |
94f71cad |
233 | else |
83ada95b |
234 | { |
94f71cad |
235 | BSplCLib::D1(aNewU,aSpanIndex,deg,periodic,POLES, |
0e14656b |
236 | BSplCLib::NoWeights(), |
237 | knots->Array1(), &mults->Array1(), |
94f71cad |
238 | P, V1); |
7fd59977 |
239 | } |
240 | } |
241 | |
242 | //======================================================================= |
243 | //function : D2 |
244 | //purpose : |
245 | //======================================================================= |
246 | |
83ada95b |
247 | void Geom_BSplineCurve::D2(const Standard_Real U, |
248 | gp_Pnt& P, |
249 | gp_Vec& V1, |
250 | gp_Vec& V2) const |
7fd59977 |
251 | { |
94f71cad |
252 | Standard_Integer aSpanIndex = 0; |
253 | Standard_Real aNewU(U); |
254 | PeriodicNormalization(aNewU); |
0e14656b |
255 | BSplCLib::LocateParameter(deg, knots->Array1(), &mults->Array1(), U, periodic, aSpanIndex, aNewU); |
94f71cad |
256 | if (aNewU < knots->Value(aSpanIndex)) |
257 | aSpanIndex--; |
258 | if (rational) |
83ada95b |
259 | { |
94f71cad |
260 | BSplCLib::D2(aNewU,aSpanIndex,deg,periodic,POLES, |
0e14656b |
261 | &weights->Array1(), |
262 | knots->Array1(), &mults->Array1(), |
94f71cad |
263 | P, V1, V2); |
7fd59977 |
264 | } |
94f71cad |
265 | else |
266 | { |
267 | BSplCLib::D2(aNewU,aSpanIndex,deg,periodic,POLES, |
0e14656b |
268 | BSplCLib::NoWeights(), |
269 | knots->Array1(), &mults->Array1(), |
94f71cad |
270 | P, V1, V2); |
7fd59977 |
271 | } |
272 | } |
273 | |
274 | //======================================================================= |
275 | //function : D3 |
276 | //purpose : |
277 | //======================================================================= |
278 | |
83ada95b |
279 | void Geom_BSplineCurve::D3(const Standard_Real U, |
280 | gp_Pnt& P, |
281 | gp_Vec& V1, |
282 | gp_Vec& V2, |
283 | gp_Vec& V3) const |
7fd59977 |
284 | { |
94f71cad |
285 | Standard_Integer aSpanIndex = 0; |
286 | Standard_Real aNewU(U); |
287 | PeriodicNormalization(aNewU); |
0e14656b |
288 | BSplCLib::LocateParameter(deg, knots->Array1(), &mults->Array1(), U, periodic, aSpanIndex, aNewU); |
94f71cad |
289 | if (aNewU < knots->Value(aSpanIndex)) |
290 | aSpanIndex--; |
291 | if (rational) |
83ada95b |
292 | { |
94f71cad |
293 | BSplCLib::D3(aNewU,aSpanIndex,deg,periodic,POLES, |
0e14656b |
294 | &weights->Array1(), |
295 | knots->Array1(), &mults->Array1(), |
94f71cad |
296 | P, V1, V2, V3); |
7fd59977 |
297 | } |
94f71cad |
298 | else |
83ada95b |
299 | { |
94f71cad |
300 | BSplCLib::D3(aNewU,aSpanIndex,deg,periodic,POLES, |
0e14656b |
301 | BSplCLib::NoWeights(), |
302 | knots->Array1(), &mults->Array1(), |
94f71cad |
303 | P, V1, V2, V3); |
7fd59977 |
304 | } |
305 | } |
306 | |
307 | //======================================================================= |
308 | //function : DN |
309 | //purpose : |
310 | //======================================================================= |
311 | |
94f71cad |
312 | gp_Vec Geom_BSplineCurve::DN(const Standard_Real U, |
313 | const Standard_Integer N) const |
7fd59977 |
314 | { |
315 | gp_Vec V; |
316 | if (rational) { |
317 | BSplCLib::DN(U,N,0,deg,periodic,POLES, |
0e14656b |
318 | &weights->Array1(), |
94f71cad |
319 | FKNOTS,FMULTS,V); |
7fd59977 |
320 | } |
321 | else { |
322 | BSplCLib::DN(U,N,0,deg,periodic,POLES, |
0e14656b |
323 | BSplCLib::NoWeights(), |
94f71cad |
324 | FKNOTS,FMULTS,V); |
7fd59977 |
325 | } |
326 | return V; |
327 | } |
328 | |
329 | //======================================================================= |
330 | //function : EndPoint |
331 | //purpose : |
332 | //======================================================================= |
333 | |
334 | gp_Pnt Geom_BSplineCurve::EndPoint () const |
335 | { |
336 | if (mults->Value (knots->Upper ()) == deg + 1) |
337 | return poles->Value (poles->Upper()); |
338 | else |
339 | return Value(LastParameter()); |
340 | } |
341 | |
342 | //======================================================================= |
343 | //function : FirstUKnotIndex |
344 | //purpose : |
345 | //======================================================================= |
346 | |
347 | Standard_Integer Geom_BSplineCurve::FirstUKnotIndex () const |
348 | { |
349 | if (periodic) return 1; |
350 | else return BSplCLib::FirstUKnotIndex (deg, mults->Array1()); |
351 | } |
352 | |
353 | //======================================================================= |
354 | //function : FirstParameter |
355 | //purpose : |
356 | //======================================================================= |
357 | |
358 | Standard_Real Geom_BSplineCurve::FirstParameter () const |
359 | { |
360 | return flatknots->Value (deg+1); |
361 | } |
362 | |
363 | //======================================================================= |
364 | //function : Knot |
365 | //purpose : |
366 | //======================================================================= |
367 | |
368 | Standard_Real Geom_BSplineCurve::Knot (const Standard_Integer Index) const |
369 | { |
370 | Standard_OutOfRange_Raise_if |
371 | (Index < 1 || Index > knots->Length(), "Geom_BSplineCurve::Knot"); |
372 | return knots->Value (Index); |
373 | } |
374 | |
375 | //======================================================================= |
376 | //function : KnotDistribution |
377 | //purpose : |
378 | //======================================================================= |
379 | |
380 | GeomAbs_BSplKnotDistribution Geom_BSplineCurve::KnotDistribution () const |
381 | { |
382 | return knotSet; |
383 | } |
384 | |
385 | //======================================================================= |
386 | //function : Knots |
387 | //purpose : |
388 | //======================================================================= |
389 | |
390 | void Geom_BSplineCurve::Knots (TColStd_Array1OfReal& K) const |
391 | { |
738d336b |
392 | Standard_DomainError_Raise_if (K.Lower() < knots->Lower() || |
393 | K.Upper() > knots->Upper(), |
394 | "Geom_BSplineCurve::Knots"); |
395 | for(Standard_Integer anIdx = K.Lower(); anIdx <= K.Upper(); anIdx++) |
396 | K(anIdx) = knots->Value(anIdx); |
7fd59977 |
397 | } |
398 | |
94f71cad |
399 | const TColStd_Array1OfReal& Geom_BSplineCurve::Knots() const |
400 | { |
401 | return knots->Array1(); |
402 | } |
403 | |
7fd59977 |
404 | //======================================================================= |
405 | //function : KnotSequence |
406 | //purpose : |
407 | //======================================================================= |
408 | |
409 | void Geom_BSplineCurve::KnotSequence (TColStd_Array1OfReal& K) const |
410 | { |
738d336b |
411 | Standard_DomainError_Raise_if (K.Lower() < flatknots->Lower() || |
412 | K.Upper() > flatknots->Upper(), |
413 | "Geom_BSplineCurve::KnotSequence"); |
414 | for(Standard_Integer anIdx = K.Lower(); anIdx <= K.Upper(); anIdx++) |
415 | K(anIdx) = flatknots->Value(anIdx); |
7fd59977 |
416 | } |
417 | |
94f71cad |
418 | const TColStd_Array1OfReal& Geom_BSplineCurve::KnotSequence() const |
419 | { |
420 | return flatknots->Array1(); |
421 | } |
422 | |
7fd59977 |
423 | //======================================================================= |
424 | //function : LastUKnotIndex |
425 | //purpose : |
426 | //======================================================================= |
427 | |
428 | Standard_Integer Geom_BSplineCurve::LastUKnotIndex() const |
429 | { |
430 | if (periodic) return knots->Length(); |
431 | else return BSplCLib::LastUKnotIndex (deg, mults->Array1()); |
432 | } |
433 | |
434 | //======================================================================= |
435 | //function : LastParameter |
436 | //purpose : |
437 | //======================================================================= |
438 | |
439 | Standard_Real Geom_BSplineCurve::LastParameter () const |
440 | { |
441 | return flatknots->Value (flatknots->Upper()-deg); |
442 | } |
443 | |
444 | //======================================================================= |
445 | //function : LocalValue |
446 | //purpose : |
447 | //======================================================================= |
448 | |
449 | gp_Pnt Geom_BSplineCurve::LocalValue |
450 | (const Standard_Real U, |
451 | const Standard_Integer FromK1, |
452 | const Standard_Integer ToK2) const |
453 | { |
454 | gp_Pnt P; |
455 | LocalD0(U,FromK1,ToK2,P); |
456 | return P; |
457 | } |
458 | |
459 | //======================================================================= |
460 | //function : LocalD0 |
461 | //purpose : |
462 | //======================================================================= |
463 | |
464 | void Geom_BSplineCurve::LocalD0 |
465 | (const Standard_Real U, |
466 | const Standard_Integer FromK1, |
467 | const Standard_Integer ToK2, |
468 | gp_Pnt& P) const |
469 | { |
470 | Standard_DomainError_Raise_if (FromK1 == ToK2, |
471 | "Geom_BSplineCurve::LocalValue"); |
472 | |
473 | Standard_Real u = U; |
474 | Standard_Integer index = 0; |
475 | BSplCLib::LocateParameter(deg, FKNOTS, U, periodic,FromK1,ToK2, index,u); |
476 | index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic); |
477 | if (rational) { |
478 | BSplCLib::D0(u,index,deg,periodic,POLES, |
0e14656b |
479 | &weights->Array1(), |
7fd59977 |
480 | FKNOTS,FMULTS,P); |
481 | } |
482 | else { |
483 | BSplCLib::D0(u,index,deg,periodic,POLES, |
0e14656b |
484 | BSplCLib::NoWeights(), |
7fd59977 |
485 | FKNOTS,FMULTS,P); |
486 | } |
487 | } |
488 | |
489 | //======================================================================= |
490 | //function : LocalD1 |
491 | //purpose : |
492 | //======================================================================= |
493 | |
494 | void Geom_BSplineCurve::LocalD1 (const Standard_Real U, |
495 | const Standard_Integer FromK1, |
496 | const Standard_Integer ToK2, |
497 | gp_Pnt& P, |
498 | gp_Vec& V1) const |
499 | { |
500 | Standard_DomainError_Raise_if (FromK1 == ToK2, |
501 | "Geom_BSplineCurve::LocalD1"); |
502 | |
503 | Standard_Real u = U; |
504 | Standard_Integer index = 0; |
505 | BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u); |
506 | index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic); |
507 | if (rational) { |
508 | BSplCLib::D1(u,index,deg,periodic,POLES, |
0e14656b |
509 | &weights->Array1(), |
7fd59977 |
510 | FKNOTS,FMULTS,P,V1); |
511 | } |
512 | else { |
513 | BSplCLib::D1(u,index,deg,periodic,POLES, |
0e14656b |
514 | BSplCLib::NoWeights(), |
7fd59977 |
515 | FKNOTS,FMULTS,P,V1); |
516 | } |
517 | } |
518 | |
519 | //======================================================================= |
520 | //function : LocalD2 |
521 | //purpose : |
522 | //======================================================================= |
523 | |
524 | void Geom_BSplineCurve::LocalD2 |
525 | (const Standard_Real U, |
526 | const Standard_Integer FromK1, |
527 | const Standard_Integer ToK2, |
528 | gp_Pnt& P, |
529 | gp_Vec& V1, |
530 | gp_Vec& V2) const |
531 | { |
532 | Standard_DomainError_Raise_if (FromK1 == ToK2, |
533 | "Geom_BSplineCurve::LocalD2"); |
534 | |
535 | Standard_Real u = U; |
536 | Standard_Integer index = 0; |
537 | BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u); |
538 | index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic); |
539 | if (rational) { |
540 | BSplCLib::D2(u,index,deg,periodic,POLES, |
0e14656b |
541 | &weights->Array1(), |
7fd59977 |
542 | FKNOTS,FMULTS,P,V1,V2); |
543 | } |
544 | else { |
545 | BSplCLib::D2(u,index,deg,periodic,POLES, |
0e14656b |
546 | BSplCLib::NoWeights(), |
7fd59977 |
547 | FKNOTS,FMULTS,P,V1,V2); |
548 | } |
549 | } |
550 | |
551 | //======================================================================= |
552 | //function : LocalD3 |
553 | //purpose : |
554 | //======================================================================= |
555 | |
556 | void Geom_BSplineCurve::LocalD3 |
557 | (const Standard_Real U, |
558 | const Standard_Integer FromK1, |
559 | const Standard_Integer ToK2, |
560 | gp_Pnt& P, |
561 | gp_Vec& V1, |
562 | gp_Vec& V2, |
563 | gp_Vec& V3) const |
564 | { |
565 | Standard_DomainError_Raise_if (FromK1 == ToK2, |
566 | "Geom_BSplineCurve::LocalD3"); |
567 | |
568 | Standard_Real u = U; |
569 | Standard_Integer index = 0; |
570 | BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u); |
571 | index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic); |
572 | if (rational) { |
573 | BSplCLib::D3(u,index,deg,periodic,POLES, |
0e14656b |
574 | &weights->Array1(), |
7fd59977 |
575 | FKNOTS,FMULTS,P,V1,V2,V3); |
576 | } |
577 | else { |
578 | BSplCLib::D3(u,index,deg,periodic,POLES, |
0e14656b |
579 | BSplCLib::NoWeights(), |
7fd59977 |
580 | FKNOTS,FMULTS,P,V1,V2,V3); |
581 | } |
582 | } |
583 | |
584 | //======================================================================= |
585 | //function : LocalDN |
586 | //purpose : |
587 | //======================================================================= |
588 | |
589 | gp_Vec Geom_BSplineCurve::LocalDN |
590 | (const Standard_Real U, |
591 | const Standard_Integer FromK1, |
592 | const Standard_Integer ToK2, |
593 | const Standard_Integer N ) const |
594 | { |
595 | Standard_DomainError_Raise_if (FromK1 == ToK2, |
596 | "Geom_BSplineCurve::LocalD3"); |
597 | |
598 | Standard_Real u = U; |
599 | Standard_Integer index = 0; |
600 | BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u); |
601 | index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic); |
602 | |
603 | gp_Vec V; |
604 | if (rational) { |
605 | BSplCLib::DN(u,N,index,deg,periodic,POLES, |
0e14656b |
606 | &weights->Array1(), |
7fd59977 |
607 | FKNOTS,FMULTS,V); |
608 | } |
609 | else { |
610 | BSplCLib::DN(u,N,index,deg,periodic,POLES, |
0e14656b |
611 | BSplCLib::NoWeights(), |
7fd59977 |
612 | FKNOTS,FMULTS,V); |
613 | } |
614 | return V; |
615 | } |
616 | |
617 | //======================================================================= |
618 | //function : Multiplicity |
619 | //purpose : |
620 | //======================================================================= |
621 | |
622 | Standard_Integer Geom_BSplineCurve::Multiplicity |
623 | (const Standard_Integer Index) const |
624 | { |
625 | Standard_OutOfRange_Raise_if (Index < 1 || Index > mults->Length(), |
626 | "Geom_BSplineCurve::Multiplicity"); |
627 | return mults->Value (Index); |
628 | } |
629 | |
630 | //======================================================================= |
631 | //function : Multiplicities |
632 | //purpose : |
633 | //======================================================================= |
634 | |
635 | void Geom_BSplineCurve::Multiplicities (TColStd_Array1OfInteger& M) const |
636 | { |
637 | Standard_DimensionError_Raise_if (M.Length() != mults->Length(), |
638 | "Geom_BSplineCurve::Multiplicities"); |
639 | M = mults->Array1(); |
640 | } |
641 | |
94f71cad |
642 | const TColStd_Array1OfInteger& Geom_BSplineCurve::Multiplicities() const |
643 | { |
644 | return mults->Array1(); |
645 | } |
646 | |
7fd59977 |
647 | //======================================================================= |
648 | //function : NbKnots |
649 | //purpose : |
650 | //======================================================================= |
651 | |
652 | Standard_Integer Geom_BSplineCurve::NbKnots () const |
653 | { return knots->Length(); } |
654 | |
655 | //======================================================================= |
656 | //function : NbPoles |
657 | //purpose : |
658 | //======================================================================= |
659 | |
660 | Standard_Integer Geom_BSplineCurve::NbPoles () const |
661 | { return poles->Length(); } |
662 | |
663 | //======================================================================= |
664 | //function : Pole |
665 | //purpose : |
666 | //======================================================================= |
667 | |
81093856 |
668 | const gp_Pnt& Geom_BSplineCurve::Pole (const Standard_Integer Index) const |
7fd59977 |
669 | { |
670 | Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(), |
671 | "Geom_BSplineCurve::Pole"); |
672 | return poles->Value (Index); |
673 | } |
674 | |
675 | //======================================================================= |
676 | //function : Poles |
677 | //purpose : |
678 | //======================================================================= |
679 | |
680 | void Geom_BSplineCurve::Poles (TColgp_Array1OfPnt& P) const |
681 | { |
682 | Standard_DimensionError_Raise_if (P.Length() != poles->Length(), |
683 | "Geom_BSplineCurve::Poles"); |
684 | P = poles->Array1(); |
685 | } |
686 | |
94f71cad |
687 | const TColgp_Array1OfPnt& Geom_BSplineCurve::Poles() const |
688 | { |
689 | return poles->Array1(); |
690 | } |
691 | |
7fd59977 |
692 | //======================================================================= |
693 | //function : StartPoint |
694 | //purpose : |
695 | //======================================================================= |
696 | |
697 | gp_Pnt Geom_BSplineCurve::StartPoint () const |
698 | { |
699 | if (mults->Value (1) == deg + 1) |
700 | return poles->Value (1); |
701 | else |
702 | return Value(FirstParameter()); |
703 | } |
704 | |
705 | //======================================================================= |
706 | //function : Weight |
707 | //purpose : |
708 | //======================================================================= |
709 | |
710 | Standard_Real Geom_BSplineCurve::Weight |
711 | (const Standard_Integer Index) const |
712 | { |
713 | Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(), |
714 | "Geom_BSplineCurve::Weight"); |
715 | if (IsRational()) |
716 | return weights->Value (Index); |
717 | else |
718 | return 1.; |
719 | } |
720 | |
721 | //======================================================================= |
722 | //function : Weights |
723 | //purpose : |
724 | //======================================================================= |
725 | |
726 | void Geom_BSplineCurve::Weights |
727 | (TColStd_Array1OfReal& W) const |
728 | { |
729 | Standard_DimensionError_Raise_if (W.Length() != poles->Length(), |
730 | "Geom_BSplineCurve::Weights"); |
731 | if (IsRational()) |
732 | W = weights->Array1(); |
733 | else { |
734 | Standard_Integer i; |
735 | |
736 | for (i = W.Lower(); i <= W.Upper(); i++) |
737 | W(i) = 1.; |
738 | } |
739 | } |
740 | |
0e14656b |
741 | const TColStd_Array1OfReal* Geom_BSplineCurve::Weights() const |
94f71cad |
742 | { |
743 | if (IsRational()) |
0e14656b |
744 | return &weights->Array1(); |
94f71cad |
745 | return BSplCLib::NoWeights(); |
746 | } |
747 | |
7fd59977 |
748 | //======================================================================= |
749 | //function : IsRational |
750 | //purpose : |
751 | //======================================================================= |
752 | |
753 | Standard_Boolean Geom_BSplineCurve::IsRational () const |
754 | { |
755 | return !weights.IsNull(); |
756 | } |
757 | |
758 | //======================================================================= |
759 | //function : Transform |
760 | //purpose : |
761 | //======================================================================= |
762 | |
763 | void Geom_BSplineCurve::Transform |
764 | (const gp_Trsf& T) |
765 | { |
766 | TColgp_Array1OfPnt & CPoles = poles->ChangeArray1(); |
767 | for (Standard_Integer I = 1; I <= CPoles.Length(); I++) |
768 | CPoles (I).Transform (T); |
7fd59977 |
769 | maxderivinvok = 0; |
770 | } |
771 | |
772 | //======================================================================= |
773 | //function : LocateU |
774 | //purpose : |
775 | // pmn : 30/01/97 mise en conformite avec le cdl, lorsque U est un noeud |
776 | // (PRO6988) |
777 | //======================================================================= |
778 | |
779 | void Geom_BSplineCurve::LocateU |
780 | (const Standard_Real U, |
781 | const Standard_Real ParametricTolerance, |
782 | Standard_Integer& I1, |
783 | Standard_Integer& I2, |
784 | const Standard_Boolean WithKnotRepetition) const |
785 | { |
786 | Standard_Real NewU = U; |
787 | Handle(TColStd_HArray1OfReal) TheKnots; |
788 | if (WithKnotRepetition) TheKnots = flatknots; |
789 | else TheKnots = knots; |
790 | const TColStd_Array1OfReal & CKnots = TheKnots->Array1(); |
791 | |
792 | PeriodicNormalization(NewU); //Attention a la periode |
793 | |
794 | Standard_Real UFirst = CKnots (1); |
795 | Standard_Real ULast = CKnots (CKnots.Length()); |
41c52af3 |
796 | Standard_Real PParametricTolerance = Abs(ParametricTolerance); |
797 | if (Abs (NewU - UFirst) <= PParametricTolerance) { I1 = I2 = 1; } |
798 | else if (Abs (NewU - ULast) <= PParametricTolerance) { |
7fd59977 |
799 | I1 = I2 = CKnots.Length(); |
800 | } |
41c52af3 |
801 | else if (NewU < UFirst) { |
7fd59977 |
802 | I2 = 1; |
803 | I1 = 0; |
804 | } |
41c52af3 |
805 | else if (NewU > ULast) { |
7fd59977 |
806 | I1 = CKnots.Length(); |
807 | I2 = I1 + 1; |
808 | } |
809 | else { |
810 | I1 = 1; |
811 | BSplCLib::Hunt (CKnots, NewU, I1); |
41c52af3 |
812 | while ( Abs( CKnots(I1+1) - NewU) <= PParametricTolerance) I1++; |
813 | if ( Abs( CKnots(I1) - NewU) <= PParametricTolerance) { |
7fd59977 |
814 | I2 = I1; |
815 | } |
816 | else { |
817 | I2 = I1 + 1; |
818 | } |
819 | } |
820 | } |
821 | |
822 | //======================================================================= |
823 | //function : Resolution |
824 | //purpose : |
825 | //======================================================================= |
826 | |
827 | void Geom_BSplineCurve::Resolution(const Standard_Real Tolerance3D, |
828 | Standard_Real & UTolerance) |
829 | { |
830 | Standard_Integer ii; |
831 | if(!maxderivinvok){ |
832 | if ( periodic) { |
833 | Standard_Integer NbKnots, NbPoles; |
834 | BSplCLib::PrepareUnperiodize( deg, |
835 | mults->Array1(), |
836 | NbKnots, |
837 | NbPoles); |
838 | TColgp_Array1OfPnt new_poles(1,NbPoles) ; |
839 | TColStd_Array1OfReal new_weights(1,NbPoles) ; |
840 | for(ii = 1 ; ii <= NbPoles ; ii++) { |
841 | new_poles(ii) = poles->Array1()((ii-1) % poles->Length() + 1) ; |
842 | } |
843 | if (rational) { |
844 | for(ii = 1 ; ii <= NbPoles ; ii++) { |
845 | new_weights(ii) = weights->Array1()((ii-1) % poles->Length() + 1) ; |
846 | } |
847 | BSplCLib::Resolution(new_poles, |
0e14656b |
848 | &new_weights, |
7fd59977 |
849 | new_poles.Length(), |
850 | flatknots->Array1(), |
851 | deg, |
852 | 1., |
853 | maxderivinv) ; |
854 | } |
855 | else { |
856 | BSplCLib::Resolution(new_poles, |
0e14656b |
857 | BSplCLib::NoWeights(), |
7fd59977 |
858 | new_poles.Length(), |
859 | flatknots->Array1(), |
860 | deg, |
861 | 1., |
862 | maxderivinv) ; |
863 | } |
864 | |
865 | } |
866 | else { |
867 | if (rational) { |
868 | BSplCLib::Resolution(poles->Array1(), |
0e14656b |
869 | &weights->Array1(), |
7fd59977 |
870 | poles->Length(), |
871 | flatknots->Array1(), |
872 | deg, |
873 | 1., |
874 | maxderivinv) ; |
875 | } |
876 | else { |
877 | BSplCLib::Resolution(poles->Array1(), |
0e14656b |
878 | BSplCLib::NoWeights(), |
7fd59977 |
879 | poles->Length(), |
880 | flatknots->Array1(), |
881 | deg, |
882 | 1., |
883 | maxderivinv) ; |
884 | } |
885 | } |
886 | maxderivinvok = 1; |
887 | } |
888 | UTolerance = Tolerance3D * maxderivinv; |
889 | } |
a7493ad4 |
890 | |
891 | //======================================================================= |
892 | //function : IsEqual |
893 | //purpose : |
894 | //======================================================================= |
895 | |
896 | Standard_Boolean Geom_BSplineCurve::IsEqual(const Handle(Geom_BSplineCurve)& theOther, |
897 | const Standard_Real thePreci) const |
898 | { |
899 | if( knots.IsNull() || poles.IsNull() || mults.IsNull() ) |
900 | return Standard_False; |
901 | if( deg != theOther->Degree()) |
902 | return Standard_False; |
903 | if( knots->Length() != theOther->NbKnots() || |
904 | poles->Length() != theOther->NbPoles()) |
905 | return Standard_False; |
906 | |
907 | Standard_Integer i = 1; |
908 | for( i = 1 ; i <= poles->Length(); i++ ) |
909 | { |
910 | const gp_Pnt& aPole1 = poles->Value(i); |
911 | const gp_Pnt& aPole2 =theOther->Pole(i); |
912 | if( fabs( aPole1.X() - aPole2.X() ) > thePreci || |
913 | fabs( aPole1.Y() - aPole2.Y() ) > thePreci || |
914 | fabs( aPole1.Z() - aPole2.Z() ) > thePreci ) |
915 | return Standard_False; |
916 | } |
917 | |
918 | for( ; i <= knots->Length(); i++ ) |
919 | { |
920 | if( fabs(knots->Value(i) - theOther->Knot(i)) > Precision::Parametric(thePreci) ) |
921 | return Standard_False; |
922 | } |
923 | |
924 | for( i = 1 ; i <= mults->Length(); i++ ) |
925 | { |
926 | if( mults->Value(i) != theOther->Multiplicity(i) ) |
927 | return Standard_False; |
928 | } |
929 | |
930 | if( rational != theOther->IsRational()) |
931 | return Standard_False; |
932 | |
933 | if(!rational) |
934 | return Standard_True; |
935 | |
936 | for( i = 1 ; i <= weights->Length(); i++ ) |
937 | { |
938 | if( fabs( Standard_Real(weights->Value(i) - theOther->Weight(i))) > Epsilon(weights->Value(i)) ) |
939 | return Standard_False; |
940 | } |
941 | return Standard_True; |
942 | } |