IMP logo
IMP Reference Guide  develop.98ef8da184,2024/04/23
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-2022 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 <cereal/access.hpp>
18 #include <cmath>
19 
20 IMPALGEBRA_BEGIN_NAMESPACE
21 
22 //! Represent a sphere in D-dimensions.
23 /** \geometry
24  */
25 template <int D>
26 class SphereD : public GeometricPrimitiveD<D> {
27  friend class cereal::access;
28 
29  template<class Archive>
30  void serialize(Archive &ar) {
31  ar(center_, radius_);
32  }
33 
34  public:
35  SphereD() {
36 #if IMP_HAS_CHECKS >= IMP_USAGE
37  radius_ = std::numeric_limits<double>::quiet_NaN();
38 #endif
39  }
40  SphereD(const VectorD<D> &center, double radius)
41  : center_(center), radius_(radius) {
42  IMP_USAGE_CHECK(radius >= 0, "Radius can't be negative");
43  }
44  double get_radius() const {
46  "Attempt to use uninitialized sphere.");
47  return radius_;
48  }
49  const VectorD<D> &get_center() const { return center_; }
50  //! Return true if this sphere contains the other one
51  bool get_contains(const SphereD<D> &o) const {
52  double d = (get_center() - o.get_center()).get_magnitude();
53  return (d + o.get_radius() < get_radius());
54  }
55 
56  //! Return true if the point is in or on the surface of the sphere
57  bool get_contains(const VectorD<D> &p) const {
58  return ((p - center_).get_squared_magnitude() <= get_squared(radius_));
59  }
61  { out << "(" << spaces_io(center_) << ": " << get_radius() << ")"; });
62 #ifdef IMP_SWIG_WRAPPER
63  static void _get_struct_size(size_t &sz, size_t &center_offset,
64  size_t &radius_offset) {
65  sz = sizeof(SphereD<D>);
66  center_offset = offsetof(SphereD<D>, center_);
67  radius_offset = offsetof(SphereD<D>, radius_);
68  }
69 #endif
70 #ifndef IMP_DOXYGEN
71 #ifndef SWIG
72  VectorD<D> &_access_center() { return center_; }
73  void _set_radius(double d) { radius_ = d; }
74  void _set_center(const VectorD<D> &center){ center_ = center; }
75  double &operator[](unsigned int i) {
76  IMP_USAGE_CHECK(i < D + 1, "Out of range");
77  if (i < D) {
78  return center_[i];
79  } else {
80  return radius_;
81  }
82  }
83  double operator[](unsigned int i) const {
84  IMP_USAGE_CHECK(i < D + 1, "Out of range");
85  if (i < D) {
86  return center_[i];
87  } else {
88  return radius_;
89  }
90  }
91 #endif
92 #endif
93  unsigned int get_dimension() const { return center_.get_dimension(); }
94 
95  private:
96  VectorD<D> center_;
97  double radius_;
98 };
99 
100 IMP_VOLUME_GEOMETRY_METHODS_D(Sphere, sphere,
101 { return PI * 4.0 * get_squared(g.get_radius()); },
102 { return PI * (4.0 / 3.0) * std::pow(g.get_radius(), 3.0); },
103  return BoundingBoxD<D>(g.get_center()) +
104  g.get_radius(););
105 
106 template <unsigned int D>
107 inline SphereD<D> get_unit_sphere_d() {
108  return SphereD<D>(get_zero_vector_d<D>(), 1.0);
109 }
110 
111 inline SphereD<-1> get_unit_sphere_kd(unsigned int d) {
112  return SphereD<-1>(get_zero_vector_kd(d), 1.0);
113 }
114 
115 //! Return the distance between the two spheres if they are disjoint
116 /** If they intersect, the distances are not meaningful.
117  \see SphereD
118 */
119 template <int D>
120 inline double get_distance(const SphereD<D> &a, const SphereD<D> &b) {
121  double d = (a.get_center() - b.get_center()).get_magnitude();
122  return d - a.get_radius() - b.get_radius();
123 }
124 
125 //! Return the power distance between the two spheres
126 /** The power distance is the square of the distance between the centers
127  minus the sum of the square of the radii.
128  \see SphereD
129 */
130 template <int D>
131 inline double get_power_distance(const SphereD<D> &a, const SphereD<D> &b) {
132  double d = (a.get_center() - b.get_center()).get_squared_magnitude();
133  return d - square(a.get_radius()) - square(b.get_radius());
134 }
135 
136 //! Return true if the two balls bounded by the two spheres intersect
137 /** \see SphereD
138  */
139 template <int D>
140 inline bool get_interiors_intersect(const SphereD<D> &a, const SphereD<D> &b) {
141  double sr = a.get_radius() + b.get_radius();
142  for (unsigned int i = 0; i < a.get_dimension(); ++i) {
143  double delta = std::abs(a.get_center()[i] - b.get_center()[i]);
144  if (delta >= sr) return false;
145  }
146  return get_squared_distance(a.get_center(), b.get_center()) < get_squared(sr);
147 }
148 
149 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
150 
151 namespace internal {
152 template <int D>
153 struct SphereSpacesIO {
154  const SphereD<D> &v_;
155  SphereSpacesIO(const SphereD<D> &v) : v_(v) {}
156 };
157 template <int D>
158 inline std::ostream &operator<<(std::ostream &out, const SphereSpacesIO<D> &s) {
159  for (unsigned int i = 0; i < s.v_.get_center().get_dimension(); ++i) {
160  out << s.v_.get_center()[i] << " ";
161  }
162  out << s.v_.get_radius();
163  return out;
164 }
165 }
166 
167 //! Use this before outputting to a stream with spaces delimiting
168 /** std::cout << spaces_io(s);
169  produces "1.0 2.0 3.0 4.0" where the radius is 4.0
170  \see SphereD
171  */
172 template <int D>
173 inline internal::SphereSpacesIO<D> spaces_io(const SphereD<D> &v) {
174  return internal::SphereSpacesIO<D>(v);
175 }
176 #endif
177 
178 #ifdef IMP_DOXYGEN
179 //! Compute the bounding box of any geometric object
180 template <class Geometry>
181 BoundingBoxD<3> get_bounding_box(const Geometry &);
182 //! Compute the surface area of any volumetric object
183 template <class Geometry>
184 double get_surface_area(const Geometry &);
185 //! Compute the volume of any volumetric object
186 template <class Geometry>
187 double get_volume(const Geometry &);
188 //! Compute the area of any surface object
189 template <class Geometry>
190 double get_area(const Geometry &);
191 
192 #endif
193 template <int D>
194 VectorD<D> get_vector_geometry(const SphereD<D> &s) {
195  return s.get_center();
196 }
197 
198 IMPALGEBRA_END_NAMESPACE
199 
200 #endif /* IMPALGEBRA_SPHERE_D_H */
Base class for geometric types.
bool get_contains(const SphereD< D > &o) const
Return true if this sphere contains the other one.
Definition: SphereD.h:51
#define IMP_SHOWABLE_INLINE(Name, how_to_show)
Declare the methods needed by an object that can be printed.
VectorD< D > get_zero_vector_kd(int Di)
Return a dynamically sized vector of zeros.
Definition: VectorD.h:263
static const double PI
the constant pi
double get_volume(const Cone3D &g)
Definition: Cone3D.h:71
double get_squared_distance(const VectorD< D > &v1, const VectorD< D > &v2)
Compute the squared distance between two vectors.
Definition: VectorD.h:188
#define IMP_INTERNAL_CHECK(expr, message)
An assertion to check for internal errors in IMP. An IMP::ErrorException will be thrown.
Definition: check_macros.h:139
Base class for geometric types.
Functions to deal with very common math operations.
A Cartesian vector in D-dimensions.
Definition: VectorD.h:39
bool get_interiors_intersect(const SphereD< D > &a, const SphereD< D > &b)
Return true if the two balls bounded by the two spheres intersect.
Definition: SphereD.h:140
BoundingBoxD< 3 > get_bounding_box(const Cone3D &g)
Definition: Cone3D.h:71
#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.
double get_surface_area(const Cone3D &g)
Definition: Cone3D.h:71
double get_area(const Plane3D &g)
Definition: Plane3D.h:86
Various useful constants.
bool isnan(const T &a)
Return true if a number is NaN.
Definition: 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:120
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Definition: check_macros.h:168
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:57
Represent a sphere in D-dimensions.
Definition: SphereD.h:26
Various helper macros.
double get_power_distance(const SphereD< D > &a, const SphereD< D > &b)
Return the power distance between the two spheres.
Definition: SphereD.h:131