EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_spheres.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ spheres geometry
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: Ernesto Mainegra-Hing
27 # Frederic Tessier
28 # Reid Townson
29 # Randle Taylor
30 # Marc Chamberland
31 # Martin Martinov
32 #
33 ###############################################################################
34 */
35 
36 
42 #include "egs_spheres.h"
43 #include "egs_input.h"
44 #include "egs_functions.h"
45 
46 #include <vector>
47 using std::vector;
48 
49 string EGS_cSpheres::type = "EGS_cSpheres";
50 
51 // generate the concentric spheres
52 EGS_cSpheres::EGS_cSpheres(int ns, const EGS_Float *radius,
53  const EGS_Vector &position, const string &Name) :
54  EGS_BaseGeometry(Name), xo(position) {
55 
56  if (ns>0) {
57 
58  R2=new EGS_Float [ns];
59  R=new EGS_Float [ns];
60 
61  // ... and sphere radii
62  for (int i=0; i<ns; i++) {
63  R2[i]=radius[i]*radius[i];
64  R[i]=radius[i];
65  }
66 
67  // for n-concentric spheres, we have n separate regions
68  nreg=ns;
69  }
70 
71  for (int ireg=0; ireg < ns; ireg++) {
72  rbounds.push_back(radius[ireg]);
73  EGS_Float router = rbounds[ireg];
74  EGS_Float rinner = ireg > 0 ? rbounds[ireg-1] : 0;
75  vol.push_back((4./3.)*M_PI*(router*router*router - rinner*rinner*rinner));
76  }
77 }
78 
79 bool EGS_cSpheres::isInside(const EGS_Vector &x) {
80  EGS_Vector tmp(x-xo);
81  EGS_Float r_sq=tmp.length2();
82  if (r_sq>R2[nreg-1]) {
83  return false;
84  }
85  return true;
86 }
87 
88 int EGS_cSpheres::isWhere(const EGS_Vector &x) {
89  EGS_Vector tmp(x-xo);
90  EGS_Float r_sq=tmp.length2();
91  if (r_sq>R2[nreg-1]) {
92  return -1;
93  }
94  if (r_sq<R2[0]) {
95  return 0;
96  }
97  return findRegion(r_sq,nreg-1,R2)+1;
98 }
99 
100 // method to determine which spheres we are in(between)
101 int EGS_cSpheres::inside(const EGS_Vector &x) {
102 
103  EGS_Vector tmp(x-xo);
104  EGS_Float r_sq=tmp.length2();
105 
106  // are we outside off all spheres? If so return that region number
107  if (r_sq>R2[nreg-1]) {
108  return -1;
109  }
110 
111  /*
112  * algorithm below fails for particle in central sphere ...ugh!
113  */if (r_sq<R2[0]) {
114  return 0;
115  }
116 
117  // search for region containing particle
118  int is=0,os=nreg,ms;
119  while (os-is>1) {
120  ms=(is+os)/2;
121  if (r_sq<=R2[ms]) {
122  os=ms;
123  }
124  else {
125  is=ms;
126  }
127  }
128  return os;
129 }
130 
131 // howfar is particle trajectory from sphere boundary
132 /* note that in general we will be between two spheres (if inside a sphere at
133  * all... so we need to check if the flight path will intersect the inner or
134  * outer sphere
135  */
136 
137 #ifdef SPHERES_DEBUG
138  EGS_Vector last_x, last_u;
139  int last_ireg;
140  EGS_Float last_d,last_t,last_aa,last_bb2,last_R2b2,last_tmp;
141 #endif
142 
143 EGS_Float EGS_cSpheres::howfarToOutside(int ireg, const EGS_Vector &x,
144  const EGS_Vector &u) {
145  if (ireg < 0) {
146  return 0;
147  }
148  EGS_Vector xp(x - xo);
149  EGS_Float aa = xp*u, aa2 = aa*aa;
150  EGS_Float bb2 = xp.length2();
151  EGS_Float R2b2 = R2[nreg-1] - bb2;
152  if (R2b2 <= 0) {
153  return 0; // outside within precision
154  }
155  EGS_Float tmp = sqrt(aa2 + R2b2);
156  return aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
157 }
158 
159 int EGS_cSpheres::howfar(int ireg, const EGS_Vector &x,
160  const EGS_Vector &u, EGS_Float &t, int *newmed, EGS_Vector *normal) {
161  int direction_flag=-1; /* keep track of direction entering or exiting a
162  sphere boundary */
163  double d=veryFar*1e5; // set a maximum distance from a boundary
164 
165  EGS_Vector xp(x - xo);
166  double aa = xp*u, aa2 = aa*aa;
167  double bb2 = xp.length2();
168 
169  double rad=0, R2b2, tmp;
170 
171  // check if we are inside of any regions at all? ...
172  if (ireg>=0) {
173 
174  /* check if particle is moving towards or away from the sphere(s) centre.
175  * we loose here if the particle is in the centre sphere as we don't need
176  * to check this condition. see next 'if' statement
177  */
178  if (aa >= 0 || !ireg) {
179 
180  /* ie. particle moving away from center of
181  spheres, OR it is IN the innermost sphere
182  => we must check the outer sphere only
183  */
184  R2b2 = R2[ireg] - bb2;
185  if (R2b2 <= 0 && aa > 0) {
186  d = halfBoundaryTolerance; // hopefully a truncation problem
187  }
188  else {
189  tmp = aa2 + R2b2;
190  if (tmp > 0) {
191  tmp = sqrt(tmp);
192  }
193  else {
194  if (tmp < -boundaryTolerance) {
195  egsWarning("EGS_cSpheres::howfar: something is wrong\n");
196  egsWarning(" we think we are in region %d, but R2b2=%g",
197  ireg,R2b2);
198  }
199  tmp = 0;
200  }
201  d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
202  // the above reduces roundoff, which is significant
203  // when aa2 is large compared to R2b2 and aa>0
204  }
205  rad = -R[ireg];
206  direction_flag=ireg+1;
207  if (direction_flag >= nreg) {
208  direction_flag = -1;
209  }
210  }
211  else {
212 
213  /* so now we know the particle is moving towards the centre of the
214  * spheres. check to see if its trajectory will intersect the nested
215  * sphere - we are guaranteed there is one - we checked that already!
216  */
217  R2b2 = R2[ireg-1] - bb2;
218  tmp = aa2 + R2b2;
219  if (tmp <= 0) { // we will not intersect the nested sphere
220  R2b2 = R2[ireg] - bb2;
221  tmp = aa2 + R2b2;
222  if (tmp > 0) {
223  d = sqrt(tmp) - aa;
224  }
225  else {
226  d = -aa;
227  }
228  rad = -R[ireg];
229  direction_flag=ireg+1;
230  if (direction_flag >= nreg) {
231  direction_flag = -1;
232  }
233  }
234  else {
235  // we're hitting the inner sphere (from the outside)
236  tmp = sqrt(tmp);
237  d = -R2b2/(tmp - aa);
238  direction_flag=ireg-1;
239  rad = R[direction_flag];
240  }
241  }
242  }
243  else {
244  // we are not inside any of the spherical regions of interest
245  if (aa<0) { // we _might_ intersect the largest sphere
246  R2b2 = R2[nreg-1] - bb2;
247  tmp = aa2 + R2b2;
248  if (tmp > 0) { // we *will* intersect the largest sphere
249  d = -R2b2/(sqrt(tmp) - aa);
250  direction_flag=nreg-1;
251  rad = R[direction_flag];
252  }
253  }
254  }
255 
256 #ifdef SPHERES_DEBUG
257  if (isnan(d)) {
258  egsWarning("\nGot nan\n");
259  }
260 
261  if (d < -boundaryTolerance) {
262  egsWarning("\nNegative step?: %g\n",d);
263  egsWarning("ireg=%d inew=%d aa=%g bb2=%g\n",ireg,direction_flag,aa,bb2);
264  //exit(1);
265  }
266 
267  last_x = x;
268  last_u = u;
269  last_ireg = ireg;
270  last_d = d;
271  last_t = t;
272  last_aa = aa;
273  last_bb2 = bb2;
274  last_R2b2 = R2b2;
275  last_tmp = tmp;
276 #endif
277 
278  // check desired step size against this d
279  if (d<=t) {
280  t=d;
281  if (newmed) {
282  if (direction_flag >= 0) {
283  *newmed = medium(direction_flag);
284  }
285  else {
286  *newmed = -1;
287  }
288  }
289  if (normal) {
290  EGS_Vector n(xp + u*d);
291  *normal = n*(1/rad);
292  }
293  return direction_flag;
294  }
295  return ireg;
296 }
297 
298 // hownear - closest perpendicular distance to sphere surface
299 EGS_Float EGS_cSpheres::hownear(int ireg, const EGS_Vector &x) {
300  EGS_Vector xp(x-xo);
301  EGS_Float r=xp.length();
302  //EGS_Float r_sq=x.x*x.x+x.y*x.y+x.z*x.z;
303  EGS_Float d;
304 
305  if (ireg>=0) {
306  d=R[ireg]-r;
307  if (ireg) {
308  EGS_Float dd=r-R[ireg-1];
309  if (dd<d) {
310  d=dd;
311  }
312  }
313  }
314  else {
315  d=r-R[nreg-1];
316  }
317 
318  return d;
319 }
320 
321 void EGS_cSpheres::printInfo() const {
323  egsInformation(" midpoint of spheres = (%g,%g,%g)\n",xo.x,xo.y,xo.z);
324  egsInformation(" sphere radii = ");
325  for (int j=0; j<nreg; j++) {
326  egsInformation("%g ",R[j]);
327  }
329  "\n=======================================================\n");
330 }
331 
332 EGS_Float EGS_cSpheres::getBound(int idir, int ind) {
333  if (idir == RDIR && ind ==0) {
334  return 0.;
335  }
336  else if (idir == RDIR && ind>0 && ind <= nreg) {
337  return rbounds[ind-1];
338  }
339  return EGS_BaseGeometry::getBound(idir, ind);
340 }
341 
342 
344  if (dir == RDIR) {
345  return nreg;
346  }
347  return EGS_BaseGeometry::getNRegDir(dir);
348 }
349 
350 
351 EGS_Float EGS_cSpheres::getVolume(int ireg) {
352  if (ireg >= 0 && ireg < nreg) {
353  return vol[ireg];
354  }
355  return 1;
356 }
357 
358 /********************** Shell *************************************/
359 
360 string EGS_cSphericalShell::type = "EGS_cSphericalShell";
361 
362 // generate the concentric spheres
363 EGS_cSphericalShell::EGS_cSphericalShell(int ns, const EGS_Float *radius,
364  const EGS_Vector &position, const string &Name) :
365  EGS_BaseGeometry(Name), xo(position) {
366 
367  is_convex = false;
368 
369  if (ns>0) {
370 
371  R2 = new EGS_Float [ns];
372  R = new EGS_Float [ns];
373 
374  for (int i=0; i<ns; i++) {
375  R2[i] = radius[i]*radius[i];
376  R[i] = radius[i];
377  }
378 
379  // for n-concentric spheres (with hollow centre), we have n - 1 separate regions
380  nreg = ns - 1;
381  }
382 
383  for (int ireg=0; ireg < nreg; ireg++) {
384  EGS_Float rinner = R[ireg];
385  EGS_Float router = R[ireg + 1];
386  vol.push_back((4./3.)*M_PI*(router*router*router - rinner*rinner*rinner));
387  }
388 }
389 
390 bool EGS_cSphericalShell::isInside(const EGS_Vector &x) {
391  EGS_Float r_sq = (x - xo).length2();
392  return (r_sq >= R2[0]) && (r_sq <= R2[nreg]);
393 }
394 
395 int EGS_cSphericalShell::isWhere(const EGS_Vector &x) {
396 
397  EGS_Float r_sq = (x - xo).length2();
398 
399  if ((r_sq < R2[0]) || (r_sq > R2[nreg])) {
400  return -1;
401  }
402  return findRegion(r_sq, nreg, R2);
403 }
404 
405 // method to determine which spheres we are in(between)
406 int EGS_cSphericalShell::inside(const EGS_Vector &x) {
407 
408  EGS_Vector tmp(x-xo);
409  EGS_Float r_sq=tmp.length2();
410 
411  // are we outside off all spheres? If so return that region number
412  if (r_sq > R2[nreg] || r_sq < R2[0]) {
413  return -1;
414  }
415 
416  for (int shell = 1; shell < nreg + 1; shell++) {
417  if (r_sq <= R2[shell]) {
418  return shell - 1;
419  }
420  }
421 
422  return -1;
423 
424 }
425 
426 EGS_Float EGS_cSphericalShell::howfarToOutside(int ireg, const EGS_Vector &x,
427  const EGS_Vector &u) {
428  if (ireg < 0) {
429  return 0;
430  }
431  EGS_Vector xp(x - xo);
432  EGS_Float aa = xp*u;
433  EGS_Float aa2 = aa*aa;
434  EGS_Float bb2 = xp.length2();
435  EGS_Float R2b2 = R2[nreg] - bb2;
436  EGS_Float R2b2in = R2[0] - bb2;
437  if (R2b2in <= 0 || R2b2 <= 0) {
438  return 0; // outside within precision
439  }
440 
441  EGS_Float d, tmp;
442  if (aa >= 0) {
443 
444  /* ie. particle moving away from center of
445  spheres we must check the outer sphere only
446  */
447  if (R2b2 <= 0 && aa > 0) {
448  d = 1e-15; // hopefully a truncation problem
449  }
450  else {
451  tmp = aa2 + R2b2;
452  if (tmp > 0) {
453  tmp = sqrt(tmp);
454  }
455  else {
456  if (tmp < -1e-2) {
457  egsWarning("EGS_cSphericalShell::howfarToOutside: something is wrong\n");
458  egsWarning(" we think we are in region %d, but R2b2=%g", ireg,R2b2);
459  }
460  tmp = 0;
461  }
462  d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
463  }
464  }
465  else {
466 
467  R2b2 = R2[0] - bb2;
468  tmp = aa2 + R2b2;
469  if (tmp <= 0) { // we will not intersect the nested sphere
470  R2b2 = R2[nreg] - bb2;
471  tmp = aa2 + R2b2;
472  if (tmp > 0) {
473  d = sqrt(tmp) - aa;
474  }
475  else {
476  d = -aa;
477  }
478  }
479  else {
480  // we're hitting the inner sphere (from the outside)
481  tmp = sqrt(tmp);
482  d = -R2b2/(tmp - aa);
483  }
484 
485  }
486  return d;
487 
488 }
489 
490 
491 // howfar is particle trajectory from sphere boundary
492 /* note that in general we will be between two spheres (if inside a sphere at
493  * all... so we need to check if the flight path will intersect the inner or
494  * outer sphere
495  */
496 int EGS_cSphericalShell::howfar(int ireg, const EGS_Vector &x,
497  const EGS_Vector &u, EGS_Float &t, int *newmed, EGS_Vector *normal) {
498  int direction_flag=-1; /* keep track of direction entering or exiting a
499  sphere boundary */
500  double d=1e35; // set a maximum distance from a boundary
501 
502  EGS_Vector xp(x - xo);
503  double aa = xp*u, aa2 = aa*aa;
504  double bb2 = xp.length2();
505 
506  double rad=0, R2b2, tmp;
507 
508  // check if we are inside of any regions at all? ...
509  if (ireg >= 0) {
510 
511  /* check if particle is moving towards or away from the sphere(s) centre.
512  * we loose here if the particle is in the centre sphere as we don't need
513  * to check this condition. see next 'if' statement
514  */
515  if (aa >= 0) {
516 
517  /* ie. particle moving away from center of
518  spheres we must check the outer sphere only
519  */
520  R2b2 = R2[ireg + 1] - bb2;
521  if (R2b2 <= 0 && aa > 0) {
522  d = 1e-15; // hopefully a truncation problem
523  }
524  else {
525  tmp = aa2 + R2b2;
526  if (tmp > 0) {
527  tmp = sqrt(tmp);
528  }
529  else {
530  if (tmp < -1e-2) {
531  egsWarning("EGS_cSphericalShell::howfar: something is wrong\n");
532  egsWarning(" we think we are in region %d, but R2b2=%g",
533  ireg,R2b2);
534  }
535  tmp = 0;
536  }
537  d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
538  // the above reduces roundoff, which is significant
539  // when aa2 is large compared to R2b2 and aa>0
540  }
541  rad = -R[ireg + 1];
542  direction_flag = ireg + 1;
543  if (direction_flag >= nreg) {
544  direction_flag = -1;
545  }
546  }
547  else {
548 
549  /* so now we know the particle is moving towards the centre of the
550  * spheres. check to see if its trajectory will intersect the nested
551  * sphere - we are guaranteed there is one - we checked that already!
552  */
553  R2b2 = R2[ireg] - bb2;
554  tmp = aa2 + R2b2;
555  if (tmp <= 0) { // we will not intersect the nested sphere
556  R2b2 = R2[ireg+1] - bb2;
557  tmp = aa2 + R2b2;
558  if (tmp > 0) {
559  d = sqrt(tmp) - aa;
560  }
561  else {
562  d = -aa;
563  }
564  rad = -R[ireg + 1];
565  direction_flag= ireg + 1;
566  if (direction_flag >= nreg) {
567  direction_flag = -1;
568  }
569  }
570  else {
571  // we're hitting the inner sphere (from the outside)
572  tmp = sqrt(tmp);
573  d = -R2b2/(tmp - aa);
574  direction_flag= ireg - 1;
575  rad = R[ireg];
576  }
577  }
578  }
579  else {
580  // if we're in here, we know we're not in the shell, so bb2
581  // can be equal to R2[0], it just means we're sitting at the
582  // boundary
583  if (bb2 <= R2[0] + epsilon) { //epsilon needed for round off errors
584  // we are in the hollow center
585  R2b2 = R2[0] - bb2;
586  tmp = sqrt(aa2 + R2b2);
587  d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
588  direction_flag = 0;
589  rad = -R[direction_flag];
590  }
591  else {
592  // we are not inside any of the spherical regions of interest
593  if (aa<0) { // we _might_ intersect the largest sphere
594  R2b2 = R2[nreg] - bb2;
595  tmp = aa2 + R2b2;
596  if (tmp > 0) { // we *will* intersect the largest sphere
597  d = -R2b2/(sqrt(tmp) - aa);
598  direction_flag=nreg-1;
599  rad = R[nreg];
600  }
601  }
602  }
603  }
604 
605  // check desired step size against this d
606  if (d <= t) {
607  t=d;
608  if (newmed) {
609  if (direction_flag >= 0) {
610  *newmed = medium(direction_flag);
611  }
612  else {
613  *newmed = -1;
614  }
615  }
616  if (normal) {
617  EGS_Vector n(xp + u*d);
618  *normal = n*(1/rad);
619  }
620  return direction_flag;
621  }
622  return ireg;
623 }
624 
625 // hownear - closest perpendicular distance to sphere surface
626 EGS_Float EGS_cSphericalShell::hownear(int ireg, const EGS_Vector &x) {
627 
628  EGS_Vector xp(x-xo);
629  EGS_Float r = xp.length();
630  EGS_Float d, dout,din;
631 
632  if (ireg >= 0) {
633  dout = R[ireg+1] - r;
634  din = r - R[ireg];
635  d = min(dout, din);
636  }
637  else if (r <= R[0] + epsilon) { //epsilon needed for round off errors
638  d = R[0] - r;
639  }
640  else {
641  d = r - R[nreg];
642  }
643 
644  return d;
645 }
646 
647 EGS_Float EGS_cSphericalShell::getBound(int idir, int ind) {
648  if (idir == RDIR && ind >= 0 && ind <= nreg) {
649  return R[ind];
650  }
651  return EGS_BaseGeometry::getBound(idir, ind);
652 }
653 
654 
655 int EGS_cSphericalShell::getNRegDir(int dir) {
656  if (dir == RDIR) {
657  return nreg;
658  }
659  return EGS_BaseGeometry::getNRegDir(dir);
660 }
661 
662 
663 EGS_Float EGS_cSphericalShell::getVolume(int ireg) {
664  if (ireg >= 0 && ireg < nreg) {
665  return vol[ireg];
666  }
667  return 1;
668 }
669 
670 
671 void EGS_cSphericalShell::printInfo() const {
673  egsInformation(" midpoint of spheres = (%g,%g,%g)\n",xo.x,xo.y,xo.z);
674  egsInformation(" sphere radii = ");
675  for (int j=0; j<nreg+1; j++) {
676  egsInformation("%g ",R[j]);
677  }
679  "\n=======================================================\n");
680 }
681 
682 extern "C" {
683 
684  EGS_SPHERES_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) {
685  if (!input) {
686  egsWarning("createGeometry(spheres): null input?\n");
687  return 0;
688  }
689  EGS_Vector xo;
690  vector<EGS_Float> Xo;
691  int err = input->getInput("midpoint",Xo);
692  if (!err && Xo.size() == 3) {
693  xo = EGS_Vector(Xo[0],Xo[1],Xo[2]);
694  }
695 
696  string type= "";
697  input->getInput("type", type);
698 
699  vector<EGS_Float> radii;
700  err = input->getInput("radii",radii);
701  if (err) {
702  egsWarning("createGeometry(spheres): wrong/missing 'radii' input\n");
703  return 0;
704  }
705  else if ((type == "shell") && (radii.size() < 2)) {
706  egsWarning("createGeometry(spheres): You must specify at least two radii for a spherical shell\n");
707  return 0;
708  }
709 
710  EGS_Float *r = new EGS_Float [radii.size()];
711  for (int j=0; j<radii.size(); j++) {
712  r[j] = radii[j];
713  }
714 
715  EGS_BaseGeometry *result;
716  if (type != "shell") {
717  result = new EGS_cSpheres(radii.size(),r,xo);
718  }
719  else {
720  result = new EGS_cSphericalShell(radii.size(), r, xo);
721  }
722  result->setName(input);
723  result->setBoundaryTolerance(input);
724  result->setMedia(input);
725  result->setLabels(input);
726  return result;
727  }
728 
729 }
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
void setMedia(EGS_Input *inp)
Set the media in the geometry from the input pointed to by inp.
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.
bool is_convex
Is this geometry convex?
EGS_Float boundaryTolerance
Boundary tolerance for geometries that need it.
void setName(EGS_Input *inp)
Set the name of the geometry from the input inp.
virtual int getNRegDir(int idir)
virtual int medium(int ireg) const
Returns the medium index in region ireg.
int setLabels(EGS_Input *input)
Set the labels from an input block.
virtual EGS_Float getBound(int idir, int ind)
Returns region boundaries in direction determined by idir.
virtual void printInfo() const
Print information about this geometry.
void setBoundaryTolerance(EGS_Input *inp)
Set the value of the boundary tolerance from the input inp.
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
int getInput(const string &key, vector< string > &values) const
Assign values to an array of strings from an input identified by key.
Definition: egs_input.cpp:338
A class representing 3D vectors.
Definition: egs_vector.h:57
EGS_Float y
y-component
Definition: egs_vector.h:62
EGS_Float z
z-component
Definition: egs_vector.h:63
EGS_Float x
x-component
Definition: egs_vector.h:61
A set of concentric spheres.
Definition: egs_spheres.h:139
EGS_Float getBound(int idir, int ind)
Implement getBound for spherical regions.
int getNRegDir(int dir)
Implement geNRegDir for spherical regions.
EGS_Float getVolume(int ireg)
Implement getVolume for spherical regions.
Implements a spherical shell geometry with a hollow centre.
Definition: egs_spheres.h:209
Global egspp functions header file.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
Definition: egs_glib.cpp:57
EGS_Input class header file.
A set of concentric spheres.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
Definition: egs_functions.h:62
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.
const EGS_Float veryFar
A very large float.