BWAPI
|
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