00001
00002
00003
00004
00005
00006
00007 #ifndef IMPALGEBRA_SPHERE_D_H
00008 #define IMPALGEBRA_SPHERE_D_H
00009
00010 #include <cmath>
00011 #include <IMP/constants.h>
00012 #include "internal/cgal_predicates.h"
00013 #include "BoundingBoxD.h"
00014 #include "Vector3D.h"
00015 #include "algebra_macros.h"
00016
00017 IMPALGEBRA_BEGIN_NAMESPACE
00018
00019
00020
00021
00022 template <unsigned int D>
00023 class SphereD {
00024 public:
00025 SphereD(){
00026 #if IMP_BUILD < IMP_FAST
00027 radius_= std::numeric_limits<double>::quiet_NaN();
00028 #endif
00029 }
00030 SphereD(const VectorD<D>& center,double radius):center_(center),
00031 radius_(radius){}
00032 double get_radius() const {
00033 IMP_USAGE_CHECK(!is_nan(radius_),
00034 "Attempt to use uninitialized sphere.");
00035 return radius_;
00036 }
00037 const VectorD<D> &get_center() const {return center_;}
00038
00039 bool get_contains(const SphereD<D> &o) const {
00040 double d= (get_center()-o.get_center()).get_magnitude();
00041 return (d+ o.get_radius() < get_radius());
00042 }
00043
00044
00045
00046
00047 bool get_contains(const VectorD<D> &p) const {
00048 return ((p-center_).get_squared_magnitude() <= square(radius_));
00049 }
00050 IMP_SHOWABLE_INLINE({
00051 out << "(" << spaces_io(center_) << ": " << get_radius()
00052 << ")";
00053 });
00054 private:
00055 VectorD<D> center_;
00056 double radius_;
00057 };
00058
00059
00060 IMP_VOLUME_GEOMETRY_METHODS_D(Sphere,
00061 {
00062 return PI * 4.0 * square(g.get_radius());
00063 },
00064 {
00065 return PI * (4.0 / 3.0)
00066 * std::pow(g.get_radius(), 3.0);
00067 },
00068 return BoundingBoxD<D>(g.get_center())
00069 +g.get_radius();
00070 );
00071
00072 template <unsigned int D>
00073 SphereD<D> get_unit_sphere_d() {
00074 return SphereD<D>(get_zero_vector_d<D>(), 1.0);
00075 }
00076
00077
00078
00079
00080
00081 template <unsigned int D>
00082 inline double get_distance(const SphereD<D>& a, const SphereD<D> &b) {
00083 double d= (a.get_center()-b.get_center()).get_magnitude();
00084 return d - a.get_radius() - b.get_radius();
00085 }
00086
00087
00088
00089
00090
00091
00092 template <unsigned int D>
00093 inline double get_power_distance(const SphereD<D>& a, const SphereD<D> &b) {
00094 double d= (a.get_center()-b.get_center()).get_squared_magnitude();
00095 return d - square(a.get_radius()) - square(b.get_radius());
00096 }
00097
00098
00099
00100
00101
00102 template <unsigned int D>
00103 inline bool get_interiors_intersect(const SphereD<D> &a, const SphereD<D> &b) {
00104 double sr= a.get_radius() + b.get_radius();
00105 for (unsigned int i=0; i< 3; ++i) {
00106 double delta=std::abs(a.get_center()[i]- b.get_center()[i]);
00107 if (delta >= sr) return false;
00108 }
00109 return get_squared_distance(a.get_center(), b.get_center())
00110 < square(sr);
00111 }
00112
00113 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
00114
00115 namespace internal {
00116 template <unsigned int D>
00117 struct SphereSpacesIO
00118 {
00119 const SphereD<D> &v_;
00120 SphereSpacesIO(const SphereD<D> &v): v_(v){}
00121 };
00122 template <unsigned int D>
00123 inline std::ostream &operator<<(std::ostream &out, const SphereD<D> &s)
00124 {
00125 out << spaces_io(s.get_center()) << " " << s.get_radius();
00126 return out;
00127 }
00128 }
00129
00130
00131
00132
00133
00134
00135 template <unsigned int D>
00136 inline internal::SphereSpacesIO<D> spaces_io(const SphereD<D> &v) {
00137 return internal::SphereSpacesIO<D>(v);
00138 }
00139 #endif
00140
00141 #ifdef IMP_DOXYGEN
00142
00143 template <class Geometry>
00144 BoundingBoxD<3> get_bounding_box(const Geometry &);
00145
00146 template <class Geometry>
00147 double get_surface_area(const Geometry &);
00148
00149 template <class Geometry>
00150 double get_volume(const Geometry &);
00151
00152 template <class Geometry>
00153 double get_area(const Geometry &);
00154 #endif
00155
00156 IMPALGEBRA_END_NAMESPACE
00157
00158 #endif