Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JCylinder3D.hh
Go to the documentation of this file.
1 #ifndef __JCYLINDER3D__
2 #define __JCYLINDER3D__
3 
4 #include <istream>
5 #include <ostream>
6 #include <limits>
7 #include <utility>
8 #include <cmath>
9 
10 #include "JTools/JConstants.hh"
11 #include "JGeometry2D/JCircle2D.hh"
12 #include "JGeometry3D/JVector3D.hh"
13 #include "JGeometry3D/JAxis3D.hh"
14 #include "JIO/JSerialisable.hh"
15 
16 
17 /**
18  * \author mdejong
19  */
20 
21 namespace JGEOMETRY3D {}
22 namespace JPP { using namespace JGEOMETRY3D; }
23 
24 namespace JGEOMETRY3D {
25 
26  using JIO::JReader;
27  using JIO::JWriter;
30 
31 
32  /**
33  * Cylinder object.
34  *
35  * A cylinder object consists of a 2D circle in (x,y) and a range in z.
36  */
37  class JCylinder3D :
38  public JCircle2D
39  {
40  public:
41  /**
42  * Default constructor.
43  */
45  JCircle2D(),
46  zmin(0.0),
47  zmax(0.0)
48  {}
49 
50 
51  /**
52  * Constructor.
53  *
54  * \param circle 2D circle in (x,y)
55  * \param zmin minimal z
56  * \param zmax maximal z
57  */
58  JCylinder3D(const JCircle2D& circle,
59  const double zmin,
60  const double zmax) :
61  JCircle2D(circle)
62  {
63  this->zmin = zmin;
64  this->zmax = zmax;
65  }
66 
67 
68  /**
69  * Constructor.
70  *
71  * Determines smallest enclosing cylinder for any number of points.
72  *
73  * \param __begin begin of data
74  * \param __end end of data
75  */
76  template<class T>
77  JCylinder3D(T __begin,
78  T __end) :
79  JCircle2D(__begin, __end),
80  zmin(0.0),
81  zmax(0.0)
82  {
83  if (__begin != __end) {
84 
85  zmin = +std::numeric_limits<double>::max();
86  zmax = -std::numeric_limits<double>::max();
87 
88  for (T i = __begin; i != __end; ++i) {
89  if (i->getZ() < zmin) zmin = i->getZ();
90  if (i->getZ() > zmax) zmax = i->getZ();
91  }
92  }
93  }
94 
95 
96  /**
97  * Get minimal z position.
98  *
99  * \return minimal z position
100  */
101  double getZmin() const
102  {
103  return zmin;
104  }
105 
106 
107  /**
108  * Get maximal z position.
109  *
110  * \return maximal z position
111  */
112  double getZmax() const
113  {
114  return zmax;
115  }
116 
117 
118  /**
119  * Set minimal z position.
120  *
121  * \param zmin minimal z position
122  */
123  void setZmin(const double zmin)
124  {
125  this->zmin = zmin;
126  }
127 
128 
129  /**
130  * Set maximal z position.
131  *
132  * \param zmax maximal z position
133  */
134  void setZmax(const double zmax)
135  {
136  this->zmax = zmax;
137  }
138 
139 
140  /**
141  * Add position.
142  *
143  * \param pos position
144  * \return this cylinder
145  */
146  JCylinder3D& add(const JVector3D& pos)
147  {
148  static_cast<JPosition2D&>(*this).add(JPosition2D(pos.getX(), pos.getY()));
149 
150  zmin += pos.getZ();
151  zmax += pos.getZ();
152 
153  return *this;
154  }
155 
156 
157  /**
158  * Add (safety) margin.
159  *
160  * \param D margin
161  * \return this cylinder
162  */
163  void addMargin(const double D)
164  {
165  __r += D;
166  zmin -= D;
167  zmax += D;
168  }
169 
170 
171  /**
172  * Get volume.
173  *
174  * \return volume
175  */
176  inline double getVolume() const
177  {
178  return (getZmax ()- getZmin()) * JTOOLS::PI * getRadius() * getRadius();
179  }
180 
181 
182  /**
183  * Get centre.
184  *
185  * \return centre
186  */
188  {
189  return JPosition3D(getPosition(), (getZmax() - getZmin())/2.0);
190  }
191 
192 
193  /**
194  * Check whether given point is inside cylinder.
195  *
196  * \param pos position
197  * \return true if inside; else false
198  */
199  inline bool is_inside(const JVector3D& pos) const
200  {
201  return (pos.getZ() >= getZmin() &&
202  pos.getZ() <= getZmax() &&
203  JCircle2D::is_inside(JVector2D(pos.getX(), pos.getY())));
204  }
205 
206 
207  /**
208  * Get distance between cylinder wall and given position.
209  *
210  * \param pos position
211  * \return distance
212  */
213  inline double getDistance(const JVector3D& pos) const
214  {
215  JVector2D D(pos);
216 
217  D.sub(*this);
218 
219  double R = D.getLength();
220 
221  if (R > this->getRadius()) {
222 
223  R -= this->getRadius();
224 
225  double dz = 0.0;
226 
227  if (pos.getZ() > this->getZmax())
228  dz = pos.getZ() - this->getZmax();
229  else if (pos.getZ() < this->getZmin())
230  dz = this->getZmin() - pos.getZ();
231  else
232  return R;
233 
234  return sqrt(R*R + dz*dz);
235 
236  } else {
237 
238  if (pos.getZ() > this->getZmax())
239  return pos.getZ() - this->getZmax();
240  else if (pos.getZ() < this->getZmin())
241  return this->getZmin() - pos.getZ();
242  else
243  return 0.0;
244  }
245  }
246 
247 
248  /**
249  * Get square of distance between cylinder wall and given position.
250  *
251  * \param pos position
252  * \return square of distance
253  */
254  inline double getDistanceSquared(const JVector3D& pos) const
255  {
256  const double d = getDistance(pos);
257 
258  return d*d;
259  }
260 
261 
262  /**
263  * Get intersection points of axis with cylinder.
264  *
265  * \param axis axis
266  * \return up and down stream positions along axis
267  */
269  {
270  double path[] = { 0.0, 0.0 };
271 
272  if (fabs(axis.getDZ()) != 0.0) {
273 
274  // intersection with bottom or top surface
275 
276  const double Z[] = {
277  axis.getDZ() > 0 ? this->getZmin() : this->getZmax(),
278  axis.getDZ() > 0 ? this->getZmax() : this->getZmin()
279  };
280 
281  for (int i = 0; i != 2; ++i) {
282 
283  const double u = (Z[i] - axis.getZ()) / axis.getDZ();
284  const double x = axis.getX() + u * axis.getDX() - this->getX();
285  const double y = axis.getY() + u * axis.getDY() - this->getY();
286 
287  if (x*x + y*y <= this->getRadius() * this->getRadius()) {
288  path[i] = u;
289  }
290  }
291  }
292 
293  if (fabs(axis.getDZ()) != 1.0) {
294 
295  // intersection with cylinder wall
296 
297  const double x = axis.getX() - this->getX();
298  const double y = axis.getY() - this->getY();
299  const double dx = axis.getDX();
300  const double dy = axis.getDY();
301  const double R = this->getRadius();
302 
303  const double a = (dx * dx + dy * dy);
304  const double b = 2*(dx * x + dy * y);
305  const double c = (x * x + y * y) - R * R;
306 
307  const double q = b*b - 4*a*c;
308 
309  if (q >= 0) {
310 
311  const double u[] = {
312  (-b - sqrt(q)) / (2*a),
313  (-b + sqrt(q)) / (2*a)
314  };
315 
316  for (int i = 0; i != 2; ++i) {
317 
318  const double z = axis.getZ() + u[i] * axis.getDZ();
319 
320  if (z >= this->getZmin() && z <= this->getZmax()) {
321  path[i] = u[i];
322  }
323  }
324  }
325  }
326 
327  return std::make_pair(path[0], path[1]);
328  }
329 
330 
331  /**
332  * Read cylinder from input stream.
333  *
334  * \param in input stream
335  * \param cylinder cylinder
336  * \return input stream
337  */
338  friend inline std::istream& operator>>(std::istream& in, JCylinder3D& cylinder)
339  {
340  in >> static_cast<JCircle2D&>(cylinder);
341  in >> cylinder.zmin >> cylinder.zmax;
342 
343  return in;
344  }
345 
346 
347  /**
348  * Write cylinder to output stream.
349  *
350  * \param out output stream
351  * \param cylinder cylinder
352  * \return output stream
353  */
354  friend inline std::ostream& operator<<(std::ostream& out, const JCylinder3D& cylinder)
355  {
356  out << static_cast<const JCircle2D&>(cylinder);
357  out << ' ';
358  out << cylinder.zmin;
359  out << ' ';
360  out << cylinder.zmax;
361 
362  return out;
363  }
364 
365 
366  /**
367  * Read cylinder from input.
368  *
369  * \param in reader
370  * \param cylinder cylinder
371  * \return reader
372  */
373  friend inline JReader& operator>>(JReader& in, JCylinder3D& cylinder)
374  {
375  in >> static_cast<JCircle2D&>(cylinder);
376  in >> cylinder.zmin >> cylinder.zmax;
377 
378  return in;
379  }
380 
381 
382  /**
383  * Write cylinder to output.
384  *
385  * \param out writer
386  * \param cylinder cylinder
387  * \return writer
388  */
389  friend inline JWriter& operator<<(JWriter& out, const JCylinder3D& cylinder)
390  {
391  out << static_cast<const JCircle2D&>(cylinder);
392  out << cylinder.zmin << cylinder.zmax;
393 
394  return out;
395  }
396 
397 
398  protected:
399  double zmin;
400  double zmax;
401  };
402 }
403 
404 #endif
const JPosition2D & getPosition() const
Get position.
Definition: JPosition2D.hh:97
Data structure for vector in two dimensions.
Definition: JVector2D.hh:30
Interface for binary output.
double getRadius() const
Get radius.
Definition: JCircle2D.hh:121
JVector2D()
Default constructor.
Definition: JVector2D.hh:37
JPosition2D()
Default constructor.
Definition: JPosition2D.hh:43
bool is_inside(const JVector2D &pos) const
Check whether given point is inside circle.
Definition: JCircle2D.hh:239
Data structure for circle in two dimensions.
Definition: JCircle2D.hh:29
void setZmin(const double zmin)
Set minimal z position.
Definition: JCylinder3D.hh:123
friend JWriter & operator<<(JWriter &out, const JCylinder3D &cylinder)
Write cylinder to output.
Definition: JCylinder3D.hh:389
static const double PI
Constants.
Definition: JConstants.hh:20
double getZmin() const
Get minimal z position.
Definition: JCylinder3D.hh:101
double getDistanceSquared(const JVector3D &pos) const
Get square of distance between cylinder wall and given position.
Definition: JCylinder3D.hh:254
JCylinder3D & add(const JVector3D &pos)
Add position.
Definition: JCylinder3D.hh:146
friend JReader & operator>>(JReader &in, JCylinder3D &cylinder)
Read cylinder from input.
Definition: JCylinder3D.hh:373
double getY() const
Get y position.
Definition: JVector2D.hh:72
friend std::istream & operator>>(std::istream &in, JCylinder3D &cylinder)
Read cylinder from input stream.
Definition: JCylinder3D.hh:338
JCylinder3D(T __begin, T __end)
Constructor.
Definition: JCylinder3D.hh:77
JVector2D & sub(const JVector2D &vector)
Subtract vector.
Definition: JVector2D.hh:113
Axis object.
Definition: JAxis3D.hh:37
JPosition3D getCenter() const
Get centre.
Definition: JCylinder3D.hh:187
friend std::ostream & operator<<(std::ostream &out, const JCylinder3D &cylinder)
Write cylinder to output stream.
Definition: JCylinder3D.hh:354
Constants.
Cylinder object.
Definition: JCylinder3D.hh:37
Data structure for vector in three dimensions.
Definition: JVector3D.hh:32
double getDY() const
Get y direction.
Definition: JVersor3D.hh:101
double getDX() const
Get x direction.
Definition: JVersor3D.hh:90
double getX() const
Get x position.
Definition: JVector2D.hh:61
void addMargin(const double D)
Add (safety) margin.
Definition: JCylinder3D.hh:163
double getY() const
Get y position.
Definition: JVector3D.hh:102
Interface for binary input.
double getVolume() const
Get volume.
Definition: JCylinder3D.hh:176
double getZmax() const
Get maximal z position.
Definition: JCylinder3D.hh:112
JCylinder3D()
Default constructor.
Definition: JCylinder3D.hh:44
double getX() const
Get x position.
Definition: JVector3D.hh:92
bool is_inside(const JVector3D &pos) const
Check whether given point is inside cylinder.
Definition: JCylinder3D.hh:199
void setZmax(const double zmax)
Set maximal z position.
Definition: JCylinder3D.hh:134
Data structure for position in three dimensions.
Definition: JPosition3D.hh:35
std::pair< double, double > getIntersection(const JAxis3D &axis) const
Get intersection points of axis with cylinder.
Definition: JCylinder3D.hh:268
JCylinder3D(const JCircle2D &circle, const double zmin, const double zmax)
Constructor.
Definition: JCylinder3D.hh:58
double getDistance(const JVector3D &pos) const
Get distance between cylinder wall and given position.
Definition: JCylinder3D.hh:213
double getLength() const
Get length.
Definition: JVector2D.hh:195
double getZ() const
Get z position.
Definition: JVector3D.hh:113
double getDZ() const
Get z direction.
Definition: JVersor3D.hh:112