0030435: Improving performance of Approx_ComputeCLine
[occt.git] / src / ProjLib / ProjLib_ProjectOnPlane.cxx
1 // Created on: 1994-09-05
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1994-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 // 09-Aug-95 : xab : changed the ProjLib_ProjectOnPlane in the case
18 //                   of the line and the parameteriation is kept
19 #include <ProjLib_ProjectOnPlane.hxx>
20 #include <AppCont_Function.hxx>
21 #include <Approx_FitAndDivide.hxx>
22 #include <AppParCurves_MultiCurve.hxx>
23 #include <Standard_ConstructionError.hxx>
24 #include <Standard_NoSuchObject.hxx>
25 #include <Standard_NotImplemented.hxx>
26 #include <Precision.hxx>
27 #include <BSplCLib.hxx>
28 #include <PLib.hxx>
29 #include <Geom_BSplineCurve.hxx>
30 #include <Geom_BezierCurve.hxx>
31 #include <TColgp_HArray1OfPnt.hxx>
32 #include <TColStd_HArray1OfReal.hxx>
33 #include <TColStd_HArray1OfInteger.hxx>
34 #include <Precision.hxx>
35 #include <ElCLib.hxx>
36 #include <Adaptor3d_Curve.hxx>
37 #include <Adaptor3d_HCurve.hxx>
38 #include <GeomAdaptor_HCurve.hxx>
39 #include <Geom_Line.hxx>
40 #include <GeomConvert.hxx>
41 #include <BSplCLib.hxx>
42 #include <Geom_TrimmedCurve.hxx>
43 #include <Geom_Circle.hxx>
44 #include <Geom_Parabola.hxx>
45 #include <Geom_Hyperbola.hxx>
46 #include <Geom_Ellipse.hxx>
47
48
49
50 //=======================================================================
51 //function : OnPlane_Value
52 //purpose  : Evaluate current point of the projected curve
53 //=======================================================================
54
55 static gp_Pnt OnPlane_Value(const Standard_Real U,
56                             const Handle(Adaptor3d_HCurve)& aCurvePtr,
57                             const gp_Ax3& Pl,
58                             const gp_Dir& D)
59 {
60   //                   PO . Z                /  Z = Pl.Direction()
61   // Proj(u) = P(u) + -------  * D     avec  \  O = Pl.Location()
62   //                   D  . Z
63
64   gp_Pnt Point = aCurvePtr->Value(U);
65   
66   gp_Vec PO(Point,Pl.Location());
67   
68   Standard_Real Alpha = PO * gp_Vec(Pl.Direction());
69   Alpha /= D * Pl.Direction();
70   Point.SetXYZ(Point.XYZ() + Alpha * D.XYZ());
71
72   return Point;
73 }
74
75 //=======================================================================
76 //function : OnPlane_DN
77 //purpose  : Evaluate current point of the projected curve
78 //=======================================================================
79
80 static gp_Vec OnPlane_DN(const Standard_Real U,
81                          const Standard_Integer DerivativeRequest,
82                          const Handle(Adaptor3d_HCurve)& aCurvePtr,
83                          const gp_Ax3& Pl,
84                          const gp_Dir& D)
85 {
86   //                   PO . Z                /  Z = Pl.Direction()
87   // Proj(u) = P(u) + -------  * D     avec  \  O = Pl.Location()
88   //                   D  . Z
89
90   gp_Vec Vector = aCurvePtr->DN(U,DerivativeRequest);
91
92   gp_Dir Z = Pl.Direction();
93   
94   Standard_Real
95   Alpha  = Vector * gp_Vec(Z);
96   Alpha /=  D * Z;
97
98   Vector.SetXYZ( Vector.XYZ() - Alpha * D.XYZ());
99   return Vector ;
100 }
101
102 //=======================================================================
103 //function : OnPlane_D1
104 //purpose  : 
105 //=======================================================================
106
107 static Standard_Boolean OnPlane_D1(const Standard_Real U,
108                                          gp_Pnt& P,
109                                          gp_Vec& V,
110                                    const Handle(Adaptor3d_HCurve)& aCurvePtr,
111                                    const gp_Ax3& Pl,
112                                    const gp_Dir& D)
113 {
114   Standard_Real Alpha;
115   gp_Pnt Point;
116   gp_Vec Vector;
117   
118   gp_Dir Z = Pl.Direction();
119
120   aCurvePtr->D1(U, Point, Vector);
121
122   // evaluate the point as in `OnPlane_Value`
123   gp_Vec PO(Point,Pl.Location());
124   Alpha  = PO * gp_Vec(Z);
125   Alpha /= D * Z;
126   P.SetXYZ(Point.XYZ() + Alpha * D.XYZ());
127
128   
129   // evaluate the derivative.
130   // 
131   //   d(Proj)  d(P)       1        d(P)
132   //   ------ = ---  - -------- * ( --- . Z ) * D
133   //     dU     dU     ( D . Z)     dU  
134   //
135
136   Alpha  = Vector * gp_Vec(Z);
137   Alpha /=  D * Z;
138
139   V.SetXYZ( Vector.XYZ() - Alpha * D.XYZ());
140
141   return Standard_True;
142 }
143 //=======================================================================
144 //function : OnPlane_D2
145 //purpose  : 
146 //=======================================================================
147
148 static Standard_Boolean OnPlane_D2(const Standard_Real U,
149                                          gp_Pnt& P,
150                                          gp_Vec& V1,
151                                          gp_Vec& V2,
152                                    const Handle(Adaptor3d_HCurve) & aCurvePtr,
153                                    const gp_Ax3& Pl,
154                                    const gp_Dir& D)
155 {
156   Standard_Real Alpha;
157   gp_Pnt Point;
158   gp_Vec Vector1,
159   Vector2;
160   
161   gp_Dir Z = Pl.Direction();
162
163   aCurvePtr->D2(U, Point, Vector1, Vector2);
164
165   // evaluate the point as in `OnPlane_Value`
166   gp_Vec PO(Point,Pl.Location());
167   Alpha  = PO * gp_Vec(Z);
168   Alpha /= D * Z;
169   P.SetXYZ(Point.XYZ() + Alpha * D.XYZ());
170
171   // evaluate the derivative.
172   // 
173   //   d(Proj)  d(P)       1        d(P)
174   //   ------ = ---  - -------- * ( --- . Z ) * D
175   //     dU     dU     ( D . Z)     dU  
176   //
177
178   Alpha  = Vector1 * gp_Vec(Z);
179   Alpha /=  D * Z;
180
181   V1.SetXYZ( Vector1.XYZ() - Alpha * D.XYZ());
182
183   Alpha  = Vector2 * gp_Vec(Z);
184   Alpha /=  D * Z;
185
186   V2.SetXYZ( Vector2.XYZ() - Alpha * D.XYZ());
187   return Standard_True;
188 }
189
190 //=======================================================================
191 //function : OnPlane_D3
192 //purpose  : 
193 //=======================================================================
194
195 static Standard_Boolean OnPlane_D3(const Standard_Real U,
196                                          gp_Pnt& P,
197                                          gp_Vec& V1,
198                                          gp_Vec& V2,
199                                          gp_Vec& V3,
200                                    const Handle(Adaptor3d_HCurve)& aCurvePtr,
201                                    const gp_Ax3& Pl,
202                                    const gp_Dir& D)
203 {
204   Standard_Real Alpha;
205   gp_Pnt Point;
206   gp_Vec Vector1,
207   Vector2,
208   Vector3;
209   
210   gp_Dir Z = Pl.Direction();
211
212   aCurvePtr->D3(U, Point, Vector1, Vector2, Vector3);
213
214   // evaluate the point as in `OnPlane_Value`
215   gp_Vec PO(Point,Pl.Location());
216   Alpha  = PO * gp_Vec(Z);
217   Alpha /= D * Z;
218   P.SetXYZ(Point.XYZ() + Alpha * D.XYZ());
219   
220   // evaluate the derivative.
221   // 
222   //   d(Proj)  d(P)       1        d(P)
223   //   ------ = ---  - -------- * ( --- . Z ) * D
224   //     dU     dU     ( D . Z)     dU  
225   //
226
227   Alpha  = Vector1 * gp_Vec(Z);
228   Alpha /=  D * Z;
229
230   V1.SetXYZ( Vector1.XYZ() - Alpha * D.XYZ());
231
232   Alpha  = Vector2 * gp_Vec(Z);
233   Alpha /=  D * Z;
234
235   V2.SetXYZ( Vector2.XYZ() - Alpha * D.XYZ());
236   Alpha  = Vector3 * gp_Vec(Z);
237   Alpha /=  D * Z;
238
239   V3.SetXYZ( Vector3.XYZ() - Alpha * D.XYZ());
240   return Standard_True;
241 }
242
243 //=======================================================================
244 //  class  : ProjLib_OnPlane
245 //purpose  : Use to approximate the projection on a plane
246 //=======================================================================
247
248 class ProjLib_OnPlane : public AppCont_Function
249
250 {
251   Handle(Adaptor3d_HCurve) myCurve;
252   gp_Ax3 myPlane;
253   gp_Dir myDirection;
254
255 public :
256
257   ProjLib_OnPlane(const Handle(Adaptor3d_HCurve)& C, 
258                   const gp_Ax3& Pl, 
259                   const gp_Dir& D) 
260 : myCurve(C),
261   myPlane(Pl),
262   myDirection(D)
263   {
264     myNbPnt = 1;
265     myNbPnt2d = 0;
266   }
267
268   Standard_Real FirstParameter() const
269     {return myCurve->FirstParameter();}
270   
271   Standard_Real LastParameter() const
272     {return myCurve->LastParameter();}
273
274     Standard_Boolean Value(const Standard_Real   theT,
275                            NCollection_Array1<gp_Pnt2d>& /*thePnt2d*/,
276                            NCollection_Array1<gp_Pnt>&   thePnt) const
277     {
278       thePnt(1) = OnPlane_Value(theT, myCurve, myPlane, myDirection);
279       return Standard_True;
280     }
281   
282   Standard_Boolean D1(const Standard_Real   theT,
283                       NCollection_Array1<gp_Vec2d>& /*theVec2d*/,
284                       NCollection_Array1<gp_Vec>&   theVec) const
285   {
286     gp_Pnt aDummyPnt;
287     return OnPlane_D1(theT, aDummyPnt, theVec(1),myCurve,myPlane,myDirection);
288   }
289 };
290
291
292
293
294 //=====================================================================//
295 //                                                                     //
296 //  D E S C R I P T I O N   O F   T H E   C L A S S  :                 // 
297 //                                                                     //
298 //         P r o j L i b _ A p p r o x P r o j e c t O n P l a n e     //
299 //                                                                     //
300 //=====================================================================//
301
302
303
304 //=======================================================================
305 //function : PerformApprox
306 //purpose  : 
307 //=======================================================================
308
309 static void  PerformApprox (const Handle(Adaptor3d_HCurve)& C,
310                             const gp_Ax3& Pl,
311                             const gp_Dir& D,
312                             Handle(Geom_BSplineCurve) &BSplineCurvePtr) 
313
314 {
315   ProjLib_OnPlane F(C,Pl,D);
316
317   Standard_Integer Deg1, Deg2;
318   Deg1 = 8; Deg2 = 8;
319   
320   Approx_FitAndDivide Fit(Deg1,Deg2,Precision::Approximation(),
321                           Precision::PApproximation(),Standard_True);
322   Fit.SetMaxSegments(100);
323   Fit.Perform(F);
324   if (!Fit.IsAllApproximated())
325   {
326     return;
327   }
328   Standard_Integer i;
329   Standard_Integer NbCurves = Fit.NbMultiCurves();
330   Standard_Integer MaxDeg = 0;
331   
332   // Pour transformer la MultiCurve en BSpline, il faut que toutes 
333   // les Bezier la constituant aient le meme degre -> Calcul de MaxDeg
334   Standard_Integer NbPoles  = 1;
335   for (i = 1; i <= NbCurves; i++) {
336     Standard_Integer Deg = Fit.Value(i).Degree();
337     MaxDeg = Max ( MaxDeg, Deg);
338   }
339   NbPoles = MaxDeg * NbCurves + 1;               //Poles sur la BSpline
340
341   TColgp_Array1OfPnt    Poles( 1, NbPoles);
342   
343   TColgp_Array1OfPnt TempPoles( 1, MaxDeg + 1);  //pour augmentation du degre
344   
345   TColStd_Array1OfReal Knots( 1, NbCurves + 1);  //Noeuds de la BSpline
346   
347   Standard_Integer Compt = 1;
348   for (i = 1; i <= Fit.NbMultiCurves(); i++) {
349     Fit.Parameters(i, Knots(i), Knots(i+1)); 
350     
351     AppParCurves_MultiCurve MC = Fit.Value( i);   //Charge la Ieme Curve
352     TColgp_Array1OfPnt LocalPoles( 1, MC.Degree() + 1);//Recupere les poles
353     MC.Curve(1, LocalPoles);
354     
355     //Augmentation eventuelle du degre
356     if (MaxDeg > MC.Degree() ) {
357       BSplCLib::IncreaseDegree(MaxDeg, LocalPoles, BSplCLib::NoWeights(),
358                                TempPoles, BSplCLib::NoWeights());
359       //mise a jour des poles de la PCurve
360       for (Standard_Integer j = 1 ; j <= MaxDeg + 1; j++) {
361         Poles.SetValue( Compt, TempPoles( j));
362         Compt++;
363       }
364     }
365     else {
366       //mise a jour des poles de la PCurve
367       for (Standard_Integer j = 1 ; j <= MaxDeg + 1; j++) {
368         Poles.SetValue( Compt, LocalPoles( j));
369         Compt++;
370       }
371     } 
372     
373     Compt--;
374   }
375   
376   //mise a jour des fields de ProjLib_Approx
377
378   Standard_Integer 
379   NbKnots = NbCurves + 1;
380
381   TColStd_Array1OfInteger    Mults(1, NbKnots);
382   Mults.SetValue( 1, MaxDeg + 1);
383   for ( i = 2; i <= NbCurves; i++) {
384     Mults.SetValue( i, MaxDeg);
385   }
386   Mults.SetValue( NbKnots, MaxDeg + 1);
387   BSplineCurvePtr = 
388     new Geom_BSplineCurve(Poles,Knots,Mults,MaxDeg,Standard_False);
389 }
390
391
392 //=======================================================================
393 //function : ProjectOnPlane
394 //purpose  : 
395 //=======================================================================
396
397 ProjLib_ProjectOnPlane::ProjLib_ProjectOnPlane() :
398 myKeepParam(Standard_False),
399 myFirstPar(0.),
400 myLastPar(0.),
401 myTolerance(0.),
402 myType     (GeomAbs_OtherCurve),
403 myIsApprox (Standard_False)
404 {
405 }
406
407 //=======================================================================
408 //function : ProjLib_ProjectOnPlane
409 //purpose  : 
410 //=======================================================================
411
412 ProjLib_ProjectOnPlane::ProjLib_ProjectOnPlane(const gp_Ax3& Pl) : 
413 myPlane     (Pl)                ,
414 myDirection (Pl.Direction())    ,
415 myKeepParam(Standard_False),
416 myFirstPar(0.),
417 myLastPar(0.),
418 myTolerance(0.),
419 myType      (GeomAbs_OtherCurve),
420 myIsApprox  (Standard_False)
421 {
422 }
423
424 //=======================================================================
425 //function : ProjLib_ProjectOnPlane
426 //purpose  : 
427 //=======================================================================
428
429 ProjLib_ProjectOnPlane::ProjLib_ProjectOnPlane(const gp_Ax3& Pl,
430                                                const gp_Dir& D  ) :
431 myPlane     (Pl)                ,
432 myDirection (D)                 ,
433 myKeepParam(Standard_False),
434 myFirstPar(0.),
435 myLastPar(0.),
436 myTolerance(0.),
437 myType      (GeomAbs_OtherCurve),
438 myIsApprox  (Standard_False)
439 {
440 //  if ( Abs(D * Pl.Direction()) < Precision::Confusion()) {
441 //    throw Standard_ConstructionError
442 //      ("ProjLib_ProjectOnPlane:  The Direction and the Plane are parallel");
443 //  }
444 }
445
446 //=======================================================================
447 //function : Project
448 //purpose  : Returns the projection of a point <Point> on a plane 
449 //           <ThePlane>  along a direction <TheDir>.
450 //=======================================================================
451
452 static gp_Pnt ProjectPnt(const gp_Ax3& ThePlane,
453                          const gp_Dir& TheDir,
454                          const gp_Pnt& Point) 
455 {
456   gp_Vec PO(Point,ThePlane.Location());
457
458   Standard_Real Alpha = PO * gp_Vec(ThePlane.Direction());
459   Alpha /= TheDir * ThePlane.Direction();
460   
461   gp_Pnt P;
462   P.SetXYZ(Point.XYZ() + Alpha * TheDir.XYZ());
463
464   return P;
465 }
466
467
468 //=======================================================================
469 //function : Project
470 //purpose  : Returns the projection of a Vector <Vec> on a plane 
471 //           <ThePlane> along a direction <TheDir>.
472 //=======================================================================
473
474 static gp_Vec ProjectVec(const gp_Ax3& ThePlane,
475                          const gp_Dir& TheDir,
476                          const gp_Vec& Vec) 
477 {
478   gp_Vec D = Vec;
479   gp_Vec Z = ThePlane.Direction();
480
481   D -= ( (Vec * Z) / (TheDir * Z)) * TheDir;
482
483   return D;
484 }
485
486 //=======================================================================
487 //function : Load
488 //purpose  : 
489 //=======================================================================
490
491 void ProjLib_ProjectOnPlane::Load(const Handle(Adaptor3d_HCurve)&    C,
492                                   const Standard_Real Tolerance,
493                                   const Standard_Boolean KeepParametrization) 
494                                   
495 {
496   myCurve      = C;
497   myType       = GeomAbs_OtherCurve;
498   myIsApprox   = Standard_False;
499   myTolerance  = Tolerance ;
500
501   Handle(Geom_BSplineCurve)  ApproxCurve;
502   Handle(GeomAdaptor_HCurve) aGAHCurve;
503
504   Handle(Geom_Line)      GeomLinePtr;
505   Handle(Geom_Circle)    GeomCirclePtr ;
506   Handle(Geom_Ellipse)   GeomEllipsePtr ;
507   Handle(Geom_Hyperbola) GeomHyperbolaPtr ;
508
509   gp_Lin   aLine; 
510   gp_Elips Elips;
511 //  gp_Hypr  Hypr ;
512
513   Standard_Integer num_knots ;
514   GeomAbs_CurveType Type = C->GetType();
515
516   gp_Ax2 Axis;
517   Standard_Real R1 =0., R2 =0.;
518
519   if ( Type != GeomAbs_Line)  // on garde le parametrage
520     myKeepParam = Standard_True;
521   else                        // on prend le choix utilisateur.
522     myKeepParam = KeepParametrization;
523
524   switch ( Type) {
525   case GeomAbs_Line: 
526     {
527       //     P(u) = O + u * Xc
528       // ==> Q(u) = f(P(u)) 
529       //          = f(O) + u * f(Xc)
530
531       gp_Lin L  = myCurve->Line();
532       gp_Vec Xc = ProjectVec(myPlane,myDirection,gp_Vec(L.Direction()));
533
534       if ( Xc.Magnitude() < Precision::Confusion()) { // line orthog au plan
535         myType = GeomAbs_BSplineCurve;
536         gp_Pnt P = ProjectPnt(myPlane,myDirection,L.Location());
537         TColStd_Array1OfInteger Mults(1,2); Mults.Init(2);
538         TColgp_Array1OfPnt      Poles(1,2); Poles.Init(P);
539         TColStd_Array1OfReal    Knots(1,2); 
540         Knots(1) = myCurve->FirstParameter();
541         Knots(2) = myCurve->LastParameter();
542         Handle(Geom_BSplineCurve) BSP = 
543           new Geom_BSplineCurve(Poles,Knots,Mults,1);
544
545 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
546         GeomAdaptor_Curve aGACurve(BSP);
547         myResult = new GeomAdaptor_HCurve(aGACurve);
548 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
549       }
550       else if ( Abs( Xc.Magnitude() - 1.) < Precision::Confusion()) {
551         myType      = GeomAbs_Line;
552         gp_Pnt P    = ProjectPnt(myPlane,myDirection,L.Location());
553         myFirstPar  = myCurve->FirstParameter();
554         myLastPar   = myCurve->LastParameter();
555         aLine       = gp_Lin(P,gp_Dir(Xc));
556         GeomLinePtr = new Geom_Line(aLine);
557         
558 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
559         GeomAdaptor_Curve aGACurve(GeomLinePtr,
560                                    myCurve->FirstParameter(),
561                                    myCurve->LastParameter() );
562         myResult = new GeomAdaptor_HCurve(aGACurve);
563 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
564       }
565       else {
566         myType     = GeomAbs_Line;
567         gp_Pnt P   = ProjectPnt(myPlane,myDirection,L.Location());
568         aLine      = gp_Lin(P,gp_Dir(Xc));
569         Standard_Real Udeb, Ufin;
570         
571         // eval the first and last parameters of the projected curve
572         Udeb = myCurve->FirstParameter();
573         Ufin = myCurve->LastParameter();
574         gp_Pnt P1  = ProjectPnt(myPlane,myDirection,
575                                 myCurve->Value(Udeb)); 
576         gp_Pnt P2  = ProjectPnt(myPlane,myDirection,
577                                 myCurve->Value(Ufin)); 
578         myFirstPar = gp_Vec(aLine.Direction()).Dot(gp_Vec(P,P1));
579         myLastPar  = gp_Vec(aLine.Direction()).Dot(gp_Vec(P,P2));
580         GeomLinePtr = new Geom_Line(aLine);
581         if (!myKeepParam) {
582 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
583           GeomAdaptor_Curve aGACurve(GeomLinePtr,
584                                      myFirstPar,
585                                      myLastPar) ;
586           myResult = new GeomAdaptor_HCurve(aGACurve);
587 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
588         }
589         else {
590           myType     = GeomAbs_BSplineCurve;
591           //
592           // make a linear BSpline of degree 1 between the end points of
593           // the projected line 
594           //
595           Handle(Geom_TrimmedCurve) NewTrimCurvePtr =
596             new Geom_TrimmedCurve(GeomLinePtr,
597                                   myFirstPar,
598                                   myLastPar) ;
599           
600           Handle(Geom_BSplineCurve) NewCurvePtr =
601             GeomConvert::CurveToBSplineCurve(NewTrimCurvePtr) ;
602           num_knots = NewCurvePtr->NbKnots() ;
603           TColStd_Array1OfReal    BsplineKnots(1,num_knots)  ;
604           NewCurvePtr->Knots(BsplineKnots) ;
605           
606           BSplCLib::Reparametrize(myCurve->FirstParameter(), 
607                                   myCurve->LastParameter(),
608                                   BsplineKnots) ;
609           
610           NewCurvePtr->SetKnots(BsplineKnots) ;
611 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
612           GeomAdaptor_Curve aGACurve(NewCurvePtr);
613           myResult = new GeomAdaptor_HCurve(aGACurve);
614 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
615         }
616       }
617       break;
618     }
619   case GeomAbs_Circle:
620     {
621       // Pour le cercle et l ellipse on a les relations suivantes:
622       // ( Rem : pour le cercle R1 = R2 = R)
623       //     P(u) = O + R1 * Cos(u) * Xc + R2 * Sin(u) * Yc
624       // ==> Q(u) = f(P(u)) 
625       //          = f(O) + R1 * Cos(u) * f(Xc) + R2 * Sin(u) * f(Yc)
626       
627       gp_Circ Circ = myCurve->Circle();
628       Axis = Circ.Position();
629       R1 = R2 = Circ.Radius();
630
631     }
632     Standard_FALLTHROUGH
633   case GeomAbs_Ellipse:
634     {
635       if ( Type == GeomAbs_Ellipse) {
636         gp_Elips E = myCurve->Ellipse();
637         Axis = E.Position();
638         R1 = E.MajorRadius();
639         R2 = E.MinorRadius();
640       }
641
642       // Common Code  for CIRCLE & ELLIPSE begin here
643       gp_Dir X  = Axis.XDirection();
644       gp_Dir Y  = Axis.YDirection();
645       gp_Vec VDx = ProjectVec(myPlane,myDirection,X);
646       gp_Vec VDy = ProjectVec(myPlane,myDirection,Y);
647       gp_Dir Dx,Dy;
648
649       Standard_Real Tol2 = myTolerance*myTolerance;
650       if (VDx.SquareMagnitude() < Tol2 ||
651           VDy.SquareMagnitude() < Tol2    ) {
652         myIsApprox = Standard_True;
653       }
654
655       if (!myIsApprox && 
656           gp_Dir(VDx).IsNormal(gp_Dir(VDy),Precision::Angular())) {
657         Dx = gp_Dir(VDx);
658         Dy = gp_Dir(VDy);
659         gp_Pnt O    = Axis.Location();
660         gp_Pnt P    = ProjectPnt(myPlane,myDirection,O);
661         gp_Pnt Px   = ProjectPnt(myPlane,myDirection,O.Translated(R1*gp_Vec(X)));
662         gp_Pnt Py   = ProjectPnt(myPlane,myDirection,O.Translated(R2*gp_Vec(Y)));
663         Standard_Real Major = P.Distance(Px);
664         Standard_Real Minor = P.Distance(Py);
665         gp_Ax2 Axe( P, Dx^Dy,Dx);
666
667         if ( Abs( Major - Minor) < Precision::Confusion()) {
668           myType = GeomAbs_Circle;
669           gp_Circ Circ(Axe, Major);
670           GeomCirclePtr  = new Geom_Circle(Circ);
671 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
672           GeomAdaptor_Curve aGACurve(GeomCirclePtr);
673           myResult = new GeomAdaptor_HCurve(aGACurve);
674 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
675         }
676         else if ( Major > Minor) {
677           myType = GeomAbs_Ellipse;
678           Elips  = gp_Elips( Axe, Major, Minor);
679           
680           GeomEllipsePtr = new Geom_Ellipse(Elips) ;
681 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
682           GeomAdaptor_Curve aGACurve(GeomEllipsePtr);
683           myResult = new GeomAdaptor_HCurve(aGACurve);
684 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
685         }
686         else {
687           myIsApprox = Standard_True;
688           myType = GeomAbs_BSplineCurve;
689           PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
690 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
691           GeomAdaptor_Curve aGACurve(ApproxCurve);
692           myResult = new GeomAdaptor_HCurve(aGACurve);
693 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
694         }
695       }
696       else {
697         myIsApprox = Standard_True;
698         myType     = GeomAbs_BSplineCurve;
699         PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
700 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
701         GeomAdaptor_Curve aGACurve(ApproxCurve);
702         myResult = new GeomAdaptor_HCurve(aGACurve);
703 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
704       }
705     }
706     break;
707   case GeomAbs_Parabola:
708     {
709       //     P(u) = O + (u*u)/(4*f) * Xc + u * Yc
710       // ==> Q(u) = f(P(u)) 
711       //          = f(O) + (u*u)/(4*f) * f(Xc) + u * f(Yc)
712
713       gp_Parab Parab  = myCurve->Parabola();
714       gp_Ax2   AxeRef = Parab.Position();
715       gp_Vec Xc = ProjectVec(myPlane,myDirection,gp_Vec(AxeRef.XDirection()));
716       gp_Vec Yc = ProjectVec(myPlane,myDirection,gp_Vec(AxeRef.YDirection()));
717
718       // fix for case when no one action is done. 28.03.2002
719       Standard_Boolean alocalIsDone = Standard_False;
720
721       if ( Abs( Yc.Magnitude() - 1.) < Precision::Confusion()) {
722         gp_Pnt P = ProjectPnt(myPlane,myDirection,AxeRef.Location());
723         if ( Xc.Magnitude() < Precision::Confusion()) {
724           myType = GeomAbs_Line;
725           aLine  = gp_Lin( P, gp_Dir(Yc));
726           
727           GeomLinePtr    = new Geom_Line(aLine) ;
728 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
729           GeomAdaptor_Curve aGACurve(GeomLinePtr);
730           myResult = new GeomAdaptor_HCurve(aGACurve);
731 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
732           alocalIsDone = Standard_True;
733         }
734         else if ( Xc.IsNormal(Yc,Precision::Angular())) {
735           myType = GeomAbs_Parabola;
736           Standard_Real F = Parab.Focal() / Xc.Magnitude();
737           gp_Parab aParab = gp_Parab( gp_Ax2(P,Xc^Yc,Xc), F);
738           Handle(Geom_Parabola) GeomParabolaPtr =
739             new Geom_Parabola(aParab) ;
740 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
741           GeomAdaptor_Curve aGACurve(GeomParabolaPtr);
742           myResult = new GeomAdaptor_HCurve(aGACurve);
743 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
744           alocalIsDone = Standard_True;
745         }
746       }
747       if (!alocalIsDone)/*else*/ {
748         myIsApprox = Standard_True;
749         myType     = GeomAbs_BSplineCurve;
750         PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
751 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
752         GeomAdaptor_Curve aGACurve(ApproxCurve);
753         myResult = new GeomAdaptor_HCurve(aGACurve);
754 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
755       }
756     }
757     break;
758   case GeomAbs_Hyperbola:
759     {
760       //     P(u) = O + R1 * Cosh(u) * Xc + R2 * Sinh(u) * Yc
761       // ==> Q(u) = f(P(u)) 
762       //          = f(O) + R1 * Cosh(u) * f(Xc) + R2 * Sinh(u) * f(Yc)
763
764       gp_Hypr Hypr  = myCurve->Hyperbola();
765       gp_Ax2 AxeRef = Hypr.Position();
766       gp_Vec Xc = ProjectVec(myPlane,myDirection,gp_Vec(AxeRef.XDirection()));
767       gp_Vec Yc = ProjectVec(myPlane,myDirection,gp_Vec(AxeRef.YDirection()));
768       gp_Pnt P  = ProjectPnt(myPlane,myDirection,AxeRef.Location());
769       Standard_Real aR1 = Hypr.MajorRadius();
770       Standard_Real aR2 = Hypr.MinorRadius();
771       gp_Dir Z = myPlane.Direction();
772
773       if ( Xc.Magnitude() < Precision::Confusion()) {
774         myType   = GeomAbs_Hyperbola;
775         gp_Dir X = gp_Dir(Yc) ^ Z;
776         Hypr   = gp_Hypr(gp_Ax2( P, Z, X), 0., aR2 * Yc.Magnitude());
777         GeomHyperbolaPtr =
778           new Geom_Hyperbola(Hypr) ;
779 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
780         GeomAdaptor_Curve aGACurve(GeomHyperbolaPtr);
781         myResult = new GeomAdaptor_HCurve(aGACurve);
782 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
783       }
784       else if ( Yc.Magnitude() < Precision::Confusion()) {
785         myType = GeomAbs_Hyperbola;
786         Hypr = 
787            gp_Hypr(gp_Ax2(P, Z, gp_Dir(Xc)), aR1 * Xc.Magnitude(), 0.);
788         GeomHyperbolaPtr =
789           new Geom_Hyperbola(Hypr) ;
790 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
791         GeomAdaptor_Curve aGACurve(GeomHyperbolaPtr);
792         myResult = new GeomAdaptor_HCurve(aGACurve);
793 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
794       }
795       else if ( Xc.IsNormal(Yc,Precision::Angular())) {
796         myType = GeomAbs_Hyperbola;
797         Hypr = gp_Hypr( gp_Ax2( P, gp_Dir( Xc ^ Yc), gp_Dir( Xc)),
798                        aR1 * Xc.Magnitude(), aR2 * Yc.Magnitude() );
799         GeomHyperbolaPtr =
800           new Geom_Hyperbola(Hypr) ;
801 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
802         GeomAdaptor_Curve aGACurve(GeomHyperbolaPtr);
803         myResult = new GeomAdaptor_HCurve(aGACurve);
804 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
805       }
806       else {
807         myIsApprox = Standard_True;
808         myType     = GeomAbs_BSplineCurve;
809         PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
810 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
811         GeomAdaptor_Curve aGACurve(ApproxCurve);
812         myResult = new GeomAdaptor_HCurve(aGACurve);
813 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
814       }
815     }
816     break;
817   case GeomAbs_BezierCurve:
818     {
819       Handle(Geom_BezierCurve) BezierCurvePtr =
820         myCurve->Bezier() ;
821       Standard_Integer NbPoles = 
822         BezierCurvePtr->NbPoles() ;
823       
824       Handle(Geom_BezierCurve) ProjCu = 
825         Handle(Geom_BezierCurve)::DownCast(BezierCurvePtr->Copy());
826
827       myIsApprox = Standard_False;
828       myType = Type;
829       for ( Standard_Integer i = 1; i <= NbPoles; i++) {
830         ProjCu->SetPole
831           (i,ProjectPnt(myPlane,myDirection,BezierCurvePtr->Pole(i)));
832       }
833       
834 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
835       GeomAdaptor_Curve aGACurve(ProjCu);
836       myResult = new GeomAdaptor_HCurve(aGACurve);
837 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
838     }
839     break ;
840   case GeomAbs_BSplineCurve:
841     {
842       Handle(Geom_BSplineCurve) BSplineCurvePtr =
843         myCurve->BSpline() ;
844       //
845       //    make a copy of the curve and projects its poles 
846       //
847       Handle(Geom_BSplineCurve) ProjectedBSplinePtr =
848         Handle(Geom_BSplineCurve)::DownCast(BSplineCurvePtr->Copy()) ;
849       
850       myIsApprox = Standard_False;
851       myType = Type;
852       for ( Standard_Integer i = 1; i <= BSplineCurvePtr->NbPoles(); i++) {
853         ProjectedBSplinePtr->SetPole
854           (i,ProjectPnt(myPlane,myDirection,BSplineCurvePtr->Pole(i)));
855       }
856       
857 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
858       GeomAdaptor_Curve aGACurve(ProjectedBSplinePtr);
859       myResult = new GeomAdaptor_HCurve(aGACurve);
860 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
861     }
862     break;
863   default:
864     {
865       myIsApprox = Standard_True;
866       myType     = GeomAbs_BSplineCurve;
867       PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
868 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
869       GeomAdaptor_Curve aGACurve(ApproxCurve);
870       myResult = new GeomAdaptor_HCurve(aGACurve);
871 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
872     }
873     break;
874   }
875 }
876
877 //=======================================================================
878 //function : GetPlane
879 //purpose  : 
880 //=======================================================================
881
882 const gp_Ax3& ProjLib_ProjectOnPlane::GetPlane() const 
883 {
884   return myPlane;
885 }
886
887 //=======================================================================
888 //function : GetDirection
889 //purpose  : 
890 //=======================================================================
891
892 const gp_Dir& ProjLib_ProjectOnPlane::GetDirection() const 
893 {
894   return myDirection;
895 }
896
897 //=======================================================================
898 //function : GetCurve
899 //purpose  : 
900 //=======================================================================
901
902 const Handle(Adaptor3d_HCurve)& ProjLib_ProjectOnPlane::GetCurve() const
903 {
904   return myCurve;
905 }
906
907 //=======================================================================
908 //function : GetResult
909 //purpose  : 
910 //=======================================================================
911
912 const Handle(GeomAdaptor_HCurve)& ProjLib_ProjectOnPlane::GetResult() const
913 {
914   return myResult;
915 }
916
917
918 //=======================================================================
919 //function : FirstParameter
920 //purpose  : 
921 //=======================================================================
922
923 Standard_Real ProjLib_ProjectOnPlane::FirstParameter() const 
924 {
925   if ( myKeepParam || myIsApprox) 
926     return myCurve->FirstParameter();
927   else
928     return myFirstPar;
929 }
930
931
932 //=======================================================================
933 //function : LastParameter
934 //purpose  : 
935 //=======================================================================
936
937 Standard_Real ProjLib_ProjectOnPlane::LastParameter() const 
938 {
939   if ( myKeepParam || myIsApprox) 
940     return myCurve->LastParameter();
941   else
942     return myLastPar;
943 }
944
945
946 //=======================================================================
947 //function : Continuity
948 //purpose  : 
949 //=======================================================================
950
951 GeomAbs_Shape ProjLib_ProjectOnPlane::Continuity() const
952 {
953   return myCurve->Continuity() ;
954 }
955
956
957 //=======================================================================
958 //function : NbIntervals
959 //purpose  : 
960 //=======================================================================
961
962 Standard_Integer ProjLib_ProjectOnPlane::NbIntervals(const GeomAbs_Shape S) const
963 {
964   return myCurve->NbIntervals(S) ;
965 }
966
967
968 //=======================================================================
969 //function : Intervals
970 //purpose  : 
971 //=======================================================================
972
973 void ProjLib_ProjectOnPlane::Intervals(TColStd_Array1OfReal& T, 
974                                        const GeomAbs_Shape S) const
975 {
976   myCurve->Intervals(T,S) ;
977 }
978
979 //=======================================================================
980 //function : Trim
981 //purpose  : 
982 //=======================================================================
983
984 Handle(Adaptor3d_HCurve)  
985 ProjLib_ProjectOnPlane::Trim(const Standard_Real First,
986                              const Standard_Real Last,
987                              const Standard_Real Tolerance) const 
988 {
989   if (myType != GeomAbs_OtherCurve){
990     return myResult->Trim(First,Last,Tolerance) ;
991   }
992   else {
993     throw Standard_NotImplemented ("ProjLib_ProjectOnPlane::Trim() - curve of unsupported type");
994   }
995 }
996
997   
998 //=======================================================================
999 //function : IsClosed
1000 //purpose  : 
1001 //=======================================================================
1002
1003 Standard_Boolean ProjLib_ProjectOnPlane::IsClosed() const
1004 {
1005  return myCurve->IsClosed() ;
1006 }
1007
1008
1009 //=======================================================================
1010 //function : IsPeriodic
1011 //purpose  : 
1012 //=======================================================================
1013
1014 Standard_Boolean ProjLib_ProjectOnPlane::IsPeriodic() const
1015 {
1016   if ( myIsApprox)
1017     return Standard_False;
1018   else 
1019     return myCurve->IsPeriodic();
1020 }
1021
1022
1023 //=======================================================================
1024 //function : Period
1025 //purpose  : 
1026 //=======================================================================
1027
1028 Standard_Real ProjLib_ProjectOnPlane::Period() const
1029 {
1030   if ( !IsPeriodic()) {
1031     throw Standard_NoSuchObject("ProjLib_ProjectOnPlane::Period");
1032   }
1033                                 
1034   if ( myIsApprox)
1035     return Standard_False;
1036   else 
1037     return myCurve->Period();
1038 }
1039
1040
1041 //=======================================================================
1042 //function : Value
1043 //purpose  : 
1044 //=======================================================================
1045
1046 gp_Pnt ProjLib_ProjectOnPlane::Value(const Standard_Real U) const 
1047 {
1048   if (myType != GeomAbs_OtherCurve) { 
1049     return myResult->Value(U);
1050   }
1051   else {
1052     return OnPlane_Value(U,
1053                          myCurve,
1054                          myPlane,
1055                          myDirection);
1056     
1057   }
1058
1059
1060
1061 //=======================================================================
1062 //function : D0
1063 //purpose  : 
1064 //=======================================================================
1065
1066 void ProjLib_ProjectOnPlane::D0(const Standard_Real U , gp_Pnt& P) const
1067 {
1068   if (myType != GeomAbs_OtherCurve) {
1069     myResult->D0(U,P) ;
1070   }
1071   else {
1072     P = OnPlane_Value(U,
1073                       myCurve,
1074                       myPlane,
1075                       myDirection);
1076   }
1077 }
1078
1079
1080 //=======================================================================
1081 //function : D1
1082 //purpose  : 
1083 //=======================================================================
1084
1085 void ProjLib_ProjectOnPlane::D1(const Standard_Real U,
1086                                       gp_Pnt&    P , 
1087                                       gp_Vec&    V ) const 
1088 {
1089   if (myType != GeomAbs_OtherCurve) {
1090     myResult->D1(U,P,V) ;
1091   }
1092   else {
1093     OnPlane_D1(U,
1094                P,
1095                V,
1096                myCurve,
1097                myPlane,
1098                myDirection);
1099   }
1100 }
1101
1102
1103 //=======================================================================
1104 //function : D2
1105 //purpose  : 
1106 //=======================================================================
1107
1108 void ProjLib_ProjectOnPlane::D2(const Standard_Real U, 
1109                                       gp_Pnt&     P, 
1110                                       gp_Vec&     V1, 
1111                                       gp_Vec&     V2) const 
1112 {
1113   if (myType != GeomAbs_OtherCurve)  {
1114     myResult->D2(U,P,V1,V2) ;
1115   }
1116   else {
1117     OnPlane_D2(U,
1118                P,
1119                V1,
1120                V2,
1121                myCurve,
1122                myPlane,
1123                myDirection);
1124   }
1125 }
1126
1127
1128 //=======================================================================
1129 //function : D3
1130 //purpose  : 
1131 //=======================================================================
1132
1133 void ProjLib_ProjectOnPlane::D3(const Standard_Real U, 
1134                                 gp_Pnt& P, 
1135                                 gp_Vec& V1, 
1136                                 gp_Vec& V2, 
1137                                 gp_Vec& V3) const 
1138 {
1139   if (myType != GeomAbs_OtherCurve)   {
1140     myResult->D3(U,P,V1,V2,V3) ;
1141   }
1142   else   {
1143     OnPlane_D3(U,
1144                P,
1145                V1,
1146                V2,
1147                V3,
1148                myCurve,
1149                myPlane,
1150                myDirection); 
1151   }
1152 }
1153
1154
1155 //=======================================================================
1156 //function : DN
1157 //purpose  : 
1158 //=======================================================================
1159
1160 gp_Vec ProjLib_ProjectOnPlane::DN(const Standard_Real U, 
1161                                   const Standard_Integer DerivativeRequest)
1162      const 
1163 {
1164   if (myType != GeomAbs_OtherCurve) {
1165     return myResult->DN(U,DerivativeRequest) ;
1166   }
1167   else {
1168     return OnPlane_DN(U,
1169                       DerivativeRequest,
1170                       myCurve,
1171                       myPlane,
1172                       myDirection); 
1173   }   
1174 }
1175
1176
1177 //=======================================================================
1178 //function : Resolution
1179 //purpose  : 
1180 //=======================================================================
1181
1182 Standard_Real ProjLib_ProjectOnPlane::Resolution
1183 (const Standard_Real Tolerance) const 
1184 {
1185   if (myType != GeomAbs_OtherCurve) {
1186     return myResult->Resolution(Tolerance) ;
1187   }
1188   else {
1189     return 0;
1190   }
1191 }
1192     
1193
1194 //=======================================================================
1195 //function : GetType
1196 //purpose  : 
1197 //=======================================================================
1198
1199 GeomAbs_CurveType ProjLib_ProjectOnPlane::GetType() const
1200 {
1201   return myType;
1202 }
1203
1204
1205 //=======================================================================
1206 //function : Line
1207 //purpose  : 
1208 //=======================================================================
1209
1210 gp_Lin ProjLib_ProjectOnPlane::Line() const
1211 {
1212   if (myType != GeomAbs_Line)
1213     throw Standard_NoSuchObject("ProjLib_ProjectOnPlane:Line");
1214
1215   return myResult->Line();
1216 }
1217
1218
1219 //=======================================================================
1220 //function : Circle
1221 //purpose  : 
1222 //=======================================================================
1223
1224 gp_Circ ProjLib_ProjectOnPlane::Circle() const
1225 {
1226   if (myType != GeomAbs_Circle)
1227     throw Standard_NoSuchObject("ProjLib_ProjectOnPlane:Circle");
1228
1229   return myResult->Circle();
1230 }
1231
1232
1233 //=======================================================================
1234 //function : Ellipse
1235 //purpose  : 
1236 //=======================================================================
1237
1238 gp_Elips ProjLib_ProjectOnPlane::Ellipse() const
1239 {
1240   if (myType != GeomAbs_Ellipse)
1241     throw Standard_NoSuchObject("ProjLib_ProjectOnPlane:Ellipse");
1242
1243   return myResult->Ellipse();
1244 }
1245
1246
1247 //=======================================================================
1248 //function : Hyperbola
1249 //purpose  : 
1250 //=======================================================================
1251
1252 gp_Hypr ProjLib_ProjectOnPlane::Hyperbola() const
1253 {
1254   if (myType != GeomAbs_Hyperbola)
1255     throw Standard_NoSuchObject("ProjLib_ProjectOnPlane:Hyperbola");
1256
1257   return myResult->Hyperbola() ;
1258 }
1259
1260
1261 //=======================================================================
1262 //function : Parabola
1263 //purpose  : 
1264 //=======================================================================
1265
1266 gp_Parab ProjLib_ProjectOnPlane::Parabola() const
1267 {
1268   if (myType != GeomAbs_Parabola)
1269     throw Standard_NoSuchObject("ProjLib_ProjectOnPlane:Parabola");
1270   
1271   return myResult->Parabola() ;
1272 }
1273
1274 //=======================================================================
1275 //function : Degree
1276 //purpose  : 
1277 //=======================================================================
1278
1279 Standard_Integer ProjLib_ProjectOnPlane::Degree() const
1280 {
1281   if ((GetType() != GeomAbs_BSplineCurve) &&
1282       (GetType() != GeomAbs_BezierCurve))
1283     throw Standard_NoSuchObject("ProjLib_ProjectOnPlane:Degree");
1284
1285   if ( myIsApprox)
1286     return myResult->Degree();
1287   else
1288     return myCurve->Degree();
1289 }
1290
1291 //=======================================================================
1292 //function : IsRational
1293 //purpose  : 
1294 //=======================================================================
1295
1296 Standard_Boolean ProjLib_ProjectOnPlane::IsRational() const 
1297 {
1298   if ((GetType() != GeomAbs_BSplineCurve) &&
1299       (GetType() != GeomAbs_BezierCurve))
1300     throw Standard_NoSuchObject("ProjLib_ProjectOnPlane:IsRational");
1301   
1302   if ( myIsApprox) 
1303     return myResult->IsRational();
1304   else
1305     return myCurve->IsRational();
1306 }
1307
1308 //=======================================================================
1309 //function : NbPoles
1310 //purpose  : 
1311 //=======================================================================
1312
1313 Standard_Integer ProjLib_ProjectOnPlane::NbPoles() const
1314 {
1315   if ((GetType() != GeomAbs_BSplineCurve) &&
1316       (GetType() != GeomAbs_BezierCurve))
1317     throw Standard_NoSuchObject("ProjLib_ProjectOnPlane:NbPoles");
1318   
1319   if ( myIsApprox)
1320     return myResult->NbPoles();
1321   else
1322     return myCurve->NbPoles();
1323 }
1324
1325 //=======================================================================
1326 //function : NbKnots
1327 //purpose  : 
1328 //=======================================================================
1329
1330 Standard_Integer ProjLib_ProjectOnPlane::NbKnots() const 
1331 {
1332   if ( GetType() != GeomAbs_BSplineCurve) 
1333     throw Standard_NoSuchObject("ProjLib_ProjectOnPlane:NbKnots");
1334   
1335   if ( myIsApprox) 
1336     return myResult->NbKnots();
1337   else
1338     return myCurve->NbKnots();
1339 }
1340
1341
1342 //=======================================================================
1343 //function : Bezier
1344 //purpose  : 
1345 //=======================================================================
1346
1347 Handle(Geom_BezierCurve)  ProjLib_ProjectOnPlane::Bezier() const
1348 {
1349   if (myType != GeomAbs_BezierCurve)
1350     throw Standard_NoSuchObject("ProjLib_ProjectOnPlane:Bezier");
1351
1352   return myResult->Bezier() ;
1353 }
1354
1355 //=======================================================================
1356 //function : Bezier
1357 //purpose  : 
1358 //=======================================================================
1359
1360 Handle(Geom_BSplineCurve)  ProjLib_ProjectOnPlane::BSpline() const
1361 {
1362   if (myType != GeomAbs_BSplineCurve)
1363     throw Standard_NoSuchObject("ProjLib_ProjectOnPlane:BSpline");
1364
1365   return myResult->BSpline() ;
1366 }
1367