47 string EGS_cSpheres::type =
"EGS_cSpheres";
50 EGS_cSpheres::EGS_cSpheres(
int ns,
const EGS_Float *radius,
51 const EGS_Vector &position,
const string &Name) :
56 R2=
new EGS_Float [ns];
60 for (
int i=0; i<ns; i++) {
61 R2[i]=radius[i]*radius[i];
69 for (
int ireg=0; ireg < ns; ireg++) {
70 rbounds.push_back(radius[ireg]);
71 EGS_Float router = rbounds[ireg];
72 EGS_Float rinner = ireg > 0 ? rbounds[ireg-1] : 0;
73 vol.push_back((4./3.)*M_PI*(router*router*router - rinner*rinner*rinner));
77 bool EGS_cSpheres::isInside(
const EGS_Vector &x) {
79 EGS_Float r_sq=tmp.length2();
80 if (r_sq>R2[
nreg-1]) {
86 int EGS_cSpheres::isWhere(
const EGS_Vector &x) {
88 EGS_Float r_sq=tmp.length2();
89 if (r_sq>R2[
nreg-1]) {
99 int EGS_cSpheres::inside(
const EGS_Vector &x) {
102 EGS_Float r_sq=tmp.length2();
105 if (r_sq>R2[
nreg-1]) {
138 EGS_Float last_d,last_t,last_aa,last_bb2,last_R2b2,last_tmp;
141 EGS_Float EGS_cSpheres::howfarToOutside(
int ireg,
const EGS_Vector &x,
147 EGS_Float aa = xp*u, aa2 = aa*aa;
148 EGS_Float bb2 = xp.length2();
149 EGS_Float R2b2 = R2[
nreg-1] - bb2;
153 EGS_Float tmp = sqrt(aa2 + R2b2);
154 return aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
157 int EGS_cSpheres::howfar(
int ireg,
const EGS_Vector &x,
159 int direction_flag=-1;
164 double aa = xp*u, aa2 = aa*aa;
165 double bb2 = xp.length2();
167 double rad=0, R2b2, tmp;
176 if (aa >= 0 || !ireg) {
182 R2b2 = R2[ireg] - bb2;
183 if (R2b2 <= 0 && aa > 0) {
184 d = halfBoundaryTolerance;
193 egsWarning(
"EGS_cSpheres::howfar: something is wrong\n");
194 egsWarning(
" we think we are in region %d, but R2b2=%g",
199 d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
204 direction_flag=ireg+1;
205 if (direction_flag >=
nreg) {
215 R2b2 = R2[ireg-1] - bb2;
218 R2b2 = R2[ireg] - bb2;
227 direction_flag=ireg+1;
228 if (direction_flag >=
nreg) {
235 d = -R2b2/(tmp - aa);
236 direction_flag=ireg-1;
237 rad = R[direction_flag];
244 R2b2 = R2[
nreg-1] - bb2;
247 d = -R2b2/(sqrt(tmp) - aa);
248 direction_flag=
nreg-1;
249 rad = R[direction_flag];
261 egsWarning(
"ireg=%d inew=%d aa=%g bb2=%g\n",ireg,direction_flag,aa,bb2);
280 if (direction_flag >= 0) {
281 *newmed =
medium(direction_flag);
291 return direction_flag;
297 EGS_Float EGS_cSpheres::hownear(
int ireg,
const EGS_Vector &x) {
299 EGS_Float r=xp.length();
306 EGS_Float dd=r-R[ireg-1];
319 void EGS_cSpheres::printInfo()
const {
323 for (
int j=0; j<
nreg; j++) {
327 "\n=======================================================\n");
331 if (idir == RDIR && ind ==0) {
334 else if (idir == RDIR && ind>0 && ind <=
nreg) {
335 return rbounds[ind-1];
350 if (ireg >= 0 && ireg <
nreg) {
358 string EGS_cSphericalShell::type =
"EGS_cSphericalShell";
361 EGS_cSphericalShell::EGS_cSphericalShell(
int ns,
const EGS_Float *radius,
362 const EGS_Vector &position,
const string &Name) :
369 R2 =
new EGS_Float [ns];
370 R =
new EGS_Float [ns];
372 for (
int i=0; i<ns; i++) {
373 R2[i] = radius[i]*radius[i];
381 for (
int ireg=0; ireg <
nreg; ireg++) {
382 EGS_Float rinner = R[ireg];
383 EGS_Float router = R[ireg + 1];
384 vol.push_back((4./3.)*M_PI*(router*router*router - rinner*rinner*rinner));
388 bool EGS_cSphericalShell::isInside(
const EGS_Vector &x) {
389 EGS_Float r_sq = (x - xo).length2();
390 return (r_sq >= R2[0]) && (r_sq <= R2[
nreg]);
393 int EGS_cSphericalShell::isWhere(
const EGS_Vector &x) {
395 EGS_Float r_sq = (x - xo).length2();
397 if ((r_sq < R2[0]) || (r_sq > R2[
nreg])) {
404 int EGS_cSphericalShell::inside(
const EGS_Vector &x) {
407 EGS_Float r_sq=tmp.length2();
410 if (r_sq > R2[nreg] || r_sq < R2[0]) {
414 for (
int shell = 1; shell < nreg + 1; shell++) {
415 if (r_sq <= R2[shell]) {
424 EGS_Float EGS_cSphericalShell::howfarToOutside(
int ireg,
const EGS_Vector &x,
431 EGS_Float aa2 = aa*aa;
432 EGS_Float bb2 = xp.length2();
433 EGS_Float R2b2 = R2[
nreg] - bb2;
434 EGS_Float R2b2in = R2[0] - bb2;
435 if (R2b2in <= 0 || R2b2 <= 0) {
445 if (R2b2 <= 0 && aa > 0) {
455 egsWarning(
"EGS_cSphericalShell::howfarToOutside: something is wrong\n");
456 egsWarning(
" we think we are in region %d, but R2b2=%g", ireg,R2b2);
460 d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
468 R2b2 = R2[
nreg] - bb2;
480 d = -R2b2/(tmp - aa);
494 int EGS_cSphericalShell::howfar(
int ireg,
const EGS_Vector &x,
496 int direction_flag=-1;
501 double aa = xp*u, aa2 = aa*aa;
502 double bb2 = xp.length2();
504 double rad=0, R2b2, tmp;
518 R2b2 = R2[ireg + 1] - bb2;
519 if (R2b2 <= 0 && aa > 0) {
529 egsWarning(
"EGS_cSphericalShell::howfar: something is wrong\n");
530 egsWarning(
" we think we are in region %d, but R2b2=%g",
535 d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
540 direction_flag = ireg + 1;
541 if (direction_flag >= nreg) {
551 R2b2 = R2[ireg] - bb2;
554 R2b2 = R2[ireg+1] - bb2;
563 direction_flag= ireg + 1;
564 if (direction_flag >= nreg) {
571 d = -R2b2/(tmp - aa);
572 direction_flag= ireg - 1;
584 tmp = sqrt(aa2 + R2b2);
585 d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
587 rad = -R[direction_flag];
592 R2b2 = R2[
nreg] - bb2;
595 d = -R2b2/(sqrt(tmp) - aa);
596 direction_flag=nreg-1;
607 if (direction_flag >= 0) {
608 *newmed =
medium(direction_flag);
618 return direction_flag;
624 EGS_Float EGS_cSphericalShell::hownear(
int ireg,
const EGS_Vector &x) {
627 EGS_Float r = xp.length();
628 EGS_Float d, dout,din;
631 dout = R[ireg+1] - r;
635 else if (r <= R[0] +
epsilon) {
645 EGS_Float EGS_cSphericalShell::getBound(
int idir,
int ind) {
646 if (idir == RDIR && ind >= 0 && ind <= nreg) {
653 int EGS_cSphericalShell::getNRegDir(
int dir) {
661 EGS_Float EGS_cSphericalShell::getVolume(
int ireg) {
662 if (ireg >= 0 && ireg < nreg) {
669 void EGS_cSphericalShell::printInfo()
const {
673 for (
int j=0; j<nreg+1; j++) {
677 "\n=======================================================\n");
684 egsWarning(
"createGeometry(spheres): null input?\n");
688 vector<EGS_Float> Xo;
689 int err = input->
getInput(
"midpoint",Xo);
690 if (!err && Xo.size() == 3) {
697 vector<EGS_Float> radii;
698 err = input->
getInput(
"radii",radii);
700 egsWarning(
"createGeometry(spheres): wrong/missing 'radii' input\n");
703 else if ((type ==
"shell") && (radii.size() < 2)) {
704 egsWarning(
"createGeometry(spheres): You must specify at least two radii for a spherical shell\n");
708 EGS_Float *r =
new EGS_Float [radii.size()];
709 for (
int j=0; j<radii.size(); j++) {
714 if (type !=
"shell") {
virtual int getNRegDir(int idir)
virtual int medium(int ireg) const
Returns the medium index in region ireg.
virtual void printInfo() const
Print information about this geometry.
EGS_Float getVolume(int ireg)
Implement getVolume for spherical regions.
A class representing 3D vectors.
int setLabels(EGS_Input *input)
Set the labels from an input block.
int getNRegDir(int dir)
Implement geNRegDir for spherical regions.
Global egspp functions header file.
static int findRegion(EGS_Float xp, int np, const EGS_Float *p)
Find the bin to which xp belongs, given np bin edges p.
const EGS_Float veryFar
A very large float.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
EGS_Float getBound(int idir, int ind)
Implement getBound for spherical regions.
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
virtual EGS_Float getBound(int idir, int ind)
Returns region boundaries in direction determined by idir.
void setBoundaryTolerance(EGS_Input *inp)
Set the value of the boundary tolerance from the input inp.
void setMedia(EGS_Input *inp)
Set the media in the geometry from the input pointed to by inp.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
bool is_convex
Is this geometry convex?
A set of concentric spheres.
Implements a spherical shell geometry with a hollow centre.
void setName(EGS_Input *inp)
Set the name of the geometry from the input inp.
EGS_Float boundaryTolerance
Boundary tolerance for geometries that need it.
A set of concentric spheres.
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
int nreg
Number of local regions in this geometry.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.