0026252: GeomAdaptor_Surface should use inner adaptor to calculate values of complex...
[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       Standard_ConstructionError::Raise("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
272 (const Standard_Real 
273 #ifndef No_Exception
274                      First
275 #endif
276  ,const Standard_Real 
277 #ifndef No_Exception
278                      Last
279 #endif
280  ,const Standard_Real 
281                          ) const 
282 {
283 #ifndef No_Exception
284   Standard_Real Eps = Precision::PConfusion();
285 #endif
286   Standard_OutOfRange_Raise_if
287     (  Abs(First) > Eps || Abs(Last - 2.*M_PI) > Eps,
288      "GeomAdaptor_SurfaceOfRevolution : UTrim : Parameters out of range");
289
290   Handle(GeomAdaptor_HSurfaceOfRevolution) HR = new GeomAdaptor_HSurfaceOfRevolution(
291       GeomAdaptor_SurfaceOfRevolution(myBasisCurve, myAxis));
292   return HR;
293 }
294
295
296 //=======================================================================
297 //function : VTrim
298 //purpose  : 
299 //=======================================================================
300
301 Handle(Adaptor3d_HSurface) GeomAdaptor_SurfaceOfRevolution::VTrim
302 (const Standard_Real First,
303  const Standard_Real Last,
304  const Standard_Real Tol) const 
305 {
306   Handle(Adaptor3d_HCurve) HC = BasisCurve()->Trim(First,Last,Tol);
307   Handle(GeomAdaptor_HSurfaceOfRevolution) HR = new GeomAdaptor_HSurfaceOfRevolution(
308       GeomAdaptor_SurfaceOfRevolution(HC, myAxis));
309   return HR;
310 }
311
312
313 //=======================================================================
314 //function : IsUClosed
315 //purpose  : 
316 //=======================================================================
317
318 Standard_Boolean GeomAdaptor_SurfaceOfRevolution::IsUClosed() const 
319 {
320   return Standard_True;
321 }
322
323 //=======================================================================
324 //function : IsVClosed
325 //purpose  : 
326 //=======================================================================
327
328 Standard_Boolean GeomAdaptor_SurfaceOfRevolution::IsVClosed() const 
329 {
330   return myBasisCurve->IsClosed();
331 }
332
333 //=======================================================================
334 //function : IsUPeriodic
335 //purpose  : 
336 //=======================================================================
337
338 Standard_Boolean GeomAdaptor_SurfaceOfRevolution::IsUPeriodic() const
339 {
340   return Standard_True;
341 }
342
343 //=======================================================================
344 //function : UPeriod
345 //purpose  : 
346 //=======================================================================
347
348 Standard_Real GeomAdaptor_SurfaceOfRevolution::UPeriod() const
349 {
350   return 2*M_PI;
351 }
352
353 //=======================================================================
354 //function : IsVPeriodic
355 //purpose  : 
356 //=======================================================================
357
358 Standard_Boolean GeomAdaptor_SurfaceOfRevolution::IsVPeriodic() const
359 {
360   return myBasisCurve->IsPeriodic();
361 }
362
363 //=======================================================================
364 //function : VPeriod
365 //purpose  : 
366 //=======================================================================
367
368 Standard_Real GeomAdaptor_SurfaceOfRevolution::VPeriod() const 
369 {
370   return myBasisCurve->Period();
371 }
372
373 //=======================================================================
374 //function : UResolution
375 //purpose  : 
376 //=======================================================================
377
378 Standard_Real GeomAdaptor_SurfaceOfRevolution::UResolution
379 (const Standard_Real R3d) const 
380 {
381   return Precision::Parametric(R3d);
382 }
383
384 //=======================================================================
385 //function : VResolution
386 //purpose  : 
387 //=======================================================================
388
389 Standard_Real GeomAdaptor_SurfaceOfRevolution::VResolution
390 (const Standard_Real R3d) const 
391 {
392   return myBasisCurve->Resolution(R3d);
393 }
394
395 //=======================================================================
396 //function : GetType
397 //purpose  : 
398 //=======================================================================
399
400 GeomAbs_SurfaceType GeomAdaptor_SurfaceOfRevolution::GetType() const 
401 {
402   Standard_Real TolConf = Precision::Confusion();
403   Standard_Real TolAng  = Precision::Angular();
404
405   switch (myBasisCurve->GetType()) {
406   case GeomAbs_Line:    {
407     gp_Ax1 Axe = myBasisCurve->Line().Position();
408     
409     if (myAxis.IsParallel(Axe, TolAng))
410       return GeomAbs_Cylinder;
411     else if (myAxis.IsNormal(Axe, TolAng))
412       return GeomAbs_Plane;
413     else
414     {
415       Standard_Real uf = myBasisCurve->FirstParameter();
416       Standard_Real ul = myBasisCurve->LastParameter();
417       Standard_Boolean istrim = (!Precision::IsInfinite(uf) && 
418                                  !Precision::IsInfinite(ul));
419       if(istrim)
420       {
421         gp_Pnt pf = myBasisCurve->Value(uf);
422         gp_Pnt pl = myBasisCurve->Value(ul);
423         Standard_Real len = pf.Distance(pl);
424         //on calcule la distance projetee sur l axe.
425         gp_Vec vlin(pf,pl);
426         gp_Vec vaxe(myAxis.Direction());
427         Standard_Real projlen = Abs(vaxe.Dot(vlin));
428         Standard_Real aTolConf = len*TolAng;
429         if ((len - projlen) <= aTolConf)
430           return GeomAbs_Cylinder;
431         else if (projlen <= aTolConf)
432           return GeomAbs_Plane;
433       }
434       gp_Vec V(myAxis.Location(), myBasisCurve->Line().Location());
435       gp_Vec W(Axe.Direction());
436       if (Abs(V.DotCross(myAxis.Direction(), W)) <= TolConf)
437         return GeomAbs_Cone;
438     }
439     break;
440   }//case GeomAbs_Line: 
441   //
442   case GeomAbs_Circle:   {
443     Standard_Real MajorRadius, aR;
444     gp_Lin aLin(myAxis);
445     //
446     gp_Circ C = myBasisCurve->Circle();
447     const gp_Pnt& aLC = C.Location();
448     aR=C.Radius();
449     //
450    
451     if (!C.Position().IsCoplanar(myAxis, TolConf, TolAng))
452       return GeomAbs_SurfaceOfRevolution;
453     else if(aLin.Distance(aLC) <= TolConf)
454       return GeomAbs_Sphere;
455     else
456     {
457       MajorRadius = aLin.Distance(aLC);
458       if(MajorRadius > aR)
459       {
460         Standard_Real aT = 0., aDx, dX;
461         gp_Pnt aPx;
462
463         aPx = ElCLib::Value(aT, C);
464         aDx = aLin.Distance(aPx);
465         dX = aDx - MajorRadius - aR;
466         if (dX < 0.)
467           dX = -dX;
468         if (dX < TolConf)
469           return GeomAbs_Torus;
470       }
471     }
472     break;
473   }
474   //  
475   default:
476     break;
477   }
478   
479   return GeomAbs_SurfaceOfRevolution;
480 }
481
482 //=======================================================================
483 //function : Plane
484 //purpose  : 
485 //=======================================================================
486
487 gp_Pln GeomAdaptor_SurfaceOfRevolution::Plane() const 
488
489   Standard_NoSuchObject_Raise_if
490     (GetType() != GeomAbs_Plane, "GeomAdaptor_SurfaceOfRevolution:Plane");
491
492   gp_Ax3 Axe = myAxeRev;
493   gp_Pnt aPonCurve = Value(0., 0.);
494   Standard_Real aDot = (aPonCurve.XYZ() - myAxis.Location().XYZ()).Dot(myAxis.Direction().XYZ());
495
496   gp_Pnt P(myAxis.Location().XYZ() + aDot * myAxis.Direction().XYZ());
497   Axe.SetLocation(P);
498   if (Axe.XDirection().Dot(myBasisCurve->Line().Direction()) >= -Precision::Confusion())
499     Axe.XReverse();
500
501   return gp_Pln( Axe);
502 }
503
504 //=======================================================================
505 //function : Cylinder
506 //purpose  : 
507 //=======================================================================
508
509 gp_Cylinder GeomAdaptor_SurfaceOfRevolution::Cylinder() const
510 {
511   Standard_NoSuchObject_Raise_if
512     (GetType() != GeomAbs_Cylinder, "GeomAdaptor_SurfaceOfRevolution::Cylinder");
513
514   gp_Pnt P = Value(0., 0.);
515   Standard_Real R = gp_Vec(myAxeRev.Location(), P) * myAxeRev.XDirection();
516   return gp_Cylinder(myAxeRev, R);
517 }
518
519 //=======================================================================
520 //function : Cone
521 //purpose  : 
522 //=======================================================================
523
524 gp_Cone GeomAdaptor_SurfaceOfRevolution::Cone() const
525 {
526   Standard_NoSuchObject_Raise_if
527     ( GetType() != GeomAbs_Cone, "GeomAdaptor_SurfaceOfRevolution:Cone");
528
529   gp_Ax3 Axe = myAxeRev;
530   gp_Dir ldir = (myBasisCurve->Line()).Direction();
531   Standard_Real Angle = (Axe.Direction()).Angle(ldir);
532   gp_Pnt P0 = Value(0., 0.);
533   Standard_Real R = (Axe.Location()).Distance(P0);
534   if ( R >= Precision::Confusion()) {
535     gp_Pnt O = Axe.Location();
536     gp_Vec OP0(O,P0);
537     Standard_Real t = OP0.Dot(Axe.XDirection());
538     t /= ldir.Dot(Axe.XDirection());
539     OP0.Add(-t * gp_Vec(ldir));
540     if ( OP0.Dot(Axe.Direction()) > 0.) Angle = -Angle;
541   }
542   return gp_Cone( Axe, Angle, R);
543 }
544
545
546 //=======================================================================
547 //function : Sphere
548 //purpose  : 
549 //=======================================================================
550
551 gp_Sphere GeomAdaptor_SurfaceOfRevolution::Sphere() const 
552 {
553   Standard_NoSuchObject_Raise_if
554     ( GetType() != GeomAbs_Sphere, "GeomAdaptor_SurfaceOfRevolution:Sphere");
555
556   gp_Circ C = myBasisCurve->Circle();
557   gp_Ax3 Axe = myAxeRev;
558   Axe.SetLocation(C.Location());
559   return gp_Sphere(Axe, C.Radius());
560 }
561
562
563 //=======================================================================
564 //function : Torus
565 //purpose  : 
566 //=======================================================================
567
568 gp_Torus GeomAdaptor_SurfaceOfRevolution::Torus() const 
569 {
570   Standard_NoSuchObject_Raise_if
571     (GetType() != GeomAbs_Torus, "GeomAdaptor_SurfaceOfRevolution:Torus");
572
573   gp_Circ C = myBasisCurve->Circle();
574   Standard_Real MajorRadius = gp_Lin(myAxis).Distance(C.Location());
575   return gp_Torus(myAxeRev, MajorRadius, C.Radius());
576 }
577
578 //=======================================================================
579 //function : VDegree
580 //purpose  : 
581 //=======================================================================
582
583 Standard_Integer GeomAdaptor_SurfaceOfRevolution::VDegree() const 
584 {
585   return myBasisCurve->Degree();
586 }
587
588 //=======================================================================
589 //function : NbVPoles
590 //purpose  : 
591 //=======================================================================
592
593 Standard_Integer GeomAdaptor_SurfaceOfRevolution::NbVPoles() const
594 {
595   return myBasisCurve->NbPoles();
596 }
597
598 //=======================================================================
599 //function : NbVKnots
600 //purpose  : 
601 //=======================================================================
602
603 Standard_Integer GeomAdaptor_SurfaceOfRevolution::NbVKnots() const 
604 {
605   Standard_NoSuchObject::Raise("GeomAdaptor_SurfaceOfRevolution::NbVKnots");
606   return 0;
607 }
608
609
610
611 //=======================================================================
612 //function : IsURational
613 //purpose  : 
614 //=======================================================================
615
616 Standard_Boolean GeomAdaptor_SurfaceOfRevolution::IsURational() const 
617 {
618   Standard_NoSuchObject::Raise("GeomAdaptor_SurfaceOfRevolution::IsURational");
619   return Standard_False;
620 }
621
622 //=======================================================================
623 //function : IsVRational
624 //purpose  : 
625 //=======================================================================
626
627 Standard_Boolean GeomAdaptor_SurfaceOfRevolution::IsVRational() const 
628 {
629   Standard_NoSuchObject::Raise("GeomAdaptor_SurfaceOfRevolution::IsVRational");
630   return Standard_False;
631 }
632
633
634 //=======================================================================
635 //function : Bezier
636 //purpose  : 
637 //=======================================================================
638
639 Handle(Geom_BezierSurface) GeomAdaptor_SurfaceOfRevolution::Bezier() const 
640 {
641   Standard_NoSuchObject::Raise("GeomAdaptor_SurfaceOfRevolution::Bezier");
642   return Handle(Geom_BezierSurface)();
643 }
644
645
646 //=======================================================================
647 //function : BSpline
648 //purpose  : 
649 //=======================================================================
650
651 Handle(Geom_BSplineSurface) GeomAdaptor_SurfaceOfRevolution::BSpline() const 
652 {
653   Standard_NoSuchObject::Raise("GeomAdaptor_SurfaceOfRevolution::BSpline");
654   return Handle(Geom_BSplineSurface)();
655 }
656
657 //=======================================================================
658 //function : Axis
659 //purpose  : 
660 //=======================================================================
661
662 const gp_Ax3& GeomAdaptor_SurfaceOfRevolution::Axis() const 
663 {
664   return myAxeRev;
665 }
666
667 //=======================================================================
668 //function : BasisCurve
669 //purpose  : 
670 //=======================================================================
671
672 Handle(Adaptor3d_HCurve) GeomAdaptor_SurfaceOfRevolution::BasisCurve() const 
673 {
674   return myBasisCurve;
675 }