0030582: Coding - avoid defining references to properties of NULL objects
[occt.git] / src / GeomAdaptor / GeomAdaptor_SurfaceOfRevolution.cxx
1 // Created on: 1993-04-21
2 // Created by: Bruno DUMORTIER
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 <GeomAdaptor_SurfaceOfRevolution.hxx>
18
19 #include <Adaptor3d_HCurve.hxx>
20 #include <ElCLib.hxx>
21 #include <GeomAdaptor_HSurfaceOfRevolution.hxx>
22 #include <GeomEvaluator_SurfaceOfRevolution.hxx>
23 #include <Standard_NoSuchObject.hxx>
24
25 //=======================================================================
26 //function : GeomAdaptor_SurfaceOfRevolution
27 //purpose  : 
28 //=======================================================================
29 GeomAdaptor_SurfaceOfRevolution::GeomAdaptor_SurfaceOfRevolution()
30   : myHaveAxis(Standard_False)
31 {}
32
33 //=======================================================================
34 //function : GeomAdaptor_SurfaceOfRevolution
35 //purpose  : 
36 //=======================================================================
37
38 GeomAdaptor_SurfaceOfRevolution::GeomAdaptor_SurfaceOfRevolution(
39     const Handle(Adaptor3d_HCurve)& C)
40   : myHaveAxis(Standard_False)
41 {
42   Load(C);
43 }
44
45 //=======================================================================
46 //function : GeomAdaptor_SurfaceOfRevolution
47 //purpose  : 
48 //=======================================================================
49
50 GeomAdaptor_SurfaceOfRevolution::GeomAdaptor_SurfaceOfRevolution(
51     const Handle(Adaptor3d_HCurve)& C,
52     const gp_Ax1& V)
53   : myHaveAxis(Standard_False)
54 {
55   Load(C);
56   Load(V);
57 }
58
59 //=======================================================================
60 //function : Load
61 //purpose  : 
62 //=======================================================================
63
64 void GeomAdaptor_SurfaceOfRevolution::Load(const Handle(Adaptor3d_HCurve)& C)
65 {
66   myBasisCurve = C;
67   if (myHaveAxis)
68     Load(myAxis); // to evaluate the new myAxeRev.
69 }
70
71 //=======================================================================
72 //function : Load
73 //purpose  : 
74 //=======================================================================
75
76 void GeomAdaptor_SurfaceOfRevolution::Load(const gp_Ax1& V)
77 {
78   myHaveAxis = Standard_True;
79   myAxis = V;
80
81   mySurfaceType = GeomAbs_SurfaceOfRevolution;
82   myNestedEvaluator = new GeomEvaluator_SurfaceOfRevolution(myBasisCurve,
83       myAxis.Direction(), myAxis.Location());
84
85   // Eval myAxeRev : axe of revolution ( Determination de Ox).
86   gp_Pnt P,Q;
87   gp_Pnt O = myAxis.Location();
88   gp_Dir Ox;
89   gp_Dir Oz = myAxis.Direction();
90   Standard_Boolean yrev = Standard_False;
91   if (myBasisCurve->GetType() == GeomAbs_Line) {
92     if((myBasisCurve->Line().Direction()).Dot(Oz) < 0.){
93       yrev = Standard_True;
94       Oz.Reverse();
95     }
96   }
97
98   if (myBasisCurve->GetType() == GeomAbs_Circle) {
99     Q = P = (myBasisCurve->Circle()).Location();
100   }
101   else {
102     Standard_Real First = myBasisCurve->FirstParameter();
103     P = Value( 0., 0.);// ce qui ne veut pas dire grand chose
104     if ( GetType() == GeomAbs_Cone) {
105       if ( gp_Lin(myAxis).Distance(P) <= Precision::Confusion())
106         Q = ElCLib::Value(1.,myBasisCurve->Line());
107       else 
108         Q = P;
109     }
110     else if (Precision::IsInfinite(First))
111       Q = P; 
112     else 
113       Q = Value( 0., First);
114   }
115   
116   gp_Dir DZ = myAxis.Direction();
117   O.SetXYZ( O.XYZ() + ( gp_Vec(O,P) * DZ) * DZ.XYZ());
118   if ( gp_Lin(myAxis).Distance(Q) > Precision::Confusion()) {
119     Ox = gp_Dir(Q.XYZ() - O.XYZ());
120   }
121   else {
122     Standard_Real First = myBasisCurve->FirstParameter();
123     Standard_Real Last  = myBasisCurve->LastParameter();
124     Standard_Integer Ratio = 1;
125     Standard_Real Dist; 
126     gp_Pnt PP;
127     do {
128       PP = myBasisCurve->Value(First+(Last-First)/Ratio);
129       Dist = gp_Lin(myAxis).Distance(PP);
130       Ratio++;
131     }
132     while ( Dist < Precision::Confusion() && Ratio < 100);
133
134     if ( Ratio >= 100 ) {
135       throw Standard_ConstructionError("Adaptor3d_SurfaceOfRevolution : Axe and meridian are confused");
136     }
137     Ox = ( (Oz^gp_Vec(PP.XYZ()-O.XYZ()))^Oz); 
138   }
139
140   myAxeRev = gp_Ax3(O,Oz,Ox);
141
142   if (yrev) {
143     myAxeRev.YReverse();
144   }
145   else if (myBasisCurve->GetType() == GeomAbs_Circle) {
146     gp_Dir DC = (myBasisCurve->Circle()).Axis().Direction();
147     if ((Ox.Crossed(Oz)).Dot(DC) < 0.)  myAxeRev.ZReverse(); 
148   }
149 }
150
151 //=======================================================================
152 //function : AxeOfRevolution
153 //purpose  : 
154 //=======================================================================
155
156 gp_Ax1 GeomAdaptor_SurfaceOfRevolution::AxeOfRevolution() const
157 {
158   return myAxis;
159 }
160
161 //=======================================================================
162 //function : FirstUParameter
163 //purpose  : 
164 //=======================================================================
165
166 Standard_Real GeomAdaptor_SurfaceOfRevolution::FirstUParameter() const 
167 {
168   return 0.;
169 }
170
171 //=======================================================================
172 //function : LastUParameter
173 //purpose  : 
174 //=======================================================================
175
176 Standard_Real GeomAdaptor_SurfaceOfRevolution::LastUParameter() const 
177 {
178   return 2*M_PI;
179 }
180
181 //=======================================================================
182 //function : FirstVParameter
183 //purpose  : 
184 //=======================================================================
185
186 Standard_Real GeomAdaptor_SurfaceOfRevolution::FirstVParameter() const 
187 {
188   return myBasisCurve->FirstParameter();
189 }
190
191 //=======================================================================
192 //function : LastVParameter
193 //purpose  : 
194 //=======================================================================
195
196 Standard_Real GeomAdaptor_SurfaceOfRevolution::LastVParameter() const 
197 {
198   return myBasisCurve->LastParameter();
199 }
200
201 //=======================================================================
202 //function : UContinuity
203 //purpose  : 
204 //=======================================================================
205
206 GeomAbs_Shape GeomAdaptor_SurfaceOfRevolution::UContinuity() const 
207 {
208   return GeomAbs_CN;
209 }
210
211 //=======================================================================
212 //function : VContinuity
213 //purpose  : 
214 //=======================================================================
215
216 GeomAbs_Shape GeomAdaptor_SurfaceOfRevolution::VContinuity() const 
217 {
218   return myBasisCurve->Continuity();
219 }
220
221 //=======================================================================
222 //function : NbUIntervals
223 //purpose  : 
224 //=======================================================================
225
226 Standard_Integer GeomAdaptor_SurfaceOfRevolution::NbUIntervals(const GeomAbs_Shape ) const
227 {
228   return 1;
229 }
230
231 //=======================================================================
232 //function : NbVIntervals
233 //purpose  : 
234 //=======================================================================
235
236 Standard_Integer GeomAdaptor_SurfaceOfRevolution::NbVIntervals(const GeomAbs_Shape S) const
237 {
238   return myBasisCurve->NbIntervals(S);
239 }
240
241 //=======================================================================
242 //function : UIntervals
243 //purpose  : 
244 //=======================================================================
245
246 void GeomAdaptor_SurfaceOfRevolution::UIntervals(TColStd_Array1OfReal& T,
247                                                  const GeomAbs_Shape ) const
248 {
249   T(T.Lower()  ) = 0.;
250   T(T.Lower()+1) = 2*M_PI;
251 }
252
253
254 //=======================================================================
255 //function : VIntervals
256 //purpose  : 
257 //=======================================================================
258
259 void GeomAdaptor_SurfaceOfRevolution::VIntervals(TColStd_Array1OfReal& T,
260                                                  const GeomAbs_Shape S) const 
261 {
262   myBasisCurve->Intervals(T,S);
263 }
264
265
266 //=======================================================================
267 //function : UTrim
268 //purpose  : 
269 //=======================================================================
270
271 Handle(Adaptor3d_HSurface) GeomAdaptor_SurfaceOfRevolution::UTrim (const Standard_Real First, const Standard_Real Last, const Standard_Real Tol) const
272 {
273   const Standard_Real Eps = Precision::PConfusion();
274   (void )Eps; (void )First; (void )Last; (void )Tol;
275   Standard_OutOfRange_Raise_if
276     (  Abs(First) > Eps || Abs(Last - 2.*M_PI) > Eps,
277      "GeomAdaptor_SurfaceOfRevolution : UTrim : Parameters out of range");
278
279   Handle(GeomAdaptor_HSurfaceOfRevolution) HR = new GeomAdaptor_HSurfaceOfRevolution(
280       GeomAdaptor_SurfaceOfRevolution(myBasisCurve, myAxis));
281   return HR;
282 }
283
284
285 //=======================================================================
286 //function : VTrim
287 //purpose  : 
288 //=======================================================================
289
290 Handle(Adaptor3d_HSurface) GeomAdaptor_SurfaceOfRevolution::VTrim
291 (const Standard_Real First,
292  const Standard_Real Last,
293  const Standard_Real Tol) const 
294 {
295   Handle(Adaptor3d_HCurve) HC = BasisCurve()->Trim(First,Last,Tol);
296   Handle(GeomAdaptor_HSurfaceOfRevolution) HR = new GeomAdaptor_HSurfaceOfRevolution(
297       GeomAdaptor_SurfaceOfRevolution(HC, myAxis));
298   return HR;
299 }
300
301
302 //=======================================================================
303 //function : IsUClosed
304 //purpose  : 
305 //=======================================================================
306
307 Standard_Boolean GeomAdaptor_SurfaceOfRevolution::IsUClosed() const 
308 {
309   return Standard_True;
310 }
311
312 //=======================================================================
313 //function : IsVClosed
314 //purpose  : 
315 //=======================================================================
316
317 Standard_Boolean GeomAdaptor_SurfaceOfRevolution::IsVClosed() const 
318 {
319   return myBasisCurve->IsClosed();
320 }
321
322 //=======================================================================
323 //function : IsUPeriodic
324 //purpose  : 
325 //=======================================================================
326
327 Standard_Boolean GeomAdaptor_SurfaceOfRevolution::IsUPeriodic() const
328 {
329   return Standard_True;
330 }
331
332 //=======================================================================
333 //function : UPeriod
334 //purpose  : 
335 //=======================================================================
336
337 Standard_Real GeomAdaptor_SurfaceOfRevolution::UPeriod() const
338 {
339   return 2*M_PI;
340 }
341
342 //=======================================================================
343 //function : IsVPeriodic
344 //purpose  : 
345 //=======================================================================
346
347 Standard_Boolean GeomAdaptor_SurfaceOfRevolution::IsVPeriodic() const
348 {
349   return myBasisCurve->IsPeriodic();
350 }
351
352 //=======================================================================
353 //function : VPeriod
354 //purpose  : 
355 //=======================================================================
356
357 Standard_Real GeomAdaptor_SurfaceOfRevolution::VPeriod() const 
358 {
359   return myBasisCurve->Period();
360 }
361
362 //=======================================================================
363 //function : UResolution
364 //purpose  : 
365 //=======================================================================
366
367 Standard_Real GeomAdaptor_SurfaceOfRevolution::UResolution
368 (const Standard_Real R3d) const 
369 {
370   return Precision::Parametric(R3d);
371 }
372
373 //=======================================================================
374 //function : VResolution
375 //purpose  : 
376 //=======================================================================
377
378 Standard_Real GeomAdaptor_SurfaceOfRevolution::VResolution
379 (const Standard_Real R3d) const 
380 {
381   return myBasisCurve->Resolution(R3d);
382 }
383
384 //=======================================================================
385 //function : GetType
386 //purpose  : 
387 //=======================================================================
388
389 GeomAbs_SurfaceType GeomAdaptor_SurfaceOfRevolution::GetType() const 
390 {
391   Standard_Real TolConf = Precision::Confusion();
392   Standard_Real TolAng  = Precision::Angular();
393   Standard_Real TolConeSemiAng = Precision::Confusion();
394
395   switch (myBasisCurve->GetType()) {
396   case GeomAbs_Line:    {
397     gp_Ax1 Axe = myBasisCurve->Line().Position();
398     
399     if (myAxis.IsParallel(Axe, TolAng))
400     {
401       gp_Pnt P = Value(0., 0.);
402       Standard_Real R = gp_Vec(myAxeRev.Location(), P) * myAxeRev.XDirection();
403       if (R > TolConf)
404       {
405         return GeomAbs_Cylinder;
406       }
407     }
408     else if (myAxis.IsNormal(Axe, TolAng))
409       return GeomAbs_Plane;
410     else
411     {
412       Standard_Real uf = myBasisCurve->FirstParameter();
413       Standard_Real ul = myBasisCurve->LastParameter();
414       Standard_Boolean istrim = (!Precision::IsInfinite(uf) && 
415                                  !Precision::IsInfinite(ul));
416       if(istrim)
417       {
418         gp_Pnt pf = myBasisCurve->Value(uf);
419         gp_Pnt pl = myBasisCurve->Value(ul);
420         Standard_Real len = pf.Distance(pl);
421         //on calcule la distance projetee sur l axe.
422         gp_Vec vlin(pf,pl);
423         gp_Vec vaxe(myAxis.Direction());
424         Standard_Real projlen = Abs(vaxe.Dot(vlin));
425         if ((len - projlen) <= TolConf)
426         {
427           gp_Pnt P = Value(0., 0.);
428           Standard_Real R = gp_Vec(myAxeRev.Location(), P) * myAxeRev.XDirection();
429           if (R > TolConf)
430           {
431             return GeomAbs_Cylinder;
432           }
433         }
434         else if (projlen <= TolConf)
435           return GeomAbs_Plane;
436       }
437       gp_Vec V(myAxis.Location(), myBasisCurve->Line().Location());
438       gp_Vec W(Axe.Direction());
439       gp_Vec AxisDir(myAxis.Direction());
440       Standard_Real proj = Abs(W.Dot(AxisDir));
441       if (Abs(V.DotCross(AxisDir, W)) <= TolConf &&
442         (proj >= TolConeSemiAng && proj <= 1. - TolConeSemiAng))
443       {
444         return GeomAbs_Cone;
445       }
446     }
447     break;
448   }//case GeomAbs_Line: 
449   //
450   case GeomAbs_Circle:   {
451     Standard_Real MajorRadius, aR;
452     gp_Lin aLin(myAxis);
453     //
454     gp_Circ C = myBasisCurve->Circle();
455     const gp_Pnt& aLC = C.Location();
456     aR=C.Radius();
457     //
458    
459     if (!C.Position().IsCoplanar(myAxis, TolConf, TolAng))
460       return GeomAbs_SurfaceOfRevolution;
461     else if(aLin.Distance(aLC) <= TolConf)
462       return GeomAbs_Sphere;
463     else
464     {
465       MajorRadius = aLin.Distance(aLC);
466       if(MajorRadius > aR)
467       {
468         Standard_Real aT = 0., aDx, dX;
469         gp_Pnt aPx;
470
471         aPx = ElCLib::Value(aT, C);
472         aDx = aLin.Distance(aPx);
473         dX = aDx - MajorRadius - aR;
474         if (dX < 0.)
475           dX = -dX;
476         if (dX < TolConf)
477           return GeomAbs_Torus;
478       }
479     }
480     break;
481   }
482   //  
483   default:
484     break;
485   }
486   
487   return GeomAbs_SurfaceOfRevolution;
488 }
489
490 //=======================================================================
491 //function : Plane
492 //purpose  : 
493 //=======================================================================
494
495 gp_Pln GeomAdaptor_SurfaceOfRevolution::Plane() const 
496
497   Standard_NoSuchObject_Raise_if
498     (GetType() != GeomAbs_Plane, "GeomAdaptor_SurfaceOfRevolution:Plane");
499
500   gp_Ax3 Axe = myAxeRev;
501   gp_Pnt aPonCurve = Value(0., 0.);
502   Standard_Real aDot = (aPonCurve.XYZ() - myAxis.Location().XYZ()).Dot(myAxis.Direction().XYZ());
503
504   gp_Pnt P(myAxis.Location().XYZ() + aDot * myAxis.Direction().XYZ());
505   Axe.SetLocation(P);
506   if (Axe.XDirection().Dot(myBasisCurve->Line().Direction()) >= -Precision::Confusion())
507     Axe.XReverse();
508
509   return gp_Pln( Axe);
510 }
511
512 //=======================================================================
513 //function : Cylinder
514 //purpose  : 
515 //=======================================================================
516
517 gp_Cylinder GeomAdaptor_SurfaceOfRevolution::Cylinder() const
518 {
519   Standard_NoSuchObject_Raise_if
520     (GetType() != GeomAbs_Cylinder, "GeomAdaptor_SurfaceOfRevolution::Cylinder");
521
522   gp_Pnt P = Value(0., 0.);
523   Standard_Real R = gp_Vec(myAxeRev.Location(), P) * myAxeRev.XDirection();
524   return gp_Cylinder(myAxeRev, R);
525 }
526
527 //=======================================================================
528 //function : Cone
529 //purpose  : 
530 //=======================================================================
531
532 gp_Cone GeomAdaptor_SurfaceOfRevolution::Cone() const
533 {
534   Standard_NoSuchObject_Raise_if
535     ( GetType() != GeomAbs_Cone, "GeomAdaptor_SurfaceOfRevolution:Cone");
536
537   gp_Ax3 Axe = myAxeRev;
538   gp_Dir ldir = (myBasisCurve->Line()).Direction();
539   Standard_Real Angle = (Axe.Direction()).Angle(ldir);
540   gp_Pnt P0 = Value(0., 0.);
541   Standard_Real R = (Axe.Location()).Distance(P0);
542   if ( R >= Precision::Confusion()) {
543     gp_Pnt O = Axe.Location();
544     gp_Vec OP0(O,P0);
545     Standard_Real t = OP0.Dot(Axe.XDirection());
546     t /= ldir.Dot(Axe.XDirection());
547     OP0.Add(-t * gp_Vec(ldir));
548     if ( OP0.Dot(Axe.Direction()) > 0.) Angle = -Angle;
549   }
550   return gp_Cone( Axe, Angle, R);
551 }
552
553
554 //=======================================================================
555 //function : Sphere
556 //purpose  : 
557 //=======================================================================
558
559 gp_Sphere GeomAdaptor_SurfaceOfRevolution::Sphere() const 
560 {
561   Standard_NoSuchObject_Raise_if
562     ( GetType() != GeomAbs_Sphere, "GeomAdaptor_SurfaceOfRevolution:Sphere");
563
564   gp_Circ C = myBasisCurve->Circle();
565   gp_Ax3 Axe = myAxeRev;
566   Axe.SetLocation(C.Location());
567   return gp_Sphere(Axe, C.Radius());
568 }
569
570
571 //=======================================================================
572 //function : Torus
573 //purpose  : 
574 //=======================================================================
575
576 gp_Torus GeomAdaptor_SurfaceOfRevolution::Torus() const 
577 {
578   Standard_NoSuchObject_Raise_if
579     (GetType() != GeomAbs_Torus, "GeomAdaptor_SurfaceOfRevolution:Torus");
580
581   gp_Circ C = myBasisCurve->Circle();
582   Standard_Real MajorRadius = gp_Lin(myAxis).Distance(C.Location());
583   return gp_Torus(myAxeRev, MajorRadius, C.Radius());
584 }
585
586 //=======================================================================
587 //function : VDegree
588 //purpose  : 
589 //=======================================================================
590
591 Standard_Integer GeomAdaptor_SurfaceOfRevolution::VDegree() const 
592 {
593   return myBasisCurve->Degree();
594 }
595
596 //=======================================================================
597 //function : NbVPoles
598 //purpose  : 
599 //=======================================================================
600
601 Standard_Integer GeomAdaptor_SurfaceOfRevolution::NbVPoles() const
602 {
603   return myBasisCurve->NbPoles();
604 }
605
606 //=======================================================================
607 //function : NbVKnots
608 //purpose  : 
609 //=======================================================================
610
611 Standard_Integer GeomAdaptor_SurfaceOfRevolution::NbVKnots() const 
612 {
613   throw Standard_NoSuchObject("GeomAdaptor_SurfaceOfRevolution::NbVKnots");
614 }
615
616
617
618 //=======================================================================
619 //function : IsURational
620 //purpose  : 
621 //=======================================================================
622
623 Standard_Boolean GeomAdaptor_SurfaceOfRevolution::IsURational() const 
624 {
625   throw Standard_NoSuchObject("GeomAdaptor_SurfaceOfRevolution::IsURational");
626 }
627
628 //=======================================================================
629 //function : IsVRational
630 //purpose  : 
631 //=======================================================================
632
633 Standard_Boolean GeomAdaptor_SurfaceOfRevolution::IsVRational() const 
634 {
635   throw Standard_NoSuchObject("GeomAdaptor_SurfaceOfRevolution::IsVRational");
636 }
637
638
639 //=======================================================================
640 //function : Bezier
641 //purpose  : 
642 //=======================================================================
643
644 Handle(Geom_BezierSurface) GeomAdaptor_SurfaceOfRevolution::Bezier() const 
645 {
646   throw Standard_NoSuchObject("GeomAdaptor_SurfaceOfRevolution::Bezier");
647 }
648
649
650 //=======================================================================
651 //function : BSpline
652 //purpose  : 
653 //=======================================================================
654
655 Handle(Geom_BSplineSurface) GeomAdaptor_SurfaceOfRevolution::BSpline() const 
656 {
657   throw Standard_NoSuchObject("GeomAdaptor_SurfaceOfRevolution::BSpline");
658 }
659
660 //=======================================================================
661 //function : Axis
662 //purpose  : 
663 //=======================================================================
664
665 const gp_Ax3& GeomAdaptor_SurfaceOfRevolution::Axis() const 
666 {
667   return myAxeRev;
668 }
669
670 //=======================================================================
671 //function : BasisCurve
672 //purpose  : 
673 //=======================================================================
674
675 Handle(Adaptor3d_HCurve) GeomAdaptor_SurfaceOfRevolution::BasisCurve() const 
676 {
677   return myBasisCurve;
678 }