BWAPI
|
00001 // Copyright (c) 2008 INRIA Sophia-Antipolis (France). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under 00005 // the terms of the Q Public License version 1.0. 00006 // See the file LICENSE.QPL distributed with CGAL. 00007 // 00008 // Licensees holding a valid commercial license may use this file in 00009 // accordance with the commercial license agreement provided with the software. 00010 // 00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00013 // 00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Circular_kernel_3/include/CGAL/Circular_kernel_3/Circular_arc_3.h $ 00015 // $Id: Circular_arc_3.h 50731 2009-07-21 09:08:07Z sloriot $ 00016 // 00017 // Author(s) : Monique Teillaud, Sylvain Pion, Pedro Machado, 00018 // Sebastien Loriot, Julien Hazebrouck, Damien Leroy 00019 00020 // Partially supported by the IST Programme of the EU as a 00021 // STREP (FET Open) Project under Contract No IST-006413 00022 // (ACS -- Algorithms for Complex Shapes) 00023 00024 #ifndef CGAL_SPHERICAL_KERNEL_CIRCULAR_ARC_3_H 00025 #define CGAL_SPHERICAL_KERNEL_CIRCULAR_ARC_3_H 00026 00027 #include <CGAL/Circular_kernel_3/internal_functions_on_circular_arc_3.h> 00028 #include <boost/tuple/tuple.hpp> 00029 00030 00031 namespace CGAL { 00032 namespace CGALi{ 00033 template < class SK > 00034 class Circular_arc_3 { 00035 typedef typename SK::Plane_3 Plane_3; 00036 typedef typename SK::Circle_3 Circle_3; 00037 typedef typename SK::Sphere_3 Sphere_3; 00038 typedef typename SK::Point_3 Point_3; 00039 typedef typename SK::Circular_arc_point_3 Circular_arc_point_3; 00040 typedef typename SK::Line_3 Line_3; 00041 typedef typename SK::FT FT; 00042 00043 private: 00044 00045 typedef boost::tuple<Circle_3, Circular_arc_point_3, 00046 Circular_arc_point_3> Rep; 00047 typedef typename SK::template Handle<Rep>::type Base; 00048 00049 Base base; 00050 mutable bool _full; 00051 // It is the sign of the cross product 00052 // of the vector (Center -> S) x (Center -> T) 00053 // it saves execution time for the has_on functor 00054 Sign _sign_cross_product; 00055 00056 public: 00057 00058 const Sphere_3& reference_sphere(){ 00059 return get_ref_sphere(get(base).get<0>()); 00060 }; 00061 00062 00063 Circular_arc_3() 00064 {} 00065 00066 // The arc of circle goes from s to t in counterclockwise orientation 00067 // in relation to the normal vector N of the supporting plane 00068 // such that 00069 // if N.x != 0 then N.x > 0 00070 // else if N.y != 0 -> N.y > 0 00071 // else N.z > 0 00072 // Interesting thing is that if _sign_cross_product is negative 00073 // the arc is the bigger one (angle > pi) 00074 Circular_arc_3(const Circle_3 &c, 00075 const Circular_arc_point_3 &s, 00076 const Circular_arc_point_3 &t) 00077 : _full(false) 00078 { 00079 // l must pass through s and t, and s != t 00080 CGAL_kernel_precondition(SK().has_on_3_object()(c,s)); 00081 CGAL_kernel_precondition(SK().has_on_3_object()(c,t)); 00082 CGAL_kernel_precondition(s != t); 00083 base = Rep(c,s,t); 00084 // we can optimize the computations of the sign (for the has_on functor), 00085 // by computing the vector s-c and t-s, in order to use them directly on 00086 // another compute_sign_of_cross_product function 00087 // we can save time computing the substractions 00088 // the problem is: more memory space is needed 00089 _sign_cross_product = 00090 CGAL::SphericalFunctors::compute_sign_of_cross_product<SK>(s,t,c.center()); 00091 } 00092 00093 Circular_arc_3(const Circle_3 &c, 00094 const Point_3 &s, 00095 const Circular_arc_point_3 &t) 00096 : _full(false) 00097 { 00098 // l must pass through s and t, and s != t 00099 CGAL_kernel_precondition(SK().has_on_3_object()(c,s)); 00100 CGAL_kernel_precondition(SK().has_on_3_object()(c,t)); 00101 CGAL_kernel_precondition(Circular_arc_point_3(s) != t); 00102 base = Rep(c,s,t); 00103 _sign_cross_product = 00104 CGAL::SphericalFunctors::compute_sign_of_cross_product<SK>(s,t,c.center()); 00105 } 00106 00107 Circular_arc_3(const Circle_3 &c, 00108 const Circular_arc_point_3 &s, 00109 const Point_3 &t) 00110 : _full(false) 00111 { 00112 // l must pass through s and t, and s != t 00113 CGAL_kernel_precondition(SK().has_on_3_object()(c,s)); 00114 CGAL_kernel_precondition(SK().has_on_3_object()(c,t)); 00115 CGAL_kernel_precondition(s != Circular_arc_point_3(t)); 00116 base = Rep(c,s,t); 00117 _sign_cross_product = 00118 CGAL::SphericalFunctors::compute_sign_of_cross_product<SK>(s,t,c.center()); 00119 } 00120 00121 Circular_arc_3(const Circle_3 &c, 00122 const Point_3 &s, 00123 const Point_3 &t) 00124 : _full(false) 00125 { 00126 // l must pass through s and t, and s != t 00127 CGAL_kernel_precondition(SK().has_on_3_object()(c,s)); 00128 CGAL_kernel_precondition(SK().has_on_3_object()(c,t)); 00129 CGAL_kernel_precondition(Circular_arc_point_3(s) != 00130 Circular_arc_point_3(t)); 00131 base = Rep(c,s,t); 00132 _sign_cross_product = 00133 CGAL::SphericalFunctors::compute_sign_of_cross_product<SK>(s,t,c.center()); 00134 } 00135 00136 // This is the one of the two cases we want that s == t 00137 // that makes the is_full() correct and complete 00138 Circular_arc_3(const Circle_3 &c) 00139 : _full(true) 00140 { 00141 const Plane_3 &p = c.supporting_plane(); 00142 if(is_zero(p.b()) && is_zero(p.c())) { 00143 const Circular_arc_point_3 v = 00144 SphericalFunctors::y_extremal_point<SK>(c,true); 00145 base = Rep(c,v,v); 00146 } else { 00147 const Circular_arc_point_3 v = 00148 SphericalFunctors::x_extremal_point<SK>(c,true); 00149 base = Rep(c,v,v); 00150 } 00151 /* don't matter 00152 _sign_cross_product = 0; 00153 */ 00154 } 00155 00156 // This is the second case where we want that s == t 00157 // that makes the is_full() correct and complete 00158 Circular_arc_3(const Circle_3 &c,const Circular_arc_point_3& point) 00159 : base(Rep(c,point,point)),_full(true) 00160 {CGAL_kernel_precondition(SK().has_on_3_object()(c,point));} 00161 00162 Circular_arc_3(const Circle_3 &c, 00163 const Sphere_3 &s1, bool less_xyz_s1, 00164 const Sphere_3 &s2, bool less_xyz_s2) 00165 { 00166 std::vector<Object> sols1, sols2; 00167 // The spheres must not include the circle 00168 CGAL_kernel_precondition(!SK().has_on_3_object()(s1,c)); 00169 CGAL_kernel_precondition(!SK().has_on_3_object()(s2,c)); 00170 SK().intersect_3_object()(c, s1, std::back_inserter(sols1)); 00171 SK().intersect_3_object()(c, s2, std::back_inserter(sols2)); 00172 // l must intersect s1 and s2 00173 CGAL_kernel_precondition(sols1.size() > 0); 00174 CGAL_kernel_precondition(sols2.size() > 0); 00175 const std::pair<typename SK::Circular_arc_point_3, unsigned>& pair1= 00176 *object_cast<std::pair<typename SK::Circular_arc_point_3, unsigned> >( 00177 &sols1[(sols1.size()==1)?(0):(less_xyz_s1?0:1)] 00178 ); 00179 const std::pair<typename SK::Circular_arc_point_3, unsigned>& pair2= 00180 *object_cast<std::pair<typename SK::Circular_arc_point_3, unsigned> >( 00181 &sols2[(sols2.size()==1)?(0):(less_xyz_s2?0:1)] 00182 ); 00183 // the source and target must be different 00184 CGAL_kernel_precondition(pair1.first != pair2.first); 00185 *this = Circular_arc_3(c, pair1.first, pair2.first); 00186 } 00187 00188 Circular_arc_3(const Circle_3 &c, 00189 const Plane_3 &p1, bool less_xyz_p1, 00190 const Plane_3 &p2, bool less_xyz_p2) 00191 { 00192 std::vector<Object> sols1, sols2; 00193 // The planes must not include the circle 00194 CGAL_kernel_precondition(!SK().has_on_3_object()(p1,c)); 00195 CGAL_kernel_precondition(!SK().has_on_3_object()(p2,c)); 00196 SK().intersect_3_object()(c, p1, std::back_inserter(sols1)); 00197 SK().intersect_3_object()(c, p2, std::back_inserter(sols2)); 00198 // l must intersect s1 and s2 00199 CGAL_kernel_precondition(sols1.size() > 0); 00200 CGAL_kernel_precondition(sols2.size() > 0); 00201 const std::pair<typename SK::Circular_arc_point_3, unsigned>& pair1= 00202 *object_cast<std::pair<typename SK::Circular_arc_point_3, unsigned> >( 00203 &sols1[(sols1.size()==1)?(0):(less_xyz_p1?0:1)] 00204 ); 00205 const std::pair<typename SK::Circular_arc_point_3, unsigned>& pair2= 00206 *object_cast<std::pair<typename SK::Circular_arc_point_3, unsigned> >( 00207 &sols2[(sols2.size()==1)?(0):(less_xyz_p2?0:1)] 00208 ); 00209 // the source and target must be different 00210 CGAL_kernel_precondition(pair1.first != pair2.first); 00211 *this = Circular_arc_3(c, pair1.first, pair2.first); 00212 } 00213 00214 Circular_arc_3(const Point_3 &begin, 00215 const Point_3 &middle, 00216 const Point_3 &end) 00217 { 00218 CGAL_kernel_precondition(!CGAL::collinear(begin, middle, end)); 00219 const Circle_3 c = Circle_3(begin, middle, end); 00220 base = Rep(c,begin,end); 00221 _sign_cross_product = 00222 CGAL::SphericalFunctors::compute_sign_of_cross_product<SK> 00223 (begin,end,c.center()); 00224 } 00225 00226 const Circle_3& supporting_circle() const 00227 { 00228 return get(base).get<0>(); 00229 } 00230 00231 const Circular_arc_point_3& source() const 00232 { 00233 return get(base).get<1>(); 00234 } 00235 00236 const Circular_arc_point_3& target() const 00237 { 00238 return get(base).get<2>(); 00239 } 00240 00241 Plane_3 supporting_plane() const { 00242 return supporting_circle().supporting_plane(); 00243 } 00244 00245 Point_3 center() const { 00246 return supporting_circle().center(); 00247 } 00248 00249 FT squared_radius() const { 00250 return supporting_circle().squared_radius(); 00251 } 00252 00253 Sphere_3 diametral_sphere() const { 00254 return supporting_circle().diametral_sphere(); 00255 } 00256 00257 bool is_full() const { 00258 return _full; 00259 } 00260 00261 Sign sign_cross_product() const { 00262 return _sign_cross_product; 00263 } 00264 00265 double approximate_angle() const { 00266 if(is_full()) return 2.0*CGAL_PI; 00267 const double x1 = to_double(source().x()); 00268 const double y1 = to_double(source().y()); 00269 const double z1 = to_double(source().z()); 00270 const double x2 = to_double(target().x()); 00271 const double y2 = to_double(target().y()); 00272 const double z2 = to_double(target().z()); 00273 const double dx = x2-x1; 00274 const double dy = y2-y1; 00275 const double dz = z2-z1; 00276 const double d_sq = dx*dx + dy*dy + dz*dz; 00277 const double r_sq = to_double(squared_radius()); 00278 const double ap_ang = 2.0 * std::asin(0.5 * std::sqrt(d_sq / r_sq)); 00279 if(sign_cross_product() == NEGATIVE) return 2.0 * CGAL_PI - ap_ang; 00280 else return ap_ang; 00281 } 00282 00283 double approximate_squared_length() const { 00284 const double ang = approximate_angle(); 00285 return ang * ang * to_double(squared_radius()); 00286 } 00287 00288 // It is of course possible to increase the precision 00289 // maybe it will be done after 00290 CGAL::Bbox_3 bbox() const { 00291 return supporting_circle().bbox(); 00292 } 00293 00294 bool operator==(const Circular_arc_3 &) const; 00295 bool operator!=(const Circular_arc_3 &) const; 00296 00297 }; 00298 00299 template < class SK > 00300 CGAL_KERNEL_INLINE 00301 bool 00302 Circular_arc_3<SK>::operator==(const Circular_arc_3<SK> &t) const 00303 { 00304 if (CGAL::identical(base, t.base)) 00305 return true; 00306 return CGAL::SphericalFunctors::non_oriented_equal<SK>(*this, t); 00307 } 00308 00309 template < class SK > 00310 CGAL_KERNEL_INLINE 00311 bool 00312 Circular_arc_3<SK>::operator!=(const Circular_arc_3<SK> &t) const 00313 { 00314 return !(*this == t); 00315 } 00316 00317 } 00318 } 00319 00320 #endif