0024624: Lost word in license statement in source files
[occt.git] / src / GeomAdaptor / GeomAdaptor_Curve.cxx
1 // Created on: 1993-04-29
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1993-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 // 20/02/97 : PMN -> Positionement local sur BSpline (PRO6902)
18 // 10/07/97 : PMN -> Pas de calcul de resolution dans Nb(Intervals)(PRO9248)
19 // 20/10/97 : RBV -> traitement des offset curves
20
21 #define No_Standard_RangeError
22 #define No_Standard_OutOfRange
23
24 #include <GeomAdaptor_Curve.ixx>
25
26 #include <GeomAdaptor_HCurve.hxx>
27 #include <Adaptor3d_HCurve.hxx>
28 #include <BSplCLib.hxx>
29 #include <GeomAbs_Shape.hxx>
30 #include <TColgp_Array1OfPnt.hxx>
31 #include <TColStd_Array1OfReal.hxx>
32 #include <TColStd_Array1OfInteger.hxx>
33 #include <TColStd_HArray1OfInteger.hxx>
34 #include <Precision.hxx>
35 #include <Geom_TrimmedCurve.hxx>
36 #include <Geom_Circle.hxx>
37 #include <Geom_Line.hxx>
38 #include <Geom_TrimmedCurve.hxx>
39 #include <Geom_BezierCurve.hxx>
40 #include <Geom_BSplineCurve.hxx>
41 #include <Geom_Ellipse.hxx>
42 #include <Geom_Parabola.hxx>
43 #include <Geom_Hyperbola.hxx>
44 //#include <GeomConvert_BSplineCurveKnotSplitting.hxx>
45
46 #include <Standard_OutOfRange.hxx>
47 #include <Standard_NoSuchObject.hxx>
48 #include <Standard_NullObject.hxx>
49 #include <Standard_NotImplemented.hxx>
50 #include <Geom_OffsetCurve.hxx>
51
52 #define myBspl (*((Handle(Geom_BSplineCurve)*)&myCurve))
53 #define PosTol Precision::PConfusion()/2
54
55 //=======================================================================
56 //function : LocalContinuity
57 //purpose  : Computes the Continuity of a BSplineCurve 
58 //           between the parameters U1 and U2
59 //           The continuity is C(d-m) 
60 //             with   d = degree, 
61 //                    m = max multiplicity of the Knots between U1 and U2
62 //=======================================================================
63
64 GeomAbs_Shape GeomAdaptor_Curve::LocalContinuity(const Standard_Real U1, 
65                                                  const Standard_Real U2) 
66      const 
67 {
68   Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
69   Standard_Integer Nb = myBspl->NbKnots();
70   Standard_Integer Index1 = 0;
71   Standard_Integer Index2 = 0;
72   Standard_Real newFirst, newLast;
73   TColStd_Array1OfReal    TK(1,Nb);
74   TColStd_Array1OfInteger TM(1,Nb);
75   myBspl->Knots(TK);
76   myBspl->Multiplicities(TM);
77   BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,U1,myBspl->IsPeriodic(),
78                             1,Nb,Index1,newFirst);
79   BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,U2,myBspl->IsPeriodic(),
80                             1,Nb,Index2,newLast);
81   if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) { 
82     if (Index1 < Nb) Index1++;
83   }
84   if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
85     Index2--;
86   Standard_Integer MultMax;
87   // attention aux courbes peridiques.
88   if ( (myBspl->IsPeriodic()) && (Index1 == Nb) )
89     Index1 = 1;
90
91   if ( Index2 - Index1 <= 0) {
92     MultMax = 100;  // CN entre 2 Noeuds consecutifs
93   }
94   else {
95     MultMax = TM(Index1+1);
96     for(Standard_Integer i = Index1+1;i<=Index2;i++) {
97       if ( TM(i)>MultMax) MultMax=TM(i);
98     }
99     MultMax = myBspl->Degree() - MultMax;
100   }
101   if ( MultMax <= 0) {
102     return GeomAbs_C0;
103   }
104   else if ( MultMax == 1) {
105     return GeomAbs_C1;
106   } 
107   else if ( MultMax == 2) {
108     return GeomAbs_C2;
109   }
110   else if ( MultMax == 3) {
111     return GeomAbs_C3;
112   }
113   else { 
114     return GeomAbs_CN;
115   }
116 }
117
118
119 //=======================================================================
120 //function : Load
121 //purpose  : 
122 //=======================================================================
123
124 void GeomAdaptor_Curve::load(const Handle(Geom_Curve)& C,
125                              const Standard_Real UFirst,
126                              const Standard_Real ULast)
127 {
128   myFirst = UFirst;
129   myLast  = ULast;
130
131   if ( myCurve != C) {
132     myCurve = C;
133     
134     const Handle(Standard_Type)& TheType = C->DynamicType();
135     if ( TheType == STANDARD_TYPE(Geom_TrimmedCurve)) {
136       Load((*((Handle(Geom_TrimmedCurve)*)&C))->BasisCurve(),UFirst,ULast);
137     }
138     else if ( TheType ==  STANDARD_TYPE(Geom_Circle)) {
139       myTypeCurve = GeomAbs_Circle;
140     }
141     else if ( TheType ==STANDARD_TYPE(Geom_Line)) {
142       myTypeCurve = GeomAbs_Line;
143     }
144     else if ( TheType == STANDARD_TYPE(Geom_Ellipse)) {
145       myTypeCurve = GeomAbs_Ellipse;
146     }
147     else if ( TheType == STANDARD_TYPE(Geom_Parabola)) {
148       myTypeCurve = GeomAbs_Parabola;
149     }
150     else if ( TheType == STANDARD_TYPE(Geom_Hyperbola)) {
151       myTypeCurve = GeomAbs_Hyperbola;
152     }
153     else if ( TheType == STANDARD_TYPE(Geom_BezierCurve)) {
154       myTypeCurve = GeomAbs_BezierCurve;
155     }
156     else if ( TheType == STANDARD_TYPE(Geom_BSplineCurve)) {
157       myTypeCurve = GeomAbs_BSplineCurve;
158     }
159     else {
160       myTypeCurve = GeomAbs_OtherCurve;
161     }
162   }
163 }  
164
165 //    --
166 //    --     Global methods - Apply to the whole curve.
167 //    --     
168
169 //=======================================================================
170 //function : Continuity
171 //purpose  : 
172 //=======================================================================
173
174 GeomAbs_Shape GeomAdaptor_Curve::Continuity() const 
175 {
176   if (myTypeCurve == GeomAbs_BSplineCurve)
177     return LocalContinuity(myFirst, myLast);
178
179   if (myCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
180   {
181     const GeomAbs_Shape S =
182       (*((Handle(Geom_OffsetCurve)*)&myCurve))->BasisCurve()->Continuity();
183     switch(S)
184     {
185       case GeomAbs_CN: return GeomAbs_CN;
186       case GeomAbs_C3: return GeomAbs_C2;
187       case GeomAbs_C2: return GeomAbs_C1;
188       case GeomAbs_C1: return GeomAbs_C0;  
189       default:
190       Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Continuity");
191     }
192   }
193   else if (myTypeCurve == GeomAbs_OtherCurve) {
194     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Contunuity");
195   }
196
197   return GeomAbs_CN;
198 }
199
200 //=======================================================================
201 //function : NbIntervals
202 //purpose  : 
203 //=======================================================================
204
205 Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) 
206 {
207   Standard_Integer myNbIntervals = 1;
208   Standard_Integer NbSplit;
209   if (myTypeCurve == GeomAbs_BSplineCurve) {
210     Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
211     Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
212     TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
213     if ( S > Continuity()) {
214       Standard_Integer Cont;
215       switch ( S) {
216       case GeomAbs_G1:
217       case GeomAbs_G2:
218         Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
219         break;
220       case GeomAbs_C0:
221         myNbIntervals = 1;
222         break;
223       case GeomAbs_C1:
224       case GeomAbs_C2:
225       case GeomAbs_C3: 
226       case GeomAbs_CN: 
227         {
228           if      ( S == GeomAbs_C1) Cont = 1;
229           else if ( S == GeomAbs_C2) Cont = 2;
230           else if ( S == GeomAbs_C3) Cont = 3;
231           else                       Cont = myBspl->Degree();
232           Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
233           Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
234           Standard_Integer Degree = myBspl->Degree();
235           Standard_Integer NbKnots = myBspl->NbKnots();
236           TColStd_Array1OfInteger Mults (1, NbKnots);
237           myBspl->Multiplicities (Mults);
238           NbSplit = 1;
239           Standard_Integer Index   = FirstIndex;
240           Inter (NbSplit) = Index;
241           Index++;
242           NbSplit++;
243           while (Index < LastIndex) 
244             {
245               if (Degree - Mults (Index) < Cont) 
246                 {
247                   Inter (NbSplit) = Index;
248                   NbSplit++;
249                 }
250               Index++;
251             }
252           Inter (NbSplit) = Index;
253
254           Standard_Integer NbInt = NbSplit-1;
255           
256           Standard_Integer Nb = myBspl->NbKnots();
257           Standard_Integer Index1 = 0;
258           Standard_Integer Index2 = 0;
259           Standard_Real newFirst, newLast;
260           TColStd_Array1OfReal    TK(1,Nb);
261           TColStd_Array1OfInteger TM(1,Nb);
262           myBspl->Knots(TK);
263           myBspl->Multiplicities(TM);
264           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
265                                     myBspl->IsPeriodic(),
266                                     1,Nb,Index1,newFirst);
267           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
268                                     myBspl->IsPeriodic(),
269                                     1,Nb,Index2,newLast);
270
271           // On decale eventuellement les indices  
272           // On utilise une "petite" tolerance, la resolution ne doit 
273           // servir que pour les tres longue courbes....(PRO9248)
274           Standard_Real Eps = Min(Resolution(Precision::Confusion()),
275                                   Precision::PConfusion()); 
276           if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
277           if ( newLast-TK(Index2)> Eps) Index2++;
278           
279           myNbIntervals = 1;
280           for ( Standard_Integer i=1; i<=NbInt; i++)
281             if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
282         }
283         break;
284       }
285     }
286   }
287   
288   else if (myCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))){
289     GeomAbs_Shape BaseS=GeomAbs_C0;
290     switch(S){
291     case GeomAbs_G1:
292     case GeomAbs_G2:
293       Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
294       break;
295     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
296     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
297     case GeomAbs_C2: BaseS = GeomAbs_C3; break;
298     default: BaseS = GeomAbs_CN;
299     }
300     GeomAdaptor_Curve C
301       ((*((Handle(Geom_OffsetCurve)*)&myCurve))->BasisCurve());
302     // akm 05/04/02 (OCC278)  If our curve is trimmed we must recalculate 
303     //                    the number of intervals obtained from the basis to
304     //              vvv   reflect parameter bounds
305     Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
306     if (iNbBasisInt>1)
307     {
308       TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
309       C.Intervals(rdfInter,BaseS);
310       for (iInt=1; iInt<=iNbBasisInt; iInt++)
311         if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
312           myNbIntervals++;
313     }
314     // akm 05/04/02 ^^^
315   }
316   return myNbIntervals;
317 }
318
319 //=======================================================================
320 //function : Intervals
321 //purpose  : 
322 //=======================================================================
323
324 void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
325                                   const GeomAbs_Shape S   )  
326 {
327   Standard_Integer myNbIntervals = 1;
328   Standard_Integer NbSplit;
329   Standard_Real FirstParam = myFirst, LastParam = myLast;
330
331   if (myTypeCurve == GeomAbs_BSplineCurve) 
332     {
333       Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
334       Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
335       TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
336       
337       if ( S > Continuity()) {
338         Standard_Integer Cont;
339         switch ( S) {
340         case GeomAbs_G1:
341         case GeomAbs_G2:
342           Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
343           break;
344         case GeomAbs_C0:
345           myNbIntervals = 1;
346           break;
347         case GeomAbs_C1:
348         case GeomAbs_C2:
349         case GeomAbs_C3: 
350         case GeomAbs_CN: 
351           {
352             if      ( S == GeomAbs_C1) Cont = 1;
353             else if ( S == GeomAbs_C2) Cont = 2;
354             else if ( S == GeomAbs_C3) Cont = 3;
355             else                       Cont = myBspl->Degree();
356             Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
357             Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
358             Standard_Integer Degree = myBspl->Degree();
359             Standard_Integer NbKnots = myBspl->NbKnots();
360             TColStd_Array1OfInteger Mults (1, NbKnots);
361             myBspl->Multiplicities (Mults);
362             NbSplit = 1;
363             Standard_Integer Index   = FirstIndex;
364             Inter (NbSplit) = Index;
365             Index++;
366             NbSplit++;
367             while (Index < LastIndex) 
368               {
369                 if (Degree - Mults (Index) < Cont) 
370                   {
371                     Inter (NbSplit) = Index;
372                     NbSplit++;
373                   }
374                 Index++;
375               }
376             Inter (NbSplit) = Index;
377             Standard_Integer NbInt = NbSplit-1;
378             //        GeomConvert_BSplineCurveKnotSplitting Convector(myBspl, Cont);
379             //        Standard_Integer NbInt = Convector.NbSplits()-1;
380             //        TColStd_Array1OfInteger Inter(1,NbInt+1);
381             //        Convector.Splitting( Inter);
382             
383             Standard_Integer Nb = myBspl->NbKnots();
384             Standard_Integer Index1 = 0;
385             Standard_Integer Index2 = 0;
386             Standard_Real newFirst, newLast;
387             TColStd_Array1OfReal    TK(1,Nb);
388             TColStd_Array1OfInteger TM(1,Nb);
389             myBspl->Knots(TK);
390             myBspl->Multiplicities(TM);
391             BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
392                                       myBspl->IsPeriodic(),
393                                       1,Nb,Index1,newFirst);
394             BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
395                                       myBspl->IsPeriodic(),
396                                       1,Nb,Index2,newLast);
397             FirstParam = newFirst;
398             LastParam = newLast;
399             // On decale eventuellement les indices  
400             // On utilise une "petite" tolerance, la resolution ne doit 
401             // servir que pour les tres longue courbes....(PRO9248)
402             Standard_Real Eps = Min(Resolution(Precision::Confusion()),
403                                     Precision::PConfusion()); 
404             if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
405             if ( newLast-TK(Index2)> Eps) Index2++;
406             
407             Inter( 1) = Index1;
408             myNbIntervals = 1;
409             for ( Standard_Integer i=1; i<=NbInt; i++) {
410               if (Inter(i) > Index1 && Inter(i)<Index2 ) {
411                 myNbIntervals++;
412                 Inter(myNbIntervals) = Inter(i);
413               }
414             }
415             Inter(myNbIntervals+1) = Index2;
416             
417             for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
418               T(I) = TK(Inter(I));
419             }
420           }
421           break;
422         }
423       }
424     }
425
426   else if (myCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))){
427     GeomAbs_Shape BaseS=GeomAbs_C0;
428     switch(S){
429     case GeomAbs_G1:
430     case GeomAbs_G2:
431       Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
432       break;
433     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
434     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
435     case GeomAbs_C2: BaseS = GeomAbs_C3; break;
436     default: BaseS = GeomAbs_CN;
437     }
438     GeomAdaptor_Curve C
439       ((*((Handle(Geom_OffsetCurve)*)&myCurve))->BasisCurve());
440     // akm 05/04/02 (OCC278)  If our curve is trimmed we must recalculate 
441     //                    the array of intervals obtained from the basis to
442     //              vvv   reflect parameter bounds
443     Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
444     if (iNbBasisInt>1)
445     {
446       TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
447       C.Intervals(rdfInter,BaseS);
448       for (iInt=1; iInt<=iNbBasisInt; iInt++)
449         if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
450           T(++myNbIntervals)=rdfInter(iInt);
451     }
452     // old - myNbIntervals = C.NbIntervals(BaseS);
453     // old - C.Intervals(T, BaseS);
454     // akm 05/04/02 ^^^
455   }
456   
457   T( T.Lower() ) = FirstParam;
458   T( T.Lower() + myNbIntervals ) = LastParam;
459 }
460
461 //=======================================================================
462 //function : Trim
463 //purpose  : 
464 //=======================================================================
465
466 Handle(Adaptor3d_HCurve) GeomAdaptor_Curve::Trim(const Standard_Real First,
467                                                  const Standard_Real Last,
468                                                  const Standard_Real /*Tol*/) const
469 {
470   return Handle(GeomAdaptor_HCurve)(new GeomAdaptor_HCurve(myCurve,First,Last));
471 }
472
473
474 //=======================================================================
475 //function : IsClosed
476 //purpose  : 
477 //=======================================================================
478
479 Standard_Boolean GeomAdaptor_Curve::IsClosed() const
480 {
481   if (!Precision::IsPositiveInfinite(myLast) &&
482       !Precision::IsNegativeInfinite(myFirst))
483   {
484     const gp_Pnt Pd = Value(myFirst);
485     const gp_Pnt Pf = Value(myLast);
486     return (Pd.Distance(Pf) <= Precision::Confusion());
487   }
488   return Standard_False;
489 }
490
491 //=======================================================================
492 //function : IsPeriodic
493 //purpose  : 
494 //=======================================================================
495
496 Standard_Boolean GeomAdaptor_Curve::IsPeriodic() const 
497 {
498   return (myCurve->IsPeriodic()? IsClosed() : Standard_False);
499 }
500
501 //=======================================================================
502 //function : Period
503 //purpose  : 
504 //=======================================================================
505
506 Standard_Real GeomAdaptor_Curve::Period() const 
507 {
508   return myCurve->LastParameter() - myCurve->FirstParameter();
509 }
510
511 //=======================================================================
512 //function : Value
513 //purpose  : 
514 //=======================================================================
515
516 gp_Pnt GeomAdaptor_Curve::Value(const Standard_Real U) const
517 {
518   if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
519       (U==myFirst || U==myLast) ) {
520     Standard_Integer Ideb = 0, Ifin = 0;
521     if (U==myFirst) {
522       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
523       if (Ideb<1) Ideb=1;
524       if (Ideb>=Ifin) Ifin = Ideb+1;
525     }
526     if (U==myLast) {
527       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
528       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
529       if (Ideb>=Ifin) Ideb = Ifin-1;
530     }
531     return myBspl->LocalValue(U, Ideb, Ifin);
532   }
533   return myCurve->Value(U);
534 }
535
536 //=======================================================================
537 //function : D0
538 //purpose  : 
539 //=======================================================================
540
541 void GeomAdaptor_Curve::D0(const Standard_Real U, gp_Pnt& P) const
542 {
543   if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
544       (U==myFirst || U==myLast) ) {
545     Standard_Integer Ideb = 0, Ifin = 0;
546     if (U==myFirst) {
547       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
548       if (Ideb<1) Ideb=1;
549       if (Ideb>=Ifin) Ifin = Ideb+1;
550     }
551     if (U==myLast) {
552       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
553       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
554       if (Ideb>=Ifin) Ideb = Ifin-1;
555     }
556     myBspl->LocalD0( U, Ideb, Ifin, P);
557   }
558   else {
559     myCurve->D0(U, P);
560   } 
561 }
562
563 //=======================================================================
564 //function : D1
565 //purpose  : 
566 //=======================================================================
567
568 void GeomAdaptor_Curve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V) const 
569 {
570   if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
571       (U==myFirst || U==myLast) ) {
572     Standard_Integer Ideb = 0, Ifin = 0;
573     if (U==myFirst) {
574       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
575       if (Ideb<1) Ideb=1;
576       if (Ideb>=Ifin) Ifin = Ideb+1;
577     }
578     if (U==myLast) {
579       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
580       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
581       if (Ideb>=Ifin) Ideb = Ifin-1;
582     }
583     myBspl->LocalD1( U, Ideb, Ifin, P, V); 
584   } 
585   else {
586     myCurve->D1( U, P, V);
587   }
588 }
589
590 //=======================================================================
591 //function : D2
592 //purpose  : 
593 //=======================================================================
594
595 void GeomAdaptor_Curve::D2(const Standard_Real U, 
596                            gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) const 
597 {
598   if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
599       (U==myFirst || U==myLast) ) {
600     Standard_Integer Ideb = 0, Ifin = 0;
601     if (U==myFirst) {
602       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
603       if (Ideb<1) Ideb=1;
604       if (Ideb>=Ifin) Ifin = Ideb+1;
605     }
606     if (U==myLast) {
607       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
608       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
609       if (Ideb>=Ifin) Ideb = Ifin-1;
610     }
611     myBspl->LocalD2( U, Ideb, Ifin, P, V1, V2);         
612   }
613   else {
614     myCurve->D2( U, P, V1, V2);
615   }
616 }
617
618 //=======================================================================
619 //function : D3
620 //purpose  : 
621 //=======================================================================
622
623 void GeomAdaptor_Curve::D3(const Standard_Real U, 
624                            gp_Pnt& P, gp_Vec& V1, 
625                            gp_Vec& V2, gp_Vec& V3) const 
626 {
627   if ( (myTypeCurve == GeomAbs_BSplineCurve) &&
628       (U==myFirst || U==myLast) ) {
629     Standard_Integer Ideb = 0, Ifin = 0;
630     if (U==myFirst) {
631       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
632       if (Ideb<1) Ideb=1;
633       if (Ideb>=Ifin) Ifin = Ideb+1;
634     }
635     if (U==myLast) {
636       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
637       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
638       if (Ideb>=Ifin) Ideb = Ifin-1;
639     }
640     myBspl->LocalD3( U, Ideb, Ifin, P, V1, V2, V3);  
641   }
642   else {
643     myCurve->D3( U, P, V1, V2, V3);
644   }
645 }
646
647 //=======================================================================
648 //function : DN
649 //purpose  : 
650 //=======================================================================
651
652 gp_Vec GeomAdaptor_Curve::DN(const Standard_Real    U, 
653                              const Standard_Integer N) const 
654 {
655   if ( (myTypeCurve == GeomAbs_BSplineCurve) &&
656       (U==myFirst || U==myLast) ) {
657     Standard_Integer Ideb = 0, Ifin = 0;
658     if (U==myFirst) {
659       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
660       if (Ideb<1) Ideb=1;
661       if (Ideb>=Ifin) Ifin = Ideb+1;
662     }
663     if (U==myLast) {
664       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
665       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
666       if (Ideb>=Ifin) Ideb = Ifin-1;
667     } 
668     return myBspl->LocalDN( U, Ideb, Ifin, N);
669   }  
670   else {
671     return myCurve->DN( U, N);
672   }
673 }
674
675 //=======================================================================
676 //function : Resolution
677 //purpose  : 
678 //=======================================================================
679
680 Standard_Real GeomAdaptor_Curve::Resolution(const Standard_Real R3D) const
681 {
682   switch ( myTypeCurve) {
683   case GeomAbs_Line :
684     return R3D;
685   case GeomAbs_Circle: {
686     Standard_Real R = (*((Handle(Geom_Circle)*)&myCurve))->Circ().Radius();
687     if ( R > R3D/2. )
688       return 2*ASin(R3D/(2*R));
689     else
690       return 2*M_PI;
691   }
692   case GeomAbs_Ellipse: {
693     return R3D / (*((Handle(Geom_Ellipse)*)&myCurve))->MajorRadius();
694   }
695   case GeomAbs_BezierCurve: {
696     Standard_Real res;
697     (*((Handle(Geom_BezierCurve)*)&myCurve))->Resolution(R3D,res);
698     return res;
699   }
700   case GeomAbs_BSplineCurve: {
701     Standard_Real res;
702     (*((Handle(Geom_BSplineCurve)*)&myCurve))->Resolution(R3D,res);
703     return res;
704   }
705   default:
706     return Precision::Parametric(R3D);
707   }  
708 }
709
710
711 //    --
712 //    --     The following methods must  be called when GetType returned
713 //    --     the corresponding type.
714 //    --     
715
716 //=======================================================================
717 //function : Line
718 //purpose  : 
719 //=======================================================================
720
721 gp_Lin GeomAdaptor_Curve::Line() const 
722 {
723   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
724   return (*((Handle(Geom_Line)*)&myCurve))->Lin();  
725 }
726
727 //=======================================================================
728 //function : Circle
729 //purpose  : 
730 //=======================================================================
731
732 gp_Circ  GeomAdaptor_Curve::Circle() const 
733 {
734   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
735   return (*((Handle(Geom_Circle)*)&myCurve))->Circ();
736 }
737
738 //=======================================================================
739 //function : Ellipse
740 //purpose  : 
741 //=======================================================================
742
743 gp_Elips GeomAdaptor_Curve::Ellipse() const 
744 {
745   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Ellipse, "");
746   return (*((Handle(Geom_Ellipse)*)&myCurve))->Elips();
747 }
748
749 //=======================================================================
750 //function : Hyperbola
751 //purpose  : 
752 //=======================================================================
753
754 gp_Hypr GeomAdaptor_Curve::Hyperbola() const 
755 {
756   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
757   return (*((Handle(Geom_Hyperbola)*)&myCurve))->Hypr();  
758 }
759
760 //=======================================================================
761 //function : Parabola
762 //purpose  : 
763 //=======================================================================
764
765 gp_Parab GeomAdaptor_Curve::Parabola() const 
766 {
767   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
768   return (*((Handle(Geom_Parabola)*)&myCurve))->Parab();
769 }
770
771 //=======================================================================
772 //function : Degree
773 //purpose  : 
774 //=======================================================================
775
776 Standard_Integer GeomAdaptor_Curve::Degree() const
777 {
778   if (myTypeCurve == GeomAbs_BezierCurve)
779     return (*((Handle(Geom_BezierCurve)*)&myCurve))->Degree();
780   else if (myTypeCurve == GeomAbs_BSplineCurve)
781     return (*((Handle(Geom_BSplineCurve)*)&myCurve))->Degree();
782   else
783     Standard_NoSuchObject::Raise();
784   // portage WNT 
785   return 0;
786 }
787
788 //=======================================================================
789 //function : IsRational
790 //purpose  : 
791 //=======================================================================
792
793 Standard_Boolean GeomAdaptor_Curve::IsRational() const {
794   switch( myTypeCurve) {
795   case GeomAbs_BSplineCurve:
796     return (*((Handle(Geom_BSplineCurve)*)&myCurve))->IsRational();
797   case GeomAbs_BezierCurve:
798     return (*((Handle(Geom_BezierCurve)*)&myCurve))->IsRational();
799   default:
800     return Standard_False;
801   }
802 }
803
804 //=======================================================================
805 //function : NbPoles
806 //purpose  : 
807 //=======================================================================
808
809 Standard_Integer GeomAdaptor_Curve::NbPoles() const
810 {
811   if (myTypeCurve == GeomAbs_BezierCurve)
812     return (*((Handle(Geom_BezierCurve)*)&myCurve))->NbPoles();
813   else if (myTypeCurve == GeomAbs_BSplineCurve)
814     return (*((Handle(Geom_BSplineCurve)*)&myCurve))->NbPoles();
815   else
816     Standard_NoSuchObject::Raise();
817   // portage WNT
818   return 0;
819 }
820
821 //=======================================================================
822 //function : NbKnots
823 //purpose  : 
824 //=======================================================================
825
826 Standard_Integer GeomAdaptor_Curve::NbKnots() const
827 {
828   if ( myTypeCurve != GeomAbs_BSplineCurve)
829     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::NbKnots");
830   return (*((Handle(Geom_BSplineCurve)*)&myCurve))->NbKnots();
831 }
832
833 //=======================================================================
834 //function : Bezier
835 //purpose  : 
836 //=======================================================================
837
838 Handle(Geom_BezierCurve) GeomAdaptor_Curve::Bezier() const 
839 {
840  if ( myTypeCurve != GeomAbs_BezierCurve)
841     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Bezier");
842   return *((Handle(Geom_BezierCurve)*)&myCurve);
843 }
844
845 //=======================================================================
846 //function : BSpline
847 //purpose  : 
848 //=======================================================================
849
850 Handle(Geom_BSplineCurve) GeomAdaptor_Curve::BSpline() const 
851 {
852  if ( myTypeCurve != GeomAbs_BSplineCurve)
853     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::BSpline");
854
855   return *((Handle(Geom_BSplineCurve)*)&myCurve);
856 }
857