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