EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_shapes.h
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ shapes headers
5 # Copyright (C) 2015 National Research Council Canada
6 #
7 # This file is part of EGSnrc.
8 #
9 # EGSnrc is free software: you can redistribute it and/or modify it under
10 # the terms of the GNU Affero General Public License as published by the
11 # Free Software Foundation, either version 3 of the License, or (at your
12 # option) any later version.
13 #
14 # EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY
15 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
17 # more details.
18 #
19 # You should have received a copy of the GNU Affero General Public License
20 # along with EGSnrc. If not, see <http://www.gnu.org/licenses/>.
21 #
22 ###############################################################################
23 #
24 # Author: Iwan Kawrakow, 2005
25 #
26 # Contributors: Frederic Tessier
27 #
28 ###############################################################################
29 */
30 
31 
37 #ifndef EGS_SHAPES_
38 #define EGS_SHAPES_
39 
40 #include "egs_vector.h"
41 #include "egs_transformations.h"
42 #include "egs_rndm.h"
43 #include "egs_object_factory.h"
44 
45 #include <string>
46 using std::string;
47 
48 class EGS_Input;
49 
113 
114 public:
115 
117  EGS_BaseShape(const string &Name="",EGS_ObjectFactory *f=0) :
118  EGS_Object(Name,f), T(0) {
119  otype = "base_shape";
120  };
122  virtual ~EGS_BaseShape() {
123  if (T) {
124  delete T;
125  }
126  };
127 
135  if (T) {
136  return (*T)*getPoint(rndm);
137  }
138  else {
139  return getPoint(rndm);
140  }
141  };
142 
150  egsFatal("You need to implement the getPoint function in your "
151  "derived class\n");
152  return EGS_Vector();
153  };
154 
163  void setTransformation(EGS_Input *inp);
164 
170  if (T) {
171  delete T;
172  }
173  T = new EGS_AffineTransform(*t);
174  };
175 
179  return T;
180  };
181 
189  static EGS_BaseShape *createShape(EGS_Input *inp);
190 
197  static EGS_BaseShape *getShape(const string &Name);
198 
204  virtual bool supportsDirectionMethod() const {
205  return false;
206  };
207 
220  virtual void getPointSourceDirection(const EGS_Vector &xo,
221  EGS_RandomGenerator *rndm, EGS_Vector &u, EGS_Float &wt) {
222  egsFatal("getPointSourceDirection: you have to implement this "
223  "method for the %s shape if you want to use it\n",otype.c_str());
224  };
225 
232  virtual EGS_Float area() const {
233  return 1;
234  };
235 
236 protected:
237 
239 
240 };
241 
253 
254 public:
255 
257  EGS_SurfaceShape(const string &Name="",EGS_ObjectFactory *f=0) :
258  EGS_BaseShape(Name,f), A(1) {};
264  bool supportsDirectionMethod() const {
265  return true;
266  };
268  EGS_Float area() const {
269  return A;
270  };
276  EGS_RandomGenerator *rndm, EGS_Vector &u, EGS_Float &wt) {
277  EGS_Vector xo = T ? Xo*(*T) : Xo;
278  EGS_Vector x = getPoint(rndm);
279  u = x - xo;
280  EGS_Float d2i = 1/u.length2(), di = sqrt(d2i);
281  u *= di;
282  wt = A*fabs(u.z)*d2i;
283  if (T) {
284  T->rotate(u);
285  }
286  };
287 
288 protected:
289 
295  EGS_Float A;
296 
297 };
298 
315 
316 public:
317 
320  const string &Name="",EGS_ObjectFactory *f=0) :
321  EGS_BaseShape(Name,f), xo(Xo) {
322  otype = "point";
323  };
324  ~EGS_PointShape() { };
327  return xo;
328  };
333 
334 protected:
335 
337 
338 };
339 
357 
358 protected:
359 
360  EGS_Float ax, ay, az;
361 
362 public:
363 
365  EGS_BoxShape(const string &Name="",EGS_ObjectFactory *f=0) :
366  EGS_BaseShape(Name,f), ax(1), ay(1), az(1) {
367  otype="box";
368  };
370  EGS_BoxShape(EGS_Float A, const EGS_AffineTransform *t = 0,
371  const string &Name="",EGS_ObjectFactory *f=0) :
372  EGS_BaseShape(Name,f), ax(A), ay(A), az(A) {
373  if (t) {
374  T = new EGS_AffineTransform(*t);
375  }
376  otype="box";
377  };
379  EGS_BoxShape(EGS_Float Ax, EGS_Float Ay, EGS_Float Az,
380  const EGS_AffineTransform *t = 0,
381  const string &Name="",EGS_ObjectFactory *f=0) :
382  EGS_BaseShape(Name,f), ax(Ax), ay(Ay), az(Az) {
383  if (t) {
384  T = new EGS_AffineTransform(*t);
385  }
386  otype="box";
387  };
390 
393  EGS_Vector v(ax*(rndm->getUniform()-0.5),
394  ay*(rndm->getUniform()-0.5),
395  az*(rndm->getUniform()-0.5));
396  return v;
397  };
398 
403 
407  bool supportsDirectionMethod() const {
408  return true;
409  };
410 
416  EGS_RandomGenerator *rndm, EGS_Vector &u, EGS_Float &wt) {
417  EGS_Vector xo = T ? Xo*(*T) : Xo;
418  EGS_Float eta = rndm->getUniform()*area();
419  if (eta < 2*ax*ay) {
420  u.x = ax*(rndm->getUniform()-0.5);
421  u.y = ay*(rndm->getUniform()-0.5);
422  if (eta < ax*ay) {
423  u.z = az/2;
424  wt = u.z - xo.z;
425  }
426  else {
427  u.z = -az/2;
428  wt = xo.z - u.z;
429  }
430  }
431  else if (eta < 2*(ax*ay + ax*az)) {
432  u.x = ax*(rndm->getUniform()-0.5);
433  u.z = az*(rndm->getUniform()-0.5);
434  if (eta < 2*ax*ay + ax*az) {
435  u.y = ay/2;
436  wt = u.y - xo.y;
437  }
438  else {
439  u.y = -ay/2;
440  wt = xo.y - u.y;
441  }
442  }
443  else {
444  eta -= 2*(ax*ay + ax*az);
445  u.y = ay*(rndm->getUniform()-0.5);
446  u.z = az*(rndm->getUniform()-0.5);
447  if (eta < ay*az) {
448  u.x = ax/2;
449  wt = u.x - xo.x;
450  }
451  else {
452  u.x = -ax/2;
453  wt = xo.x - u.x;
454  }
455  }
456  u -= xo;
457  EGS_Float d2 = u.length2(), d = sqrt(d2);
458  u *= (1/d);
459  wt *= (area()/(d2*d));
460  if (T) {
461  T->rotate(u);
462  }
463  };
465  EGS_Float area() const {
466  return 2*(ax*ay + ax*az + ay*az);
467  };
468 
469 };
470 
489 
490 protected:
491 
492  EGS_Float R;
494 
495 public:
496 
498  EGS_SphereShape(const string &Name="",EGS_ObjectFactory *f=0) :
499  EGS_BaseShape(Name,f), R(1), xo() {
500  otype="sphere";
501  };
503  EGS_SphereShape(EGS_Float r, const EGS_Vector &Xo = EGS_Vector(0,0,0),
504  const string &Name="",EGS_ObjectFactory *f=0) :
505  EGS_BaseShape(Name,f), R(r), xo(Xo) {
506  otype = "sphere";
507  };
510 
513  EGS_Float r = rndm->getUniform(), r1 = rndm->getUniform(),
514  r2 = rndm->getUniform();
515  if (r1 > r) {
516  r = r1;
517  }
518  if (r2 > r) {
519  r = r2;
520  }
521  EGS_Float cost = 2*rndm->getUniform()-1;
522  EGS_Float sint = sqrt(1-cost*cost);
523  r1 = R*r*sint;
524  EGS_Float cphi, sphi;
525  rndm->getAzimuth(cphi,sphi);
526  return xo + EGS_Vector(r1*cphi,r1*sphi,R*r*cost);
527  };
528 
533 
537  bool supportsDirectionMethod() const {
538  return true;
539  };
540 
546  EGS_RandomGenerator *rndm, EGS_Vector &u, EGS_Float &wt) {
547  EGS_Vector xo = T ? Xo*(*T) : Xo;
548  EGS_Float cost = 2*rndm->getUniform()-1;
549  EGS_Float sint = 1-cost*cost;
550  EGS_Vector x;
551  if (sint > epsilon) {
552  EGS_Float cphi, sphi;
553  rndm->getAzimuth(cphi,sphi);
554  sint = R*sqrt(sint);
555  x.x = sint*cphi;
556  x.y = sint*sphi;
557  x.z = R*cost;
558  }
559  else {
560  x.z = R*cost;
561  }
562  u = (x + this->xo) - xo;
563  EGS_Float di = 1/u.length();
564  u *= di;
565  wt = u*x*4*M_PI*R*di*di;
566  };
568  EGS_Float area() const {
569  return 4*M_PI*R*R;
570  };
571 };
572 
597 
598 protected:
599 
600  EGS_Float R;
601  EGS_Float h;
604  EGS_Float phi_min;
605  EGS_Float phi_max;
606  bool has_phi;
607 
609  inline void getPointInCircle(EGS_RandomGenerator *rndm, EGS_Float &x,
610  EGS_Float &y) {
611  if (!has_phi) {
612  do {
613  x = 2*rndm->getUniform()-1;
614  y = 2*rndm->getUniform()-1;
615  }
616  while (x*x + y*y > 1);
617  x *= R;
618  y *= R;
619  }
620  else {
621  EGS_Float r = R*sqrt(rndm->getUniform());
622  EGS_Float eta = rndm->getUniform();
623  EGS_Float phi = phi_min*(1-eta) + phi_max*eta;
624  x = r*cos(phi);
625  y = r*sin(phi);
626  }
627  };
628 
629 
630 public:
631 
635  EGS_CylinderShape(const string &Name="",EGS_ObjectFactory *f=0) :
636  EGS_BaseShape(), R(1), h(1), xo(), a(0,0,1),
637  phi_min(0), phi_max(2*M_PI), has_phi(false) {
638  otype="cylinder";
639  };
640  EGS_CylinderShape(EGS_Float r, EGS_Float H,
641  const EGS_Vector &Xo = EGS_Vector(0,0,0),
642  const EGS_Vector &A = EGS_Vector(0,0,1),
643  const string &Name="",EGS_ObjectFactory *f=0) :
644  EGS_BaseShape(Name,f), R(r), h(H), xo(Xo), a(A),
645  phi_min(0), phi_max(2*M_PI), has_phi(false) {
646  EGS_RotationMatrix rmat(a);
647  if (xo.length2() > epsilon || !rmat.isI()) {
648  T = new EGS_AffineTransform(rmat.inverse(),xo);
649  }
650  otype="cylinder";
651  };
655  EGS_CylinderShape(EGS_Float r, EGS_Float H, const EGS_AffineTransform *t,
656  const string &Name="",EGS_ObjectFactory *f=0) :
657  EGS_BaseShape(Name,f), R(r), h(H),
658  phi_min(0), phi_max(2*M_PI), has_phi(false) {
659  if (t) {
660  T = new EGS_AffineTransform(*t);
661  }
662  otype="cylinder";
663  };
666 
668  void setPhiRange(EGS_Float Phi_min, EGS_Float Phi_max) {
669  if (Phi_min < Phi_max) {
670  phi_min = Phi_min;
671  phi_max = Phi_max;
672  }
673  else {
674  phi_min = Phi_max;
675  phi_max = Phi_min;
676  }
677  if (phi_max - phi_min < 1.99999*M_PI) {
678  has_phi = true;
679  }
680  else {
681  has_phi = false;
682  }
683  };
684 
689  EGS_Float x,y;
690  getPointInCircle(rndm,x,y);
691  EGS_Float z = h*(rndm->getUniform()-0.5);
692  return EGS_Vector(x,y,z);
693  };
694 
699 
701  EGS_Float getRadius() const {
702  return R;
703  };
705  EGS_Float getHeight() const {
706  return h;
707  };
708 
712  bool supportsDirectionMethod() const {
713  return true;
714  };
715 
721  EGS_RandomGenerator *rndm, EGS_Vector &u, EGS_Float &wt) {
722  EGS_Vector xo = T ? Xo*(*T) : Xo;
723  EGS_Float eta = rndm->getUniform()*(R+h);
724  EGS_Vector x; // point on cylinder with respect to midpoint
725  EGS_Vector n; // normal to cylinder at point x
726  if (eta < R) {
727  getPointInCircle(rndm,x.x,x.y);
728  if (2*eta < R) {
729  x.z = h/2; // top face: normal is up
730  n.z = 1;
731  }
732  else {
733  x.z = -h/2; // bottom face: normal is down
734  n.z = -1;
735  }
736  }
737  else {
738  EGS_Float cphi,sphi;
739  rndm->getAzimuth(cphi,sphi);
740  x.x = R*cphi;
741  x.y = R*sphi;
742  x.z = h*(rndm->getUniform()-0.5);
743  n.x = x.x;
744  n.y = x.y; // side face: normal is (x,y)
745  }
746  u = (x+this->xo) - xo; // direction vector from origin to cylinder point
747  EGS_Float d2 = u.length2(), d = sqrt(d2);
748  u *= (1/d); // normalize direction vectors
749  n.normalize(); // normalize normal
750  wt = u*n*area()/d2;
751  if (T) {
752  T->rotate(u);
753  }
754  };
756  EGS_Float area() const {
757  return 2*M_PI*R*(R+h);
758  };
759 };
760 
761 #endif
762 
A surface shape.
Definition: egs_shapes.h:252
Base egspp object.
#define EGS_EXPORT
Export symbols from the egspp library.
Definition: egs_libconfig.h:90
EGS_SphereShape(EGS_Float r, const EGS_Vector &Xo=EGS_Vector(0, 0, 0), const string &Name="", EGS_ObjectFactory *f=0)
Construct a sphere of radius r with midpoint Xo.
Definition: egs_shapes.h:503
EGS_Vector getPoint(EGS_RandomGenerator *)
Returns a fixed point.
Definition: egs_shapes.h:326
~EGS_BoxShape()
Destructor. Does nothing.
Definition: egs_shapes.h:389
EGS_Vector getPoint(EGS_RandomGenerator *rndm)
Returns a point uniformely distributed within the box.
Definition: egs_shapes.h:392
EGS_Vector xo
The sphere midpoint.
Definition: egs_shapes.h:493
EGS_Float getRadius() const
Definition: egs_shapes.h:701
void getPointInCircle(EGS_RandomGenerator *rndm, EGS_Float &x, EGS_Float &y)
Get a point uniformly distributed within a circle.
Definition: egs_shapes.h:609
virtual EGS_Vector getRandomPoint(EGS_RandomGenerator *rndm)
Returns a random 3D vector.
Definition: egs_shapes.h:134
bool supportsDirectionMethod() const
Returns true. (It is easy to implement the getPointSourceDirection() method for a cylinder...
Definition: egs_shapes.h:712
A class providing affine transformations.
EGS_SurfaceShape(const string &Name="", EGS_ObjectFactory *f=0)
Construct a surface shape named Name.
Definition: egs_shapes.h:257
void getPointSourceDirection(const EGS_Vector &Xo, EGS_RandomGenerator *rndm, EGS_Vector &u, EGS_Float &wt)
Sets the direction u by picking a random point uniformly on the cylinder surface. ...
Definition: egs_shapes.h:720
A class for vector rotations.
~EGS_SurfaceShape()
Destructor. Does nothing.
Definition: egs_shapes.h:260
EGS_SphereShape(const string &Name="", EGS_ObjectFactory *f=0)
Construct a sphere of unit radius about the origin.
Definition: egs_shapes.h:498
EGS_Vector methods for the manipulation of 3D vectors in cartesian co-ordinates.
EGS_Float y
y-component
Definition: egs_vector.h:61
EGS_CylinderShape(EGS_Float r, EGS_Float H, const EGS_AffineTransform *t, const string &Name="", EGS_ObjectFactory *f=0)
Definition: egs_shapes.h:655
A class representing 3D vectors.
Definition: egs_vector.h:56
void getAzimuth(EGS_Float &cphi, EGS_Float &sphi)
Sets cphi and sphi to the cosine and sine of a random angle uniformely distributed between 0 and ...
Definition: egs_rndm.h:138
virtual EGS_Object * createObject(EGS_Input *inp)
Create an object from the infromation pointed to by inp.
Base shape class. All shapes in the EGSnrc C++ class library are derived from EGS_BaseShape.
Definition: egs_shapes.h:112
EGS_Float R
Cylinder radius.
Definition: egs_shapes.h:600
EGS_BoxShape(EGS_Float Ax, EGS_Float Ay, EGS_Float Az, const EGS_AffineTransform *t=0, const string &Name="", EGS_ObjectFactory *f=0)
Create a box shape with size Ax,Ay,Az.
Definition: egs_shapes.h:379
void getPointSourceDirection(const EGS_Vector &Xo, EGS_RandomGenerator *rndm, EGS_Vector &u, EGS_Float &wt)
Sets the direction u by picking a random point uniformely the on the box surface. ...
Definition: egs_shapes.h:415
EGS_Vector xo
The point position.
Definition: egs_shapes.h:336
void setTransformation(EGS_AffineTransform *t)
Set the transformation attached to this shape.
Definition: egs_shapes.h:169
EGS_Vector xo
midpoint
Definition: egs_shapes.h:602
virtual EGS_Vector getPoint(EGS_RandomGenerator *rndm)
Sample and return a random 3D vector.
Definition: egs_shapes.h:149
Base random number generator class. All random number generators should be derived from this class...
Definition: egs_rndm.h:67
virtual EGS_Float area() const
Definition: egs_shapes.h:232
const EGS_AffineTransform * getTransform() const
Get a pointer to the affine transformation attached to this shape.
Definition: egs_shapes.h:178
EGS_Float z
z-component
Definition: egs_vector.h:62
virtual bool supportsDirectionMethod() const
Definition: egs_shapes.h:204
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
A point shape. This is the simplest shape possible: it simply always returns the same point...
Definition: egs_shapes.h:314
EGS_RandomGenerator class header file.
A sphere shape.
Definition: egs_shapes.h:488
virtual void getPointSourceDirection(const EGS_Vector &xo, EGS_RandomGenerator *rndm, EGS_Vector &u, EGS_Float &wt)
Definition: egs_shapes.h:220
EGS_Vector getPoint(EGS_RandomGenerator *rndm)
Samples and returns a point uniformly distributed within the cylinder.
Definition: egs_shapes.h:688
EGS_Float az
The box size.
Definition: egs_shapes.h:360
EGS_Float R
The sphere radius.
Definition: egs_shapes.h:492
EGS_Float h
Cylinder height.
Definition: egs_shapes.h:601
EGS_BoxShape(const string &Name="", EGS_ObjectFactory *f=0)
Create a box shape with unit size.
Definition: egs_shapes.h:365
EGS_BoxShape(EGS_Float A, const EGS_AffineTransform *t=0, const string &Name="", EGS_ObjectFactory *f=0)
Create a cube with size A.
Definition: egs_shapes.h:370
An object factory.
EGS_AffineTransform and EGS_RotationMatrix class header file.
A cylinder shape.
Definition: egs_shapes.h:596
EGS_Float area() const
Returns the cylinder surface area.
Definition: egs_shapes.h:756
A box shape.
Definition: egs_shapes.h:356
EGS_Vector a
Cylinder axis.
Definition: egs_shapes.h:603
void setPhiRange(EGS_Float Phi_min, EGS_Float Phi_max)
Definition: egs_shapes.h:668
void getPointSourceDirection(const EGS_Vector &Xo, EGS_RandomGenerator *rndm, EGS_Vector &u, EGS_Float &wt)
Sets the direction u by picking a random point uniformely on the sphere surface.
Definition: egs_shapes.h:545
EGS_Float getUniform()
Returns a random number uniformly distributed between zero (inclusive) and 1 (exclusive).
Definition: egs_rndm.h:103
bool supportsDirectionMethod() const
Always returns true. Shapes derived from this class must implement the getPoint() method to return po...
Definition: egs_shapes.h:264
EGS_Vector getPoint(EGS_RandomGenerator *rndm)
Returns a random point within the sphere.
Definition: egs_shapes.h:512
EGS_BaseShape(const string &Name="", EGS_ObjectFactory *f=0)
Construct a shape named Name.
Definition: egs_shapes.h:117
EGS_Float x
x-component
Definition: egs_vector.h:60
EGS_Float getHeight() const
Definition: egs_shapes.h:705
EGS_PointShape(const EGS_Vector &Xo=EGS_Vector(), const string &Name="", EGS_ObjectFactory *f=0)
Construct a point shape located at Xo.
Definition: egs_shapes.h:319
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
Definition: egs_functions.h:61
void getPointSourceDirection(const EGS_Vector &Xo, EGS_RandomGenerator *rndm, EGS_Vector &u, EGS_Float &wt)
Get a random direction given a source position Xo.
Definition: egs_shapes.h:275
EGS_Object and EGS_ObjectFactory class header file.
EGS_CylinderShape(const string &Name="", EGS_ObjectFactory *f=0)
Definition: egs_shapes.h:635
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
EGS_Float area() const
Returns the box surface area.
Definition: egs_shapes.h:465
EGS_Float area() const
Returns the area of this surface shape.
Definition: egs_shapes.h:268
virtual ~EGS_BaseShape()
Destructor. Deletes T if it is not null.
Definition: egs_shapes.h:122
bool has_phi
True, if azimuthal range restricted.
Definition: egs_shapes.h:606
bool supportsDirectionMethod() const
Returns true. (It is easy to implement the getPointSourceDirection() method for a box...
Definition: egs_shapes.h:407
EGS_Float area() const
Returns the sphere surface area.
Definition: egs_shapes.h:568
bool supportsDirectionMethod() const
Returns true. (It is easy to implement the getPointSourceDirection() method for a sphere...
Definition: egs_shapes.h:537