BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Cartesian/Circle_3.h
Go to the documentation of this file.
00001 // Copyright (c) 2000  Utrecht University (The Netherlands),
00002 // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany),
00003 // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg
00004 // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria),
00005 // and Tel-Aviv University (Israel).  All rights reserved.
00006 //
00007 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public License as
00009 // published by the Free Software Foundation; version 2.1 of the License.
00010 // See the file LICENSE.LGPL distributed with CGAL.
00011 //
00012 // Licensees holding a valid commercial license may use this file in
00013 // accordance with the commercial license agreement provided with the software.
00014 //
00015 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 //
00018 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Cartesian_kernel/include/CGAL/Cartesian/Circle_3.h $
00019 // $Id:
00020 // 
00021 // Author(s)     : Monique Teillaud, Pedro Machado, Sebastien Loriot
00022 
00023 #ifndef CGAL_CARTESIAN_CIRCLEC3_H
00024 #define CGAL_CARTESIAN_CIRCLEC3_H
00025 
00026 #include <CGAL/Interval_nt.h>
00027 
00028 CGAL_BEGIN_NAMESPACE
00029 
00030 template <class R_ >
00031 class CircleC3 {
00032   typedef typename R_::Sphere_3                 Sphere_3;
00033   typedef typename R_::Plane_3                  Plane_3;
00034   typedef typename R_::Point_3                  Point_3;
00035   typedef typename R_::Vector_3                 Vector_3;
00036   typedef typename R_::Direction_3              Direction_3;
00037   typedef typename R_::FT                       FT;
00038 
00039   typedef std::pair<Sphere_3, Plane_3>             Rep;
00040   typedef typename R_::template Handle<Rep>::type  Base;
00041   Base base;  
00042 
00043 public:
00044   typedef R_                                     R;
00045 
00046   CircleC3() {}
00047 
00048   CircleC3(const Point_3& center, const FT& squared_r, const Direction_3& d)
00049   {
00050     CGAL_kernel_assertion(squared_r >= FT(0));
00051     // non-degenerated Direction
00052     CGAL_kernel_assertion((d.dx() != FT(0)) || (d.dy() != FT(0)) || (d.dz() != FT(0)));
00053     base = Rep(Sphere_3(center,squared_r),
00054                 plane_from_point_direction(center, d));
00055   }
00056 
00057   CircleC3(const Point_3& center, const FT& squared_r, const Vector_3& normal) 
00058   {
00059     CGAL_kernel_assertion(squared_r >= FT(0));
00060     // non-degenerated Vector
00061     CGAL_kernel_assertion((normal.x() != FT(0)) ||
00062                           (normal.y() != FT(0)) ||
00063                           (normal.z() != FT(0)));
00064     base = Rep(Sphere_3(center,squared_r),
00065                 Plane_3(center, normal.direction()));
00066   }
00067 
00068   CircleC3(const Point_3& center, const FT& squared_r, const Plane_3& p)
00069   {
00070     // the plane contains the center and it is not degenerate
00071     CGAL_kernel_assertion(!R().is_degenerate_3_object()(p));
00072     CGAL_kernel_assertion((p.a() * center.x() +
00073                            p.b() * center.y() +
00074                            p.c() * center.z() +
00075                            p.d()) == CGAL::ZERO);
00076     CGAL_kernel_assertion(squared_r >= FT(0));
00077     base = Rep(Sphere_3(center,squared_r), p);
00078   }
00079 
00080   CircleC3(const Sphere_3 &s1, const Sphere_3 &s2) {
00081     Object obj = R().intersect_3_object()(s1, s2);
00082     // s1,s2 must intersect
00083     CGAL_kernel_precondition(!(obj.is_empty()));
00084     const typename R::Circle_3* circle_ptr=object_cast<typename R::Circle_3>(&obj);
00085     if(circle_ptr!=NULL)
00086       base = Rep(circle_ptr->diametral_sphere(), circle_ptr->supporting_plane());
00087     else {
00088       const typename R::Point_3* point=object_cast<typename R::Point_3>(&obj);
00089       CGAL_kernel_precondition(point!=NULL);
00090       CircleC3 circle = CircleC3(*point, FT(0), Vector_3(FT(1),FT(0),FT(0)));
00091       base = Rep(circle.diametral_sphere(), circle.supporting_plane());
00092     }
00093   }
00094 
00095   CircleC3(const Plane_3 &p, const Sphere_3 &s, int) : base(s, p) {}
00096 
00097   CircleC3(const Plane_3 &p, const Sphere_3 &s) {
00098     Object obj = R().intersect_3_object()(p, s);
00099     // s1,s2 must intersect
00100     CGAL_kernel_precondition(!(obj.is_empty()));
00101     const typename R::Circle_3* circle_ptr=object_cast<typename R::Circle_3>(&obj);
00102     if(circle_ptr!=NULL)
00103       base = Rep(circle_ptr->diametral_sphere(), circle_ptr->supporting_plane());
00104     else {
00105       const typename R::Point_3* point=object_cast<typename R::Point_3>(&obj);
00106       CGAL_kernel_precondition(point!=NULL);
00107       CircleC3 circle = CircleC3(*point, FT(0), Vector_3(FT(1),FT(0),FT(0)));
00108       base = Rep(circle.diametral_sphere(), circle.supporting_plane());
00109     }
00110   }
00111 
00112   CircleC3(const Point_3 &p, const Point_3 &q, const Point_3 &r) {
00113           // p, q, r are not collinear
00114           CGAL_kernel_precondition(!R().collinear_3_object()(p, q, r));
00115                 Plane_3 p1 = R().construct_plane_3_object()(p, q, r);
00116     Plane_3 p2 = R().construct_bisector_3_object()(p, q);
00117     Plane_3 p3 = R().construct_bisector_3_object()(p, r);
00118     Object obj = R().intersect_3_object()(p1, p2, p3);
00119     // must be a point, otherwise they are collinear
00120     const Point_3& center=*object_cast<Point_3>(&obj);
00121                 FT sqr = R().compute_squared_distance_3_object()(center, r);
00122                 Sphere_3 s = R().construct_sphere_3_object()(center, sqr);
00123                 base = Rep(s, p1);
00124   }
00125 
00126   const Plane_3& supporting_plane() const
00127   {
00128     return get(base).second;
00129   }
00130 
00131   const Sphere_3& supporting_sphere() const
00132   {
00133     return diametral_sphere();
00134   }
00135 
00136   Point_3 center() const
00137   {
00138     return diametral_sphere().center();
00139   }
00140 
00141   FT squared_radius() const
00142   {
00143     return diametral_sphere().squared_radius();
00144   }
00145 
00146   const Sphere_3& diametral_sphere() const
00147   {
00148     return get(base).first;
00149   }
00150 
00151   double approximate_area() const
00152   {
00153     return CGAL_PI * to_double(squared_radius());
00154   }
00155 
00156   double approximate_squared_length() const
00157   {
00158     return CGAL_PI * CGAL_PI * 4.0 * to_double(squared_radius());
00159   }
00160 
00161   FT area_divided_by_pi() const
00162   {
00163     return squared_radius();
00164   }
00165 
00166   FT squared_length_divided_by_pi_square() const
00167   {
00168     return 4 * squared_radius();
00169   }
00170 
00171   // this bbox function
00172   // can be optimize by doing different cases
00173   // for each variable = 0 (cases with is_zero)
00174   CGAL::Bbox_3 bbox() const
00175   {
00176     typedef CGAL::Interval_nt<false> Interval;
00177     CGAL::Interval_nt<false>::Protector ip;
00178     const Sphere_3 &s = diametral_sphere();
00179     const FT &sq_r = s.squared_radius();
00180     const Point_3 &p = s.center();
00181     if(sq_r == FT(0)) return p.bbox();
00182     const Plane_3 &plane = supporting_plane();
00183     const Interval a = CGAL::to_interval(plane.a());
00184     const Interval b = CGAL::to_interval(plane.b());
00185     const Interval c = CGAL::to_interval(plane.c());
00186     const Interval x = CGAL::to_interval(p.x());
00187     const Interval y = CGAL::to_interval(p.y());
00188     const Interval z = CGAL::to_interval(p.z());
00189     const Interval r2 = CGAL::to_interval(sq_r);
00190     const Interval r = CGAL::sqrt(r2); // maybe we can work with r2
00191                                        // in order to save this operation
00192                                        // but if the coefficients are to high
00193                                        // the multiplication would lead to inf
00194                                        // results
00195     const Interval a2 = CGAL::square(a);
00196     const Interval b2 = CGAL::square(b);
00197     const Interval c2 = CGAL::square(c);
00198     const Interval sqr_sum = a2 + b2 + c2;
00199     const Interval mx = r * CGAL::sqrt((sqr_sum - a2)/sqr_sum);
00200     const Interval my = r * CGAL::sqrt((sqr_sum - b2)/sqr_sum);
00201     const Interval mz = r * CGAL::sqrt((sqr_sum - c2)/sqr_sum);
00202     return CGAL::Bbox_3((x-mx).inf(),(y-my).inf(),(z-mz).inf(),
00203                         (x+mx).sup(),(y+my).sup(),(z+mz).sup());
00204   }
00205 
00206   bool operator==(const CircleC3 &) const;
00207   bool operator!=(const CircleC3 &) const;
00208 
00209   bool has_on(const Point_3 &p) const;
00210   bool has_on_bounded_side(const Point_3 &p) const;
00211   bool has_on_unbounded_side(const Point_3 &p) const;
00212   Bounded_side bounded_side(const Point_3 &p) const;
00213 
00214   bool is_degenerate() const
00215   {
00216     return diametral_sphere().is_degenerate();
00217   }
00218 
00219 };
00220 
00221 template < class R >
00222 inline
00223 bool
00224 CircleC3<R>::
00225 has_on(const typename CircleC3<R>::Point_3 &p) const
00226 {
00227   return R().has_on_3_object()(diametral_sphere(),p) &&
00228          R().has_on_3_object()(supporting_plane(),p);
00229 }
00230 
00231 template < class R >
00232 inline
00233 bool
00234 CircleC3<R>::
00235 has_on_bounded_side(const typename CircleC3<R>::Point_3 &p) const
00236 {
00237   CGAL_kernel_precondition(R().has_on_3_object()(supporting_plane(), p));
00238   return squared_distance(center(),p) < squared_radius();
00239 }
00240 
00241 template < class R >
00242 inline
00243 bool
00244 CircleC3<R>::
00245 has_on_unbounded_side(const typename CircleC3<R>::Point_3 &p) const
00246 {
00247   CGAL_kernel_precondition(R().has_on_3_object()(supporting_plane(), p));
00248   return squared_distance(center(),p) > squared_radius();
00249 }
00250 
00251 template < class R >
00252 CGAL_KERNEL_INLINE
00253 Bounded_side
00254 CircleC3<R>::
00255 bounded_side(const typename CircleC3<R>::Point_3 &p) const
00256 {
00257   CGAL_kernel_precondition(is_degenerate() || R().has_on_3_object()(supporting_plane(), p));
00258   return diametral_sphere().bounded_side(p);
00259 }
00260 
00261 template < class R >
00262 CGAL_KERNEL_INLINE
00263 bool
00264 CircleC3<R>::operator==(const CircleC3<R> &t) const
00265 {
00266   if (CGAL::identical(base, t.base))
00267     return true;
00268   if(!(center() == t.center() &&
00269        squared_radius() == t.squared_radius())) return false;
00270 
00271   const typename R::Plane_3 p1 = supporting_plane();
00272   const typename R::Plane_3 p2 = t.supporting_plane();
00273 
00274   if(is_zero(p1.a())) {
00275     if(!is_zero(p2.a())) return false;
00276     if(is_zero(p1.b())) {
00277       if(!is_zero(p2.b())) return false;
00278       return p1.c() * p2.d() == p1.d() * p2.c();
00279     }
00280     return (p2.c() * p1.b() == p1.c() * p2.b()) &&
00281            (p2.d() * p1.b() == p1.d() * p2.b());
00282   }
00283   return (p2.b() * p1.a() == p1.b() * p2.a()) &&
00284          (p2.c() * p1.a() == p1.c() * p2.a()) &&
00285          (p2.d() * p1.a() == p1.d() * p2.a());
00286 }
00287 
00288 template < class R >
00289 CGAL_KERNEL_INLINE
00290 bool
00291 CircleC3<R>::operator!=(const CircleC3<R> &t) const
00292 {
00293   return !(*this == t);
00294 }
00295 
00296 CGAL_END_NAMESPACE
00297 
00298 #endif // CGAL_CARTESIAN_CIRCLEC3_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines