BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Circular_kernel_3/Circular_arc_3.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines