0030582: Coding - avoid defining references to properties of NULL objects
[occt.git] / src / Geom / Geom_BSplineCurve_1.cxx
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
43 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
67 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 bounadries
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
146 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
155 Standard_Boolean Geom_BSplineCurve::IsPeriodic () const
156 { return periodic; }
157
158 //=======================================================================
159 //function : Continuity
160 //purpose  : 
161 //=======================================================================
162
163 GeomAbs_Shape Geom_BSplineCurve::Continuity () const
164 { return smooth; }
165
166 //=======================================================================
167 //function : Degree
168 //purpose  : 
169 //=======================================================================
170
171 Standard_Integer Geom_BSplineCurve::Degree () const
172 { return deg; }
173
174 //=======================================================================
175 //function : D0
176 //purpose  : 
177 //=======================================================================
178
179 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
199 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
221 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
244 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
268 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
283 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
296 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
307 Standard_Real Geom_BSplineCurve::FirstParameter () const
308 {
309   return flatknots->Value (deg+1); 
310 }
311
312 //=======================================================================
313 //function : Knot
314 //purpose  : 
315 //=======================================================================
316
317 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
329 GeomAbs_BSplKnotDistribution Geom_BSplineCurve::KnotDistribution () const
330
331   return knotSet; 
332 }
333
334 //=======================================================================
335 //function : Knots
336 //purpose  : 
337 //=======================================================================
338
339 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
348 const TColStd_Array1OfReal& Geom_BSplineCurve::Knots() const
349 {
350   return knots->Array1();
351 }
352
353 //=======================================================================
354 //function : KnotSequence
355 //purpose  : 
356 //=======================================================================
357
358 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
367 const TColStd_Array1OfReal& Geom_BSplineCurve::KnotSequence() const
368 {
369   return flatknots->Array1();
370 }
371
372 //=======================================================================
373 //function : LastUKnotIndex
374 //purpose  : 
375 //=======================================================================
376
377 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
388 Standard_Real Geom_BSplineCurve::LastParameter () const
389 {
390   return flatknots->Value (flatknots->Upper()-deg); 
391 }
392
393 //=======================================================================
394 //function : LocalValue
395 //purpose  : 
396 //=======================================================================
397
398 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
413 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
436 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
459 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
484 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
510 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
536 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
549 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
556 const TColStd_Array1OfInteger& Geom_BSplineCurve::Multiplicities() const
557 {
558   return mults->Array1();
559 }
560
561 //=======================================================================
562 //function : NbKnots
563 //purpose  : 
564 //=======================================================================
565
566 Standard_Integer Geom_BSplineCurve::NbKnots () const
567 { return knots->Length(); }
568
569 //=======================================================================
570 //function : NbPoles
571 //purpose  : 
572 //=======================================================================
573
574 Standard_Integer Geom_BSplineCurve::NbPoles () const
575 { return poles->Length(); }
576
577 //=======================================================================
578 //function : Pole
579 //purpose  : 
580 //=======================================================================
581
582 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
594 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
601 const TColgp_Array1OfPnt& Geom_BSplineCurve::Poles() const
602 {
603   return poles->Array1();
604 }
605
606 //=======================================================================
607 //function : StartPoint
608 //purpose  : 
609 //=======================================================================
610
611 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
624 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
640 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
655 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
667 Standard_Boolean Geom_BSplineCurve::IsRational () const
668
669   return !weights.IsNull(); 
670
671
672 //=======================================================================
673 //function : Transform
674 //purpose  : 
675 //=======================================================================
676
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
693 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
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
796 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 }