0024988: Wrong result done by projection algorithm
[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(F,Deg1,Deg2,Precision::Approximation(),
321                           Precision::PApproximation(),Standard_True);
322   Standard_Integer i;
323   Standard_Integer NbCurves = Fit.NbMultiCurves();
324   Standard_Integer MaxDeg = 0;
325   
326   // Pour transformer la MultiCurve en BSpline, il faut que toutes 
327   // les Bezier la constituant aient le meme degre -> Calcul de MaxDeg
328   Standard_Integer NbPoles  = 1;
329   for (i = 1; i <= NbCurves; i++) {
330     Standard_Integer Deg = Fit.Value(i).Degree();
331     MaxDeg = Max ( MaxDeg, Deg);
332   }
333   NbPoles = MaxDeg * NbCurves + 1;               //Poles sur la BSpline
334
335   TColgp_Array1OfPnt    Poles( 1, NbPoles);
336   
337   TColgp_Array1OfPnt TempPoles( 1, MaxDeg + 1);  //pour augmentation du degre
338   
339   TColStd_Array1OfReal Knots( 1, NbCurves + 1);  //Noeuds de la BSpline
340   
341   Standard_Integer Compt = 1;
342   for (i = 1; i <= Fit.NbMultiCurves(); i++) {
343     Fit.Parameters(i, Knots(i), Knots(i+1)); 
344     
345     AppParCurves_MultiCurve MC = Fit.Value( i);   //Charge la Ieme Curve
346     TColgp_Array1OfPnt LocalPoles( 1, MC.Degree() + 1);//Recupere les poles
347     MC.Curve(1, LocalPoles);
348     
349     //Augmentation eventuelle du degre
350     Standard_Integer Inc = MaxDeg - MC.Degree();
351     if ( Inc > 0) {
352       BSplCLib::IncreaseDegree(Inc, Poles, PLib::NoWeights(),
353                                TempPoles, PLib::NoWeights());
354       //mise a jour des poles de la PCurve
355       for (Standard_Integer j = 1 ; j <= MaxDeg + 1; j++) {
356         Poles.SetValue( Compt, TempPoles( j));
357         Compt++;
358       }
359     }
360     else {
361       //mise a jour des poles de la PCurve
362       for (Standard_Integer j = 1 ; j <= MaxDeg + 1; j++) {
363         Poles.SetValue( Compt, LocalPoles( j));
364         Compt++;
365       }
366     } 
367     
368     Compt--;
369   }
370   
371   //mise a jour des fields de ProjLib_Approx
372
373   Standard_Integer 
374   NbKnots = NbCurves + 1;
375
376   TColStd_Array1OfInteger    Mults(1, NbKnots);
377   Mults.SetValue( 1, MaxDeg + 1);
378   for ( i = 2; i <= NbCurves; i++) {
379     Mults.SetValue( i, MaxDeg);
380   }
381   Mults.SetValue( NbKnots, MaxDeg + 1);
382   BSplineCurvePtr = 
383     new Geom_BSplineCurve(Poles,Knots,Mults,MaxDeg,Standard_False);
384 }
385
386
387 //=======================================================================
388 //function : ProjectOnPlane
389 //purpose  : 
390 //=======================================================================
391
392 ProjLib_ProjectOnPlane::ProjLib_ProjectOnPlane() :
393 myKeepParam(Standard_False),
394 myFirstPar(0.),
395 myLastPar(0.),
396 myTolerance(0.),
397 myType     (GeomAbs_OtherCurve),
398 myIsApprox (Standard_False)
399 {
400 }
401
402 //=======================================================================
403 //function : ProjLib_ProjectOnPlane
404 //purpose  : 
405 //=======================================================================
406
407 ProjLib_ProjectOnPlane::ProjLib_ProjectOnPlane(const gp_Ax3& Pl) : 
408 myPlane     (Pl)                ,
409 myDirection (Pl.Direction())    ,
410 myKeepParam(Standard_False),
411 myFirstPar(0.),
412 myLastPar(0.),
413 myTolerance(0.),
414 myType      (GeomAbs_OtherCurve),
415 myIsApprox  (Standard_False)
416 {
417 }
418
419 //=======================================================================
420 //function : ProjLib_ProjectOnPlane
421 //purpose  : 
422 //=======================================================================
423
424 ProjLib_ProjectOnPlane::ProjLib_ProjectOnPlane(const gp_Ax3& Pl,
425                                                const gp_Dir& D  ) :
426 myPlane     (Pl)                ,
427 myDirection (D)                 ,
428 myKeepParam(Standard_False),
429 myFirstPar(0.),
430 myLastPar(0.),
431 myTolerance(0.),
432 myType      (GeomAbs_OtherCurve),
433 myIsApprox  (Standard_False)
434 {
435 //  if ( Abs(D * Pl.Direction()) < Precision::Confusion()) {
436 //    Standard_ConstructionError::Raise
437 //      ("ProjLib_ProjectOnPlane:  The Direction and the Plane are parallel");
438 //  }
439 }
440
441 //=======================================================================
442 //function : Project
443 //purpose  : Returns the projection of a point <Point> on a plane 
444 //           <ThePlane>  along a direction <TheDir>.
445 //=======================================================================
446
447 static gp_Pnt ProjectPnt(const gp_Ax3& ThePlane,
448                          const gp_Dir& TheDir,
449                          const gp_Pnt& Point) 
450 {
451   gp_Vec PO(Point,ThePlane.Location());
452
453   Standard_Real Alpha = PO * gp_Vec(ThePlane.Direction());
454   Alpha /= TheDir * ThePlane.Direction();
455   
456   gp_Pnt P;
457   P.SetXYZ(Point.XYZ() + Alpha * TheDir.XYZ());
458
459   return P;
460 }
461
462
463 //=======================================================================
464 //function : Project
465 //purpose  : Returns the projection of a Vector <Vec> on a plane 
466 //           <ThePlane> along a direction <TheDir>.
467 //=======================================================================
468
469 static gp_Vec ProjectVec(const gp_Ax3& ThePlane,
470                          const gp_Dir& TheDir,
471                          const gp_Vec& Vec) 
472 {
473   gp_Vec D = Vec;
474   gp_Vec Z = ThePlane.Direction();
475
476   D -= ( (Vec * Z) / (TheDir * Z)) * TheDir;
477
478   return D;
479 }
480
481 //=======================================================================
482 //function : Load
483 //purpose  : 
484 //=======================================================================
485
486 void ProjLib_ProjectOnPlane::Load(const Handle(Adaptor3d_HCurve)&    C,
487                                   const Standard_Real Tolerance,
488                                   const Standard_Boolean KeepParametrization) 
489                                   
490 {
491   myCurve      = C;
492   myType       = GeomAbs_OtherCurve;
493   myIsApprox   = Standard_False;
494   myTolerance  = Tolerance ;
495
496   Handle(Geom_BSplineCurve)  ApproxCurve;
497   Handle(GeomAdaptor_HCurve) aGAHCurve;
498
499   Handle(Geom_Line)      GeomLinePtr;
500   Handle(Geom_Circle)    GeomCirclePtr ;
501   Handle(Geom_Ellipse)   GeomEllipsePtr ;
502   Handle(Geom_Hyperbola) GeomHyperbolaPtr ;
503
504   gp_Lin   aLine; 
505   gp_Elips Elips;
506 //  gp_Hypr  Hypr ;
507
508   Standard_Integer num_knots ;
509   GeomAbs_CurveType Type = C->GetType();
510
511   gp_Ax2 Axis;
512   Standard_Real R1 =0., R2 =0.;
513
514   if ( Type != GeomAbs_Line)  // on garde le parametrage
515     myKeepParam = Standard_True;
516   else                        // on prend le choix utilisateur.
517     myKeepParam = KeepParametrization;
518
519   switch ( Type) {
520   case GeomAbs_Line: 
521     {
522       //     P(u) = O + u * Xc
523       // ==> Q(u) = f(P(u)) 
524       //          = f(O) + u * f(Xc)
525
526       gp_Lin L  = myCurve->Line();
527       gp_Vec Xc = ProjectVec(myPlane,myDirection,gp_Vec(L.Direction()));
528
529       if ( Xc.Magnitude() < Precision::Confusion()) { // line orthog au plan
530         myType = GeomAbs_BSplineCurve;
531         gp_Pnt P = ProjectPnt(myPlane,myDirection,L.Location());
532         TColStd_Array1OfInteger Mults(1,2); Mults.Init(2);
533         TColgp_Array1OfPnt      Poles(1,2); Poles.Init(P);
534         TColStd_Array1OfReal    Knots(1,2); 
535         Knots(1) = myCurve->FirstParameter();
536         Knots(2) = myCurve->LastParameter();
537         Handle(Geom_BSplineCurve) BSP = 
538           new Geom_BSplineCurve(Poles,Knots,Mults,1);
539
540 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
541         GeomAdaptor_Curve aGACurve(BSP);
542         myResult = new GeomAdaptor_HCurve(aGACurve);
543 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
544       }
545       else if ( Abs( Xc.Magnitude() - 1.) < Precision::Confusion()) {
546         myType      = GeomAbs_Line;
547         gp_Pnt P    = ProjectPnt(myPlane,myDirection,L.Location());
548         myFirstPar  = myCurve->FirstParameter();
549         myLastPar   = myCurve->LastParameter();
550         aLine       = gp_Lin(P,gp_Dir(Xc));
551         GeomLinePtr = new Geom_Line(aLine);
552         
553 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
554         GeomAdaptor_Curve aGACurve(GeomLinePtr,
555                                    myCurve->FirstParameter(),
556                                    myCurve->LastParameter() );
557         myResult = new GeomAdaptor_HCurve(aGACurve);
558 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
559       }
560       else {
561         myType     = GeomAbs_Line;
562         gp_Pnt P   = ProjectPnt(myPlane,myDirection,L.Location());
563         aLine      = gp_Lin(P,gp_Dir(Xc));
564         Standard_Real Udeb, Ufin;
565         
566         // eval the first and last parameters of the projected curve
567         Udeb = myCurve->FirstParameter();
568         Ufin = myCurve->LastParameter();
569         gp_Pnt P1  = ProjectPnt(myPlane,myDirection,
570                                 myCurve->Value(Udeb)); 
571         gp_Pnt P2  = ProjectPnt(myPlane,myDirection,
572                                 myCurve->Value(Ufin)); 
573         myFirstPar = gp_Vec(aLine.Direction()).Dot(gp_Vec(P,P1));
574         myLastPar  = gp_Vec(aLine.Direction()).Dot(gp_Vec(P,P2));
575         GeomLinePtr = new Geom_Line(aLine);
576         if (!myKeepParam) {
577 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
578           GeomAdaptor_Curve aGACurve(GeomLinePtr,
579                                      myFirstPar,
580                                      myLastPar) ;
581           myResult = new GeomAdaptor_HCurve(aGACurve);
582 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
583         }
584         else {
585           myType     = GeomAbs_BSplineCurve;
586           //
587           // make a linear BSpline of degree 1 between the end points of
588           // the projected line 
589           //
590           Handle(Geom_TrimmedCurve) NewTrimCurvePtr =
591             new Geom_TrimmedCurve(GeomLinePtr,
592                                   myFirstPar,
593                                   myLastPar) ;
594           
595           Handle(Geom_BSplineCurve) NewCurvePtr =
596             GeomConvert::CurveToBSplineCurve(NewTrimCurvePtr) ;
597           num_knots = NewCurvePtr->NbKnots() ;
598           TColStd_Array1OfReal    BsplineKnots(1,num_knots)  ;
599           NewCurvePtr->Knots(BsplineKnots) ;
600           
601           BSplCLib::Reparametrize(myCurve->FirstParameter(), 
602                                   myCurve->LastParameter(),
603                                   BsplineKnots) ;
604           
605           NewCurvePtr->SetKnots(BsplineKnots) ;
606 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
607           GeomAdaptor_Curve aGACurve(NewCurvePtr);
608           myResult = new GeomAdaptor_HCurve(aGACurve);
609 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
610         }
611       }
612       break;
613     }
614   case GeomAbs_Circle:
615     {
616       // Pour le cercle et l ellipse on a les relations suivantes:
617       // ( Rem : pour le cercle R1 = R2 = R)
618       //     P(u) = O + R1 * Cos(u) * Xc + R2 * Sin(u) * Yc
619       // ==> Q(u) = f(P(u)) 
620       //          = f(O) + R1 * Cos(u) * f(Xc) + R2 * Sin(u) * f(Yc)
621       
622       gp_Circ Circ = myCurve->Circle();
623       Axis = Circ.Position();
624       R1 = R2 = Circ.Radius();
625
626     }
627   case GeomAbs_Ellipse:
628     {
629       if ( Type == GeomAbs_Ellipse) {
630         gp_Elips E = myCurve->Ellipse();
631         Axis = E.Position();
632         R1 = E.MajorRadius();
633         R2 = E.MinorRadius();
634       }
635
636       // Common Code  for CIRCLE & ELLIPSE begin here
637       gp_Dir X  = Axis.XDirection();
638       gp_Dir Y  = Axis.YDirection();
639       gp_Vec VDx = ProjectVec(myPlane,myDirection,X);
640       gp_Vec VDy = ProjectVec(myPlane,myDirection,Y);
641       gp_Dir Dx,Dy;
642
643       Standard_Real Tol2 = myTolerance*myTolerance;
644       if (VDx.SquareMagnitude() < Tol2 ||
645           VDy.SquareMagnitude() < Tol2    ) {
646         myIsApprox = Standard_True;
647       }
648
649       if (!myIsApprox && 
650           gp_Dir(VDx).IsNormal(gp_Dir(VDy),Precision::Angular())) {
651         Dx = gp_Dir(VDx);
652         Dy = gp_Dir(VDy);
653         gp_Pnt O    = Axis.Location();
654         gp_Pnt P    = ProjectPnt(myPlane,myDirection,O);
655         gp_Pnt Px   = ProjectPnt(myPlane,myDirection,O.Translated(R1*gp_Vec(X)));
656         gp_Pnt Py   = ProjectPnt(myPlane,myDirection,O.Translated(R2*gp_Vec(Y)));
657         Standard_Real Major = P.Distance(Px);
658         Standard_Real Minor = P.Distance(Py);
659         gp_Ax2 Axe( P, Dx^Dy,Dx);
660
661         if ( Abs( Major - Minor) < Precision::Confusion()) {
662           myType = GeomAbs_Circle;
663           gp_Circ Circ(Axe, Major);
664           GeomCirclePtr  = new Geom_Circle(Circ);
665 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
666           GeomAdaptor_Curve aGACurve(GeomCirclePtr);
667           myResult = new GeomAdaptor_HCurve(aGACurve);
668 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
669         }
670         else if ( Major > Minor) {
671           myType = GeomAbs_Ellipse;
672           Elips  = gp_Elips( Axe, Major, Minor);
673           
674           GeomEllipsePtr = new Geom_Ellipse(Elips) ;
675 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
676           GeomAdaptor_Curve aGACurve(GeomEllipsePtr);
677           myResult = new GeomAdaptor_HCurve(aGACurve);
678 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
679         }
680         else {
681           myIsApprox = Standard_True;
682           myType = GeomAbs_BSplineCurve;
683           PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
684 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
685           GeomAdaptor_Curve aGACurve(ApproxCurve);
686           myResult = new GeomAdaptor_HCurve(aGACurve);
687 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
688         }
689       }
690       else {
691         myIsApprox = Standard_True;
692         myType     = GeomAbs_BSplineCurve;
693         PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
694 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
695         GeomAdaptor_Curve aGACurve(ApproxCurve);
696         myResult = new GeomAdaptor_HCurve(aGACurve);
697 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
698       }
699     }
700     break;
701   case GeomAbs_Parabola:
702     {
703       //     P(u) = O + (u*u)/(4*f) * Xc + u * Yc
704       // ==> Q(u) = f(P(u)) 
705       //          = f(O) + (u*u)/(4*f) * f(Xc) + u * f(Yc)
706
707       gp_Parab Parab  = myCurve->Parabola();
708       gp_Ax2   AxeRef = Parab.Position();
709       gp_Vec Xc = ProjectVec(myPlane,myDirection,gp_Vec(AxeRef.XDirection()));
710       gp_Vec Yc = ProjectVec(myPlane,myDirection,gp_Vec(AxeRef.YDirection()));
711
712       // fix for case when no one action is done. 28.03.2002
713       Standard_Boolean alocalIsDone = Standard_False;
714
715       if ( Abs( Yc.Magnitude() - 1.) < Precision::Confusion()) {
716         gp_Pnt P = ProjectPnt(myPlane,myDirection,AxeRef.Location());
717         if ( Xc.Magnitude() < Precision::Confusion()) {
718           myType = GeomAbs_Line;
719           aLine  = gp_Lin( P, gp_Dir(Yc));
720           
721           GeomLinePtr    = new Geom_Line(aLine) ;
722 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
723           GeomAdaptor_Curve aGACurve(GeomLinePtr);
724           myResult = new GeomAdaptor_HCurve(aGACurve);
725 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
726           alocalIsDone = Standard_True;
727         }
728         else if ( Xc.IsNormal(Yc,Precision::Angular())) {
729           myType = GeomAbs_Parabola;
730           Standard_Real F = Parab.Focal() / Xc.Magnitude();
731           gp_Parab Parab = gp_Parab( gp_Ax2(P,Xc^Yc,Xc), F);
732           Handle(Geom_Parabola) GeomParabolaPtr =
733             new Geom_Parabola(Parab) ;
734 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
735           GeomAdaptor_Curve aGACurve(GeomParabolaPtr);
736           myResult = new GeomAdaptor_HCurve(aGACurve);
737 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
738           alocalIsDone = Standard_True;
739         }
740       }
741       if (!alocalIsDone)/*else*/ {
742         myIsApprox = Standard_True;
743         myType     = GeomAbs_BSplineCurve;
744         PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
745 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
746         GeomAdaptor_Curve aGACurve(ApproxCurve);
747         myResult = new GeomAdaptor_HCurve(aGACurve);
748 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
749       }
750     }
751     break;
752   case GeomAbs_Hyperbola:
753     {
754       //     P(u) = O + R1 * Cosh(u) * Xc + R2 * Sinh(u) * Yc
755       // ==> Q(u) = f(P(u)) 
756       //          = f(O) + R1 * Cosh(u) * f(Xc) + R2 * Sinh(u) * f(Yc)
757
758       gp_Hypr Hypr  = myCurve->Hyperbola();
759       gp_Ax2 AxeRef = Hypr.Position();
760       gp_Vec Xc = ProjectVec(myPlane,myDirection,gp_Vec(AxeRef.XDirection()));
761       gp_Vec Yc = ProjectVec(myPlane,myDirection,gp_Vec(AxeRef.YDirection()));
762       gp_Pnt P  = ProjectPnt(myPlane,myDirection,AxeRef.Location());
763       Standard_Real R1 = Hypr.MajorRadius();
764       Standard_Real R2 = Hypr.MinorRadius();
765       gp_Dir Z = myPlane.Direction();
766
767       if ( Xc.Magnitude() < Precision::Confusion()) {
768         myType   = GeomAbs_Hyperbola;
769         gp_Dir X = gp_Dir(Yc) ^ Z;
770         Hypr   = gp_Hypr(gp_Ax2( P, Z, X), 0., R2 * Yc.Magnitude());
771         GeomHyperbolaPtr =
772           new Geom_Hyperbola(Hypr) ;
773 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
774         GeomAdaptor_Curve aGACurve(GeomHyperbolaPtr);
775         myResult = new GeomAdaptor_HCurve(aGACurve);
776 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
777       }
778       else if ( Yc.Magnitude() < Precision::Confusion()) {
779         myType = GeomAbs_Hyperbola;
780         Hypr = 
781            gp_Hypr(gp_Ax2(P, Z, gp_Dir(Xc)), R1 * Xc.Magnitude(), 0.);
782         GeomHyperbolaPtr =
783           new Geom_Hyperbola(Hypr) ;
784 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
785         GeomAdaptor_Curve aGACurve(GeomHyperbolaPtr);
786         myResult = new GeomAdaptor_HCurve(aGACurve);
787 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
788       }
789       else if ( Xc.IsNormal(Yc,Precision::Angular())) {
790         myType = GeomAbs_Hyperbola;
791         Hypr = gp_Hypr( gp_Ax2( P, gp_Dir( Xc ^ Yc), gp_Dir( Xc)),
792                        R1 * Xc.Magnitude(), R2 * Yc.Magnitude() );
793         GeomHyperbolaPtr =
794           new Geom_Hyperbola(Hypr) ;
795 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
796         GeomAdaptor_Curve aGACurve(GeomHyperbolaPtr);
797         myResult = new GeomAdaptor_HCurve(aGACurve);
798 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
799       }
800       else {
801         myIsApprox = Standard_True;
802         myType     = GeomAbs_BSplineCurve;
803         PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
804 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
805         GeomAdaptor_Curve aGACurve(ApproxCurve);
806         myResult = new GeomAdaptor_HCurve(aGACurve);
807 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
808       }
809     }
810     break;
811   case GeomAbs_BezierCurve:
812     {
813       Handle(Geom_BezierCurve) BezierCurvePtr =
814         myCurve->Bezier() ;
815       Standard_Integer NbPoles = 
816         BezierCurvePtr->NbPoles() ;
817       
818       Handle(Geom_BezierCurve) ProjCu = 
819         Handle(Geom_BezierCurve)::DownCast(BezierCurvePtr->Copy());
820
821       myIsApprox = Standard_False;
822       myType = Type;
823       for ( Standard_Integer i = 1; i <= NbPoles; i++) {
824         ProjCu->SetPole
825           (i,ProjectPnt(myPlane,myDirection,BezierCurvePtr->Pole(i)));
826       }
827       
828 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
829       GeomAdaptor_Curve aGACurve(ProjCu);
830       myResult = new GeomAdaptor_HCurve(aGACurve);
831 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
832     }
833     break ;
834   case GeomAbs_BSplineCurve:
835     {
836       Handle(Geom_BSplineCurve) BSplineCurvePtr =
837         myCurve->BSpline() ;
838       //
839       //    make a copy of the curve and projects its poles 
840       //
841       Handle(Geom_BSplineCurve) ProjectedBSplinePtr =
842         Handle(Geom_BSplineCurve)::DownCast(BSplineCurvePtr->Copy()) ;
843       
844       myIsApprox = Standard_False;
845       myType = Type;
846       for ( Standard_Integer i = 1; i <= BSplineCurvePtr->NbPoles(); i++) {
847         ProjectedBSplinePtr->SetPole
848           (i,ProjectPnt(myPlane,myDirection,BSplineCurvePtr->Pole(i)));
849       }
850       
851 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
852       GeomAdaptor_Curve aGACurve(ProjectedBSplinePtr);
853       myResult = new GeomAdaptor_HCurve(aGACurve);
854 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
855     }
856     break;
857   default:
858     {
859       myIsApprox = Standard_True;
860       myType     = GeomAbs_BSplineCurve;
861       PerformApprox(myCurve,myPlane,myDirection,ApproxCurve);
862 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:29 2002 Begin
863       GeomAdaptor_Curve aGACurve(ApproxCurve);
864       myResult = new GeomAdaptor_HCurve(aGACurve);
865 //  Modified by Sergey KHROMOV - Tue Jan 29 16:57:30 2002 End
866     }
867     break;
868   }
869 }
870
871 //=======================================================================
872 //function : GetPlane
873 //purpose  : 
874 //=======================================================================
875
876 const gp_Ax3& ProjLib_ProjectOnPlane::GetPlane() const 
877 {
878   return myPlane;
879 }
880
881 //=======================================================================
882 //function : GetDirection
883 //purpose  : 
884 //=======================================================================
885
886 const gp_Dir& ProjLib_ProjectOnPlane::GetDirection() const 
887 {
888   return myDirection;
889 }
890
891 //=======================================================================
892 //function : GetCurve
893 //purpose  : 
894 //=======================================================================
895
896 const Handle(Adaptor3d_HCurve)& ProjLib_ProjectOnPlane::GetCurve() const
897 {
898   return myCurve;
899 }
900
901
902 //=======================================================================
903 //function : FirstParameter
904 //purpose  : 
905 //=======================================================================
906
907 Standard_Real ProjLib_ProjectOnPlane::FirstParameter() const 
908 {
909   if ( myKeepParam || myIsApprox) 
910     return myCurve->FirstParameter();
911   else
912     return myFirstPar;
913 }
914
915
916 //=======================================================================
917 //function : LastParameter
918 //purpose  : 
919 //=======================================================================
920
921 Standard_Real ProjLib_ProjectOnPlane::LastParameter() const 
922 {
923   if ( myKeepParam || myIsApprox) 
924     return myCurve->LastParameter();
925   else
926     return myLastPar;
927 }
928
929
930 //=======================================================================
931 //function : Continuity
932 //purpose  : 
933 //=======================================================================
934
935 GeomAbs_Shape ProjLib_ProjectOnPlane::Continuity() const
936 {
937   return myCurve->Continuity() ;
938 }
939
940
941 //=======================================================================
942 //function : NbIntervals
943 //purpose  : 
944 //=======================================================================
945
946 Standard_Integer ProjLib_ProjectOnPlane::NbIntervals(const GeomAbs_Shape S) 
947 {
948   return myCurve->NbIntervals(S) ;
949 }
950
951
952 //=======================================================================
953 //function : Intervals
954 //purpose  : 
955 //=======================================================================
956
957 void ProjLib_ProjectOnPlane::Intervals(TColStd_Array1OfReal& T, 
958                                        const GeomAbs_Shape S) 
959 {
960   myCurve->Intervals(T,S) ;
961 }
962
963 //=======================================================================
964 //function : Trim
965 //purpose  : 
966 //=======================================================================
967
968 Handle(Adaptor3d_HCurve)  
969 ProjLib_ProjectOnPlane::Trim(const Standard_Real First,
970                              const Standard_Real Last,
971                              const Standard_Real Tolerance) const 
972 {
973   if (myType != GeomAbs_OtherCurve){
974     return myResult->Trim(First,Last,Tolerance) ;
975   }
976   else {
977     Standard_NotImplemented::Raise("");
978   }
979
980   // portage WNT
981   Handle(Adaptor3d_HCurve) dummy;
982   return dummy;
983 }
984
985   
986 //=======================================================================
987 //function : IsClosed
988 //purpose  : 
989 //=======================================================================
990
991 Standard_Boolean ProjLib_ProjectOnPlane::IsClosed() const
992 {
993  return myCurve->IsClosed() ;
994 }
995
996
997 //=======================================================================
998 //function : IsPeriodic
999 //purpose  : 
1000 //=======================================================================
1001
1002 Standard_Boolean ProjLib_ProjectOnPlane::IsPeriodic() const
1003 {
1004   if ( myIsApprox)
1005     return Standard_False;
1006   else 
1007     return myCurve->IsPeriodic();
1008 }
1009
1010
1011 //=======================================================================
1012 //function : Period
1013 //purpose  : 
1014 //=======================================================================
1015
1016 Standard_Real ProjLib_ProjectOnPlane::Period() const
1017 {
1018   if ( !IsPeriodic()) {
1019     Standard_NoSuchObject::Raise("ProjLib_ProjectOnPlane::Period");
1020   }
1021                                 
1022   if ( myIsApprox)
1023     return Standard_False;
1024   else 
1025     return myCurve->Period();
1026 }
1027
1028
1029 //=======================================================================
1030 //function : Value
1031 //purpose  : 
1032 //=======================================================================
1033
1034 gp_Pnt ProjLib_ProjectOnPlane::Value(const Standard_Real U) const 
1035 {
1036   if (myType != GeomAbs_OtherCurve) { 
1037     return myResult->Value(U);
1038   }
1039   else {
1040     return OnPlane_Value(U,
1041                          myCurve,
1042                          myPlane,
1043                          myDirection);
1044     
1045   }
1046
1047
1048
1049 //=======================================================================
1050 //function : D0
1051 //purpose  : 
1052 //=======================================================================
1053
1054 void ProjLib_ProjectOnPlane::D0(const Standard_Real U , gp_Pnt& P) const
1055 {
1056   if (myType != GeomAbs_OtherCurve) {
1057     myResult->D0(U,P) ;
1058   }
1059   else {
1060     P = OnPlane_Value(U,
1061                       myCurve,
1062                       myPlane,
1063                       myDirection);
1064   }
1065 }
1066
1067
1068 //=======================================================================
1069 //function : D1
1070 //purpose  : 
1071 //=======================================================================
1072
1073 void ProjLib_ProjectOnPlane::D1(const Standard_Real U,
1074                                       gp_Pnt&    P , 
1075                                       gp_Vec&    V ) const 
1076 {
1077   if (myType != GeomAbs_OtherCurve) {
1078     myResult->D1(U,P,V) ;
1079   }
1080   else {
1081     OnPlane_D1(U,
1082                P,
1083                V,
1084                myCurve,
1085                myPlane,
1086                myDirection);
1087   }
1088 }
1089
1090
1091 //=======================================================================
1092 //function : D2
1093 //purpose  : 
1094 //=======================================================================
1095
1096 void ProjLib_ProjectOnPlane::D2(const Standard_Real U, 
1097                                       gp_Pnt&     P, 
1098                                       gp_Vec&     V1, 
1099                                       gp_Vec&     V2) const 
1100 {
1101   if (myType != GeomAbs_OtherCurve)  {
1102     myResult->D2(U,P,V1,V2) ;
1103   }
1104   else {
1105     OnPlane_D2(U,
1106                P,
1107                V1,
1108                V2,
1109                myCurve,
1110                myPlane,
1111                myDirection);
1112   }
1113 }
1114
1115
1116 //=======================================================================
1117 //function : D3
1118 //purpose  : 
1119 //=======================================================================
1120
1121 void ProjLib_ProjectOnPlane::D3(const Standard_Real U, 
1122                                 gp_Pnt& P, 
1123                                 gp_Vec& V1, 
1124                                 gp_Vec& V2, 
1125                                 gp_Vec& V3) const 
1126 {
1127   if (myType != GeomAbs_OtherCurve)   {
1128     myResult->D3(U,P,V1,V2,V3) ;
1129   }
1130   else   {
1131     OnPlane_D3(U,
1132                P,
1133                V1,
1134                V2,
1135                V3,
1136                myCurve,
1137                myPlane,
1138                myDirection); 
1139   }
1140 }
1141
1142
1143 //=======================================================================
1144 //function : DN
1145 //purpose  : 
1146 //=======================================================================
1147
1148 gp_Vec ProjLib_ProjectOnPlane::DN(const Standard_Real U, 
1149                                   const Standard_Integer DerivativeRequest)
1150      const 
1151 {
1152   if (myType != GeomAbs_OtherCurve) {
1153     return myResult->DN(U,DerivativeRequest) ;
1154   }
1155   else {
1156     return OnPlane_DN(U,
1157                       DerivativeRequest,
1158                       myCurve,
1159                       myPlane,
1160                       myDirection); 
1161   }   
1162 }
1163
1164
1165 //=======================================================================
1166 //function : Resolution
1167 //purpose  : 
1168 //=======================================================================
1169
1170 Standard_Real ProjLib_ProjectOnPlane::Resolution
1171 (const Standard_Real Tolerance) const 
1172 {
1173   if (myType != GeomAbs_OtherCurve) {
1174     return myResult->Resolution(Tolerance) ;
1175   }
1176   else {
1177     return 0;
1178   }
1179 }
1180     
1181
1182 //=======================================================================
1183 //function : GetType
1184 //purpose  : 
1185 //=======================================================================
1186
1187 GeomAbs_CurveType ProjLib_ProjectOnPlane::GetType() const
1188 {
1189   return myType;
1190 }
1191
1192
1193 //=======================================================================
1194 //function : Line
1195 //purpose  : 
1196 //=======================================================================
1197
1198 gp_Lin ProjLib_ProjectOnPlane::Line() const
1199 {
1200   if (myType != GeomAbs_Line)
1201     Standard_NoSuchObject::Raise("ProjLib_ProjectOnPlane:Line");
1202
1203   return myResult->Line();
1204 }
1205
1206
1207 //=======================================================================
1208 //function : Circle
1209 //purpose  : 
1210 //=======================================================================
1211
1212 gp_Circ ProjLib_ProjectOnPlane::Circle() const
1213 {
1214   if (myType != GeomAbs_Circle)
1215     Standard_NoSuchObject::Raise("ProjLib_ProjectOnPlane:Circle");
1216
1217   return myResult->Circle();
1218 }
1219
1220
1221 //=======================================================================
1222 //function : Ellipse
1223 //purpose  : 
1224 //=======================================================================
1225
1226 gp_Elips ProjLib_ProjectOnPlane::Ellipse() const
1227 {
1228   if (myType != GeomAbs_Ellipse)
1229     Standard_NoSuchObject::Raise("ProjLib_ProjectOnPlane:Ellipse");
1230
1231   return myResult->Ellipse();
1232 }
1233
1234
1235 //=======================================================================
1236 //function : Hyperbola
1237 //purpose  : 
1238 //=======================================================================
1239
1240 gp_Hypr ProjLib_ProjectOnPlane::Hyperbola() const
1241 {
1242   if (myType != GeomAbs_Hyperbola)
1243     Standard_NoSuchObject::Raise("ProjLib_ProjectOnPlane:Hyperbola");
1244
1245   return myResult->Hyperbola() ;
1246 }
1247
1248
1249 //=======================================================================
1250 //function : Parabola
1251 //purpose  : 
1252 //=======================================================================
1253
1254 gp_Parab ProjLib_ProjectOnPlane::Parabola() const
1255 {
1256   if (myType != GeomAbs_Parabola)
1257     Standard_NoSuchObject::Raise("ProjLib_ProjectOnPlane:Parabola");
1258   
1259   return myResult->Parabola() ;
1260 }
1261
1262 //=======================================================================
1263 //function : Degree
1264 //purpose  : 
1265 //=======================================================================
1266
1267 Standard_Integer ProjLib_ProjectOnPlane::Degree() const
1268 {
1269   if ((GetType() != GeomAbs_BSplineCurve) &&
1270       (GetType() != GeomAbs_BezierCurve))
1271     Standard_NoSuchObject::Raise("ProjLib_ProjectOnPlane:Degree");
1272
1273   if ( myIsApprox)
1274     return myResult->Degree();
1275   else
1276     return myCurve->Degree();
1277 }
1278
1279 //=======================================================================
1280 //function : IsRational
1281 //purpose  : 
1282 //=======================================================================
1283
1284 Standard_Boolean ProjLib_ProjectOnPlane::IsRational() const 
1285 {
1286   if ((GetType() != GeomAbs_BSplineCurve) &&
1287       (GetType() != GeomAbs_BezierCurve))
1288     Standard_NoSuchObject::Raise("ProjLib_ProjectOnPlane:IsRational");
1289   
1290   if ( myIsApprox) 
1291     return myResult->IsRational();
1292   else
1293     return myCurve->IsRational();
1294 }
1295
1296 //=======================================================================
1297 //function : NbPoles
1298 //purpose  : 
1299 //=======================================================================
1300
1301 Standard_Integer ProjLib_ProjectOnPlane::NbPoles() const
1302 {
1303   if ((GetType() != GeomAbs_BSplineCurve) &&
1304       (GetType() != GeomAbs_BezierCurve))
1305     Standard_NoSuchObject::Raise("ProjLib_ProjectOnPlane:NbPoles");
1306   
1307   if ( myIsApprox)
1308     return myResult->NbPoles();
1309   else
1310     return myCurve->NbPoles();
1311 }
1312
1313 //=======================================================================
1314 //function : NbKnots
1315 //purpose  : 
1316 //=======================================================================
1317
1318 Standard_Integer ProjLib_ProjectOnPlane::NbKnots() const 
1319 {
1320   if ( GetType() != GeomAbs_BSplineCurve) 
1321     Standard_NoSuchObject::Raise("ProjLib_ProjectOnPlane:NbKnots");
1322   
1323   if ( myIsApprox) 
1324     return myResult->NbKnots();
1325   else
1326     return myCurve->NbKnots();
1327 }
1328
1329
1330 //=======================================================================
1331 //function : Bezier
1332 //purpose  : 
1333 //=======================================================================
1334
1335 Handle(Geom_BezierCurve)  ProjLib_ProjectOnPlane::Bezier() const
1336 {
1337   if (myType != GeomAbs_BezierCurve)
1338     Standard_NoSuchObject::Raise("ProjLib_ProjectOnPlane:Bezier");
1339
1340   return myResult->Bezier() ;
1341 }
1342
1343 //=======================================================================
1344 //function : Bezier
1345 //purpose  : 
1346 //=======================================================================
1347
1348 Handle(Geom_BSplineCurve)  ProjLib_ProjectOnPlane::BSpline() const
1349 {
1350   if (myType != GeomAbs_BSplineCurve)
1351     Standard_NoSuchObject::Raise("ProjLib_ProjectOnPlane:BSpline");
1352
1353   return myResult->BSpline() ;
1354 }
1355