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