BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Kernel_d/Sphere_d.h
Go to the documentation of this file.
00001 // Copyright (c) 2000,2001  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/Kernel_d/include/CGAL/Kernel_d/Sphere_d.h $
00019 // $Id: Sphere_d.h 42932 2008-04-17 10:13:31Z spion $
00020 // 
00021 //
00022 // Author(s)     : Michael Seel
00023 
00024 #ifndef CGAL_SPHERE_D_H
00025 #define CGAL_SPHERE_D_H
00026 
00027 #include <CGAL/basic.h>
00028 #include <vector>
00029 #include <CGAL/Dimension.h>
00030 
00031 CGAL_BEGIN_NAMESPACE
00032 
00033 template <class R> class Sphere_d;
00034 template <class R> bool equal_as_sets(const Sphere_d<R>&, const Sphere_d<R>&);
00035 
00036 template <class R>
00037 class  Sphere_d_rep  {
00038 
00039   typedef typename R::Point_d Point_d;
00040 
00041   friend class Sphere_d<R>;
00042   friend bool equal_as_sets <>
00043     (const Sphere_d<R>&, const Sphere_d<R>&);
00044 
00045   std::vector< Point_d > P; // d+1 defining points, index range 0-d
00046   Orientation orient;       // orientation(P)
00047   Point_d* cp;              // pointer to center (lazy calculated)
00048   
00049 public:
00050   Sphere_d_rep() : cp(0) {}
00051   Sphere_d_rep(int d)  : P(d), cp(0) {}
00052 
00053   template <class ForwardIterator>
00054   Sphere_d_rep(int d, ForwardIterator first, ForwardIterator last) : 
00055      P(first,last), cp(0)
00056   { TUPLE_DIM_CHECK(P.begin(),P.end(),Sphere_d);
00057     CGAL_assertion(d+1==int(P.size()));
00058     typename R::Orientation_d orientation_;
00059     orient = orientation_(P.begin(),P.end()); }
00060 
00061   ~Sphere_d_rep() { if (cp) delete cp; }
00062 
00063 };  // Sphere_d_rep<R>
00064 
00065 /*{\Manpage {Sphere_d}{R}{Simple Spheres}{S}}*/ 
00066 
00067 template <class R_>
00068 class Sphere_d : public Handle_for< Sphere_d_rep<R_> > {
00069 
00070 /*{\Mdefinition 
00071 An instance $S$ of the data type |Sphere_d| is an oriented sphere in
00072 some $d$-dimensional space. A sphere is defined by $d+1$ points with
00073 rational coordinates (class |Point_d<R>|). We use $A$ to denote the
00074 array of the defining points.  A set $A$ of defining points is
00075 \emph{legal} if either the points are affinely independent or if the
00076 points are all equal. Only a legal set of points defines a sphere in
00077 the geometric sense and hence many operations on spheres require the
00078 set of defining points to be legal.  The orientation of $S$ is equal
00079 to the orientation of the defining points, i.e., |orientation(A)|. }*/
00080 
00081 public: 
00082   typedef CGAL::Dynamic_dimension_tag Ambient_dimension;
00083   typedef CGAL::Dynamic_dimension_tag Feature_dimension;
00084 
00085 /*{\Mtypes 4}*/
00086 
00087 typedef Sphere_d_rep<R_>  Rep;
00088 typedef Handle_for<Rep>   Base;
00089 typedef Sphere_d<R_>      Self;
00090 typedef typename R_::Point_d Point_d;
00091 
00092 using Base::ptr;
00093 
00094 Sphere_d(const Base& b) : Base(b) {}
00095 
00096 typedef R_ R;
00097 /*{\Mtypemember the representation type.}*/
00098 
00099 typedef typename R::RT RT;
00100 /*{\Mtypemember the ring type.}*/
00101 
00102 typedef typename R::FT FT;
00103 /*{\Mtypemember the field type.}*/
00104 
00105 typedef typename R::LA LA;
00106 /*{\Mtypemember the linear algebra layer.}*/
00107 
00108 typedef typename std::vector< Point_d >::const_iterator point_iterator;
00109 /*{\Mtypemember a read-only iterator for points defining the sphere.}*/
00110 
00111 /*{\Mcreation 4}*/ 
00112 
00113 Sphere_d(int d = 0) : Base( Rep(d+1) ) 
00114 /*{\Mcreate introduces a variable |\Mvar| of type |\Mname|. |\Mvar|
00115 is initialized to the empty sphere centered at the origin of
00116 $d$-dimensional space. }*/
00117 { 
00118   Point_d p(d);
00119   for (int i = 0; i <= d; i++) ptr()->P[i] = p;
00120   ptr()->orient = ZERO;
00121   ptr()->cp = new Point_d(p); 
00122 }
00123 
00124 template <class ForwardIterator>
00125 Sphere_d(int d, ForwardIterator first, ForwardIterator last) :
00126 /*{\Mcreate introduces a variable |\Mvar| of type |\Mname|. |\Mvar| is
00127 initialized to the sphere through the points in |A = set [first,last)|. 
00128 \precond $A$ consists of $d+1$ $d$-dimensional points.}*/
00129   Base( Rep(d,first,last) ) {}
00130 
00131 Sphere_d(const Self& c) : Base(c) {}
00132 ~Sphere_d() {}
00133 
00134 /*{\Moperations 4 3}*/
00135 
00136 int dimension() const 
00137 /*{\Mop returns the dimension of |\Mvar|.}*/
00138 { return ptr()->P.size() - 1; }
00139 
00140 Point_d point(int i) const
00141 /*{\Mop returns the $i$-th defining point. \precond $0 \le i \le |dim|$.}*/
00142 { CGAL_assertion_msg((0<=i && i<=dimension()), 
00143     "Sphere_d::point(): index out of range.");
00144   return ptr()->P[i]; 
00145 }
00146 
00147 point_iterator points_begin() const { return ptr()->P.begin(); }
00148 /*{\Mop returns an iterator pointing to the first defining point.}*/
00149 
00150 point_iterator points_end() const { return ptr()->P.end(); }
00151 /*{\Mop returns an iterator pointing beyond the last defining point.}*/
00152 
00153 bool is_degenerate() const { return (ptr()->orient == CGAL::ZERO); }
00154 /*{\Mop returns true iff the defining points are not full dimenional.}*/
00155 
00156 bool is_legal() const
00157 /*{\Mop returns true iff the set of defining points is legal.
00158 A set of defining points is legal iff their orientation is
00159 non-zero or if they are all equal.}*/
00160 { if (ptr()->orient != ZERO ) return true;
00161   const std::vector< Point_d >& A = ptr()->P;
00162   Point_d po = A[0];
00163   for (int i = 1; i < int(A.size()); ++i) 
00164     if (A[i] != po) return false;
00165   return true;
00166 }
00167 
00168 Point_d center() const
00169 /*{\Mop  returns the center of |\Mvar|. \precond The orientation 
00170 of |\Mvar| is non-zero. }*/
00171 { 
00172   if (ptr()->cp == 0) {
00173     if (ptr()->orient == 0) {
00174       const std::vector< Point_d >& A = ptr()->P;
00175       Point_d po = A[0];
00176       for (int i = 1; i < int(A.size()); ++i) 
00177         if (A[i] != po)
00178           CGAL_error_msg("Sphere_d::center(): points are illegal.");
00179       const_cast<Self&>(*this).ptr()->cp = new Point_d(A[0]);
00180       return *(ptr()->cp);
00181     }
00182     typename R::Center_of_sphere_d center_of_sphere_;
00183     const_cast<Self&>(*this).ptr()->cp = 
00184       new Point_d(center_of_sphere_(points_begin(),points_end()));
00185   }
00186   return *(ptr()->cp);
00187 }
00188 
00189 
00190 
00191 FT squared_radius() const
00192 /*{\Mop returns the squared radius of the sphere.}*/
00193 { if (is_degenerate()) return 0;
00194   return (point(0)-center()).squared_length();
00195 }
00196 
00197 Orientation orientation()  const { return ptr()->orient; }
00198 /*{\Mop returns the orientation of |\Mvar|.}*/
00199 
00200 Oriented_side oriented_side(const Point_d& p) const
00201 /*{\Mop returns either the constant |ON_ORIENTED_BOUNDARY|,
00202 |ON_POSITIVE_SIDE|, or |ON_NEGATIVE_SIDE|, iff p lies on the boundary,
00203 properly on the positive side, or properly on the negative side of
00204 circle, resp.}*/ 
00205 { typename R::Side_of_oriented_sphere_d side; 
00206   return side(points_begin(),points_end(),p); }
00207 
00208 Bounded_side bounded_side(const Point_d& p) const
00209 /*{\Mop returns |ON_BOUNDED_SIDE|, |ON_BOUNDARY|, or
00210 |ON_UNBOUNDED_SIDE| iff p lies properly inside, on
00211  the boundary, or properly outside of circle, resp.}*/
00212 { typename R::Side_of_bounded_sphere_d side;
00213   return side(points_begin(),points_end(),p); }
00214 
00215 bool has_on_positive_side (const Point_d& p) const
00216 /*{\Mop returns |\Mvar.oriented_side(p)==ON_POSITIVE_SIDE|.}*/
00217 { return oriented_side(p) == ON_POSITIVE_SIDE; }
00218 
00219 bool has_on_negative_side (const Point_d& p) const
00220 /*{\Mop returns |\Mvar.oriented_side(p)==ON_NEGATIVE_SIDE|.}*/
00221 { return oriented_side(p) == ON_NEGATIVE_SIDE; }
00222 
00223 bool has_on_boundary (const Point_d& p) const
00224 /*{\Mop returns |\Mvar.oriented_side(p)==ON_ORIENTED_BOUNDARY|,
00225 which is the same as |\Mvar.bounded_side(p)==ON_BOUNDARY|.}*/
00226 { return oriented_side(p) == ON_ORIENTED_BOUNDARY; }
00227 
00228 bool has_on_bounded_side (const Point_d& p) const
00229 /*{\Mop returns |\Mvar.bounded_side(p)==ON_BOUNDED_SIDE|.}*/
00230 { return (int(ptr()->orient) * int(oriented_side(p))) > 0 ; }
00231 
00232 bool has_on_unbounded_side (const Point_d& p) const
00233 /*{\Mop returns |\Mvar.bounded_side(p)==ON_UNBOUNDED_SIDE|.}*/
00234 { return (int(ptr()->orient) * int(oriented_side(p))) < 0; }
00235 
00236 Sphere_d<R> opposite() const
00237 /*{\Mop returns the sphere with the same center and squared
00238   radius as |\Mvar| but with opposite orientation.}*/
00239 { CGAL_assertion(dimension()>1);
00240   if (is_degenerate()) return *this;
00241   std::vector< Point_d > V(points_begin(),points_end());
00242   std::swap(V[0],V[1]);
00243   return Sphere_d<R>(dimension(),V.begin(),V.end());
00244 }
00245 
00246 Sphere_d<R> transform(const Aff_transformation_d<R>& t) const
00247 /*{\Mopl returns $t(s)$. }*/ 
00248 { std::vector< Point_d > B(points_begin(),points_end());
00249   typename std::vector< Point_d >::iterator it;
00250   for (it = B.begin(); it != B.end(); ++it)
00251     *it = it->transform(t);
00252   return Sphere_d<R>(dimension(),B.begin(),B.end());
00253 }
00254 
00255 Sphere_d<R> operator+(const Vector_d<R>& v) const
00256 /*{\Mbinop returns the sphere translated by |v|. }*/ 
00257 { std::vector< Point_d > B(points_begin(),points_end());
00258   typename std::vector< Point_d >::iterator it;
00259   for (it = B.begin(); it != B.end(); ++it) it->operator+=(v);
00260   return Sphere_d<R>(dimension(),B.begin(),B.end());
00261 }
00262 
00263 bool operator==(const Sphere_d<R>& D) const
00264 { if (this->identical(D)) return true;
00265   if (dimension() != D.dimension()) return false;
00266   return (center()==D.center() &&
00267           squared_radius() == D.squared_radius() &&
00268           orientation() == D.orientation());
00269 }
00270 
00271 bool operator!=(const Sphere_d<R>& D) const 
00272 { return !operator==(D); }
00273 
00274 
00275 }; // end of class Sphere_d
00276 
00277 /*{\Mtext \headerline{Non-Member Functions} }*/
00278 template <class R>
00279 bool weak_equality(const Sphere_d<R>& s1, const Sphere_d<R>& s2)
00280 /*{\Mfunc Test for equality as unoriented spheres.}*/
00281 { if (s1.identical(s2)) return true;
00282   if (s1.dimension() != s2.dimension()) return false;
00283   return (s1.center()==s2.center() &&
00284           s1.squared_radius() == s2.squared_radius());
00285 }
00286 
00287 /*{\Mimplementation Spheres are implemented by a vector of points as
00288 an item type.  All operations like creation, initialization, tests,
00289 input and output of a sphere $s$ take time
00290 $O(|s.dimension()|)$. |dimension()|, point access take constant time.
00291 The space requirement for spheres is $O(|s.dimension()|)$ 
00292 neglecting the storage room of the points.}*/
00293 
00294 template <class R>
00295 std::ostream& operator<<(std::ostream& os, const CGAL::Sphere_d<R>& s) 
00296 { typedef typename Sphere_d<R>::point_iterator iterator;
00297   os << s.dimension()+1 << " ";
00298   for (iterator it=s.points_begin(); it!=s.points_end(); ++it)
00299     os << *it << " ";
00300   return os;
00301 } 
00302 
00303 template <class R> std::istream&  
00304 operator>>(std::istream& is, CGAL::Sphere_d<R>& s) 
00305 { int d; is >> d;
00306   std::vector< Point_d<R> > V(d);
00307   Point_d<R> p;
00308   while ( d-- ) { 
00309     if (!(is >> p)) return is;
00310     V[d] = p; 
00311   }
00312   s = Sphere_d<R>(V.size()-1, V.begin(), V.end() );
00313   return is;
00314 }
00315 
00316 
00317 /*
00318 The center is only defined if the set of defining points are
00319 legal. If the defining points are all equal the sphere is trivial. So
00320 assume otherwise. Then the center $c$ is the unique point with equal
00321 distance to all the defining points. A point $c$ has equal distance to
00322 point $p_0$ and $p_i$ if it lies on the perpendicual bisector of $p_d$
00323 and $p_i$, i.e., if it satiesfies the plane equation $(p_i - p_d)^T c
00324 = (p_i - p_d) (p_i + p_d)/2$. Note that $p_i - p_d$ is the normal
00325 vector of the bisector hyperplane and $(p_i + p_d)/2$ is the midpoint
00326 of $p_d$ and $p_i$. The equation above translates into the equation \[
00327 \sum_{0 \le j < d} 2*p_{dd}p_{id}(p_{ij}p_{dd} - p_{dj}p_{id})c_j/c_d
00328 = \sum_{0 \le j < d} (p_{ij}p_{dd} - p_{dj}p_{id})(p_{ij}p_{dd} +
00329 p_{dj}p_{id}) \] for the homogeneous coordinates of the points and the
00330 center. We may tentatively assume that $c_d = 1$, solve the
00331 corresponding linear system, and then define the center.
00332 */
00333 
00334 CGAL_END_NAMESPACE
00335 
00336 #endif // CGAL_SPHERE_D_H
00337 //----------------------- end of file ----------------------------------
00338 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines