1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
|
// Copyright (c) 2000,2001
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/next/Kernel_d/include/CGAL/Kernel_d/Sphere_d.h $
// $Id: Sphere_d.h 67093 2012-01-13 11:22:39Z lrineau $
//
//
// Author(s) : Michael Seel
#ifndef CGAL_SPHERE_D_H
#define CGAL_SPHERE_D_H
#include <CGAL/basic.h>
#include <vector>
#include <CGAL/Dimension.h>
namespace CGAL {
template <class R> class Sphere_d;
template <class R> bool equal_as_sets(const Sphere_d<R>&, const Sphere_d<R>&);
template <class R>
class Sphere_d_rep {
typedef typename R::Point_d Point_d;
friend class Sphere_d<R>;
friend bool equal_as_sets <>
(const Sphere_d<R>&, const Sphere_d<R>&);
std::vector< Point_d > P; // d+1 defining points, index range 0-d
Orientation orient; // orientation(P)
Point_d* cp; // pointer to center (lazy calculated)
public:
Sphere_d_rep() : cp(0) {}
Sphere_d_rep(int d) : P(d), cp(0) {}
template <class ForwardIterator>
Sphere_d_rep(int d, ForwardIterator first, ForwardIterator last) :
P(first,last), cp(0)
{ TUPLE_DIM_CHECK(P.begin(),P.end(),Sphere_d);
CGAL_assertion(d+1==int(P.size()));
typename R::Orientation_d orientation_;
orient = orientation_(P.begin(),P.end()); }
~Sphere_d_rep() { if (cp) delete cp; }
}; // Sphere_d_rep<R>
/*{\Manpage {Sphere_d}{R}{Simple Spheres}{S}}*/
template <class R_>
class Sphere_d : public Handle_for< Sphere_d_rep<R_> > {
/*{\Mdefinition
An instance $S$ of the data type |Sphere_d| is an oriented sphere in
some $d$-dimensional space. A sphere is defined by $d+1$ points with
rational coordinates (class |Point_d<R>|). We use $A$ to denote the
array of the defining points. A set $A$ of defining points is
\emph{legal} if either the points are affinely independent or if the
points are all equal. Only a legal set of points defines a sphere in
the geometric sense and hence many operations on spheres require the
set of defining points to be legal. The orientation of $S$ is equal
to the orientation of the defining points, i.e., |orientation(A)|. }*/
public:
typedef CGAL::Dynamic_dimension_tag Ambient_dimension;
typedef CGAL::Dynamic_dimension_tag Feature_dimension;
/*{\Mtypes 4}*/
typedef Sphere_d_rep<R_> Rep;
typedef Handle_for<Rep> Base;
typedef Sphere_d<R_> Self;
typedef typename R_::Point_d Point_d;
using Base::ptr;
Sphere_d(const Base& b) : Base(b) {}
typedef R_ R;
/*{\Mtypemember the representation type.}*/
typedef typename R::RT RT;
/*{\Mtypemember the ring type.}*/
typedef typename R::FT FT;
/*{\Mtypemember the field type.}*/
typedef typename R::LA LA;
/*{\Mtypemember the linear algebra layer.}*/
typedef typename std::vector< Point_d >::const_iterator point_iterator;
/*{\Mtypemember a read-only iterator for points defining the sphere.}*/
/*{\Mcreation 4}*/
Sphere_d(int d = 0) : Base( Rep(d+1) )
/*{\Mcreate introduces a variable |\Mvar| of type |\Mname|. |\Mvar|
is initialized to the empty sphere centered at the origin of
$d$-dimensional space. }*/
{
Point_d p(d);
for (int i = 0; i <= d; i++) ptr()->P[i] = p;
ptr()->orient = ZERO;
ptr()->cp = new Point_d(p);
}
template <class ForwardIterator>
Sphere_d(int d, ForwardIterator first, ForwardIterator last) :
/*{\Mcreate introduces a variable |\Mvar| of type |\Mname|. |\Mvar| is
initialized to the sphere through the points in |A = set [first,last)|.
\precond $A$ consists of $d+1$ $d$-dimensional points.}*/
Base( Rep(d,first,last) ) {}
Sphere_d(const Self& c) : Base(c) {}
~Sphere_d() {}
/*{\Moperations 4 3}*/
int dimension() const
/*{\Mop returns the dimension of |\Mvar|.}*/
{ return static_cast<int>(ptr()->P.size()) - 1; }
Point_d point(int i) const
/*{\Mop returns the $i$-th defining point. \precond $0 \le i \le |dim|$.}*/
{ CGAL_assertion_msg((0<=i && i<=dimension()),
"Sphere_d::point(): index out of range.");
return ptr()->P[i];
}
point_iterator points_begin() const { return ptr()->P.begin(); }
/*{\Mop returns an iterator pointing to the first defining point.}*/
point_iterator points_end() const { return ptr()->P.end(); }
/*{\Mop returns an iterator pointing beyond the last defining point.}*/
bool is_degenerate() const { return (ptr()->orient == CGAL::ZERO); }
/*{\Mop returns true iff the defining points are not full dimenional.}*/
bool is_legal() const
/*{\Mop returns true iff the set of defining points is legal.
A set of defining points is legal iff their orientation is
non-zero or if they are all equal.}*/
{ if (ptr()->orient != ZERO ) return true;
const std::vector< Point_d >& A = ptr()->P;
Point_d po = A[0];
for (int i = 1; i < int(A.size()); ++i)
if (A[i] != po) return false;
return true;
}
Point_d center() const
/*{\Mop returns the center of |\Mvar|. \precond The orientation
of |\Mvar| is non-zero. }*/
{
if (ptr()->cp == 0) {
if (ptr()->orient == 0) {
const std::vector< Point_d >& A = ptr()->P;
Point_d po = A[0];
for (int i = 1; i < int(A.size()); ++i)
if (A[i] != po)
CGAL_error_msg("Sphere_d::center(): points are illegal.");
const_cast<Self&>(*this).ptr()->cp = new Point_d(A[0]);
return *(ptr()->cp);
}
typename R::Center_of_sphere_d center_of_sphere_;
const_cast<Self&>(*this).ptr()->cp =
new Point_d(center_of_sphere_(points_begin(),points_end()));
}
return *(ptr()->cp);
}
FT squared_radius() const
/*{\Mop returns the squared radius of the sphere.}*/
{ if (is_degenerate()) return 0;
return (point(0)-center()).squared_length();
}
Orientation orientation() const { return ptr()->orient; }
/*{\Mop returns the orientation of |\Mvar|.}*/
Oriented_side oriented_side(const Point_d& p) const
/*{\Mop returns either the constant |ON_ORIENTED_BOUNDARY|,
|ON_POSITIVE_SIDE|, or |ON_NEGATIVE_SIDE|, iff p lies on the boundary,
properly on the positive side, or properly on the negative side of
circle, resp.}*/
{ typename R::Side_of_oriented_sphere_d side;
return side(points_begin(),points_end(),p); }
Bounded_side bounded_side(const Point_d& p) const
/*{\Mop returns |ON_BOUNDED_SIDE|, |ON_BOUNDARY|, or
|ON_UNBOUNDED_SIDE| iff p lies properly inside, on
the boundary, or properly outside of circle, resp.}*/
{ typename R::Side_of_bounded_sphere_d side;
return side(points_begin(),points_end(),p); }
bool has_on_positive_side (const Point_d& p) const
/*{\Mop returns |\Mvar.oriented_side(p)==ON_POSITIVE_SIDE|.}*/
{ return oriented_side(p) == ON_POSITIVE_SIDE; }
bool has_on_negative_side (const Point_d& p) const
/*{\Mop returns |\Mvar.oriented_side(p)==ON_NEGATIVE_SIDE|.}*/
{ return oriented_side(p) == ON_NEGATIVE_SIDE; }
bool has_on_boundary (const Point_d& p) const
/*{\Mop returns |\Mvar.oriented_side(p)==ON_ORIENTED_BOUNDARY|,
which is the same as |\Mvar.bounded_side(p)==ON_BOUNDARY|.}*/
{ return oriented_side(p) == ON_ORIENTED_BOUNDARY; }
bool has_on_bounded_side (const Point_d& p) const
/*{\Mop returns |\Mvar.bounded_side(p)==ON_BOUNDED_SIDE|.}*/
{ return (int(ptr()->orient) * int(oriented_side(p))) > 0 ; }
bool has_on_unbounded_side (const Point_d& p) const
/*{\Mop returns |\Mvar.bounded_side(p)==ON_UNBOUNDED_SIDE|.}*/
{ return (int(ptr()->orient) * int(oriented_side(p))) < 0; }
Sphere_d<R> opposite() const
/*{\Mop returns the sphere with the same center and squared
radius as |\Mvar| but with opposite orientation.}*/
{ CGAL_assertion(dimension()>1);
if (is_degenerate()) return *this;
std::vector< Point_d > V(points_begin(),points_end());
std::swap(V[0],V[1]);
return Sphere_d<R>(dimension(),V.begin(),V.end());
}
Sphere_d<R> transform(const Aff_transformation_d<R>& t) const
/*{\Mopl returns $t(s)$. }*/
{ std::vector< Point_d > B(points_begin(),points_end());
typename std::vector< Point_d >::iterator it;
for (it = B.begin(); it != B.end(); ++it)
*it = it->transform(t);
return Sphere_d<R>(dimension(),B.begin(),B.end());
}
Sphere_d<R> operator+(const Vector_d<R>& v) const
/*{\Mbinop returns the sphere translated by |v|. }*/
{ std::vector< Point_d > B(points_begin(),points_end());
typename std::vector< Point_d >::iterator it;
for (it = B.begin(); it != B.end(); ++it) it->operator+=(v);
return Sphere_d<R>(dimension(),B.begin(),B.end());
}
bool operator==(const Sphere_d<R>& D) const
{ if (this->identical(D)) return true;
if (dimension() != D.dimension()) return false;
return (center()==D.center() &&
squared_radius() == D.squared_radius() &&
orientation() == D.orientation());
}
bool operator!=(const Sphere_d<R>& D) const
{ return !operator==(D); }
}; // end of class Sphere_d
/*{\Mtext \headerline{Non-Member Functions} }*/
template <class R>
bool weak_equality(const Sphere_d<R>& s1, const Sphere_d<R>& s2)
/*{\Mfunc Test for equality as unoriented spheres.}*/
{ if (s1.identical(s2)) return true;
if (s1.dimension() != s2.dimension()) return false;
return (s1.center()==s2.center() &&
s1.squared_radius() == s2.squared_radius());
}
/*{\Mimplementation Spheres are implemented by a vector of points as
an item type. All operations like creation, initialization, tests,
input and output of a sphere $s$ take time
$O(|s.dimension()|)$. |dimension()|, point access take constant time.
The space requirement for spheres is $O(|s.dimension()|)$
neglecting the storage room of the points.}*/
template <class R>
std::ostream& operator<<(std::ostream& os, const CGAL::Sphere_d<R>& s)
{ typedef typename Sphere_d<R>::point_iterator iterator;
os << s.dimension()+1 << " ";
for (iterator it=s.points_begin(); it!=s.points_end(); ++it)
os << *it << " ";
return os;
}
template <class R> std::istream&
operator>>(std::istream& is, CGAL::Sphere_d<R>& s)
{ int d; is >> d;
std::vector< Point_d<R> > V(d);
Point_d<R> p;
while ( d-- ) {
if (!(is >> p)) return is;
V[d] = p;
}
s = Sphere_d<R>(static_cast<int>(V.size())-1, V.begin(), V.end() );
return is;
}
/*
The center is only defined if the set of defining points are
legal. If the defining points are all equal the sphere is trivial. So
assume otherwise. Then the center $c$ is the unique point with equal
distance to all the defining points. A point $c$ has equal distance to
point $p_0$ and $p_i$ if it lies on the perpendicual bisector of $p_d$
and $p_i$, i.e., if it satiesfies the plane equation $(p_i - p_d)^T c
= (p_i - p_d) (p_i + p_d)/2$. Note that $p_i - p_d$ is the normal
vector of the bisector hyperplane and $(p_i + p_d)/2$ is the midpoint
of $p_d$ and $p_i$. The equation above translates into the equation \[
\sum_{0 \le j < d} 2*p_{dd}p_{id}(p_{ij}p_{dd} - p_{dj}p_{id})c_j/c_d
= \sum_{0 \le j < d} (p_{ij}p_{dd} - p_{dj}p_{id})(p_{ij}p_{dd} +
p_{dj}p_{id}) \] for the homogeneous coordinates of the points and the
center. We may tentatively assume that $c_d = 1$, solve the
corresponding linear system, and then define the center.
*/
} //namespace CGAL
#endif // CGAL_SPHERE_D_H
//----------------------- end of file ----------------------------------
|