IMP  2.2.1
The Integrative Modeling Platform
SphereD.h
Go to the documentation of this file.
1 /**
2  * \file IMP/algebra/SphereD.h \brief Simple 3D sphere class.
3  *
4  * Copyright 2007-2014 IMP Inventors. All rights reserved.
5  *
6  */
7 
8 #ifndef IMPALGEBRA_SPHERE_D_H
9 #define IMPALGEBRA_SPHERE_D_H
10 
11 #include "algebra_macros.h"
12 #include "constants.h"
13 #include "BoundingBoxD.h"
14 #include "VectorD.h"
15 #include "utility.h"
16 #include "GeometricPrimitiveD.h"
17 #include <cmath>
18 
19 IMPALGEBRA_BEGIN_NAMESPACE
20 
21 /** Represent a sphere in D-dimensions.
22  \geometry
23  */
24 template <int D>
25 class SphereD : public GeometricPrimitiveD<D> {
26  public:
27  SphereD() {
28 #if IMP_HAS_CHECKS >= IMP_USAGE
29  radius_ = std::numeric_limits<double>::quiet_NaN();
30 #endif
31  }
32  SphereD(const VectorD<D> &center, double radius)
33  : center_(center), radius_(radius) {
34  IMP_USAGE_CHECK(radius >= 0, "Radius can't be negative");
35  }
36  double get_radius() const {
37  IMP_USAGE_CHECK(!base::isnan(radius_),
38  "Attempt to use uninitialized sphere.");
39  return radius_;
40  }
41  const VectorD<D> &get_center() const { return center_; }
42  //! Return true if this sphere contains the other one
43  bool get_contains(const SphereD<D> &o) const {
44  double d = (get_center() - o.get_center()).get_magnitude();
45  return (d + o.get_radius() < get_radius());
46  }
47 
48  //! Return true if the point is in or on the surface of the sphere
49  /**
50  */
51  bool get_contains(const VectorD<D> &p) const {
52  return ((p - center_).get_squared_magnitude() <= get_squared(radius_));
53  }
55  { out << "(" << spaces_io(center_) << ": " << get_radius() << ")"; });
56 #ifndef IMP_DOXYGEN
57 #ifndef SWIG
58  VectorD<D> &_access_center() { return center_; }
59  void _set_radius(double d) { radius_ = d; }
60  double &operator[](unsigned int i) {
61  IMP_USAGE_CHECK(i < D + 1, "Out of range");
62  if (i < D) {
63  return center_[i];
64  } else {
65  return radius_;
66  }
67  }
68  double operator[](unsigned int i) const {
69  IMP_USAGE_CHECK(i < D + 1, "Out of range");
70  if (i < D) {
71  return center_[i];
72  } else {
73  return radius_;
74  }
75  }
76 #endif
77 #endif
78  unsigned int get_dimension() const { return center_.get_dimension(); }
79 
80  private:
81  VectorD<D> center_;
82  double radius_;
83 };
84 
85 IMP_VOLUME_GEOMETRY_METHODS_D(Sphere, sphere,
86 { return PI * 4.0 * get_squared(g.get_radius()); },
87 { return PI * (4.0 / 3.0) * std::pow(g.get_radius(), 3.0); },
88  return BoundingBoxD<D>(g.get_center()) +
89  g.get_radius(););
90 
91 template <unsigned int D>
92 inline SphereD<D> get_unit_sphere_d() {
93  return SphereD<D>(get_zero_vector_d<D>(), 1.0);
94 }
95 
96 inline SphereD<-1> get_unit_sphere_kd(unsigned int d) {
97  return SphereD<-1>(get_zero_vector_kd(d), 1.0);
98 }
99 
100 //! Return the distance between the two spheres if they are disjoint
101 /** If they intersect, the distances are not meaningful.
102  See SphereD
103 */
104 template <int D>
105 inline double get_distance(const SphereD<D> &a, const SphereD<D> &b) {
106  double d = (a.get_center() - b.get_center()).get_magnitude();
107  return d - a.get_radius() - b.get_radius();
108 }
109 
110 //! Return the power distance between the two spheres
111 /** The power distance is the square of the distance between the centers
112  minus the sum of the square of the radii.
113  See SphereD
114 */
115 template <int D>
116 inline double get_power_distance(const SphereD<D> &a, const SphereD<D> &b) {
117  double d = (a.get_center() - b.get_center()).get_squared_magnitude();
118  return d - square(a.get_radius()) - square(b.get_radius());
119 }
120 
121 //! Return true if the two balls bounded by the two spheres interesect
122 /** See SphereD
123  */
124 template <int D>
125 inline bool get_interiors_intersect(const SphereD<D> &a, const SphereD<D> &b) {
126  double sr = a.get_radius() + b.get_radius();
127  for (unsigned int i = 0; i < 3; ++i) {
128  double delta = std::abs(a.get_center()[i] - b.get_center()[i]);
129  if (delta >= sr) return false;
130  }
131  return get_squared_distance(a.get_center(), b.get_center()) < get_squared(sr);
132 }
133 
134 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
135 
136 namespace internal {
137 template <int D>
138 struct SphereSpacesIO {
139  const SphereD<D> &v_;
140  SphereSpacesIO(const SphereD<D> &v) : v_(v) {}
141 };
142 template <int D>
143 inline std::ostream &operator<<(std::ostream &out, const SphereSpacesIO<D> &s) {
144  for (unsigned int i = 0; i < s.v_.get_center().get_dimension(); ++i) {
145  out << s.v_.get_center()[i] << " ";
146  }
147  out << s.v_.get_radius();
148  return out;
149 }
150 }
151 
152 //! Use this before outputing to a stream with spaces delimiting
153 /** std::cout << spaces_io(s);
154  produces "1.0 2.0 3.0 4.0" where the radius is 4.0
155  See SphereD
156  */
157 template <int D>
158 inline internal::SphereSpacesIO<D> spaces_io(const SphereD<D> &v) {
159  return internal::SphereSpacesIO<D>(v);
160 }
161 #endif
162 
163 #ifdef IMP_DOXYGEN
164 //! Compute the bounding box of any geometric object
165 template <class Geometry>
166 BoundingBoxD<3> get_bounding_box(const Geometry &);
167 //! Compute the surface area of any volumetric object
168 template <class Geometry>
169 double get_surface_area(const Geometry &);
170 //! Compute the volume of any volumetric object
171 template <class Geometry>
172 double get_volume(const Geometry &);
173 //! Compute the area of any surface object
174 template <class Geometry>
175 double get_area(const Geometry &);
176 
177 #endif
178 template <int D>
179 VectorD<D> get_vector_geometry(const SphereD<D> &s) {
180  return s.get_center();
181 }
182 
183 IMPALGEBRA_END_NAMESPACE
184 
185 #endif /* IMPALGEBRA_SPHERE_D_H */
Basic types used by IMP.
bool get_contains(const SphereD< D > &o) const
Return true if this sphere contains the other one.
Definition: SphereD.h:43
BoundingBoxD< 3 > get_bounding_box(const Geometry &)
Compute the bounding box of any geometric object.
VectorD< D > get_zero_vector_kd(int Di)
Return a dynamically sized vector of zeros.
Definition: VectorD.h:262
static const double PI
the constant pi
double get_area(const Geometry &)
Compute the area of any surface object.
#define IMP_SHOWABLE_INLINE(Name, how_to_show)
Declare the methods needed by an object that can be printed.
double get_squared_distance(const VectorD< D > &v1, const VectorD< D > &v2)
compute the squared distance between two vectors
Definition: VectorD.h:201
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Functions to deal with very common math operations.
A Cartesian vector in D-dimensions.
Definition: VectorD.h:52
bool get_interiors_intersect(const SphereD< D > &a, const SphereD< D > &b)
Return true if the two balls bounded by the two spheres interesect.
Definition: SphereD.h:125
#define IMP_VOLUME_GEOMETRY_METHODS_D(Name, name, area, volume, bounding_box)
implement the needed namespace methods for a geometry type
A bounding box in D dimensions.
Simple D vector class.
Various useful constants.
bool isnan(const T &a)
Return true if a number is NaN.
Definition: base/math.h:24
double get_distance(const SphereD< D > &a, const SphereD< D > &b)
Return the distance between the two spheres if they are disjoint.
Definition: SphereD.h:105
bool get_contains(const VectorD< D > &p) const
Return true if the point is in or on the surface of the sphere.
Definition: SphereD.h:51
double get_surface_area(const Geometry &)
Compute the surface area of any volumetric object.
Various important macros for implementing geometry.
double get_volume(const Geometry &)
Compute the volume of any volumetric object.
double get_power_distance(const SphereD< D > &a, const SphereD< D > &b)
Return the power distance between the two spheres.
Definition: SphereD.h:116