1#ifndef SPHERE_HPP
2#define SPHERE_HPP
3
4#include <boost/fusion/sequence/intrinsic/at_c.hpp>
5#include <boost/fusion/include/at_c.hpp>
6#include <boost/fusion/container/vector.hpp>
7#include <boost/fusion/include/vector.hpp>
8#include <boost/fusion/container/vector/vector_fwd.hpp>
9#include <boost/fusion/include/vector_fwd.hpp>
10#include "boost/multi_array.hpp"
11#include "Point.hpp"
12
13
14/*! \brief This class implement the Sphere concept in an N-dimensional space
15 *
16 * This class implement the sphere shape in an N-dimensional space
17 *
18 * \tparam T type of the space
19 * \tparam dim dimensionality
20 *
21 */
22
23template<unsigned int dim ,typename T> class Sphere
24{
25 public:
26
27 //! boost fusion that store the point
28 typedef boost::fusion::vector<T[dim],T> type;
29
30 //! Structure that store the data
31 type data;
32
33 //! property id of the center position of the sphere
34 static const unsigned int x = 0;
35 //! property id of the radius of the sphere
36 static const unsigned int r = 1;
37
38 /*! \brief Get the component i of the center
39 *
40 * \param i coordinate
41 * \return the coordinate i of the center
42 *
43 */
44 __device__ __host__ T center(unsigned int i)
45 {
46 return boost::fusion::at_c<x>(data)[i];
47 }
48
49 /*! \brief Sphere constructor
50 *
51 * Sphere constructor
52 *
53 * \tparam k dimensionality of the center point (and the sphere)
54 * \param c center point
55 * \param radius
56 *
57 */
58 __device__ __host__ Sphere(const Sphere<dim,T> & sph)
59 {
60 // Copy the center
61 for (int i = 0 ; i < dim ; i++)
62 {
63 boost::fusion::at_c<x>(data)[i] = boost::fusion::at_c<x>(sph.data)[i];
64 }
65
66 boost::fusion::at_c<r>(data) = boost::fusion::at_c<r>(sph.data);
67 }
68
69 /*! \brief Sphere constructor
70 *
71 * Sphere constructor
72 *
73 * \tparam k dimensionality of the center point (and the sphere)
74 * \param c center point
75 * \param radius
76 *
77 */
78 template<unsigned int k>
79 Sphere(boost::fusion::vector<T[k]> & c, T radius)
80 {
81 // Copy the center
82 for (int i = 0 ; i < dim ; i++)
83 {
84 boost::fusion::at_c<x>(data)[i] = boost::fusion::at_c<x>(c)[i];
85 }
86
87 boost::fusion::at_c<r>(data) = radius;
88 }
89
90 /*! \brief Sphere constructor
91 *
92 * Sphere constructor
93 *
94 * \tparam k dimensionality of the center point (and the sphere)
95 * \param c center point
96 * \param radius
97 *
98 */
99 Sphere(Point<dim,double> & c, T radius)
100 {
101 // Copy the center
102 for (int i = 0 ; i < dim ; i++)
103 {
104 boost::fusion::at_c<x>(data)[i] = c.get(i);
105 }
106
107 boost::fusion::at_c<r>(data) = radius;
108 }
109
110 /*! \brief Get the radius of the sphere
111 *
112 * \return the radius of the sphere
113 *
114 */
115 __device__ __host__ T radius() const
116 {
117 return boost::fusion::at_c<r>(data);
118 }
119
120 /*! \brief Check if a point is inside
121 *
122 * \tparam distance distance functor used to calculate the distance two points
123 * \param p Point to check if it is inside
124 *
125 * \return true if the point is inside
126 *
127 */
128 __device__ __host__ bool isInside(Point<dim,T> p) const
129 {
130 T dist = 0.0;
131
132 // calculate the distance of the center from the point
133
134 for (int i = 0; i < dim ; i++)
135 {
136 dist += (boost::fusion::at_c<x>(data)[i] - p.get(i) )*(boost::fusion::at_c<x>(data)[i] - p.get(i) );
137 }
138
139 // Check if the distance is smaller than the radius
140
141 if (dist <= boost::fusion::at_c<r>(data)*boost::fusion::at_c<r>(data))
142 {return true;}
143
144
145 return false;
146 }
147
148 /*! \brief Check if a point is inside
149 *
150 * \tparam distance distance functor used to calculate the distance two points
151 * \param p Point to check if it is inside
152 *
153 * \return true if the point is inside
154 *
155 */
156 template<typename Distance>
157 __device__ __host__ bool isInside(Point<dim,T> p) const
158 {
159 T dist = 0.0;
160
161 // Object to calculate distances
162 Distance d;
163
164 // calculate the distance of the center from the point
165
166 for (int i = 0; i < dim ; i++)
167 {
168 dist += d.accum_dist(boost::fusion::at_c<x>(data)[i],p.get(i) );
169 }
170
171 // Check if the distance is smaller than the radius
172
173 if (dist <= boost::fusion::at_c<r>(data))
174 {return true;}
175
176
177 return false;
178 }
179
180 /*! \brief Is the point inside the sphere
181 *
182 * \param pnt check if the point is inside
183 * \return true if it is inside
184 *
185 */
186
187 template<typename Distance> bool
188 __device__ __host__ isInside(float * pnt) const
189 {
190 T dist = 0.0;
191
192 // Object to calculate distances
193 Distance d;
194
195 // calculate the distance of the center from the point
196
197 for (int i = 0; i < dim ; i++)
198 {
199 dist += d.accum_dist(boost::fusion::at_c<x>(data)[i],pnt[i],i);
200 }
201
202 // Check if the distance is smaller than the radius
203
204 if (dist <= boost::fusion::at_c<r>(data))
205 {return true;}
206
207 return false;
208 }
209
210 /*! \brief Return the distance from the surface
211 *
212 * \param p point
213 * \return the distance from the surface. The sign indicate if is outside or inside the shape
214 *
215 */
216 __device__ __host__ T distance(Point<dim,T> & p) const
217 {
218 T dist = 0.0;
219
220 // calculate the distance of the center from the point
221
222 for (int i = 0; i < dim ; i++)
223 {
224 dist += (boost::fusion::at_c<x>(data)[i] - p.get(i))*(boost::fusion::at_c<x>(data)[i] - p.get(i));
225 }
226
227 return sqrt(dist) - radius();
228 }
229};
230
231#endif
232