1 // Created on: 1993-03-10
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <BSplCLib.hxx>
19 #include <BSplSLib.hxx>
20 #include <Geom_BSplineCurve.hxx>
21 #include <Geom_Circle.hxx>
22 #include <Geom_Curve.hxx>
23 #include <Geom_Geometry.hxx>
24 #include <Geom_SurfaceOfRevolution.hxx>
25 #include <Geom_UndefinedDerivative.hxx>
29 #include <gp_Ax2d.hxx>
31 #include <gp_GTrsf2d.hxx>
34 #include <gp_Trsf.hxx>
37 #include <Precision.hxx>
38 #include <Standard_ConstructionError.hxx>
39 #include <Standard_NotImplemented.hxx>
40 #include <Standard_RangeError.hxx>
41 #include <Standard_Type.hxx>
43 #define POLES (poles->Array2())
44 #define WEIGHTS (weights->Array2())
45 #define UKNOTS (uknots->Array1())
46 #define VKNOTS (vknots->Array1())
47 #define UFKNOTS (ufknots->Array1())
48 #define VFKNOTS (vfknots->Array1())
49 #define FMULTS (BSplCLib::NoMults())
51 typedef Geom_SurfaceOfRevolution SurfaceOfRevolution;
52 typedef Geom_Curve Curve;
62 //=======================================================================
63 //function : LocateSide
64 //purpose : This method locates U parameter on basis BSpline curve
65 // and calls LocalDi methods corresponding an order of
66 // derivative and position of the surface side contained
67 // the point relatively the curve knots.
68 //=======================================================================
69 static void LocateSide(const Standard_Real U,
70 const Standard_Integer Side,
71 const Handle(Geom_BSplineCurve)& BSplC,
72 const Standard_Integer NDir,
78 Standard_Integer Ideb, Ifin;
79 Standard_Real ParTol=Precision::PConfusion()/2;
80 BSplC->Geom_BSplineCurve::LocateU(U,ParTol,Ideb,Ifin,Standard_False);
84 if ((Ideb>=Ifin)) Ifin = Ideb+1;
88 if(Ifin > BSplC -> NbKnots()) Ifin=BSplC->NbKnots();
89 if ((Ideb>=Ifin)) Ideb = Ifin-1;
93 case 0 : BSplC->Geom_BSplineCurve::LocalD0(U,Ideb,Ifin,P); break;
94 case 1 : BSplC->Geom_BSplineCurve::LocalD1(U,Ideb,Ifin,P,D1U); break;
95 case 2 : BSplC->Geom_BSplineCurve::LocalD2(U,Ideb,Ifin,P,D1U,D2U); break;
96 case 3 : BSplC->Geom_BSplineCurve::LocalD3(U,Ideb,Ifin,P,D1U,D2U,D3U); break;
100 //=======================================================================
101 //function : LocateSideN
102 //purpose : This method locates U parameter on basis BSpline curve
103 // and calls LocalDN method corresponding position of surface side
104 // contained the point relatively the curve knots.
105 //=======================================================================
106 static gp_Vec LocateSideN(const Standard_Real V,
107 const Standard_Integer Side,
108 const Handle(Geom_BSplineCurve)& BSplC,
109 const Standard_Integer Nv )
111 Standard_Integer Ideb, Ifin;
112 Standard_Real ParTol=Precision::PConfusion()/2;
113 BSplC->Geom_BSplineCurve::LocateU(V,ParTol,Ideb,Ifin,Standard_False);
117 if ((Ideb>=Ifin)) Ifin = Ideb+1;
121 if(Ifin > BSplC -> NbKnots()) Ifin=BSplC->NbKnots();
122 if ((Ideb>=Ifin)) Ideb = Ifin-1;
124 return BSplC->Geom_BSplineCurve::LocalDN(V,Ideb,Ifin,Nv);
130 //=======================================================================
133 //=======================================================================
135 Handle(Geom_Geometry) Geom_SurfaceOfRevolution::Copy () const {
137 return new Geom_SurfaceOfRevolution (basisCurve, Axis());
141 //=======================================================================
142 //function : Geom_SurfaceOfRevolution
144 //=======================================================================
146 Geom_SurfaceOfRevolution::Geom_SurfaceOfRevolution
147 (const Handle(Geom_Curve)& C ,
148 const Ax1& A1 ) : loc (A1.Location()) {
150 basisCurve = Handle(Geom_Curve)::DownCast(C->Copy());
151 direction = A1.Direction();
152 smooth = C->Continuity();
156 //=======================================================================
157 //function : UReverse
159 //=======================================================================
161 void Geom_SurfaceOfRevolution::UReverse () {
167 //=======================================================================
168 //function : UReversedParameter
170 //=======================================================================
172 Standard_Real Geom_SurfaceOfRevolution::UReversedParameter (const Standard_Real U) const {
174 return ( 2.*M_PI - U);
178 //=======================================================================
179 //function : VReverse
181 //=======================================================================
183 void Geom_SurfaceOfRevolution::VReverse () {
185 basisCurve->Reverse();
189 //=======================================================================
190 //function : VReversedParameter
192 //=======================================================================
194 Standard_Real Geom_SurfaceOfRevolution::VReversedParameter (const Standard_Real V) const {
196 return basisCurve->ReversedParameter(V);
200 //=======================================================================
201 //function : Location
203 //=======================================================================
205 const gp_Pnt& Geom_SurfaceOfRevolution::Location () const {
210 //=======================================================================
211 //function : IsUPeriodic
213 //=======================================================================
215 Standard_Boolean Geom_SurfaceOfRevolution::IsUPeriodic () const {
217 return Standard_True;
220 //=======================================================================
223 //=======================================================================
225 Standard_Boolean Geom_SurfaceOfRevolution::IsCNu (const Standard_Integer ) const {
227 return Standard_True;
230 //=======================================================================
233 //=======================================================================
235 Ax1 Geom_SurfaceOfRevolution::Axis () const {
237 return Ax1 (loc, direction);
240 //=======================================================================
243 //=======================================================================
245 Standard_Boolean Geom_SurfaceOfRevolution::IsCNv (const Standard_Integer N) const {
247 Standard_RangeError_Raise_if (N < 0, " ");
248 return basisCurve->IsCN(N);
252 //=======================================================================
253 //function : IsUClosed
255 //=======================================================================
257 Standard_Boolean Geom_SurfaceOfRevolution::IsUClosed () const {
259 return Standard_True;
262 //=======================================================================
263 //function : IsVClosed
265 //=======================================================================
267 Standard_Boolean Geom_SurfaceOfRevolution::IsVClosed () const
269 return basisCurve->IsClosed();
273 //=======================================================================
274 //function : IsVPeriodic
276 //=======================================================================
278 Standard_Boolean Geom_SurfaceOfRevolution::IsVPeriodic () const {
280 return basisCurve->IsPeriodic();
284 //=======================================================================
287 //=======================================================================
289 void Geom_SurfaceOfRevolution::SetAxis (const Ax1& A1) {
291 direction = A1.Direction();
296 //=======================================================================
297 //function : SetDirection
299 //=======================================================================
301 void Geom_SurfaceOfRevolution::SetDirection (const Dir& V) {
307 //=======================================================================
308 //function : SetBasisCurve
310 //=======================================================================
312 void Geom_SurfaceOfRevolution::SetBasisCurve (const Handle(Geom_Curve)& C) {
314 basisCurve = Handle(Geom_Curve)::DownCast(C->Copy());
315 smooth = C->Continuity();
319 //=======================================================================
320 //function : SetLocation
322 //=======================================================================
324 void Geom_SurfaceOfRevolution::SetLocation (const Pnt& P) {
330 //=======================================================================
333 //=======================================================================
335 void Geom_SurfaceOfRevolution::Bounds ( Standard_Real& U1,
338 Standard_Real& V2 ) const {
342 V1 = basisCurve->FirstParameter();
343 V2 = basisCurve->LastParameter();
347 //=======================================================================
350 //=======================================================================
352 void Geom_SurfaceOfRevolution::D0
353 (const Standard_Real U, const Standard_Real V, Pnt& P) const {
355 // C origine sur l'axe de revolution
356 // Vdir vecteur unitaire definissant la direction de l'axe de revolution
357 // Q(v) point de parametre V sur la courbe de revolution
358 // OM (u,v) = OC + CQ * Cos(U) + (CQ.Vdir)(1-Cos(U)) * Vdir +
362 Pnt Pc = basisCurve->Value (V); //Q(v)
363 XYZ Q = Pc.XYZ(); //Q
364 XYZ C = loc.XYZ(); //C
366 XYZ Vdir = direction.XYZ(); //Vdir
367 XYZ VcrossCQ = Vdir.Crossed (Q); //Vdir^CQ
368 VcrossCQ.Multiply (Sin(U)); //(Vdir^CQ)*Sin(U)
370 Vdir.Multiplied ((Vdir.Dot(Q))*(1.0 - Cos(U)));//(CQ.Vdir)(1-Cos(U))Vdir
371 VdotCQ.Add (VcrossCQ); //addition des composantes
379 //=======================================================================
382 //=======================================================================
384 void Geom_SurfaceOfRevolution::D1
385 (const Standard_Real U, const Standard_Real V,
387 Vec& D1U, Vec& D1V ) const {
389 // C origine sur l'axe de revolution
390 // Vdir vecteur unitaire definissant la direction de l'axe de revolution
391 // Q(v) point de parametre V sur la courbe de revolution
393 // OM (u,v) = OC + CQ * Cos(U) + (CQ.Vdir)(1-Cos(U)) * Vdir +
394 // (Vdir^CQ) * Sin(U)
395 // D1U_M(u,v) = - CQ * Sin(U) + (CQ.Vdir)(Sin(U)) * Vdir +
396 // (Vdir^CQ) * Cos(U)
397 // D1V_M(u,v) = Q' * Cos(U) + (Q'.Vdir)(1-Cos(U)) * Vdir +
398 // (Vdir^Q') * Sin(U)
402 basisCurve->D1 (V, Pc, V1);
403 XYZ Q = Pc.XYZ(); //Q
404 XYZ DQv = V1.XYZ(); //Q'
405 XYZ C = loc.XYZ(); //C
406 XYZ Vdir = direction.XYZ(); //Vdir
408 XYZ VcrossCQ = Vdir.Crossed (Q); //Vdir^CQ
409 // If the point is placed on the axis of revolution then derivatives on U are undefined.
410 // Manually set them to zero.
411 if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
412 VcrossCQ.SetCoord(0.0, 0.0, 0.0);
413 XYZ VcrossDQv = Vdir.Crossed (DQv); //(Vdir^Q')
414 XYZ VdotCQ = Vdir.Multiplied (Vdir.Dot(Q)); //(Vdir.CQ)Vdir
415 XYZ VdotDQv = Vdir.Multiplied (Vdir.Dot(DQv)); //(Vdir.Q')Vdir
417 VcrossDQv.Multiply (Sin(U));
418 VdotDQv.Multiply (1.0 - Cos(U));
419 VdotDQv.Add (VcrossDQv);
420 DQv.Multiply (Cos(U));
424 XYZ DQu = Q.Multiplied (-Sin(U));
425 DQu.Add (VcrossCQ.Multiplied (Cos(U)));
426 DQu.Add (VdotCQ.Multiplied (Sin(U)));
431 VcrossCQ.Multiply (Sin(U));
433 VdotCQ.Multiply (1.0-Cos(U));
438 //=======================================================================
441 //=======================================================================
443 void Geom_SurfaceOfRevolution::D2
444 (const Standard_Real U, const Standard_Real V,
447 Vec& D2U, Vec& D2V, Vec& D2UV ) const {
450 // C origine sur l'axe de revolution
451 // V vecteur unitaire definissant la direction de l'axe de revolution
452 // Q(v) point de parametre V sur la courbe de revolution
455 // OM (u,v) = OC + CQ * Cos(U) + (CQ.Vdir)(1-Cos(U)) * Vdir +
456 // (Vdir^CQ) * Sin(U)
457 // D1U_M(u,v) = - CQ * Sin(U) + (CQ.Vdir)(Sin(U)) * Vdir +
458 // (Vdir^CQ) * Cos(U)
459 // D1V_M(u,v) = Q' * Cos(U) + (Q'.Vdir)(1-Cos(U)) * Vdir +
460 // (Vdir^Q') * Sin(U)
461 // D2U_M(u,v) = -CQ * Cos(U) + (CQ.Vdir)(Cos(U)) * Vdir +
462 // (Vdir^CQ) * -(Sin(U))
463 // D2V_M(u,v) = Q" * Cos(U) + (Q".Vdir)(1-Cos(U)) * Vdir +
464 // (Vdir^Q") * Sin(U)
465 // D2UV_M(u,v)= -Q' * Sin(U) + (Q'.Vdir)(Sin(U)) * Vdir +
466 // (Vdir^Q') * Cos(U)
471 basisCurve->D2 (V, Pc, V1, V2);
472 XYZ Q = Pc.XYZ(); //Q
473 XYZ D1Qv = V1.XYZ(); //Q'
474 XYZ D2Qv = V2.XYZ(); //Q"
475 XYZ C = loc.XYZ(); //C
476 XYZ Vdir = direction.XYZ(); //Vdir
478 XYZ VcrossCQ = Vdir.Crossed (Q); //Vdir^CQ
479 // If the point is placed on the axis of revolution then derivatives on U are undefined.
480 // Manually set them to zero.
481 if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
482 VcrossCQ.SetCoord(0.0, 0.0, 0.0);
483 XYZ VcrossD1Qv = Vdir.Crossed (D1Qv); //(Vdir^Q')
484 XYZ VcrossD2Qv = Vdir.Crossed (D2Qv); //(Vdir^Q")
485 XYZ VdotCQ = Vdir.Multiplied (Vdir.Dot(Q)); //(Vdir.CQ)Vdir
486 XYZ VdotD1Qv = Vdir.Multiplied (Vdir.Dot(D1Qv)); //(Vdir.Q')Vdir
487 XYZ VdotD2Qv = Vdir.Multiplied (Vdir.Dot(D2Qv)); //(Vdir.Q")Vdir
490 XYZ D2Quv = D1Qv.Multiplied(-Sin(U));
491 D2Quv.Add (VcrossD1Qv.Multiplied (Cos(U)));
492 D2Quv.Add (VdotD1Qv.Multiplied (Sin(U)));
495 D1Qv.Multiply (Cos(U));
496 VcrossD1Qv.Multiply (Sin(U));
497 VdotD1Qv.Multiply (1.0 - Cos(U));
498 D1Qv.Add (VcrossD1Qv);
502 VcrossD2Qv.Multiply (Sin(U));
503 VdotD2Qv.Multiply (1.0 - Cos(U));
504 VdotD2Qv.Add (VcrossD2Qv);
505 D2Qv.Multiply (Cos(U));
509 XYZ D1Qu = Q.Multiplied (-Sin(U));
510 D1Qu.Add (VcrossCQ.Multiplied (Cos(U)));
511 D1Qu.Add (VdotCQ.Multiplied (Sin(U)));
515 VcrossCQ.Multiply (Sin(U));
517 XYZ D2Qu = Q.Multiplied(-1.0);
518 D2Qu.Add (VdotCQ.Multiplied (Cos(U)));
520 VdotCQ.Multiply (1.0-Cos(U));
528 //=======================================================================
531 //=======================================================================
533 void Geom_SurfaceOfRevolution::D3
534 (const Standard_Real U, const Standard_Real V,
537 Vec& D2U, Vec& D2V, Vec& D2UV,
538 Vec& D3U, Vec& D3V, Vec& D3UUV, Vec& D3UVV ) const {
540 // C origine sur l'axe de revolution
541 // Vdir vecteur unitaire definissant la direction de l'axe de revolution
542 // Q(v) point de parametre V sur la courbe de revolution
545 // OM (u,v) = OC + CQ * Cos(u) + (CQ.Vdir)(1-Cos(u)) * Vdir +
546 // (Vdir^CQ) * Sin(u)
547 // D1U_M(u,v) = - CQ * Sin(u) + (CQ.Vdir)(Sin(u)) * Vdir +
548 // (Vdir^CQ) * Cos(u)
549 // D2U_M(u,v) = -CQ * Cos(u) + (CQ.Vdir)(Cos(u)) * Vdir +
550 // (Vdir^CQ) * -Sin(u)
551 // D2UV_M(u,v)= -Q' * Sin(u) + (Q'.Vdir)(Sin(u)) * Vdir +
552 // (Vdir^Q') * Cos(u)
553 // D3UUV_M(u,v) = -Q' * Cos(u) + (Q'.Vdir)(Cos(u)) * Vdir +
554 // (Vdir^Q') * -Sin(u)
555 // D3U_M(u,v) = CQ * Sin(u) + (CQ.Vdir)(-Sin(u)) * Vdir +
556 // (Vdir^CQ) * -Cos(u)
557 // D1V_M(u,v) = Q' * Cos(u) + (Q'.Vdir)(1-Cos(u)) * Vdir +
558 // (Vdir^Q') * Sin(u)
559 // D2V_M(u,v) = Q" * Cos(u) + (Q".Vdir)(1-Cos(u)) * Vdir +
560 // (Vdir^Q") * Sin(u)
561 // D3UVV_M(u,v) = -Q" * Sin(u) + (Q".Vdir)(Sin(u)) * Vdir +
562 // (Vdir^Q") * Cos(u)
563 // D3V_M(u,v) = Q'''* Cos(u) + (Q'''.Vdir)(1-Cos(u)) * Vdir +
564 // (Vdir^Q''') * Sin(u)
569 basisCurve->D3 (V, Pc, V1, V2, V3);
570 XYZ Q = Pc.XYZ(); //Q
571 XYZ D1Qv = V1.XYZ(); //Q'
572 XYZ D2Qv = V2.XYZ(); //Q"
573 XYZ D3Qv = V3.XYZ(); //Q'''
574 XYZ C = loc.XYZ(); //C
575 XYZ Vdir = direction.XYZ(); //Vdir
577 XYZ VcrossCQ = Vdir.Crossed (Q); //Vdir^CQ
578 // If the point is placed on the axis of revolution then derivatives on U are undefined.
579 // Manually set them to zero.
580 if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
581 VcrossCQ.SetCoord(0.0, 0.0, 0.0);
582 XYZ VcrossD1Qv = Vdir.Crossed (D1Qv); //(Vdir^Q')
583 XYZ VcrossD2Qv = Vdir.Crossed (D2Qv); //(Vdir^Q")
584 XYZ VcrossD3Qv = Vdir.Crossed (D3Qv); //(Vdir^Q''')
585 XYZ VdotCQ = Vdir.Multiplied (Vdir.Dot(Q)); //(Vdir.CQ)Vdir
586 XYZ VdotD1Qv = Vdir.Multiplied (Vdir.Dot(D1Qv)); //(Vdir.Q')Vdir
587 XYZ VdotD2Qv = Vdir.Multiplied (Vdir.Dot(D2Qv)); //(Vdir.Q")Vdir
588 XYZ VdotD3Qv = Vdir.Multiplied (Vdir.Dot(D3Qv)); //(Vdir.Q''')Vdir
590 XYZ D3Quuv = D1Qv.Multiplied (-Cos(U));
591 D3Quuv.Add (VcrossD1Qv.Multiplied (-Sin(U)));
592 D3Quuv.Add (VdotD1Qv.Multiplied (Cos(U)));
593 D3UUV.SetXYZ (D3Quuv);
595 XYZ D2Quv = D1Qv.Multiplied (-Sin(U));
596 D2Quv.Add (VcrossD1Qv.Multiplied (Cos(U)));
597 D2Quv.Add (VdotD1Qv.Multiplied (Sin(U)));
600 D1Qv.Multiply (Cos(U));
601 VcrossD1Qv.Multiply (Sin(U));
602 VdotD1Qv.Multiply (1.0 - Cos(U));
603 D1Qv.Add (VcrossD1Qv);
607 XYZ D3Qvvu = D2Qv.Multiplied (-Sin(U));
608 D3Qvvu.Add (VcrossD2Qv.Multiplied (Cos(U)));
609 D3Qvvu.Add (VdotD2Qv.Multiplied (Sin(U)));
610 D3UVV.SetXYZ (D3Qvvu);
612 VcrossD2Qv.Multiply (Sin(U));
613 VdotD2Qv.Multiply (1.0 - Cos(U));
614 VdotD2Qv.Add (VcrossD2Qv);
615 D2Qv.Multiply (Cos(U));
619 VcrossD3Qv.Multiply (Sin(U));
620 VdotD3Qv.Multiply (1.0 - Cos(U));
621 VdotD3Qv.Add (VcrossD2Qv);
622 D3Qv.Multiply (Cos(U));
626 XYZ D1Qu = Q.Multiplied (- Sin(U));
627 D1Qu.Add (VcrossCQ.Multiplied (Cos(U)));
628 XYZ D3Qu = D1Qu.Multiplied (-1.0);
629 D1Qu.Add (VdotCQ.Multiplied (Sin(U)));
630 D3Qu.Add (VdotCQ.Multiplied (-Sin(U)));
635 VcrossCQ.Multiply (Sin(U));
637 XYZ D2Qu = Q.Multiplied(-1.0);
638 D2Qu.Add (VdotCQ.Multiplied (Cos(U)));
640 VdotCQ.Multiply (1.0-Cos(U));
647 //=======================================================================
650 //=======================================================================
652 Vec Geom_SurfaceOfRevolution::DN (const Standard_Real U , const Standard_Real V,
653 const Standard_Integer Nu, const Standard_Integer Nv) const {
655 Standard_RangeError_Raise_if (Nu + Nv < 1 || Nu < 0 || Nv < 0, " ");
657 XYZ Vn = (basisCurve->DN (V, Nv)).XYZ();
658 XYZ Vdir = direction.XYZ();
659 XYZ VDot = Vdir.Multiplied (Vn.Dot (Vdir));
660 VDot.Multiply (1-Cos(U));
661 XYZ VCross = Vdir.Crossed (Vn);
662 VCross.Multiply (Sin(U));
663 Vn.Multiply (Cos(U));
669 XYZ CQ = (basisCurve->Value (V)).XYZ() - loc.XYZ();
670 XYZ Vdir = direction.XYZ();
671 XYZ VDot = Vdir.Multiplied (CQ.Dot (Vdir));
672 XYZ VCross = Vdir.Crossed (CQ);
673 if ((Nu + 6) % 4 == 0) {
674 CQ.Multiply (-Cos (U));
675 VDot.Multiply (Cos(U));
676 VCross.Multiply (-Sin(U));
678 else if ((Nu + 5) % 4 == 0) {
679 CQ.Multiply (Sin (U));
680 VDot.Multiply (-Sin(U));
681 VCross.Multiply (-Cos(U));
683 else if ((Nu+3) % 4 == 0) {
684 CQ.Multiply (-Sin (U));
685 VDot.Multiply (+Sin(U));
686 VCross.Multiply (Cos(U));
688 else if (Nu+4 % 4 == 0) {
689 CQ.Multiply (Cos (U));
690 VDot.Multiply (-Cos(U));
691 VCross.Multiply (Sin(U));
698 XYZ Vn = (basisCurve->DN (V, Nv)).XYZ();
699 XYZ Vdir = direction.XYZ();
700 XYZ VDot = Vdir.Multiplied (Vn.Dot (Vdir));
701 XYZ VCross = Vdir.Crossed (Vn);
702 if ((Nu + 6) % 4 == 0) {
703 Vn.Multiply (-Cos (U));
704 VDot.Multiply (Cos(U));
705 VCross.Multiply (-Sin(U));
707 else if ((Nu + 5) % 4 == 0) {
708 Vn.Multiply (Sin (U));
709 VDot.Multiply (-Sin(U));
710 VCross.Multiply (-Cos(U));
712 else if ((Nu+3) % 4 == 0) {
713 Vn.Multiply (-Sin (U));
714 VDot.Multiply (+Sin(U));
715 VCross.Multiply (Cos(U));
717 else if (Nu+4 % 4 == 0) {
718 Vn.Multiply (Cos (U));
719 VDot.Multiply (-Cos(U));
720 VCross.Multiply (Sin(U));
728 //=======================================================================
731 //=======================================================================
733 void Geom_SurfaceOfRevolution::LocalD0 (const Standard_Real U,
734 const Standard_Real V,
735 const Standard_Integer VSide,
738 if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
741 Handle( Geom_BSplineCurve) BSplC;
742 BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
744 LocateSide(V,VSide,BSplC,0,P,D1V,D2V,D3V);
746 XYZ C = loc.XYZ(); //C
748 XYZ Vdir = direction.XYZ(); //Vdir
749 XYZ VcrossCQ = Vdir.Crossed (Q); //Vdir^CQ
750 VcrossCQ.Multiply (Sin(U)); //(Vdir^CQ)*Sin(U)
752 Vdir.Multiplied ((Vdir.Dot(Q))*(1.0 - Cos(U)));//(CQ.Vdir)(1-Cos(U))Vdir
753 VdotCQ.Add (VcrossCQ); //addition des composantes
762 //=======================================================================
765 //=======================================================================
767 void Geom_SurfaceOfRevolution::LocalD1 (const Standard_Real U,
768 const Standard_Real V,
769 const Standard_Integer VSide,
774 if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
776 Handle( Geom_BSplineCurve) BSplC;
777 BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
780 LocateSide(V,VSide,BSplC,1,P,V1,D2V,D3V);
782 XYZ DQv = V1.XYZ(); //Q'
783 XYZ C = loc.XYZ(); //C
784 XYZ Vdir = direction.XYZ(); //Vdir
786 XYZ VcrossCQ = Vdir.Crossed (Q); //Vdir^CQ
787 // If the point is placed on the axis of revolution then derivatives on U are undefined.
788 // Manually set them to zero.
789 if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
790 VcrossCQ.SetCoord(0.0, 0.0, 0.0);
792 XYZ VcrossDQv = Vdir.Crossed (DQv); //(Vdir^Q')
793 XYZ VdotCQ = Vdir.Multiplied (Vdir.Dot(Q)); //(Vdir.CQ)Vdir
794 XYZ VdotDQv = Vdir.Multiplied (Vdir.Dot(DQv)); //(Vdir.Q')Vdir
796 VcrossDQv.Multiply (Sin(U));
797 VdotDQv.Multiply (1.0 - Cos(U));
798 VdotDQv.Add (VcrossDQv);
799 DQv.Multiply (Cos(U));
803 XYZ DQu = Q.Multiplied (-Sin(U));
804 DQu.Add (VcrossCQ.Multiplied (Cos(U)));
805 DQu.Add (VdotCQ.Multiplied (Sin(U)));
810 VcrossCQ.Multiply (Sin(U));
812 VdotCQ.Multiply (1.0-Cos(U));
819 //=======================================================================
822 //=======================================================================
824 void Geom_SurfaceOfRevolution::LocalD2 (const Standard_Real U,
825 const Standard_Real V,
826 const Standard_Integer VSide,
834 if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
836 Handle( Geom_BSplineCurve) BSplC;
837 BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
839 LocateSide(V,VSide,BSplC,2,P,D1V,D2V,d3v);
841 XYZ D1Qv = D1V.XYZ(); //Q'
842 XYZ D2Qv = D2V.XYZ(); //Q"
843 XYZ C = loc.XYZ(); //C
844 XYZ Vdir = direction.XYZ(); //Vdir
846 XYZ VcrossCQ = Vdir.Crossed (Q); //Vdir^CQ
847 // If the point is placed on the axis of revolution then derivatives on U are undefined.
848 // Manually set them to zero.
849 if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
850 VcrossCQ.SetCoord(0.0, 0.0, 0.0);
852 XYZ VcrossD1Qv = Vdir.Crossed (D1Qv); //(Vdir^Q')
853 XYZ VcrossD2Qv = Vdir.Crossed (D2Qv); //(Vdir^Q")
854 XYZ VdotCQ = Vdir.Multiplied (Vdir.Dot(Q)); //(Vdir.CQ)Vdir
855 XYZ VdotD1Qv = Vdir.Multiplied (Vdir.Dot(D1Qv)); //(Vdir.Q')Vdir
856 XYZ VdotD2Qv = Vdir.Multiplied (Vdir.Dot(D2Qv)); //(Vdir.Q")Vdir
859 XYZ D2Quv = D1Qv.Multiplied(-Sin(U));
860 D2Quv.Add (VcrossD1Qv.Multiplied (Cos(U)));
861 D2Quv.Add (VdotD1Qv.Multiplied (Sin(U)));
864 D1Qv.Multiply (Cos(U));
865 VcrossD1Qv.Multiply (Sin(U));
866 VdotD1Qv.Multiply (1.0 - Cos(U));
867 D1Qv.Add (VcrossD1Qv);
871 VcrossD2Qv.Multiply (Sin(U));
872 VdotD2Qv.Multiply (1.0 - Cos(U));
873 VdotD2Qv.Add (VcrossD2Qv);
874 D2Qv.Multiply (Cos(U));
878 XYZ D1Qu = Q.Multiplied (-Sin(U));
879 D1Qu.Add (VcrossCQ.Multiplied (Cos(U)));
880 D1Qu.Add (VdotCQ.Multiplied (Sin(U)));
884 VcrossCQ.Multiply (Sin(U));
886 XYZ D2Qu = Q.Multiplied(-1.0);
887 D2Qu.Add (VdotCQ.Multiplied (Cos(U)));
889 VdotCQ.Multiply (1.0-Cos(U));
895 D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
897 //=======================================================================
900 //=======================================================================
902 void Geom_SurfaceOfRevolution::LocalD3 (const Standard_Real U,
903 const Standard_Real V,
904 const Standard_Integer VSide,
916 if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
918 Handle( Geom_BSplineCurve) BSplC;
919 BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
921 LocateSide(V,VSide,BSplC,3,P,D1V,D2V,D3V);
923 XYZ D1Qv = D1V.XYZ(); //Q'
924 XYZ D2Qv = D2V.XYZ(); //Q"
925 XYZ D3Qv = D3V.XYZ(); //Q'''
926 XYZ C = loc.XYZ(); //C
927 XYZ Vdir = direction.XYZ(); //Vdir
929 XYZ VcrossCQ = Vdir.Crossed (Q); //Vdir^CQ
930 // If the point is placed on the axis of revolution then derivatives on U are undefined.
931 // Manually set them to zero.
932 if (VcrossCQ.SquareModulus() < Precision::SquareConfusion())
933 VcrossCQ.SetCoord(0.0, 0.0, 0.0);
935 XYZ VcrossD1Qv = Vdir.Crossed (D1Qv); //(Vdir^Q')
936 XYZ VcrossD2Qv = Vdir.Crossed (D2Qv); //(Vdir^Q")
937 XYZ VcrossD3Qv = Vdir.Crossed (D3Qv); //(Vdir^Q''')
938 XYZ VdotCQ = Vdir.Multiplied (Vdir.Dot(Q)); //(Vdir.CQ)Vdir
939 XYZ VdotD1Qv = Vdir.Multiplied (Vdir.Dot(D1Qv)); //(Vdir.Q')Vdir
940 XYZ VdotD2Qv = Vdir.Multiplied (Vdir.Dot(D2Qv)); //(Vdir.Q")Vdir
941 XYZ VdotD3Qv = Vdir.Multiplied (Vdir.Dot(D3Qv)); //(Vdir.Q''')Vdir
943 XYZ D3Quuv = D1Qv.Multiplied (-Cos(U));
944 D3Quuv.Add (VcrossD1Qv.Multiplied (-Sin(U)));
945 D3Quuv.Add (VdotD1Qv.Multiplied (Cos(U)));
946 D3UUV.SetXYZ (D3Quuv);
948 XYZ D2Quv = D1Qv.Multiplied (-Sin(U));
949 D2Quv.Add (VcrossD1Qv.Multiplied (Cos(U)));
950 D2Quv.Add (VdotD1Qv.Multiplied (Sin(U)));
953 D1Qv.Multiply (Cos(U));
954 VcrossD1Qv.Multiply (Sin(U));
955 VdotD1Qv.Multiply (1.0 - Cos(U));
956 D1Qv.Add (VcrossD1Qv);
960 XYZ D3Qvvu = D2Qv.Multiplied (-Sin(U));
961 D3Qvvu.Add (VcrossD2Qv.Multiplied (Cos(U)));
962 D3Qvvu.Add (VdotD2Qv.Multiplied (Sin(U)));
963 D3UVV.SetXYZ (D3Qvvu);
965 VcrossD2Qv.Multiply (Sin(U));
966 VdotD2Qv.Multiply (1.0 - Cos(U));
967 VdotD2Qv.Add (VcrossD2Qv);
968 D2Qv.Multiply (Cos(U));
972 VcrossD3Qv.Multiply (Sin(U));
973 VdotD3Qv.Multiply (1.0 - Cos(U));
974 VdotD3Qv.Add (VcrossD2Qv);
975 D3Qv.Multiply (Cos(U));
979 XYZ D1Qu = Q.Multiplied (- Sin(U));
980 D1Qu.Add (VcrossCQ.Multiplied (Cos(U)));
981 XYZ D3Qu = D1Qu.Multiplied (-1.0);
982 D1Qu.Add (VdotCQ.Multiplied (Sin(U)));
983 D3Qu.Add (VdotCQ.Multiplied (-Sin(U)));
988 VcrossCQ.Multiply (Sin(U));
990 XYZ D2Qu = Q.Multiplied(-1.0);
991 D2Qu.Add (VdotCQ.Multiplied (Cos(U)));
993 VdotCQ.Multiply (1.0-Cos(U));
999 D3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
1001 //=======================================================================
1002 //function : LocalDN
1004 //=======================================================================
1006 gp_Vec Geom_SurfaceOfRevolution::LocalDN (const Standard_Real U,
1007 const Standard_Real V,
1008 const Standard_Integer VSide,
1009 const Standard_Integer Nu,
1010 const Standard_Integer Nv) const
1012 Standard_RangeError_Raise_if (Nu + Nv < 1 || Nu < 0 || Nv < 0, " ");
1015 if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
1017 Handle( Geom_BSplineCurve) BSplC;
1018 BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
1019 Vn = LocateSideN(V,VSide,BSplC,Nv).XYZ();
1021 return DN(U,V,Nu,Nv);
1022 XYZ Vdir = direction.XYZ();
1023 XYZ VDot = Vdir.Multiplied (Vn.Dot (Vdir));
1024 VDot.Multiply (1-Cos(U));
1025 XYZ VCross = Vdir.Crossed (Vn);
1026 VCross.Multiply (Sin(U));
1027 Vn.Multiply (Cos(U));
1034 if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
1036 Handle( Geom_BSplineCurve) BSplC;
1037 BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
1038 CQ = LocateSideN(V,VSide,BSplC,Nv).XYZ() - loc.XYZ();
1040 return DN(U,V,Nu,Nv);
1041 XYZ Vdir = direction.XYZ();
1042 XYZ VDot = Vdir.Multiplied (CQ.Dot (Vdir));
1043 XYZ VCross = Vdir.Crossed (CQ);
1044 if ((Nu + 6) % 4 == 0) {
1045 CQ.Multiply (-Cos (U));
1046 VDot.Multiply (Cos(U));
1047 VCross.Multiply (-Sin(U));
1049 else if ((Nu + 5) % 4 == 0) {
1050 CQ.Multiply (Sin (U));
1051 VDot.Multiply (-Sin(U));
1052 VCross.Multiply (-Cos(U));
1054 else if ((Nu+3) % 4 == 0) {
1055 CQ.Multiply (-Sin (U));
1056 VDot.Multiply (+Sin(U));
1057 VCross.Multiply (Cos(U));
1059 else if (Nu+4 % 4 == 0) {
1060 CQ.Multiply (Cos (U));
1061 VDot.Multiply (-Cos(U));
1062 VCross.Multiply (Sin(U));
1070 if((VSide !=0 ) && basisCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
1072 Handle( Geom_BSplineCurve) BSplC;
1073 BSplC= Handle(Geom_BSplineCurve)::DownCast(basisCurve);
1074 Vn = LocateSideN(V,VSide,BSplC,Nv).XYZ();
1076 return DN(U,V,Nu,Nv);
1077 XYZ Vdir = direction.XYZ();
1078 XYZ VDot = Vdir.Multiplied (Vn.Dot (Vdir));
1079 XYZ VCross = Vdir.Crossed (Vn);
1080 if ((Nu + 6) % 4 == 0) {
1081 Vn.Multiply (-Cos (U));
1082 VDot.Multiply (Cos(U));
1083 VCross.Multiply (-Sin(U));
1085 else if ((Nu + 5) % 4 == 0) {
1086 Vn.Multiply (Sin (U));
1087 VDot.Multiply (-Sin(U));
1088 VCross.Multiply (-Cos(U));
1090 else if ((Nu+3) % 4 == 0) {
1091 Vn.Multiply (-Sin (U));
1092 VDot.Multiply (+Sin(U));
1093 VCross.Multiply (Cos(U));
1095 else if (Nu+4 % 4 == 0) {
1096 Vn.Multiply (Cos (U));
1097 VDot.Multiply (-Cos(U));
1098 VCross.Multiply (Sin(U));
1106 //=======================================================================
1107 //function : ReferencePlane
1109 //=======================================================================
1111 Ax2 Geom_SurfaceOfRevolution::ReferencePlane() const {
1113 Standard_NotImplemented::Raise ();
1118 //=======================================================================
1121 //=======================================================================
1123 Handle(Geom_Curve) Geom_SurfaceOfRevolution::UIso (const Standard_Real U) const {
1125 Handle(Geom_Curve) C = Handle(Geom_Curve)::DownCast(basisCurve->Copy());
1126 Ax1 RotAxis = Ax1 (loc, direction);
1127 C->Rotate (RotAxis, U);
1132 //=======================================================================
1135 //=======================================================================
1137 Handle(Geom_Curve) Geom_SurfaceOfRevolution::VIso (const Standard_Real V) const {
1139 Handle(Geom_Circle) Circ;
1140 Pnt Pc = basisCurve->Value (V);
1141 gp_Lin L1(loc,direction);
1142 Standard_Real Rad= L1.Distance(Pc);
1145 if ( Rad > gp::Resolution()) {
1148 C.SetLinearForm((P-loc.XYZ()).Dot(direction.XYZ()),
1149 direction.XYZ(), loc.XYZ() );
1151 if(P.Modulus() > gp::Resolution()) {
1152 gp_Dir D = P.Normalized();
1153 Rep = gp_Ax2(C, direction, D);
1156 Rep = gp_Ax2(C, direction);
1159 Rep = gp_Ax2(Pc, direction);
1161 Circ = new Geom_Circle (Rep, Rad);
1166 //=======================================================================
1167 //function : Transform
1169 //=======================================================================
1171 void Geom_SurfaceOfRevolution::Transform (const Trsf& T) {
1174 direction.Transform (T);
1175 basisCurve->Transform (T);
1176 if(T.ScaleFactor()*T.HVectorialPart().Determinant() < 0.) UReverse();
1179 //=======================================================================
1180 //function : TransformParameters
1182 //=======================================================================
1184 void Geom_SurfaceOfRevolution::TransformParameters(Standard_Real& ,
1189 V = basisCurve->TransformedParameter(V,T);
1192 //=======================================================================
1193 //function : ParametricTransformation
1195 //=======================================================================
1197 gp_GTrsf2d Geom_SurfaceOfRevolution::ParametricTransformation
1198 (const gp_Trsf& T) const
1201 gp_Ax2d Axis(gp::Origin2d(),gp::DX2d());
1202 T2.SetAffinity(Axis, basisCurve->ParametricTransformation(T));