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