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