0024023: Revamp the OCCT Handle -- general
[occt.git] / src / Geom / Geom_SurfaceOfRevolution.cxx
1 // Created on: 1993-03-10
2 // Created by: JCV
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Geom_SurfaceOfRevolution.ixx>
18 #include <BSplSLib.hxx>
19 #include <BSplCLib.hxx>
20 #include <Geom_Circle.hxx>
21 #include <gp.hxx>
22 #include <gp_Ax2d.hxx>
23 #include <gp_XYZ.hxx>
24 #include <gp_Lin.hxx>
25 #include <gp_Dir.hxx>
26 #include <gp_Pnt.hxx>
27 #include <Standard_ConstructionError.hxx>
28 #include <Standard_NotImplemented.hxx>
29 #include <Standard_RangeError.hxx>
30 #include <Geom_BSplineCurve.hxx>
31 #include <Precision.hxx>
32 #define  POLES    (poles->Array2())
33 #define  WEIGHTS  (weights->Array2())
34 #define  UKNOTS   (uknots->Array1())
35 #define  VKNOTS   (vknots->Array1())
36 #define  UFKNOTS  (ufknots->Array1())
37 #define  VFKNOTS  (vfknots->Array1())
38 #define  FMULTS   (BSplCLib::NoMults())
39
40 typedef Geom_SurfaceOfRevolution         SurfaceOfRevolution;
41 typedef Geom_Curve                       Curve;
42 typedef gp_Ax1  Ax1;
43 typedef gp_Ax2  Ax2;
44 typedef gp_Dir  Dir;
45 typedef gp_Lin  Lin;
46 typedef gp_Pnt  Pnt;
47 typedef gp_Trsf Trsf;
48 typedef gp_Vec  Vec;
49 typedef gp_XYZ  XYZ;
50
51 //=======================================================================
52 //function : LocateSide
53 //purpose  : This  method locates U parameter on basis BSpline curve 
54 //             and calls LocalDi  methods corresponding an  order of  
55 //             derivative and  position of the surface side contained      
56 //             the point relatively the curve knots.
57 //=======================================================================
58 static void LocateSide(const Standard_Real U,
59                        const Standard_Integer Side,
60                        const Handle(Geom_BSplineCurve)& BSplC,
61                        const Standard_Integer NDir,
62                        gp_Pnt& P,
63                        gp_Vec& D1U,
64                        gp_Vec& D2U,
65                        gp_Vec& D3U) 
66
67   Standard_Integer Ideb, Ifin;
68   Standard_Real ParTol=Precision::PConfusion()/2;
69   BSplC->Geom_BSplineCurve::LocateU(U,ParTol,Ideb,Ifin,Standard_False);   
70   if(Side == 1)
71     {
72       if(Ideb<1) Ideb=1;
73       if ((Ideb>=Ifin))  Ifin = Ideb+1;
74     }else
75       if(Side ==-1)
76         { 
77           if(Ifin > BSplC -> NbKnots()) Ifin=BSplC->NbKnots();
78           if ((Ideb>=Ifin))  Ideb = Ifin-1;
79         }
80    
81   switch(NDir) {
82   case 0 :  BSplC->Geom_BSplineCurve::LocalD0(U,Ideb,Ifin,P); break;
83   case 1 :  BSplC->Geom_BSplineCurve::LocalD1(U,Ideb,Ifin,P,D1U);  break;
84   case 2 :  BSplC->Geom_BSplineCurve::LocalD2(U,Ideb,Ifin,P,D1U,D2U); break;
85   case 3 :  BSplC->Geom_BSplineCurve::LocalD3(U,Ideb,Ifin,P,D1U,D2U,D3U); break;
86   }
87 }
88
89 //=======================================================================
90 //function : LocateSideN
91 //purpose  : This  method locates U parameter on basis BSpline curve 
92 //             and calls LocalDN  method corresponding  position of  surface side 
93 //             contained the point relatively the curve knots.  
94 //=======================================================================
95 static gp_Vec LocateSideN(const Standard_Real V,
96                           const Standard_Integer Side,
97                           const Handle(Geom_BSplineCurve)& BSplC,
98                           const Standard_Integer  Nv ) 
99
100   Standard_Integer Ideb, Ifin;
101   Standard_Real ParTol=Precision::PConfusion()/2;
102   BSplC->Geom_BSplineCurve::LocateU(V,ParTol,Ideb,Ifin,Standard_False);   
103   if(Side == 1)
104     {
105       if(Ideb<1) Ideb=1;
106       if ((Ideb>=Ifin))  Ifin = Ideb+1;
107     }else
108       if(Side ==-1)
109         { 
110           if(Ifin > BSplC -> NbKnots()) Ifin=BSplC->NbKnots();
111           if ((Ideb>=Ifin))  Ideb = Ifin-1;
112         }
113   return BSplC->Geom_BSplineCurve::LocalDN(V,Ideb,Ifin,Nv);
114 }
115
116
117
118
119 //=======================================================================
120 //function : Copy
121 //purpose  : 
122 //=======================================================================
123
124 Handle(Geom_Geometry) Geom_SurfaceOfRevolution::Copy () const {
125
126   return new Geom_SurfaceOfRevolution (basisCurve, Axis());
127 }
128
129
130 //=======================================================================
131 //function : Geom_SurfaceOfRevolution
132 //purpose  : 
133 //=======================================================================
134
135 Geom_SurfaceOfRevolution::Geom_SurfaceOfRevolution 
136   (const Handle(Geom_Curve)& C , 
137    const Ax1&           A1 ) : loc (A1.Location()) {
138
139   basisCurve = Handle(Geom_Curve)::DownCast(C->Copy());
140   direction  = A1.Direction();
141   smooth     = C->Continuity();
142 }
143
144
145 //=======================================================================
146 //function : UReverse
147 //purpose  : 
148 //=======================================================================
149
150 void Geom_SurfaceOfRevolution::UReverse () { 
151
152   direction.Reverse(); 
153 }
154
155
156 //=======================================================================
157 //function : UReversedParameter
158 //purpose  : 
159 //=======================================================================
160
161 Standard_Real Geom_SurfaceOfRevolution::UReversedParameter (const Standard_Real U) const {
162
163   return ( 2.*M_PI - U);
164 }
165
166
167 //=======================================================================
168 //function : VReverse
169 //purpose  : 
170 //=======================================================================
171
172 void Geom_SurfaceOfRevolution::VReverse () { 
173
174   basisCurve->Reverse(); 
175 }
176
177
178 //=======================================================================
179 //function : VReversedParameter
180 //purpose  : 
181 //=======================================================================
182
183 Standard_Real Geom_SurfaceOfRevolution::VReversedParameter (const Standard_Real V) const {
184
185   return basisCurve->ReversedParameter(V);
186 }
187
188
189 //=======================================================================
190 //function : Location
191 //purpose  : 
192 //=======================================================================
193
194 const gp_Pnt& Geom_SurfaceOfRevolution::Location () const { 
195
196   return loc; 
197 }
198
199 //=======================================================================
200 //function : IsUPeriodic
201 //purpose  : 
202 //=======================================================================
203
204 Standard_Boolean Geom_SurfaceOfRevolution::IsUPeriodic () const {
205
206   return Standard_True; 
207 }
208
209 //=======================================================================
210 //function : IsCNu
211 //purpose  : 
212 //=======================================================================
213
214 Standard_Boolean Geom_SurfaceOfRevolution::IsCNu (const Standard_Integer ) const  {
215
216   return Standard_True;
217 }
218
219 //=======================================================================
220 //function : Axis
221 //purpose  : 
222 //=======================================================================
223
224 Ax1 Geom_SurfaceOfRevolution::Axis () const  { 
225
226   return Ax1 (loc, direction); 
227 }
228
229 //=======================================================================
230 //function : IsCNv
231 //purpose  : 
232 //=======================================================================
233
234 Standard_Boolean Geom_SurfaceOfRevolution::IsCNv (const Standard_Integer N) const {
235
236   Standard_RangeError_Raise_if (N < 0, " ");
237   return basisCurve->IsCN(N);
238 }
239
240
241 //=======================================================================
242 //function : IsUClosed
243 //purpose  : 
244 //=======================================================================
245
246 Standard_Boolean Geom_SurfaceOfRevolution::IsUClosed () const { 
247
248   return Standard_True; 
249 }
250
251 //=======================================================================
252 //function : IsVClosed
253 //purpose  : 
254 //=======================================================================
255
256 Standard_Boolean Geom_SurfaceOfRevolution::IsVClosed () const 
257
258   return basisCurve->IsClosed();
259 }
260
261
262 //=======================================================================
263 //function : IsVPeriodic
264 //purpose  : 
265 //=======================================================================
266
267 Standard_Boolean Geom_SurfaceOfRevolution::IsVPeriodic () const { 
268
269   return basisCurve->IsPeriodic(); 
270 }
271
272
273 //=======================================================================
274 //function : SetAxis
275 //purpose  : 
276 //=======================================================================
277
278 void Geom_SurfaceOfRevolution::SetAxis (const Ax1& A1) {
279
280    direction = A1.Direction();
281    loc = A1.Location();
282 }
283
284
285 //=======================================================================
286 //function : SetDirection
287 //purpose  : 
288 //=======================================================================
289
290 void Geom_SurfaceOfRevolution::SetDirection (const Dir& V) {
291
292    direction = V;
293 }
294
295
296 //=======================================================================
297 //function : SetBasisCurve
298 //purpose  : 
299 //=======================================================================
300
301 void Geom_SurfaceOfRevolution::SetBasisCurve (const Handle(Geom_Curve)& C) {
302
303    basisCurve = Handle(Geom_Curve)::DownCast(C->Copy());
304    smooth     = C->Continuity();
305 }
306
307
308 //=======================================================================
309 //function : SetLocation
310 //purpose  : 
311 //=======================================================================
312
313 void Geom_SurfaceOfRevolution::SetLocation (const Pnt& P) {
314
315    loc = P;
316 }
317
318
319 //=======================================================================
320 //function : Bounds
321 //purpose  : 
322 //=======================================================================
323
324 void Geom_SurfaceOfRevolution::Bounds ( Standard_Real& U1, 
325                                         Standard_Real& U2, 
326                                         Standard_Real& V1, 
327                                         Standard_Real& V2 ) const {
328
329   U1 = 0.0; 
330   U2 = 2.0 * M_PI; 
331   V1 = basisCurve->FirstParameter();  
332   V2 = basisCurve->LastParameter();
333 }
334
335
336 //=======================================================================
337 //function : D0
338 //purpose  : 
339 //=======================================================================
340
341 void Geom_SurfaceOfRevolution::D0 
342   (const Standard_Real U, const Standard_Real V, Pnt& P) const {
343
344    // C origine sur l'axe de revolution
345    // Vdir vecteur unitaire definissant la direction de l'axe de revolution
346    // Q(v) point de parametre V sur la courbe de revolution
347    // OM (u,v) = OC + CQ * Cos(U) + (CQ.Vdir)(1-Cos(U)) * Vdir +
348    //            (Vdir^CQ)* Sin(U)
349
350
351    Pnt Pc = basisCurve->Value (V);                  //Q(v)
352    XYZ Q  = Pc.XYZ();                               //Q
353    XYZ C  = loc.XYZ();                              //C
354    Q.Subtract(C);                                   //CQ
355    XYZ Vdir     = direction.XYZ();                  //Vdir
356    XYZ VcrossCQ = Vdir.Crossed (Q);                 //Vdir^CQ
357    VcrossCQ.Multiply (Sin(U));                      //(Vdir^CQ)*Sin(U)
358    XYZ VdotCQ =
359      Vdir.Multiplied ((Vdir.Dot(Q))*(1.0 - Cos(U)));//(CQ.Vdir)(1-Cos(U))Vdir
360    VdotCQ.Add (VcrossCQ);                           //addition des composantes
361    Q.Multiply (Cos(U));
362    Q.Add (VdotCQ);
363    Q.Add (C);
364    P.SetXYZ(Q);
365 }
366
367
368 //=======================================================================
369 //function : D1
370 //purpose  : 
371 //=======================================================================
372
373 void Geom_SurfaceOfRevolution::D1 
374   (const Standard_Real U, const Standard_Real V, 
375          Pnt& P, 
376          Vec& D1U, Vec& D1V   ) const {
377
378    // C origine sur l'axe de revolution
379    // Vdir vecteur unitaire definissant la direction de l'axe de revolution
380    // Q(v) point de parametre V sur la courbe de revolution
381    // Q'(v) = DQ/DV
382    // OM (u,v) = OC + CQ * Cos(U) + (CQ.Vdir)(1-Cos(U)) * Vdir + 
383    //            (Vdir^CQ) * Sin(U)
384    // D1U_M(u,v) = - CQ * Sin(U) + (CQ.Vdir)(Sin(U)) * Vdir +
385    //              (Vdir^CQ) * Cos(U)
386    // D1V_M(u,v) = Q' * Cos(U) + (Q'.Vdir)(1-Cos(U)) * Vdir +
387    //              (Vdir^Q') * Sin(U)
388            
389       Pnt Pc;
390       Vec V1;
391       basisCurve->D1 (V, Pc, V1);
392       XYZ Q    = Pc.XYZ();                               //Q
393       XYZ DQv  = V1.XYZ();                               //Q'
394       XYZ C    = loc.XYZ();                              //C
395       XYZ Vdir = direction.XYZ();                        //Vdir
396       Q.Subtract(C);                                     //CQ
397       XYZ VcrossCQ  = Vdir.Crossed (Q);                  //Vdir^CQ
398       // If the point is placed on the axis of revolution then derivatives on U are undefined.
399       // Manually set them to zero.
400       if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
401         VcrossCQ.SetCoord(0.0, 0.0, 0.0);
402       XYZ VcrossDQv = Vdir.Crossed (DQv);                //(Vdir^Q')
403       XYZ VdotCQ    = Vdir.Multiplied (Vdir.Dot(Q));     //(Vdir.CQ)Vdir
404       XYZ VdotDQv   = Vdir.Multiplied (Vdir.Dot(DQv));   //(Vdir.Q')Vdir
405
406       VcrossDQv.Multiply (Sin(U));
407       VdotDQv.Multiply   (1.0 - Cos(U));
408       VdotDQv.Add        (VcrossDQv);
409       DQv.Multiply       (Cos(U));
410       DQv.Add            (VdotDQv);
411       D1V.SetXYZ         (DQv);
412
413       XYZ DQu = Q.Multiplied       (-Sin(U));
414       DQu.Add (VcrossCQ.Multiplied (Cos(U)));
415       DQu.Add (VdotCQ.Multiplied (Sin(U)));
416       D1U.SetXYZ (DQu);
417
418       Q.Multiply (Cos(U));
419       Q.Add      (C);
420       VcrossCQ.Multiply (Sin(U));
421       Q.Add             (VcrossCQ);   
422       VdotCQ.Multiply (1.0-Cos(U));
423       Q.Add           (VdotCQ);   
424       P.SetXYZ (Q);      
425     }
426
427 //=======================================================================
428 //function : D2
429 //purpose  : 
430 //=======================================================================
431
432 void Geom_SurfaceOfRevolution::D2 
433   (const Standard_Real   U, const Standard_Real V,
434          Pnt&   P, 
435          Vec& D1U, Vec& D1V, 
436          Vec& D2U, Vec& D2V, Vec& D2UV ) const {
437
438
439    // C origine sur l'axe de revolution
440    // V vecteur unitaire definissant la direction de l'axe de revolution
441    // Q(v) point de parametre V sur la courbe de revolution
442    // Q'(v) = D1Q/DV
443    // Q"(v) = D2Q/DV
444    // OM (u,v) = OC + CQ * Cos(U) + (CQ.Vdir)(1-Cos(U)) * Vdir +
445    //            (Vdir^CQ) * Sin(U)
446    // D1U_M(u,v) = - CQ * Sin(U) + (CQ.Vdir)(Sin(U)) * Vdir +
447    //              (Vdir^CQ) * Cos(U)
448    // D1V_M(u,v) = Q' * Cos(U) + (Q'.Vdir)(1-Cos(U)) * Vdir +
449    //              (Vdir^Q') * Sin(U)
450    // D2U_M(u,v) = -CQ * Cos(U) + (CQ.Vdir)(Cos(U)) * Vdir + 
451    //              (Vdir^CQ) * -(Sin(U))
452    // D2V_M(u,v) = Q" * Cos(U) + (Q".Vdir)(1-Cos(U)) * Vdir +
453    //              (Vdir^Q") * Sin(U)
454    // D2UV_M(u,v)= -Q' * Sin(U) + (Q'.Vdir)(Sin(U)) * Vdir +
455    //              (Vdir^Q') * Cos(U)
456
457
458       Pnt Pc;
459       Vec V1 , V2;
460       basisCurve->D2 (V, Pc, V1, V2);
461       XYZ Q     = Pc.XYZ();                                 //Q
462       XYZ D1Qv  = V1.XYZ();                                 //Q'
463       XYZ D2Qv  = V2.XYZ();                                 //Q"
464       XYZ C     = loc.XYZ();                                //C
465       XYZ Vdir  = direction.XYZ();                          //Vdir
466       Q.Subtract(C);                                        //CQ
467       XYZ VcrossCQ   = Vdir.Crossed (Q);                    //Vdir^CQ
468       // If the point is placed on the axis of revolution then derivatives on U are undefined.
469       // Manually set them to zero.
470       if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
471         VcrossCQ.SetCoord(0.0, 0.0, 0.0);
472       XYZ VcrossD1Qv = Vdir.Crossed (D1Qv);                 //(Vdir^Q')
473       XYZ VcrossD2Qv = Vdir.Crossed (D2Qv);                 //(Vdir^Q")
474       XYZ VdotCQ     = Vdir.Multiplied (Vdir.Dot(Q));       //(Vdir.CQ)Vdir
475       XYZ VdotD1Qv   = Vdir.Multiplied (Vdir.Dot(D1Qv));    //(Vdir.Q')Vdir
476       XYZ VdotD2Qv   = Vdir.Multiplied (Vdir.Dot(D2Qv));    //(Vdir.Q")Vdir
477
478       
479       XYZ D2Quv = D1Qv.Multiplied(-Sin(U));
480       D2Quv.Add (VcrossD1Qv.Multiplied (Cos(U)));      
481       D2Quv.Add (VdotD1Qv.Multiplied (Sin(U)));
482       D2UV.SetXYZ (D2Quv);
483
484       D1Qv.Multiply       (Cos(U));
485       VcrossD1Qv.Multiply (Sin(U));
486       VdotD1Qv.Multiply   (1.0 - Cos(U));
487       D1Qv.Add            (VcrossD1Qv);
488       D1Qv.Add            (VdotD1Qv);
489       D1V.SetXYZ          (D1Qv);
490
491       VcrossD2Qv.Multiply (Sin(U));
492       VdotD2Qv.Multiply (1.0 - Cos(U));
493       VdotD2Qv.Add (VcrossD2Qv);
494       D2Qv.Multiply (Cos(U));
495       D2Qv.Add (VdotD2Qv);
496       D2V.SetXYZ (D2Qv);
497
498       XYZ D1Qu = Q.Multiplied (-Sin(U));
499       D1Qu.Add (VcrossCQ.Multiplied (Cos(U)));
500       D1Qu.Add (VdotCQ.Multiplied (Sin(U)));
501       D1U.SetXYZ (D1Qu);
502
503       Q.Multiply (Cos(U));
504       VcrossCQ.Multiply (Sin(U));
505       Q.Add (VcrossCQ);   
506       XYZ D2Qu = Q.Multiplied(-1.0);
507       D2Qu.Add (VdotCQ.Multiplied (Cos(U)));
508       D2U.SetXYZ (D2Qu);
509       VdotCQ.Multiply (1.0-Cos(U));
510       Q.Add (VdotCQ);   
511       Q.Add (C);
512       P.SetXYZ (Q);      
513 }
514
515
516
517 //=======================================================================
518 //function : D3
519 //purpose  : 
520 //=======================================================================
521
522 void Geom_SurfaceOfRevolution::D3 
523   (const Standard_Real U, const Standard_Real V,
524          Pnt& P,
525          Vec& D1U, Vec& D1V, 
526          Vec& D2U, Vec& D2V, Vec& D2UV,
527          Vec& D3U, Vec& D3V, Vec& D3UUV, Vec& D3UVV ) const {
528
529    // C origine sur l'axe de revolution
530    // Vdir vecteur unitaire definissant la direction de l'axe de revolution
531    // Q(v) point de parametre V sur la courbe de revolution
532    // Q'(v) = D1Q/DV
533    // Q"(v) = D2Q/DV
534    // OM (u,v) = OC + CQ * Cos(u) + (CQ.Vdir)(1-Cos(u)) * Vdir +
535    //            (Vdir^CQ) * Sin(u)
536    // D1U_M(u,v) = - CQ * Sin(u) + (CQ.Vdir)(Sin(u)) * Vdir +
537    //              (Vdir^CQ) * Cos(u)
538    // D2U_M(u,v) = -CQ * Cos(u) + (CQ.Vdir)(Cos(u)) * Vdir +
539    //              (Vdir^CQ) * -Sin(u)
540    // D2UV_M(u,v)= -Q' * Sin(u) + (Q'.Vdir)(Sin(u)) * Vdir +
541    //              (Vdir^Q') * Cos(u)
542    // D3UUV_M(u,v) = -Q' * Cos(u) + (Q'.Vdir)(Cos(u)) * Vdir +
543    //                (Vdir^Q') * -Sin(u)
544    // D3U_M(u,v) = CQ * Sin(u) + (CQ.Vdir)(-Sin(u)) * Vdir +
545    //              (Vdir^CQ) * -Cos(u)
546    // D1V_M(u,v) = Q' * Cos(u) + (Q'.Vdir)(1-Cos(u)) * Vdir + 
547    //              (Vdir^Q') * Sin(u)
548    // D2V_M(u,v) = Q" * Cos(u) + (Q".Vdir)(1-Cos(u)) * Vdir +
549    //              (Vdir^Q") * Sin(u)
550    // D3UVV_M(u,v) = -Q" * Sin(u) + (Q".Vdir)(Sin(u)) * Vdir +
551    //                (Vdir^Q") * Cos(u)
552    // D3V_M(u,v) = Q'''* Cos(u) + (Q'''.Vdir)(1-Cos(u)) * Vdir +
553    //             (Vdir^Q''') * Sin(u)
554    
555
556       Pnt Pc;
557       Vec V1 , V2, V3;
558       basisCurve->D3 (V, Pc, V1, V2, V3);
559       XYZ Q     = Pc.XYZ();                                 //Q
560       XYZ D1Qv  = V1.XYZ();                                 //Q'
561       XYZ D2Qv  = V2.XYZ();                                 //Q"
562       XYZ D3Qv  = V3.XYZ();                                 //Q'''
563       XYZ C     = loc.XYZ();                                //C
564       XYZ Vdir  = direction.XYZ();                          //Vdir
565       Q.Subtract(C);                                        //CQ
566       XYZ VcrossCQ   = Vdir.Crossed (Q);                    //Vdir^CQ
567       // If the point is placed on the axis of revolution then derivatives on U are undefined.
568       // Manually set them to zero.
569       if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
570         VcrossCQ.SetCoord(0.0, 0.0, 0.0);
571       XYZ VcrossD1Qv = Vdir.Crossed (D1Qv);                 //(Vdir^Q')
572       XYZ VcrossD2Qv = Vdir.Crossed (D2Qv);                 //(Vdir^Q")
573       XYZ VcrossD3Qv = Vdir.Crossed (D3Qv);                 //(Vdir^Q''')
574       XYZ VdotCQ     = Vdir.Multiplied (Vdir.Dot(Q));       //(Vdir.CQ)Vdir
575       XYZ VdotD1Qv   = Vdir.Multiplied (Vdir.Dot(D1Qv));    //(Vdir.Q')Vdir
576       XYZ VdotD2Qv   = Vdir.Multiplied (Vdir.Dot(D2Qv));    //(Vdir.Q")Vdir
577       XYZ VdotD3Qv   = Vdir.Multiplied (Vdir.Dot(D3Qv));    //(Vdir.Q''')Vdir
578
579       XYZ D3Quuv = D1Qv.Multiplied (-Cos(U));
580       D3Quuv.Add (VcrossD1Qv.Multiplied (-Sin(U)));      
581       D3Quuv.Add (VdotD1Qv.Multiplied (Cos(U)));
582       D3UUV.SetXYZ (D3Quuv);
583
584       XYZ D2Quv = D1Qv.Multiplied (-Sin(U));
585       D2Quv.Add (VcrossD1Qv.Multiplied (Cos(U)));      
586       D2Quv.Add (VdotD1Qv.Multiplied (Sin(U)));
587       D2UV.SetXYZ (D2Quv);
588
589       D1Qv.Multiply (Cos(U));
590       VcrossD1Qv.Multiply (Sin(U));
591       VdotD1Qv.Multiply (1.0 - Cos(U));
592       D1Qv.Add (VcrossD1Qv);
593       D1Qv.Add (VdotD1Qv);
594       D1V.SetXYZ (D1Qv);
595
596       XYZ D3Qvvu = D2Qv.Multiplied (-Sin(U));
597       D3Qvvu.Add (VcrossD2Qv.Multiplied (Cos(U)));
598       D3Qvvu.Add (VdotD2Qv.Multiplied (Sin(U)));
599       D3UVV.SetXYZ (D3Qvvu);
600       
601       VcrossD2Qv.Multiply (Sin(U));
602       VdotD2Qv.Multiply (1.0 - Cos(U));
603       VdotD2Qv.Add (VcrossD2Qv);
604       D2Qv.Multiply (Cos(U));
605       D2Qv.Add (VdotD2Qv);
606       D2V.SetXYZ (D2Qv);
607
608       VcrossD3Qv.Multiply (Sin(U));
609       VdotD3Qv.Multiply (1.0 - Cos(U));
610       VdotD3Qv.Add (VcrossD2Qv);
611       D3Qv.Multiply (Cos(U));
612       D3Qv.Add (VdotD3Qv);
613       D3V.SetXYZ (D3Qv);
614
615       XYZ D1Qu = Q.Multiplied (- Sin(U));
616       D1Qu.Add (VcrossCQ.Multiplied (Cos(U)));
617       XYZ D3Qu = D1Qu.Multiplied (-1.0);
618       D1Qu.Add (VdotCQ.Multiplied (Sin(U)));
619       D3Qu.Add (VdotCQ.Multiplied (-Sin(U)));
620       D1U.SetXYZ (D1Qu);
621       D3U.SetXYZ (D3Qu);
622
623       Q.Multiply (Cos(U));
624       VcrossCQ.Multiply (Sin(U));
625       Q.Add (VcrossCQ);   
626       XYZ D2Qu = Q.Multiplied(-1.0);
627       D2Qu.Add (VdotCQ.Multiplied (Cos(U)));
628       D2U.SetXYZ (D2Qu);
629       VdotCQ.Multiply (1.0-Cos(U));
630       Q.Add (VdotCQ);   
631       Q.Add (C);
632       P.SetXYZ (Q);      
633 }
634
635
636 //=======================================================================
637 //function : DN
638 //purpose  : 
639 //=======================================================================
640
641 Vec Geom_SurfaceOfRevolution::DN (const Standard_Real    U , const Standard_Real    V, 
642                                   const Standard_Integer Nu, const Standard_Integer Nv) const {
643
644    Standard_RangeError_Raise_if (Nu + Nv < 1 || Nu < 0 || Nv < 0, " ");
645    if (Nu == 0) {
646      XYZ Vn = (basisCurve->DN (V, Nv)).XYZ();
647      XYZ Vdir = direction.XYZ();
648      XYZ VDot = Vdir.Multiplied (Vn.Dot (Vdir));
649      VDot.Multiply (1-Cos(U));
650      XYZ VCross = Vdir.Crossed (Vn);
651      VCross.Multiply (Sin(U));
652      Vn.Multiply (Cos(U));
653      Vn.Add (VDot);
654      Vn.Add (VCross);     
655      return Vec (Vn);
656    }
657    else if (Nv == 0) {
658      XYZ CQ = (basisCurve->Value (V)).XYZ() - loc.XYZ();
659      XYZ Vdir = direction.XYZ();
660      XYZ VDot = Vdir.Multiplied (CQ.Dot (Vdir));
661      XYZ VCross = Vdir.Crossed (CQ);
662      if ((Nu + 6) % 4 == 0) {
663        CQ.Multiply (-Cos (U));
664        VDot.Multiply (Cos(U));
665        VCross.Multiply (-Sin(U));
666      }
667      else if ((Nu + 5) % 4 == 0) {
668        CQ.Multiply (Sin (U));
669        VDot.Multiply (-Sin(U));
670        VCross.Multiply (-Cos(U));
671      }
672      else if ((Nu+3) % 4 == 0) {
673        CQ.Multiply (-Sin (U));
674        VDot.Multiply (+Sin(U));
675        VCross.Multiply (Cos(U));
676      }
677      else if (Nu+4 % 4 == 0) {
678        CQ.Multiply (Cos (U));
679        VDot.Multiply (-Cos(U));
680        VCross.Multiply (Sin(U));
681      }
682      CQ.Add (VDot);
683      CQ.Add (VCross);
684      return Vec (CQ);
685    }
686    else {
687      XYZ Vn = (basisCurve->DN (V, Nv)).XYZ();
688      XYZ Vdir = direction.XYZ();
689      XYZ VDot = Vdir.Multiplied (Vn.Dot (Vdir));
690      XYZ VCross = Vdir.Crossed (Vn);
691      if ((Nu + 6) % 4 == 0) {
692        Vn.Multiply (-Cos (U));
693        VDot.Multiply (Cos(U));
694        VCross.Multiply (-Sin(U));
695      }
696      else if ((Nu + 5) % 4 == 0) {
697        Vn.Multiply (Sin (U));
698        VDot.Multiply (-Sin(U));
699        VCross.Multiply (-Cos(U));
700      }
701      else if ((Nu+3) % 4 == 0) {
702        Vn.Multiply (-Sin (U));
703        VDot.Multiply (+Sin(U));
704        VCross.Multiply (Cos(U));
705      }
706      else if (Nu+4 % 4 == 0) {
707        Vn.Multiply (Cos (U));
708        VDot.Multiply (-Cos(U));
709        VCross.Multiply (Sin(U));
710      }
711      Vn.Add (VDot);
712      Vn.Add (VCross);     
713      return Vec (Vn);
714    }
715 }
716
717 //=======================================================================
718 //function : LocalD0
719 //purpose  : 
720 //=======================================================================
721
722 void Geom_SurfaceOfRevolution::LocalD0 (const Standard_Real    U,
723                                    const Standard_Real    V, 
724                                    const Standard_Integer VSide,
725                                          gp_Pnt&          P     )  const
726 {
727   if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
728     { 
729       gp_Vec D1V,D2V,D3V;
730       Handle( Geom_BSplineCurve) BSplC;
731       BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
732
733           LocateSide(V,VSide,BSplC,0,P,D1V,D2V,D3V);
734           XYZ Q  = P.XYZ();                               //Q
735           XYZ C  = loc.XYZ();                              //C
736           Q.Subtract(C);                                   //CQ
737           XYZ Vdir     = direction.XYZ();                  //Vdir
738           XYZ VcrossCQ = Vdir.Crossed (Q);                 //Vdir^CQ
739           VcrossCQ.Multiply (Sin(U));                      //(Vdir^CQ)*Sin(U)
740           XYZ VdotCQ =
741             Vdir.Multiplied ((Vdir.Dot(Q))*(1.0 - Cos(U)));//(CQ.Vdir)(1-Cos(U))Vdir
742           VdotCQ.Add (VcrossCQ);                           //addition des composantes
743           Q.Multiply (Cos(U));
744           Q.Add (VdotCQ);
745           Q.Add (C);
746           P.SetXYZ(Q);
747     }
748   else  D0(U,V,P);
749 }
750
751 //=======================================================================
752 //function : LocalD1
753 //purpose  : 
754 //=======================================================================
755
756 void Geom_SurfaceOfRevolution::LocalD1 (const Standard_Real    U, 
757                                    const Standard_Real    V,
758                                    const Standard_Integer VSide, 
759                                          gp_Pnt&          P,
760                                          gp_Vec&          D1U, 
761                                          gp_Vec&          D1V)     const
762 {
763  if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
764    {
765      Handle( Geom_BSplineCurve) BSplC;
766      BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
767          Vec D2V,D3V; 
768          Vec V1; 
769          LocateSide(V,VSide,BSplC,1,P,V1,D2V,D3V);
770          XYZ Q    = P.XYZ();                               //Q
771          XYZ DQv  = V1.XYZ();                               //Q'
772          XYZ C    = loc.XYZ();                              //C
773          XYZ Vdir = direction.XYZ();                        //Vdir
774          Q.Subtract(C);                                     //CQ
775          XYZ VcrossCQ  = Vdir.Crossed (Q);                  //Vdir^CQ
776       // If the point is placed on the axis of revolution then derivatives on U are undefined.
777       // Manually set them to zero.
778       if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
779         VcrossCQ.SetCoord(0.0, 0.0, 0.0);
780
781          XYZ VcrossDQv = Vdir.Crossed (DQv);                //(Vdir^Q')
782          XYZ VdotCQ    = Vdir.Multiplied (Vdir.Dot(Q));     //(Vdir.CQ)Vdir
783          XYZ VdotDQv   = Vdir.Multiplied (Vdir.Dot(DQv));   //(Vdir.Q')Vdir
784          
785          VcrossDQv.Multiply (Sin(U));
786          VdotDQv.Multiply   (1.0 - Cos(U));
787          VdotDQv.Add        (VcrossDQv);
788          DQv.Multiply       (Cos(U));
789          DQv.Add            (VdotDQv);
790          D1V.SetXYZ         (DQv);
791          
792          XYZ DQu = Q.Multiplied       (-Sin(U));
793          DQu.Add (VcrossCQ.Multiplied (Cos(U)));
794          DQu.Add (VdotCQ.Multiplied (Sin(U)));
795          D1U.SetXYZ (DQu);
796          
797          Q.Multiply (Cos(U));
798          Q.Add      (C);
799          VcrossCQ.Multiply (Sin(U));
800          Q.Add             (VcrossCQ);   
801          VdotCQ.Multiply (1.0-Cos(U));
802          Q.Add           (VdotCQ);   
803          P.SetXYZ (Q);  
804    }else 
805      D1(U,V,P,D1U,D1V);
806 }
807
808 //=======================================================================
809 //function : LocalD2
810 //purpose  : 
811 //=======================================================================
812
813 void Geom_SurfaceOfRevolution::LocalD2 (const Standard_Real    U,
814                                    const Standard_Real    V,
815                                    const Standard_Integer VSide,
816                                          gp_Pnt&          P,
817                                          gp_Vec&          D1U,
818                                          gp_Vec&          D1V,
819                                          gp_Vec&          D2U,
820                                          gp_Vec&          D2V,
821                                          gp_Vec&          D2UV) const
822 {
823   if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
824     {
825       Handle( Geom_BSplineCurve) BSplC;
826       BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
827           Vec d3v;
828           LocateSide(V,VSide,BSplC,2,P,D1V,D2V,d3v);
829           XYZ Q     = P.XYZ();                                   //Q
830           XYZ D1Qv  = D1V.XYZ();                                 //Q'
831           XYZ D2Qv  = D2V.XYZ();                                 //Q"
832           XYZ C     = loc.XYZ();                                 //C
833           XYZ Vdir  = direction.XYZ();                           //Vdir
834           Q.Subtract(C);                                         //CQ
835           XYZ VcrossCQ   = Vdir.Crossed (Q);                     //Vdir^CQ
836       // If the point is placed on the axis of revolution then derivatives on U are undefined.
837       // Manually set them to zero.
838       if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
839         VcrossCQ.SetCoord(0.0, 0.0, 0.0);
840
841           XYZ VcrossD1Qv = Vdir.Crossed (D1Qv);                  //(Vdir^Q')
842           XYZ VcrossD2Qv = Vdir.Crossed (D2Qv);                  //(Vdir^Q")
843           XYZ VdotCQ     = Vdir.Multiplied (Vdir.Dot(Q));        //(Vdir.CQ)Vdir
844           XYZ VdotD1Qv   = Vdir.Multiplied (Vdir.Dot(D1Qv));     //(Vdir.Q')Vdir
845           XYZ VdotD2Qv   = Vdir.Multiplied (Vdir.Dot(D2Qv));     //(Vdir.Q")Vdir
846           
847           
848           XYZ D2Quv = D1Qv.Multiplied(-Sin(U));
849           D2Quv.Add (VcrossD1Qv.Multiplied (Cos(U)));      
850           D2Quv.Add (VdotD1Qv.Multiplied (Sin(U)));
851           D2UV.SetXYZ (D2Quv);
852           
853           D1Qv.Multiply       (Cos(U));
854           VcrossD1Qv.Multiply (Sin(U));
855           VdotD1Qv.Multiply   (1.0 - Cos(U));
856           D1Qv.Add            (VcrossD1Qv);
857           D1Qv.Add            (VdotD1Qv);
858           D1V.SetXYZ          (D1Qv);
859           
860           VcrossD2Qv.Multiply (Sin(U));
861           VdotD2Qv.Multiply (1.0 - Cos(U));
862           VdotD2Qv.Add (VcrossD2Qv);
863           D2Qv.Multiply (Cos(U));
864           D2Qv.Add (VdotD2Qv);
865           D2V.SetXYZ (D2Qv);
866
867           XYZ D1Qu = Q.Multiplied (-Sin(U));
868           D1Qu.Add (VcrossCQ.Multiplied (Cos(U)));
869           D1Qu.Add (VdotCQ.Multiplied (Sin(U)));
870           D1U.SetXYZ (D1Qu);
871           
872           Q.Multiply (Cos(U));
873           VcrossCQ.Multiply (Sin(U));
874           Q.Add (VcrossCQ);   
875           XYZ D2Qu = Q.Multiplied(-1.0);
876           D2Qu.Add (VdotCQ.Multiplied (Cos(U)));
877           D2U.SetXYZ (D2Qu);
878           VdotCQ.Multiply (1.0-Cos(U));
879           Q.Add (VdotCQ);   
880           Q.Add (C);
881           P.SetXYZ (Q);      
882     } 
883   else
884     D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
885 }
886 //=======================================================================
887 //function : LocalD3
888 //purpose  : 
889 //=======================================================================
890
891 void Geom_SurfaceOfRevolution::LocalD3 (const Standard_Real    U, 
892                                    const Standard_Real    V,
893                                    const Standard_Integer VSide, 
894                                          gp_Pnt&          P,
895                                          gp_Vec&          D1U,
896                                          gp_Vec&          D1V, 
897                                          gp_Vec&          D2U, 
898                                          gp_Vec&          D2V, 
899                                          gp_Vec&          D2UV, 
900                                          gp_Vec&          D3U,
901                                          gp_Vec&          D3V,
902                                          gp_Vec&          D3UUV,
903                                          gp_Vec&          D3UVV) const
904 {
905   if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
906     {
907       Handle( Geom_BSplineCurve) BSplC;
908       BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
909
910           LocateSide(V,VSide,BSplC,3,P,D1V,D2V,D3V);
911           XYZ Q     = P.XYZ();                                   //Q
912           XYZ D1Qv  = D1V.XYZ();                                 //Q'
913           XYZ D2Qv  = D2V.XYZ();                                 //Q"
914           XYZ D3Qv  = D3V.XYZ();                                 //Q'''
915           XYZ C     = loc.XYZ();                                //C
916           XYZ Vdir  = direction.XYZ();                          //Vdir
917           Q.Subtract(C);                                        //CQ
918           XYZ VcrossCQ   = Vdir.Crossed (Q);                    //Vdir^CQ
919       // If the point is placed on the axis of revolution then derivatives on U are undefined.
920       // Manually set them to zero.
921       if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
922         VcrossCQ.SetCoord(0.0, 0.0, 0.0);
923
924           XYZ VcrossD1Qv = Vdir.Crossed (D1Qv);                 //(Vdir^Q')
925           XYZ VcrossD2Qv = Vdir.Crossed (D2Qv);                 //(Vdir^Q")
926           XYZ VcrossD3Qv = Vdir.Crossed (D3Qv);                 //(Vdir^Q''')
927           XYZ VdotCQ     = Vdir.Multiplied (Vdir.Dot(Q));       //(Vdir.CQ)Vdir
928           XYZ VdotD1Qv   = Vdir.Multiplied (Vdir.Dot(D1Qv));    //(Vdir.Q')Vdir
929           XYZ VdotD2Qv   = Vdir.Multiplied (Vdir.Dot(D2Qv));    //(Vdir.Q")Vdir
930           XYZ VdotD3Qv   = Vdir.Multiplied (Vdir.Dot(D3Qv));    //(Vdir.Q''')Vdir
931
932           XYZ D3Quuv = D1Qv.Multiplied (-Cos(U));
933           D3Quuv.Add (VcrossD1Qv.Multiplied (-Sin(U)));      
934           D3Quuv.Add (VdotD1Qv.Multiplied (Cos(U)));
935           D3UUV.SetXYZ (D3Quuv);
936           
937           XYZ D2Quv = D1Qv.Multiplied (-Sin(U));
938           D2Quv.Add (VcrossD1Qv.Multiplied (Cos(U)));      
939           D2Quv.Add (VdotD1Qv.Multiplied (Sin(U)));
940           D2UV.SetXYZ (D2Quv);
941           
942           D1Qv.Multiply (Cos(U));
943           VcrossD1Qv.Multiply (Sin(U));
944           VdotD1Qv.Multiply (1.0 - Cos(U));
945           D1Qv.Add (VcrossD1Qv);
946           D1Qv.Add (VdotD1Qv);
947           D1V.SetXYZ (D1Qv);
948
949           XYZ D3Qvvu = D2Qv.Multiplied (-Sin(U));
950           D3Qvvu.Add (VcrossD2Qv.Multiplied (Cos(U)));
951           D3Qvvu.Add (VdotD2Qv.Multiplied (Sin(U)));
952           D3UVV.SetXYZ (D3Qvvu);
953           
954           VcrossD2Qv.Multiply (Sin(U));
955           VdotD2Qv.Multiply (1.0 - Cos(U));
956           VdotD2Qv.Add (VcrossD2Qv);
957           D2Qv.Multiply (Cos(U));
958           D2Qv.Add (VdotD2Qv);
959           D2V.SetXYZ (D2Qv);
960           
961           VcrossD3Qv.Multiply (Sin(U));
962           VdotD3Qv.Multiply (1.0 - Cos(U));
963           VdotD3Qv.Add (VcrossD2Qv);
964           D3Qv.Multiply (Cos(U));
965           D3Qv.Add (VdotD3Qv);
966           D3V.SetXYZ (D3Qv);
967           
968           XYZ D1Qu = Q.Multiplied (- Sin(U));
969           D1Qu.Add (VcrossCQ.Multiplied (Cos(U)));
970           XYZ D3Qu = D1Qu.Multiplied (-1.0);
971           D1Qu.Add (VdotCQ.Multiplied (Sin(U)));
972           D3Qu.Add (VdotCQ.Multiplied (-Sin(U)));
973           D1U.SetXYZ (D1Qu);
974           D3U.SetXYZ (D3Qu);
975           
976           Q.Multiply (Cos(U));
977           VcrossCQ.Multiply (Sin(U));
978           Q.Add (VcrossCQ);   
979           XYZ D2Qu = Q.Multiplied(-1.0);
980           D2Qu.Add (VdotCQ.Multiplied (Cos(U)));
981           D2U.SetXYZ (D2Qu);
982           VdotCQ.Multiply (1.0-Cos(U));
983           Q.Add (VdotCQ);   
984           Q.Add (C);
985           P.SetXYZ (Q); 
986     }
987   else
988     D3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
989 }
990 //=======================================================================
991 //function : LocalDN
992 //purpose  : 
993 //=======================================================================
994
995 gp_Vec Geom_SurfaceOfRevolution::LocalDN  (const Standard_Real    U, 
996                                       const Standard_Real    V,
997                                       const Standard_Integer VSide,
998                                       const Standard_Integer Nu,
999                                       const Standard_Integer Nv) const
1000 {
1001   Standard_RangeError_Raise_if (Nu + Nv < 1 || Nu < 0 || Nv < 0, " "); 
1002   XYZ Vn, CQ;
1003   if (Nu == 0) {
1004     if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
1005       {
1006         Handle( Geom_BSplineCurve) BSplC;
1007         BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);  
1008         Vn = LocateSideN(V,VSide,BSplC,Nv).XYZ();
1009       }else
1010         return DN(U,V,Nu,Nv);
1011     XYZ Vdir = direction.XYZ();
1012     XYZ VDot = Vdir.Multiplied (Vn.Dot (Vdir));
1013     VDot.Multiply (1-Cos(U));
1014     XYZ VCross = Vdir.Crossed (Vn);
1015     VCross.Multiply (Sin(U));
1016     Vn.Multiply (Cos(U));
1017     Vn.Add (VDot);
1018     Vn.Add (VCross);     
1019     return Vec (Vn);
1020   }
1021   
1022   else if (Nv == 0) {
1023     if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
1024       {
1025         Handle( Geom_BSplineCurve) BSplC;
1026         BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
1027         CQ = LocateSideN(V,VSide,BSplC,Nv).XYZ() - loc.XYZ();
1028       }else
1029         return DN(U,V,Nu,Nv);
1030     XYZ Vdir = direction.XYZ();
1031     XYZ VDot = Vdir.Multiplied (CQ.Dot (Vdir));
1032     XYZ VCross = Vdir.Crossed (CQ);
1033     if ((Nu + 6) % 4 == 0) {
1034       CQ.Multiply (-Cos (U));
1035       VDot.Multiply (Cos(U));
1036       VCross.Multiply (-Sin(U));
1037     }
1038     else if ((Nu + 5) % 4 == 0) {
1039       CQ.Multiply (Sin (U));
1040       VDot.Multiply (-Sin(U));
1041       VCross.Multiply (-Cos(U));
1042     }
1043     else if ((Nu+3) % 4 == 0) {
1044       CQ.Multiply (-Sin (U));
1045       VDot.Multiply (+Sin(U));
1046       VCross.Multiply (Cos(U));
1047     }
1048     else if (Nu+4 % 4 == 0) {
1049       CQ.Multiply (Cos (U));
1050       VDot.Multiply (-Cos(U));
1051       VCross.Multiply (Sin(U));
1052     }
1053     CQ.Add (VDot);
1054     CQ.Add (VCross);
1055     return Vec (CQ);
1056   }
1057   
1058   else {
1059     if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) 
1060       {
1061         Handle( Geom_BSplineCurve) BSplC;
1062         BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
1063         Vn = LocateSideN(V,VSide,BSplC,Nv).XYZ();
1064       }else 
1065         return DN(U,V,Nu,Nv);
1066     XYZ Vdir = direction.XYZ();
1067     XYZ VDot = Vdir.Multiplied (Vn.Dot (Vdir));
1068     XYZ VCross = Vdir.Crossed (Vn);
1069     if ((Nu + 6) % 4 == 0) {
1070       Vn.Multiply (-Cos (U));
1071       VDot.Multiply (Cos(U));
1072       VCross.Multiply (-Sin(U));
1073     }
1074     else if ((Nu + 5) % 4 == 0) {
1075       Vn.Multiply (Sin (U));
1076       VDot.Multiply (-Sin(U));
1077       VCross.Multiply (-Cos(U));
1078     }
1079     else if ((Nu+3) % 4 == 0) {
1080       Vn.Multiply (-Sin (U));
1081       VDot.Multiply (+Sin(U));
1082       VCross.Multiply (Cos(U));
1083     }
1084     else if (Nu+4 % 4 == 0) {
1085       Vn.Multiply (Cos (U));
1086       VDot.Multiply (-Cos(U));
1087       VCross.Multiply (Sin(U));
1088     }
1089     Vn.Add (VDot);
1090     Vn.Add (VCross);     
1091     return Vec (Vn);
1092   }
1093 }
1094
1095 //=======================================================================
1096 //function : ReferencePlane
1097 //purpose  : 
1098 //=======================================================================
1099
1100 Ax2 Geom_SurfaceOfRevolution::ReferencePlane() const {
1101         
1102    Standard_NotImplemented::Raise ();
1103    return gp_Ax2();
1104 }
1105
1106
1107 //=======================================================================
1108 //function : UIso
1109 //purpose  : 
1110 //=======================================================================
1111
1112 Handle(Geom_Curve) Geom_SurfaceOfRevolution::UIso (const Standard_Real U) const {
1113
1114    Handle(Geom_Curve) C = Handle(Geom_Curve)::DownCast(basisCurve->Copy());
1115    Ax1 RotAxis = Ax1 (loc, direction);
1116    C->Rotate (RotAxis, U);
1117    return C;
1118 }
1119
1120
1121 //=======================================================================
1122 //function : VIso
1123 //purpose  : 
1124 //=======================================================================
1125
1126 Handle(Geom_Curve) Geom_SurfaceOfRevolution::VIso (const Standard_Real V) const {
1127
1128   Handle(Geom_Circle) Circ;
1129   Pnt Pc = basisCurve->Value (V);
1130   gp_Lin L1(loc,direction);
1131   Standard_Real Rad= L1.Distance(Pc);
1132
1133   Ax2 Rep ;
1134   if ( Rad > gp::Resolution()) { 
1135     XYZ P  = Pc.XYZ(); 
1136     XYZ C;
1137     C.SetLinearForm((P-loc.XYZ()).Dot(direction.XYZ()), 
1138                     direction.XYZ(), loc.XYZ() );
1139     P = P-C;
1140     if(P.Modulus() > gp::Resolution()) {
1141       gp_Dir D = P.Normalized();
1142       Rep = gp_Ax2(C, direction, D);
1143     }
1144     else 
1145       Rep = gp_Ax2(C, direction);
1146   }
1147   else
1148     Rep = gp_Ax2(Pc, direction);
1149
1150   Circ   = new Geom_Circle (Rep, Rad);
1151   return Circ;
1152 }
1153
1154
1155 //=======================================================================
1156 //function : Transform
1157 //purpose  : 
1158 //=======================================================================
1159
1160 void Geom_SurfaceOfRevolution::Transform (const Trsf& T) {
1161
1162   loc.Transform (T);
1163   direction.Transform (T);
1164   basisCurve->Transform (T);
1165   if(T.ScaleFactor()*T.HVectorialPart().Determinant() < 0.) UReverse(); 
1166 }
1167
1168 //=======================================================================
1169 //function : TransformParameters
1170 //purpose  : 
1171 //=======================================================================
1172
1173 void Geom_SurfaceOfRevolution::TransformParameters(Standard_Real& ,
1174                                                    Standard_Real& V,
1175                                                    const gp_Trsf& T) 
1176 const
1177 {
1178   V = basisCurve->TransformedParameter(V,T);
1179 }
1180
1181 //=======================================================================
1182 //function : ParametricTransformation
1183 //purpose  : 
1184 //=======================================================================
1185
1186 gp_GTrsf2d Geom_SurfaceOfRevolution::ParametricTransformation
1187 (const gp_Trsf& T) const
1188 {
1189   gp_GTrsf2d T2;
1190   gp_Ax2d Axis(gp::Origin2d(),gp::DX2d());
1191   T2.SetAffinity(Axis, basisCurve->ParametricTransformation(T));
1192   return T2;
1193 }
1194