45 #ifndef EGS_ND_GEOMETRY_
46 #define EGS_ND_GEOMETRY_
51 #define EGS_NDG_EXPORT __declspec(dllexport)
53 #define EGS_NDG_EXPORT __declspec(dllimport)
59 #ifdef HAVE_VISIBILITY
60 #define EGS_NDG_EXPORT __attribute__ ((visibility ("default")))
61 #define EGS_NDG_LOCAL __attribute__ ((visibility ("hidden")))
63 #define EGS_NDG_EXPORT
325 EGS_NDGeometry(vector<EGS_BaseGeometry *> &G,
const string &Name =
"",
331 for (
int j=0; j<N; j++)
if (!g[j]->
isInside(x)) {
339 for (
int j=0; j<N; j++) {
340 int ij = g[j]->isWhere(x);
360 for (
int j=N-1; j>=0; j--) {
362 EGS_Float t = g[j]->howfarToOutside(l,x,u);
374 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
377 int inext = -1, idelta=0, lnew_j=0;
378 for (
int j=N-1; j>=0; j--) {
380 int lnew = g[j]->howfar(l,x,u,t,0,normal);
391 int inew = lnew_j >= 0 ? ireg + idelta*n[inext] : lnew_j;
395 *newmed = inew >= 0 ?
medium(inew) : -1;
399 for (
int j=0; j<N; j++) {
401 bool is_in = g[j]->isInside(x);
408 int i = g[j]->howfar(ireg,x,u,tj,0,np);
413 for (
int k=0; k<N; k++) {
415 int check = g[k]->isWhere(tmp);
443 int ii = g[j]->isWhere(x);
445 for (EGS_I64 loopCount=0; loopCount<=
loopMax; ++loopCount) {
447 egsFatal(
"EGS_NDGeometry::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
450 EGS_Float tt = tleft;
451 int inew = g[j]->howfar(ii,tmp,u,tt);
467 EGS_Float tt = tleft;
468 int inew = g[j]->howfar(ii,tmp,u,tt,0,np);
474 for (
int k=0; k<N; k++) {
476 int check = g[k]->isWhere(tmp);
506 for (
int j=N-1; j>=0; j--) {
508 EGS_Float t = g[j]->hownear(l,x);
521 EGS_Float s1=0, s2=0;
522 for (
int j=0; j<N; j++) {
524 EGS_Float t = g[j]->hownear(-1,x);
537 for (
int j=0; j<N; j++) {
539 int i = g[j]->isWhere(x);
540 t = g[j]->hownear(i,x);
554 for (
int j=0; j<N; ++j) {
555 nstep += g[j]->getMaxStep();
563 for (
int j=0; j<N; j++) {
564 g[j]->getNextGeom(rndm);
568 void updatePosition(EGS_Float time) {
571 for (
int j=0; j<N; j++) {
572 g[j]->updatePosition(time);
576 void containsDynamic(
bool &hasdynamic) {
579 for (
int j=0; j<N; j++) {
581 g[j]->containsDynamic(hasdynamic);
586 const string &
getType()
const {
593 void ndRegions(
int r,
int dim,
int dimk,
int k, vector<int> ®s);
615 void setM(
int ib,
int idim,
const vector<int> &ranges,
int medium);
619 #include "../egs_planes/egs_planes.h"
774 const string &Name =
"");
779 if (!xp->isInside(x)) {
782 if (!yp->isInside(x)) {
785 if (!zp->isInside(x)) {
792 int ix = xp->isWhere(x);
796 int iy = yp->isWhere(x);
800 int iz = zp->isWhere(x);
804 return ix + iy*nx + iz*nxy;
817 EGS_Float t, t_ini = 0;
822 ireg =
howfar(ireg,x,u,t,&imed);
827 isections[0].
rhof = 1;
828 isections[0].
ireg = -1;
829 isections[0].
imed = -1;
837 EGS_Float *px = xp->getPositions(),
838 *py = yp->getPositions(),
839 *pz = zp->getPositions();
841 int ir = ireg - iz*nxy;
844 EGS_Float uxi, uyi, uzi, nextx, nexty, nextz;
845 int dirx, icx, diry, icy, dirz, icz;
891 nextx = (px[ix+icx] - x.
x)*uxi + t_ini;
892 nexty = (py[iy+icy] - x.
y)*uyi + t_ini;
893 nextz = (pz[iz+icz] - x.
z)*uzi + t_ini;
894 for (
int j=ifirst; j<n; j++) {
895 isections[j].
imed = imed;
896 isections[j].
ireg = ireg;
899 if (nextx < nexty && nextx < nextz) {
902 if (ix < 0 || ix >= nx) {
907 nextx = (px[ix+icx] - x.
x)*uxi + t_ini;
910 else if (nexty < nextz) {
913 if (iy < 0 || iy >= ny) {
917 inew = ireg + nx*diry;
918 nexty = (py[iy+icy] - x.
y)*uyi + t_ini;
924 if (iz < 0 || iz >= nz) {
928 inew = ireg + nxy*dirz;
929 nextz = (pz[iz+icz] - x.
z)*uzi + t_ini;
939 return ireg >= 0 ? -1 : n;
948 int ir = ireg - iz*nxy;
951 EGS_Float d = xp->howfarToOutside(ix,x,u);
952 EGS_Float ty = yp->howfarToOutside(iy,x,u);
956 EGS_Float tz = zp->howfarToOutside(iz,x,u);
964 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
967 int ir = ireg - iz*nxy;
972 EGS_Float d = (xpos[ix+1]-x.
x)/u.
x;
974 if (d <= boundaryTolerance) {
977 t = halfBoundaryTolerance;
994 EGS_Float d = (xpos[ix]-x.
x)/u.
x;
996 if (d <= boundaryTolerance) {
997 t = halfBoundaryTolerance;
1014 EGS_Float d = (ypos[iy+1]-x.
y)/u.
y;
1016 if (d <= boundaryTolerance) {
1017 t = halfBoundaryTolerance;
1034 EGS_Float d = (ypos[iy]-x.
y)/u.
y;
1036 if (d <= boundaryTolerance) {
1037 t = halfBoundaryTolerance;
1054 EGS_Float d = (zpos[iz+1]-x.
z)/u.
z;
1056 if (d <= boundaryTolerance) {
1057 t = halfBoundaryTolerance;
1074 EGS_Float d = (zpos[iz]-x.
z)/u.
z;
1076 if (d <= boundaryTolerance) {
1077 t = halfBoundaryTolerance;
1093 if (newmed && inew >= 0) {
1099 int inew = howfarFromOut(x,u,t,ix,iy,iz,face,normal);
1100 if (inew >= 0 && newmed) {
1109 int ir = ireg - iz*nxy;
1111 int ix = ir - iy*nx;
1112 EGS_Float t = xp->hownear(ix,x);
1113 EGS_Float t1 = yp->hownear(iy,x);
1117 t1 = zp->hownear(iz,x);
1124 EGS_Float s1=0, s2=0;
1125 if (!xp->isInside(x)) {
1126 EGS_Float t = xp->hownear(-1,x);
1131 if (!yp->isInside(x)) {
1132 EGS_Float t = yp->hownear(-1,x);
1137 if (!zp->isInside(x)) {
1138 EGS_Float t = zp->hownear(-1,x);
1152 int ir = ireg - iz*nxy;
1154 int ix = ir - iy*nx;
1155 return (xpos[ix+1]-xpos[ix])*(ypos[iy+1]-ypos[iy])*(zpos[iz+1]-zpos[iz]);
1158 EGS_Float
getBound(
int idir,
int ind) {
1161 if (ind>=0 && ind<=nx) {
1165 egsWarning(
"Error in getBound: Looking for X bound out of range %d\n"
1166 "Will set this to zero.\n",ind);
1170 else if (idir == 1) {
1171 if (ind>=0 && ind<=ny) {
1175 egsWarning(
"Error in getBound: Looking for Y bound out of range %d\n"
1176 "Will set this to zero.\n",ind);
1180 else if (idir == 2) {
1181 if (ind>=0 && ind<=nz) {
1185 egsWarning(
"Error in getBound: Looking for Z bound out of range %d\n"
1186 "Will set this to zero.\n",ind);
1191 egsWarning(
"Error in getBound: Dimension %d undefined in EGS_XYZGeometry.\n",idir);
1208 egsWarning(
"Error in getNregDir: Dimension %d undefined in EGS_XYZGeometry.\n",
1229 EGS_Float *getXPositions() {
1230 return xp->getPositions();
1232 EGS_Float *getYPositions() {
1233 return yp->getPositions();
1235 EGS_Float *getZPositions() {
1236 return zp->getPositions();
1239 static int getDigits(
int i);
1241 const string &
getType()
const {
1247 static EGS_XYZGeometry *constructGeometry(
const char *dens_or_egphant_file,
1248 const char *ramp_file,
int dens_or_egphant=0);
1249 static EGS_XYZGeometry *constructCTGeometry(
const char *dens_or_egphant_file);
1251 void voxelizeGeometry(
EGS_Input *input);
1256 void getXLabelRegions(
const string &str, vector<int> ®s) {
1257 xp->getLabelRegions(str, regs);
1259 void getYLabelRegions(
const string &str, vector<int> ®s) {
1260 yp->getLabelRegions(str, regs);
1262 void getZLabelRegions(
const string &str, vector<int> ®s) {
1263 zp->getLabelRegions(str, regs);
1274 int nx, ny, nz, nxy;
1282 EGS_Float &t,
int &ix,
int &iy,
int &iz,
1286 if (x.
x <= xpos[0] && u.
x > 0) {
1287 t1 = (xpos[0]-x.
x)/u.
x;
1291 else if (x.
x >= xpos[nx] && u.
x < 0) {
1292 t1 = (xpos[nx]-x.
x)/u.
x;
1296 if (ix >= 0 && t1 <= t) {
1298 iy = yp->isWhere(tmp);
1300 iz = zp->isWhere(tmp);
1302 int inew = ix + iy*nx + iz*nxy;
1303 if (t1 < boundaryTolerance) {
1304 int itest =
howfar(inew, tmp, u, t1);
1305 if (itest == -1 && t1 < boundaryTolerance) {
1309 if (normal) *normal = face == 0 ?
EGS_Vector(-1,0,0) :
1317 if (x.
y <= ypos[0] && u.
y > 0) {
1318 t1 = (ypos[0]-x.
y)/u.
y;
1322 else if (x.
y >= ypos[ny] && u.
y < 0) {
1323 t1 = (ypos[ny]-x.
y)/u.
y;
1327 if (iy >= 0 && t1 <= t) {
1329 ix = xp->isWhere(tmp);
1331 iz = zp->isWhere(tmp);
1333 int inew = ix + iy*nx + iz*nxy;
1334 if (t1 < boundaryTolerance) {
1335 int itest =
howfar(inew, tmp, u, t1);
1336 if (itest == -1 && t1 < boundaryTolerance) {
1340 if (normal) *normal = face == 2 ?
EGS_Vector(0,-1,0) :
1348 if (x.
z <= zpos[0] && u.
z > 0) {
1349 t1 = (zpos[0]-x.
z)/u.
z;
1353 else if (x.
z >= zpos[nz] && u.
z < 0) {
1354 t1 = (zpos[nz]-x.
z)/u.
z;
1358 if (iz >= 0 && t1 <= t) {
1360 ix = xp->isWhere(tmp);
1362 iy = yp->isWhere(tmp);
1364 int inew = ix + iy*nx + iz*nxy;
1365 if (t1 < boundaryTolerance) {
1366 int itest =
howfar(inew, tmp, u, t1);
1367 if (itest == -1 && t1 < boundaryTolerance) {
1371 if (normal) *normal = face == 4 ?
EGS_Vector(0,0,-1) :
1401 const char *defFile,
const string &Name =
"");
1406 int ireg = EGS_XYZGeometry::isWhere(x);
1407 if (ireg >= 0)
egsFatal(
"EGS_DeformedXYZ::isWhere(): this geometry "
1408 "does not allow the use of this method with position inside\n");
1416 int medium(
int ireg)
const {
1421 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
1423 int ir = ireg/6, tetra = ireg - 6*ir, tetra4 = 4*tetra;
1426 ind[1] = (ir - ind[2]*nxy)/nx;
1427 ind[0] = ir - ind[2]*nxy - ind[1]*nx;
1428 int edge = ir + ind[1] + ind[2]*nxyp1;
1430 n1(vectors[edge+tnodes[tetra4+1]]-n0),
1431 n2(vectors[edge+tnodes[tetra4+2]]-n0),
1432 n3(vectors[edge+tnodes[tetra4+3]]-n0);
1434 EGS_Float disti[4],dpi[4];
1438 disti[0]=normvec*n0x;
1441 disti[2]=normvec*n0x;
1444 disti[1]=normvec*n0x;
1445 normvec = (n3-n1)%(n2-n1);
1447 disti[3] = normvec*(n0x+n1);
1449 EGS_Float mindist = t, mindp=1;
1450 for (
int i=0; i<4; ++i) {
1451 if (dpi[i] > 0 && disti[i]*mindp < mindist*dpi[i]) {
1457 if (nextplane == 4) {
1461 int j = 12*tetra + 3*nextplane;
1462 int next = tetra_data[j];
1465 ind[next] += tetra_data[j+1];
1466 if (ind[next] < 0 || ind[next] >= np[next]) {
1469 irnew = ind[0] + ind[1]*nx + ind[2]*nxy;
1475 switch (nextplane) {
1486 *normal = (n2-n1)%(n3-n1);
1489 return 6*irnew + tetra_data[j+2];
1492 int inew = howfarFromOut(x,u,t,ix,iy,iz,face,normal);
1500 int edge = inew + iy + iz*nxyp1;
1502 int tetra1 = enter_tetra1[face], plane1 = enter_plane1[face];
1503 int node1 = tnodes[4*tetra1 + plane_order[3*plane1]],
1504 node2 = tnodes[4*tetra1 + plane_order[3*plane1+1]],
1505 node3 = tnodes[4*tetra1 + plane_order[3*plane1+2]];
1506 if (inTriangle(vectors[edge+node1],vectors[edge+node2],
1507 vectors[edge+node3],tmp)) {
1508 return 6*inew + tetra1;
1510 int tetra2 = enter_tetra2[face], plane2 = enter_plane2[face];
1511 int node1a = tnodes[4*tetra2 + plane_order[3*plane2]],
1512 node2a = tnodes[4*tetra2 + plane_order[3*plane2+1]],
1513 node3a = tnodes[4*tetra2 + plane_order[3*plane2+2]];
1514 if (inTriangle(vectors[edge+node1a],vectors[edge+node2a],
1515 vectors[edge+node3a],tmp)) {
1516 return 6*inew + tetra2;
1519 egsWarning(
"deformed geometry: entering from face %d but inTriangle()"
1520 " fails for both triangles\n",face);
1521 egsWarning(
"x_enter=(%16.10f,%16.10f,%16.10f)\n",tmp.
x,tmp.
y,tmp.
z);
1527 return EGS_XYZGeometry::hownear(ireg,x);
1529 int ir = ireg/6, tetra = ireg - 6*ir, tetra4 = 4*tetra;
1532 ind[1] = (ir - ind[2]*nxy)/nx;
1533 ind[0] = ir - ind[2]*nxy - ind[1]*nx;
1534 int edge = ir + ind[1] + ind[2]*nxyp1;
1536 n1(vectors[edge+tnodes[tetra4+1]]-n0),
1537 n2(vectors[edge+tnodes[tetra4+2]]-n0),
1538 n3(vectors[edge+tnodes[tetra4+3]]-n0);
1540 EGS_Float disti[4],dpi[4];
1543 dpi[0]=normvec.length2();
1544 disti[0]=normvec*n0x;
1546 dpi[2]=normvec.length2();
1547 disti[2]=normvec*n0x;
1549 dpi[1]=normvec.length2();
1550 disti[1]=normvec*n0x;
1551 normvec = (n3-n1)%(n2-n1);
1552 dpi[3] = normvec.length2();
1553 disti[3] = normvec*(n0x+n1);
1554 EGS_Float mindist =
veryFar, mindp=1;
1555 for (
int i=0; i<4; ++i) {
1556 if (disti[i]*mindp < mindist*dpi[i]) {
1561 return mindist/mindp;
1576 int ir1 = ir - iz*nxy;
1578 int ix = ir1 - iy*nx;
1579 EGS_Float d = xp->howfarToOutside(ix,x,u);
1580 EGS_Float ty = yp->howfarToOutside(iy,x,u);
1584 EGS_Float tz = zp->howfarToOutside(iz,x,u);
1592 return 6*(nx+ny+nz) + 1;
1595 const string &
getType()
const {
1612 int setDeformations(
const char *defFile);
1617 EGS_Float a=u1.length2(), b=u1*u2, c=u2.length2(), b1=xp*u1, b2=xp*u2;
1618 EGS_Float D=a*c-b*b;
1619 EGS_Float u=b1*c-b2*b;
1623 EGS_Float v=b2*a-b1*b;
1640 static string def_type;
1642 static char tetrahedra[];
1644 static char plane_order[];
1646 static char tetra_data[];
1648 static char enter_tetra1[];
1649 static char enter_plane1[];
1650 static char enter_tetra2[];
1651 static char enter_plane2[];
1732 EGS_Float Ymin, EGS_Float Ymax,
1733 EGS_Float Zmin, EGS_Float Zmax,
1735 const string &Name =
"");
1740 int cell = xyz->isWhere(x);
1746 int ir = g->isWhere(xp);
1748 return ir >= 0 ? cell*ng + ir : nreg-1;
1752 return xyz->isInside(x);
1759 int medium(
int ireg)
const {
1760 if (ireg == nreg-1) {
1764 int ilocal = ireg - ng*cell;
1765 return g->medium(ilocal);
1773 return xyz->howfarToOutside(0,x,u);
1777 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
1782 int cell = xyz->howfar(ireg,x,u,t,0,normal);
1793 if (ireg < nreg-1) {
1795 int ilocal = ireg - cell*ng;
1797 int inew = g->howfar(ilocal,xp,u,t,newmed,normal);
1801 return cell*ng + inew;
1811 int ix = (int)(x.
x*dxi + ax);
1815 int iy = (int)(x.
y*dyi + ay);
1819 int iz = (int)(x.
z*dzi + az);
1823 int cell = ix + iy*nx + iz*nxy;
1825 EGS_Float t_left = t;
1828 for (EGS_I64 loopCount=0; loopCount<=
loopMax; ++loopCount) {
1830 egsFatal(
"EGS_XYZRepeater::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
1833 EGS_Float this_t = t_left;
1835 int inew = g->howfar(-1,xp,u,this_t,newmed,normal);
1840 return cell*ng + inew;
1842 int next_cell = xyz->howfar(cell,xtmp,u,this_t,0,normal);
1844 if (next_cell == cell) {
1847 if (next_cell < 0) {
1862 return xyz->hownear(ireg,x);
1864 if (ireg < nreg-1) {
1866 int ilocal = ireg - cell*ng;
1868 return g->hownear(ilocal,xp);
1872 int ix = (int)(x.
x*dxi + ax);
1876 int iy = (int)(x.
y*dyi + ay);
1880 int iz = (int)(x.
z*dzi + az);
1884 int cell = ix + iy*nx + iz*nxy;
1886 EGS_Float t = g->hownear(-1,xp);
1887 EGS_Float tcell = xyz->hownear(cell,x);
1891 for (
int iix=ix-1; iix<=ix+1; ++iix) {
1892 if (iix >= 0 && iix < nx) {
1893 for (
int iiy=iy-1; iiy<=iy+1; ++iiy) {
1894 if (iiy >= 0 && iiy < ny) {
1895 for (
int iiz=iz-1; iiz<=iz+1; ++iiz) {
1896 if (iiz >= 0 && iiz < nz) {
1897 if (iix != ix || iiy != iy || iiz != iz) {
1898 int cell1 = iix+iiy*nx+iiz*nxy;
1900 EGS_Float t1 = g->hownear(-1,tmp);
1915 return nxyz*(g->getMaxStep() + 1) + 1;
1918 const string &
getType()
const {
1925 xyz->setXYZLabels(input);
1935 EGS_Float dx, dxi, ax;
1936 EGS_Float dy, dyi, ay;
1937 EGS_Float dz, dzi, az;
1938 int nx, ny, nz, nxy, nxyz, ng;
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
virtual int computeIntersections(int ireg, int n, const EGS_Vector &x, const EGS_Vector &u, EGS_GeometryIntersections *isections)
Calculates intersection distances to region boundaries.
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)
virtual EGS_Float howfarToOutside(int ireg, const EGS_Vector &x, const EGS_Vector &u)
void setMedia(EGS_Input *inp)
Set the media in the geometry from the input pointed to by inp.
virtual const string & getType() const =0
Get the geometry type.
virtual void getLabelRegions(const string &str, vector< int > ®s)
Get the list of all regions labeled with str.
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.
virtual EGS_Float getVolume(int ireg)
Calculates the volume of region ireg.
virtual bool isInside(const EGS_Vector &x)=0
Is the position x inside the geometry?
virtual EGS_Float getRelativeRho(int ireg) const
Get the relative mass density in region ireg.
bool isConvex() const
Is the geometry convex?
virtual int getNRegDir(int idir)
virtual int getMaxStep() const
Returns the maximum number of steps through the geometry.
virtual int medium(int ireg) const
Returns the medium index in region ireg.
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.
virtual int isWhere(const EGS_Vector &x)=0
In which region is poisition x?
A class modeling a N-dimensional geometry.
static string type
The geometry type.
int * n
Used for calculating region indeces.
bool ortho
Is the geometry orthogonal ?
EGS_BaseGeometry ** g
The dimensions.
int N
Number of dimensions.
A set of parallel planes.
Base random number generator class. All random number generators should be derived from this class.
A class representing 3D vectors.
A geometry repeated on a regular XYZ grid.
EGS_BaseGeometry class header file.
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
const EGS_I64 loopMax
The maximum number of iterations for near-infinite loops.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.
const EGS_Float veryFar
A very large float.
EGS_Float t
distance to next region boundary
EGS_Float rhof
relative mass density in that region