EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_base_geometry.h
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ base geometry 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 # Blake Walters
28 # Marc Chamberland
29 # Reid Townson
30 # Ernesto Mainegra-Hing
31 # Hugo Bouchard
32 # Martin Martinov
33 # Alexandre Demelo
34 #
35 ###############################################################################
36 */
37 
38 
44 #ifndef EGS_BASE_GEOMETRY_
45 #define EGS_BASE_GEOMETRY_
46 
47 #include "egs_vector.h"
48 #include "egs_rndm.h"
49 
50 #include <string>
51 #include <vector>
52 #include <iostream>
53 
54 using std::string;
55 using std::vector;
56 
57 class EGS_Application; // forward declaration
58 class EGS_Input;
60 
61 #ifdef BPROPERTY64
62  typedef EGS_I64 EGS_BPType;
63 #elif defined BPROPERTY32
64  typedef unsigned int EGS_BPType;
65 #elif defined BPROPERTY16
66  typedef unsigned short EGS_BPType;
67 #else
68  typedef unsigned char EGS_BPType;
69 #endif
70 
71 class label {
72 public:
73  string name;
74  vector<int> regions;
75 };
76 
97 
98 public:
99 
105  EGS_BaseGeometry(const string &Name);
106 
112  virtual ~EGS_BaseGeometry();
113 
127  inline bool isConvex() const {
128  return is_convex;
129  };
130 
136  virtual int inside(const EGS_Vector &x) = 0;
137 
144  virtual bool isInside(const EGS_Vector &x) = 0;
145 
153  virtual int isWhere(const EGS_Vector &x) = 0;
154 
155  /* getNextGeom is the equivalent of getNextParticle but for the simulation
156  * object. Its goal is to determine the next state of the geometry, either
157  * by synchronizing itself to the source time parameter, or by sampling its
158  * own time parameter and updating itself accordingly if the source has
159  * provided no time index.
160  *
161  * This function has a non-empty implementation in 2 cases.
162  *
163  * 1) it is reimplemented in any composite geometry, where it will call next
164  * geom on all of its components
165  *
166  * 2) it is reimplemented in the dynamic geometry class. This is where the
167  * code will find the current (non static) state of the geometry. */
168  virtual void getNextGeom(EGS_RandomGenerator *rndm) {};
169 
178  static int findRegion(EGS_Float xp, int np, const EGS_Float *p) {
179  int ml = 0, mu = np;
180  while (mu - ml > 1) {
181  int mav = (ml+mu)/2;
182  if (xp <= p[mav]) {
183  mu = mav;
184  }
185  else {
186  ml = mav;
187  }
188  }
189  return mu - 1;
190  };
191 
222  virtual int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
223  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) = 0;
224 
237  virtual EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
238  const EGS_Vector &u);
239 
250  virtual EGS_Float hownear(int ireg, const EGS_Vector &x) = 0;
251 
257  virtual EGS_Float getVolume(int ireg) {
258  return 1.0;
259  }
260 
266  virtual EGS_Float getBound(int idir, int ind) {
267  return 0.0;
268  }
269 
275  virtual int getNRegDir(int idir) {
276  return 0;
277  }
278 
285  int regions() const {
286  return nreg;
287  };
288 
296  virtual bool isRealRegion(int ireg) const {
297  return (ireg >= 0 && ireg < nreg);
298  };
299 
306  virtual int medium(int ireg) const {
307  return region_media ? region_media[ireg] : med;
308  };
309 
315  virtual int getMaxStep() const {
316  return nreg+1;
317  };
318 
331  virtual int computeIntersections(int ireg, int n, const EGS_Vector &x,
332  const EGS_Vector &u, EGS_GeometryIntersections *isections);
333 
343  void setMedium(const string &Name);
344 
352  void setMedium(int start, int end, const string &Name, int delta=1);
353 
358  void setMedium(int imed) {
359  med = imed;
360  };
361 
369  void setMedium(int istart, int iend, int imed, int delta=1);
370 
381  void setMedia(EGS_Input *inp);
382 
390  static int nMedia();
391 
397  static const char *getMediumName(int ind);
398 
407  static int addMedium(const string &medname);
408 
414  static int getMediumIndex(const string &medname);
415 
419  inline bool hasRhoScaling() const {
420  return has_rho_scaling;
421  };
422 
426  virtual EGS_Float getRelativeRho(int ireg) const {
427  return rhor && ireg >= 0 && ireg < nreg ? rhor[ireg] : 1;
428  };
429 
435  virtual void setRelativeRho(int start, int end, EGS_Float rho);
436 
446  virtual void setRelativeRho(EGS_Input *);
447 
448  EGS_Float getMediumRho(int ind) const;
449 
450  virtual void setApplication(EGS_Application *app);
451 
454  inline bool hasBScaling() const {
455  return (has_B_scaling || has_Ref_rho);
456  };
457 
460  virtual EGS_Float getBScaling(int ireg) const {
461  if (has_Ref_rho && has_B_scaling) {
462  if (bfactor && ireg >= 0 && ireg < nreg) {
463  return getMediumRho(medium(ireg))/rhoRef*bfactor[ireg];
464  }
465  else {
466  return 1.0;
467  }
468  }
469  else if (has_Ref_rho && !has_B_scaling) {
470  if (ireg >= 0 && ireg < nreg) {
471  return getMediumRho(medium(ireg))/rhoRef;
472  }
473  else {
474  return 1.0;
475  }
476  }
477  else if (!has_Ref_rho && has_B_scaling) {
478  if (bfactor && ireg >= 0 && ireg < nreg) {
479  return bfactor[ireg];
480 
481  }
482  else {
483  return 1.0;
484  }
485  }
486  else {
487  return 1.0;
488  }
489  }
490 
496  virtual void setBScaling(int start, int end, EGS_Float bf);
497 
507  virtual void setBScaling(EGS_Input *);
508 
514  const string &getName() const {
515  return name;
516  };
517 
524  virtual const string &getType() const = 0;
525 
545 
562  static EGS_BaseGeometry *createSingleGeometry(EGS_Input *inp);
563 
571  static void clearGeometries();
572 
578  void setDebug(bool deb) {
579  debug = deb;
580  };
581 
588  static EGS_BaseGeometry *getGeometry(const string &Name);
589 
590  static EGS_BaseGeometry **getGeometries();
591 
592  static int getNGeometries();
593 
600  static string getUniqueName();
601 
610  void setName(EGS_Input *inp);
611 
620  void setBoundaryTolerance(EGS_Input *inp);
621 
624  void setBoundaryTolerance(EGS_Float tol) {
625  boundaryTolerance = tol;
626  halfBoundaryTolerance = tol/2.;
627  }
628 
631  virtual bool hasBooleanProperty(int ireg, EGS_BPType prop) const {
632  if (!bp_array) {
633  return (prop & bproperty);
634  }
635  return ireg >= 0 && ireg < nreg ? prop & bp_array[ireg] : false;
636  };
637 
643  virtual void setBooleanProperty(EGS_BPType prop);
644 
652  virtual void addBooleanProperty(int bit);
653 
660  virtual void setBooleanProperty(EGS_BPType prop, int start, int end,
661  int step=1);
662 
669  virtual void addBooleanProperty(int bit, int start, int end, int step=1);
670 
681  virtual void printInfo() const;
682 
688  static void describeGeometries();
689 
696  inline int ref() {
697  return ++nref;
698  };
699 
700 
708  inline int deref() {
709  return --nref;
710  };
711 
715  static void setActiveGeometryList(int list);
716 
717  static int getLastError() {
718  return error_flag;
719  };
720 
721  static void resetErrorFlag() {
722  error_flag = 0;
723  };
724 
726  EGS_Float getBoundaryTolerance() {
727  return boundaryTolerance;
728  };
729 
731  virtual void getNumberRegions(const string &str, vector<int> &regs);
732 
734  virtual void getLabelRegions(const string &str, vector<int> &regs);
735 
737  virtual const string &getLabelName(const int i) {
738  return labels[i].name;
739  }
740 
742  virtual int getLabelCount() {
743  return labels.size();
744  }
745 
747  int setLabels(EGS_Input *input);
748 
750  int setLabels(const string &inp);
751 
752  virtual void updatePosition(EGS_Float time) { };
753 
754  /* This method is essentially used to determine whether the simulation
755  * geometry contains a dynamic geometry. Like getNextGeom(), the only
756  * non-empty implementations of this function are in composite geometries
757  * (where it simply calls containsDynamic on its components), and in the
758  * dynamic geometry, where it will update the boolean reference to true and
759  * call on its base geometry. This function was conceived to be used in the
760  * view/viewcontrol (to determine whether time index objects are visible or
761  * hidden), and track scoring */
762  virtual void containsDynamic(bool &hasdynamic) { };
763 
764 protected:
765 
771  int nreg;
772 
778  string name;
779 
786  short *region_media;
787 
794  int med;
795 
800 
804  EGS_Float *rhor;
805 
809  bool has_B_scaling, has_Ref_rho;
810 
814  EGS_Float *bfactor;
815 
819  EGS_Float rhoRef;
820 
825  int nref;
826 
835  virtual void setMedia(EGS_Input *inp, int nmed, const int *med_ind);
836 
841  bool debug;
842 
851  bool is_convex;
852 
857  EGS_BPType bproperty;
858 
864  EGS_BPType *bp_array;
865 
867  EGS_Float boundaryTolerance, halfBoundaryTolerance;
868 
870  static int error_flag;
871 
887  vector<label> labels;
888 
891 
892 private:
893 
903  static int active_glist;
904 
905 };
906 
908  EGS_Float t;
909  EGS_Float rhof;
910  EGS_I32 ireg;
911  EGS_I32 imed;
912 };
913 
1157 /* \example geometry/example1/geometry_example1.cpp
1158 
1159  Suppose that you frequently use the same complex geometry and you
1160  are tired of always having to include the long definition of this geometry
1161  into your input file. In this case it may be worthwhile to implement your
1162  own geometry DSO that constructs the geometry of interest with very little
1163  input (or even no input at all). This example illustrates how to do this
1164  programatically.
1165 
1166  As this is just an example, the geometry we will be constructing is not very
1167  complex: it consists of a cylinder inscribed in a sphere and the sphere
1168  inscribed in a box as shown in the figure ???. We want to be able to define
1169  the media of the cylinder, the sphere and the box in the input file
1170  (so that we can easily use different PEGS data sets, for example). All other
1171  dimensions of our example geometry are fixed.
1172 
1173  To create our new geometry, we make a new subdirectory in the egspp
1174  geometries subdirectory called \c example1. To be able to use the
1175  predefined rules for building geometry libraries we create a dummy
1176  header file \c %geometry_example1.h that does nothing else except to
1177  define the \c EGS_EXAMPLE1_DLL
1178  macro:
1179  \include geometry/example1/geometry_example1.h
1180  and put the implementation in \c %geometry_example1.cpp.
1181  \dontinclude geometry/example1/geometry_example1.cpp
1182  In this file we include the just created header file and the EGS_Input
1183  class header file to get access to its definition,
1184  needed in the \c %createGeometry() function (see below):
1185  \until egs_input
1186  We also need the declarations of the various geometry classes that we
1187  will use to construct our geometry:
1188  \until egs_envelope_geometry.h
1189  We then define the dimensions of the various geometrical structures
1190  \until box_size
1191 
1192  The remaining task is to implement a C-style \c %createGeometry() function
1193  exported by the DSO
1194  \until EGS_EXAMPLE1_EXPORT
1195  We check that the input object is valid and return \c null if it is not
1196  \until }
1197  We then look for a definition of the cylinder medium and print a warning if
1198  such a definition is missing:
1199  \skipline cyl_medium
1200  \until }
1201  We repeat basically the same code to obtain the sphere and the box
1202  media
1203  \until }
1204  \until }
1205  and return \c null if any of the media definition was missing:
1206  \until if
1207  Now we are ready to construct our geometry. We first create a set of
1208  parallel z-planes
1209  \until EGS_ZProjector
1210  As the planes will only be used by our geometry object internally, we don't
1211  care how the plane set is named and therefore give it a name using
1212  the static function EGS_BaseGeometry::getUniqueName().
1213  In a similar way we create a set of z-cylinders consisting of a single
1214  cylinder
1215  \until ZProjector
1216  and make a closed cylinder modeled as a 2D-geometry from the planes and the
1217  cylinder surface:
1218  \until getUniqueName
1219  We then set the medium of the cylinder
1220  \until setMedium
1221  The next step is to create the sphere as a set of spheres consisting of
1222  a single sphere
1223  \until getUniqueName
1224  and to fill it with the sphere medium defined in the input
1225  \until setMedium
1226  We then use an envelope geometry to inscribe the cylinder into the just
1227  created sphere:
1228  \until getUniqueName
1229  The next step is to create the outer box and fill it with the box medium
1230  defined in the input
1231  \until setMedium
1232  (as our geometry will always be centered about the origin, we pass a
1233  \c null affine transformation to the constructor of the box).
1234  We now inscribe the \c the_sphere geometry object (which is the sphere
1235  with the cylinder inscribed in it) into the just created box using
1236  again an envelope geometry,
1237  \until the_box
1238  set the name of \c the_box from the input using the inherited
1239  \link EGS_BaseGeometry::setName(EGS_Input*) setName() \endlink method,
1240  \until setName
1241  and return a pointer to the just created geometry
1242  \until }
1243  \until }
1244  That's all.
1245 
1246  In the Makefile we include the egspp make config files,
1247  \dontinclude geometry/example1/Makefile
1248  \skipline EGS_CONFIG
1249  \until my_machine
1250  set the C-preprocessor defines to the standard set of defines
1251  for our egspp configuration,
1252  \until DEFS
1253  define the name of our DSO,
1254  \until library
1255  and and the set of files needed to build the DSO
1256  \until lib_files
1257  Because we are using planes, cylinders, spheres, a ND-geometry, a box
1258  geometry and an envelope geometry to construct our geometry, we must
1259  link against the geometry libraries containing these geometries.
1260  We accomplish this by seting the \c link2_libs make variable to the
1261  list of needed libraries
1262  \until egs_genvelope
1263  We then include the standard rules for building a DSO
1264  \until include
1265  and set the dependencies of our object files
1266  \until make_depend
1267  We must also add the dependencies on the various geometry header files
1268  that we are including
1269  \until egs_envelope_geometry.h
1270  We can now build our geometry DSO by typing \c make and use
1271  it by including input like this in the input file
1272  \verbatim
1273  :start geometry:
1274  library = geometry_example1
1275  name = some_name
1276  cylinder medium = H2O521ICRU
1277  sphere medium = AL521ICRU
1278  box medium = AIR521ICRU
1279  :stop geometry:
1280  \endverbatim
1281  It is worth noting that we could have constructed this geometry as the
1282  \link EGS_UnionGeometry union \endlink of the cylinder pointed to
1283  by \c the_cyl, the sphere pointed to by \c sphere and the
1284  box pointed to by \c box. However, such an implementation would be
1285  much slower at run time because for each invocation of a geometry
1286  method the union will have to interogate the geometry methods of all
1287  3 objects. In contrast, the envelope geometry will be checking only
1288  against the box for points outside of the box, the box and the sphere for
1289  points inside the box but outside the sphere, the sphere and the cylinder
1290  for points inside the sphere but outside the cylinder and the cylinder
1291  only for points inside the cylinder.
1292 
1293  The complete source code of this example geometry is below
1294  \include geometry/example1/Makefile
1295  \include geometry/example1/geometry_example1.h
1296 
1297 */
1298 
1299 /* \example geometry/example2/geometry_example2.cpp
1300 
1301  This example illustrates how to create the same geometry as
1302  described in
1303  <a href="geometry_2example1_2geometry__example1_8cpp-example.html">
1304  this example</a> but using EGS_BaseGeometry::createSingleGeometry
1305  to create the geometry from definitions stored in an EGS_Input objects.
1306  The header file is similar as in the previous
1307  <a href="geometry_2example1_2geometry__example1_8cpp-example.html">
1308  example</a>, but unlike in the previous example we don't need the
1309  header files of the various geometries being used.
1310  Our implementation consists of a single C-style function
1311  \c %createGeometry()
1312  \dontinclude geometry/example2/geometry_example2.cpp
1313  \skipline createGeometry
1314  As with the previous
1315  <a href="geometry_2example1_2geometry__example1_8cpp-example.html">
1316  example</a>, we check for valid input and extract the
1317  media of the cylinder, sphere and the box from the input
1318  \until !ok
1319  We will create the various geometry objects needed in our composite
1320  geometry by passing EGS_Input objects containing geometry definitions
1321  to the EGS_BaseGeometry::createSingleGeometry function.
1322  We start with the set of planes needed to close the cylinder.
1323  We first create an EGS_Input object named \c geometry that we will
1324  be passing to the geometry creation function:
1325  \until plane_input
1326  We then create properties for the library name,
1327  \until plane_library
1328  the plane-set type,
1329  \until plane_type
1330  the name of the set of planes,
1331  \until plane_name
1332  and the plane positions
1333  \until plane_positions
1334  and add them to the geometry definition
1335  \until plane_positions
1336  We then create the set of planes
1337  \until createSingleGeometry
1338  The definition and creation of the set of cylinders is very similar
1339  \until createSingleGeometry
1340  We now make a closed cylinder as a 2D geometry
1341  \until createSingleGeometry
1342  and set its medium
1343  \until setMedium
1344  In a similar fashion we create the sphere, use an envelope geometry
1345  to inscribe the cylinder into the sphere, create a box, and use again
1346  an envelope to inscribe the sphere into the box. The code is not shown
1347  here as it is lengthy and boring but can be found at the end of this page.
1348  Finally we set the name of the newly created geometry \c the_box and
1349  return it:
1350  \skipline the_box->setName
1351  \until }
1352  \until }
1353 
1354  The Makefile is now simpler as we don't need to link against the
1355  various geometry DSOs as they are loaded dynamically at run time
1356  by the EGS_BaseGeometry::createSingleGeometry function and
1357  our implementation also does not depend on the header files of the
1358  various geometry classes being used:
1359  \include geometry/example2/Makefile
1360 
1361  For completeness here is the header file:
1362  \include geometry/example2/geometry_example2.h
1363  and the complete implementation:
1364 */
1365 
1366 
1367 #endif
Base class for advanced EGSnrc C++ applications.
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
virtual int getLabelCount()
Get the number of explicit labels in the geometry.
virtual EGS_Float hownear(int ireg, const EGS_Vector &x)=0
Calculate the distance to a boundary for position x in any direction.
virtual int inside(const EGS_Vector &x)=0
Returns the region index, if inside, or -1 if outside (obsolete)
int deref()
Decrease the reference count to this geometry.
virtual bool hasBooleanProperty(int ireg, EGS_BPType prop) const
Is the boolean property prop set for region ireg ?
EGS_BPType bproperty
A bit mask of boolean properties for the entire geometry.
bool debug
Debugging flag.
virtual EGS_Float getBScaling(int ireg) const
Get the B field scaling factor in region ireg.
virtual const string & getType() const =0
Get the geometry type.
static int findRegion(EGS_Float xp, int np, const EGS_Float *p)
Find the bin to which xp belongs, given np bin edges p.
int nreg
Number of local regions in this geometry.
virtual int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u, EGS_Float &t, int *newmed=0, EGS_Vector *normal=0)=0
Calculate the distance to a boundary from x along the direction u.
bool has_B_scaling
Does this geometry has B field scaling factor?
int nref
Number of references to this geometry.
bool is_convex
Is this geometry convex?
bool has_rho_scaling
Does this geometry have relative mass density scvaling?
virtual EGS_Float getVolume(int ireg)
Calculates the volume of region ireg.
void setDebug(bool deb)
Turn debugging on.
EGS_Float boundaryTolerance
Boundary tolerance for geometries that need it.
bool hasBScaling() const
Does this geometry object have a B field scaling feature?
short * region_media
Array of media indeces.
virtual bool isRealRegion(int ireg) const
Returnes true if ireg is a real region, false otherwise.
virtual bool isInside(const EGS_Vector &x)=0
Is the position x inside the geometry?
const string & getName() const
Get the name of this geometry.
void setBoundaryTolerance(EGS_Float tol)
Set the value of the boundary tolerance from argument.
EGS_Float * rhor
Array with relative mass densities.
virtual EGS_Float getRelativeRho(int ireg) const
Get the relative mass density in region ireg.
EGS_Float * bfactor
Array with B field scaling factors.
bool isConvex() const
Is the geometry convex?
virtual const string & getLabelName(const int i)
Get the name of the i-th explicit label in the geometry.
int med
Medium index.
virtual int getNRegDir(int idir)
virtual int getMaxStep() const
Returns the maximum number of steps through the geometry.
EGS_Application * app
The application this object belongs to.
bool hasRhoScaling() const
Does this geometry object have a mass density scaling feature?
void setMedium(int imed)
Set all regions to a medium with index imed.
virtual int medium(int ireg) const
Returns the medium index in region ireg.
static int error_flag
Set to non-zero status if a geometry problem is encountered.
string name
Name of this geometry.
int regions() const
Returns the number of local regions in this geometry.
virtual EGS_Float getBound(int idir, int ind)
Returns region boundaries in direction determined by idir.
vector< label > labels
Labels.
EGS_Float getBoundaryTolerance()
Get the value of the boundary tolerance.
int ref()
Increase the reference count to this geometry.
EGS_Float rhoRef
Reference density for B field scaling.
virtual int isWhere(const EGS_Vector &x)=0
In which region is poisition x?
EGS_BPType * bp_array
An array of boolean properties on a region by region basis.
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
Base random number generator class. All random number generators should be derived from this class.
Definition: egs_rndm.h:67
A class representing 3D vectors.
Definition: egs_vector.h:57
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
Definition: egs_glib.cpp:57
#define EGS_EXPORT
Export symbols from the egspp library.
Definition: egs_libconfig.h:90
EGS_RandomGenerator class header file.
EGS_Vector methods for the manipulation of 3D vectors in cartesian co-ordinates.
EGS_I32 ireg
region index
EGS_Float t
distance to next region boundary
EGS_Float rhof
relative mass density in that region
EGS_I32 imed
medium index