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