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++) {
565 g[j]->getNextGeom(rndm);
570 void updatePosition(EGS_Float time) {
573 for (
int j=0; j<N; j++) {
575 g[j]->updatePosition(time);
580 void containsDynamic(
bool &hasdynamic) {
583 for (
int j=0; j<N; j++) {
584 if (!hasdynamic && g[j]) {
585 g[j]->containsDynamic(hasdynamic);
591 if (has_rho_scaling) {
595 for (
int j=0; j<N; j++) {
596 bool hasRS = g[j]->hasRhoScaling();
598 has_rho_scaling = hasRS;
606 void finishInitialization()
override {
607 for (
int j=0; j<N; j++) {
608 g[j]->finishInitialization();
612 const string &
getType()
const {
618 virtual void getLabelRegions(
const string &str, vector<int> ®s,
bool sanitize=
true);
619 void ndRegions(
int r,
int dim,
int dimk,
int k, vector<int> ®s);
641 void setM(
int ib,
int idim,
const vector<int> &ranges,
int medium);
645 #include "../egs_planes/egs_planes.h"
799 const string &Name =
"");
803 int medIndex(
char medium);
806 if (!xp->isInside(x)) {
809 if (!yp->isInside(x)) {
812 if (!zp->isInside(x)) {
819 int ix = xp->isWhere(x);
823 int iy = yp->isWhere(x);
827 int iz = zp->isWhere(x);
831 return ix + iy*nx + iz*nxy;
844 EGS_Float t, t_ini = 0;
849 ireg =
howfar(ireg,x,u,t,&imed);
854 isections[0].
rhof = 1;
855 isections[0].
ireg = -1;
856 isections[0].
imed = -1;
864 EGS_Float *px = xp->getPositions(),
865 *py = yp->getPositions(),
866 *pz = zp->getPositions();
868 int ir = ireg - iz*nxy;
871 EGS_Float uxi, uyi, uzi, nextx, nexty, nextz;
872 int dirx, icx, diry, icy, dirz, icz;
918 nextx = (px[ix+icx] - x.
x)*uxi + t_ini;
919 nexty = (py[iy+icy] - x.
y)*uyi + t_ini;
920 nextz = (pz[iz+icz] - x.
z)*uzi + t_ini;
921 for (
int j=ifirst; j<n; j++) {
922 isections[j].
imed = imed;
923 isections[j].
ireg = ireg;
926 if (nextx < nexty && nextx < nextz) {
929 if (ix < 0 || ix >= nx) {
934 nextx = (px[ix+icx] - x.
x)*uxi + t_ini;
937 else if (nexty < nextz) {
940 if (iy < 0 || iy >= ny) {
944 inew = ireg + nx*diry;
945 nexty = (py[iy+icy] - x.
y)*uyi + t_ini;
951 if (iz < 0 || iz >= nz) {
955 inew = ireg + nxy*dirz;
956 nextz = (pz[iz+icz] - x.
z)*uzi + t_ini;
966 return ireg >= 0 ? -1 : n;
975 int ir = ireg - iz*nxy;
978 EGS_Float d = xp->howfarToOutside(ix,x,u);
979 EGS_Float ty = yp->howfarToOutside(iy,x,u);
983 EGS_Float tz = zp->howfarToOutside(iz,x,u);
991 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
994 int ir = ireg - iz*nxy;
999 EGS_Float d = (xpos[ix+1]-x.
x)/u.
x;
1001 if (d <= boundaryTolerance) {
1004 t = halfBoundaryTolerance;
1021 EGS_Float d = (xpos[ix]-x.
x)/u.
x;
1023 if (d <= boundaryTolerance) {
1024 t = halfBoundaryTolerance;
1041 EGS_Float d = (ypos[iy+1]-x.
y)/u.
y;
1043 if (d <= boundaryTolerance) {
1044 t = halfBoundaryTolerance;
1061 EGS_Float d = (ypos[iy]-x.
y)/u.
y;
1063 if (d <= boundaryTolerance) {
1064 t = halfBoundaryTolerance;
1081 EGS_Float d = (zpos[iz+1]-x.
z)/u.
z;
1083 if (d <= boundaryTolerance) {
1084 t = halfBoundaryTolerance;
1101 EGS_Float d = (zpos[iz]-x.
z)/u.
z;
1103 if (d <= boundaryTolerance) {
1104 t = halfBoundaryTolerance;
1120 if (newmed && inew >= 0) {
1126 int inew = howfarFromOut(x,u,t,ix,iy,iz,face,normal);
1127 if (inew >= 0 && newmed) {
1136 int ir = ireg - iz*nxy;
1138 int ix = ir - iy*nx;
1139 EGS_Float t = xp->hownear(ix,x);
1140 EGS_Float t1 = yp->hownear(iy,x);
1144 t1 = zp->hownear(iz,x);
1151 EGS_Float s1=0, s2=0;
1152 if (!xp->isInside(x)) {
1153 EGS_Float t = xp->hownear(-1,x);
1158 if (!yp->isInside(x)) {
1159 EGS_Float t = yp->hownear(-1,x);
1164 if (!zp->isInside(x)) {
1165 EGS_Float t = zp->hownear(-1,x);
1179 int ir = ireg - iz*nxy;
1181 int ix = ir - iy*nx;
1182 return (xpos[ix+1]-xpos[ix])*(ypos[iy+1]-ypos[iy])*(zpos[iz+1]-zpos[iz]);
1185 EGS_Float
getBound(
int idir,
int ind) {
1188 if (ind>=0 && ind<=nx) {
1192 egsWarning(
"Error in getBound: Looking for X bound out of range %d\n"
1193 "Will set this to zero.\n",ind);
1197 else if (idir == 1) {
1198 if (ind>=0 && ind<=ny) {
1202 egsWarning(
"Error in getBound: Looking for Y bound out of range %d\n"
1203 "Will set this to zero.\n",ind);
1207 else if (idir == 2) {
1208 if (ind>=0 && ind<=nz) {
1212 egsWarning(
"Error in getBound: Looking for Z bound out of range %d\n"
1213 "Will set this to zero.\n",ind);
1218 egsWarning(
"Error in getBound: Dimension %d undefined in EGS_XYZGeometry.\n",idir);
1235 egsWarning(
"Error in getNregDir: Dimension %d undefined in EGS_XYZGeometry.\n",
1256 EGS_Float *getXPositions() {
1257 return xp->getPositions();
1259 EGS_Float *getYPositions() {
1260 return yp->getPositions();
1262 EGS_Float *getZPositions() {
1263 return zp->getPositions();
1266 static int getDigits(
int i);
1268 const string &
getType()
const {
1274 static EGS_XYZGeometry *constructGeometry(
const char *dens_or_egphant_file,
1275 const char *ramp_file,
int dens_or_egphant=0);
1276 static EGS_XYZGeometry *constructCTGeometry(
const char *dens_or_egphant_file);
1278 void voxelizeGeometry(
EGS_Input *input);
1282 virtual void getLabelRegions(
const string &str, vector<int> ®s,
bool sanitize=
true);
1283 void getXLabelRegions(
const string &str, vector<int> ®s,
bool sanitize=
true) {
1284 xp->getLabelRegions(str, regs, sanitize);
1286 void getYLabelRegions(
const string &str, vector<int> ®s,
bool sanitize=
true) {
1287 yp->getLabelRegions(str, regs, sanitize);
1289 void getZLabelRegions(
const string &str, vector<int> ®s,
bool sanitize=
true) {
1290 zp->getLabelRegions(str, regs, sanitize);
1293 void finishInitialization();
1303 int nx, ny, nz, nxy;
1311 EGS_Float &t,
int &ix,
int &iy,
int &iz,
1315 if (x.
x <= xpos[0] && u.
x > 0) {
1316 t1 = (xpos[0]-x.
x)/u.
x;
1320 else if (x.
x >= xpos[nx] && u.
x < 0) {
1321 t1 = (xpos[nx]-x.
x)/u.
x;
1325 if (ix >= 0 && t1 <= t) {
1327 iy = yp->isWhere(tmp);
1329 iz = zp->isWhere(tmp);
1331 int inew = ix + iy*nx + iz*nxy;
1332 if (t1 < boundaryTolerance) {
1333 int itest =
howfar(inew, tmp, u, t1);
1334 if (itest == -1 && t1 < boundaryTolerance) {
1338 if (normal) *normal = face == 0 ?
EGS_Vector(-1,0,0) :
1346 if (x.
y <= ypos[0] && u.
y > 0) {
1347 t1 = (ypos[0]-x.
y)/u.
y;
1351 else if (x.
y >= ypos[ny] && u.
y < 0) {
1352 t1 = (ypos[ny]-x.
y)/u.
y;
1356 if (iy >= 0 && t1 <= t) {
1358 ix = xp->isWhere(tmp);
1360 iz = zp->isWhere(tmp);
1362 int inew = ix + iy*nx + iz*nxy;
1363 if (t1 < boundaryTolerance) {
1364 int itest =
howfar(inew, tmp, u, t1);
1365 if (itest == -1 && t1 < boundaryTolerance) {
1369 if (normal) *normal = face == 2 ?
EGS_Vector(0,-1,0) :
1377 if (x.
z <= zpos[0] && u.
z > 0) {
1378 t1 = (zpos[0]-x.
z)/u.
z;
1382 else if (x.
z >= zpos[nz] && u.
z < 0) {
1383 t1 = (zpos[nz]-x.
z)/u.
z;
1387 if (iz >= 0 && t1 <= t) {
1389 ix = xp->isWhere(tmp);
1391 iy = yp->isWhere(tmp);
1393 int inew = ix + iy*nx + iz*nxy;
1394 if (t1 < boundaryTolerance) {
1395 int itest =
howfar(inew, tmp, u, t1);
1396 if (itest == -1 && t1 < boundaryTolerance) {
1400 if (normal) *normal = face == 4 ?
EGS_Vector(0,0,-1) :
1412 int dens_or_egsphant_or_interfile;
1413 bool useEgsphantDensities;
1435 const char *defFile,
const string &Name =
"");
1440 int ireg = EGS_XYZGeometry::isWhere(x);
1441 if (ireg >= 0)
egsFatal(
"EGS_DeformedXYZ::isWhere(): this geometry "
1442 "does not allow the use of this method with position inside\n");
1450 int medium(
int ireg)
const {
1455 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
1457 int ir = ireg/6, tetra = ireg - 6*ir, tetra4 = 4*tetra;
1460 ind[1] = (ir - ind[2]*nxy)/nx;
1461 ind[0] = ir - ind[2]*nxy - ind[1]*nx;
1462 int edge = ir + ind[1] + ind[2]*nxyp1;
1464 n1(vectors[edge+tnodes[tetra4+1]]-n0),
1465 n2(vectors[edge+tnodes[tetra4+2]]-n0),
1466 n3(vectors[edge+tnodes[tetra4+3]]-n0);
1468 EGS_Float disti[4],dpi[4];
1472 disti[0]=normvec*n0x;
1475 disti[2]=normvec*n0x;
1478 disti[1]=normvec*n0x;
1479 normvec = (n3-n1)%(n2-n1);
1481 disti[3] = normvec*(n0x+n1);
1483 EGS_Float mindist = t, mindp=1;
1484 for (
int i=0; i<4; ++i) {
1485 if (dpi[i] > 0 && disti[i]*mindp < mindist*dpi[i]) {
1491 if (nextplane == 4) {
1495 int j = 12*tetra + 3*nextplane;
1496 int next = tetra_data[j];
1499 ind[next] += tetra_data[j+1];
1500 if (ind[next] < 0 || ind[next] >= np[next]) {
1503 irnew = ind[0] + ind[1]*nx + ind[2]*nxy;
1509 switch (nextplane) {
1520 *normal = (n2-n1)%(n3-n1);
1523 return 6*irnew + tetra_data[j+2];
1526 int inew = howfarFromOut(x,u,t,ix,iy,iz,face,normal);
1534 int edge = inew + iy + iz*nxyp1;
1536 int tetra1 = enter_tetra1[face], plane1 = enter_plane1[face];
1537 int node1 = tnodes[4*tetra1 + plane_order[3*plane1]],
1538 node2 = tnodes[4*tetra1 + plane_order[3*plane1+1]],
1539 node3 = tnodes[4*tetra1 + plane_order[3*plane1+2]];
1540 if (inTriangle(vectors[edge+node1],vectors[edge+node2],
1541 vectors[edge+node3],tmp)) {
1542 return 6*inew + tetra1;
1544 int tetra2 = enter_tetra2[face], plane2 = enter_plane2[face];
1545 int node1a = tnodes[4*tetra2 + plane_order[3*plane2]],
1546 node2a = tnodes[4*tetra2 + plane_order[3*plane2+1]],
1547 node3a = tnodes[4*tetra2 + plane_order[3*plane2+2]];
1548 if (inTriangle(vectors[edge+node1a],vectors[edge+node2a],
1549 vectors[edge+node3a],tmp)) {
1550 return 6*inew + tetra2;
1553 egsWarning(
"deformed geometry: entering from face %d but inTriangle()"
1554 " fails for both triangles\n",face);
1555 egsWarning(
"x_enter=(%16.10f,%16.10f,%16.10f)\n",tmp.
x,tmp.
y,tmp.
z);
1561 return EGS_XYZGeometry::hownear(ireg,x);
1563 int ir = ireg/6, tetra = ireg - 6*ir, tetra4 = 4*tetra;
1566 ind[1] = (ir - ind[2]*nxy)/nx;
1567 ind[0] = ir - ind[2]*nxy - ind[1]*nx;
1568 int edge = ir + ind[1] + ind[2]*nxyp1;
1570 n1(vectors[edge+tnodes[tetra4+1]]-n0),
1571 n2(vectors[edge+tnodes[tetra4+2]]-n0),
1572 n3(vectors[edge+tnodes[tetra4+3]]-n0);
1574 EGS_Float disti[4],dpi[4];
1577 dpi[0]=normvec.length2();
1578 disti[0]=normvec*n0x;
1580 dpi[2]=normvec.length2();
1581 disti[2]=normvec*n0x;
1583 dpi[1]=normvec.length2();
1584 disti[1]=normvec*n0x;
1585 normvec = (n3-n1)%(n2-n1);
1586 dpi[3] = normvec.length2();
1587 disti[3] = normvec*(n0x+n1);
1588 EGS_Float mindist =
veryFar, mindp=1;
1589 for (
int i=0; i<4; ++i) {
1590 if (disti[i]*mindp < mindist*dpi[i]) {
1595 return mindist/mindp;
1610 int ir1 = ir - iz*nxy;
1612 int ix = ir1 - iy*nx;
1613 EGS_Float d = xp->howfarToOutside(ix,x,u);
1614 EGS_Float ty = yp->howfarToOutside(iy,x,u);
1618 EGS_Float tz = zp->howfarToOutside(iz,x,u);
1626 return 6*(nx+ny+nz) + 1;
1629 const string &
getType()
const {
1646 int setDeformations(
const char *defFile);
1651 EGS_Float a=u1.length2(), b=u1*u2, c=u2.length2(), b1=xp*u1, b2=xp*u2;
1652 EGS_Float D=a*c-b*b;
1653 EGS_Float u=b1*c-b2*b;
1657 EGS_Float v=b2*a-b1*b;
1674 static string def_type;
1676 static char tetrahedra[];
1678 static char plane_order[];
1680 static char tetra_data[];
1682 static char enter_tetra1[];
1683 static char enter_plane1[];
1684 static char enter_tetra2[];
1685 static char enter_plane2[];
1766 EGS_Float Ymin, EGS_Float Ymax,
1767 EGS_Float Zmin, EGS_Float Zmax,
1769 const string &Name =
"");
1774 int cell = xyz->isWhere(x);
1780 int ir = g->isWhere(xp);
1782 return ir >= 0 ? cell*ng + ir : nreg-1;
1786 return xyz->isInside(x);
1793 int medium(
int ireg)
const {
1794 if (ireg == nreg-1) {
1798 int ilocal = ireg - ng*cell;
1799 return g->medium(ilocal);
1807 return xyz->howfarToOutside(0,x,u);
1811 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
1816 int cell = xyz->howfar(ireg,x,u,t,0,normal);
1827 if (ireg < nreg-1) {
1829 int ilocal = ireg - cell*ng;
1831 int inew = g->howfar(ilocal,xp,u,t,newmed,normal);
1835 return cell*ng + inew;
1845 int ix = (int)(x.
x*dxi + ax);
1849 int iy = (int)(x.
y*dyi + ay);
1853 int iz = (int)(x.
z*dzi + az);
1857 int cell = ix + iy*nx + iz*nxy;
1859 EGS_Float t_left = t;
1862 for (EGS_I64 loopCount=0; loopCount<=
loopMax; ++loopCount) {
1864 egsFatal(
"EGS_XYZRepeater::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
1867 EGS_Float this_t = t_left;
1869 int inew = g->howfar(-1,xp,u,this_t,newmed,normal);
1874 return cell*ng + inew;
1876 int next_cell = xyz->howfar(cell,xtmp,u,this_t,0,normal);
1878 if (next_cell == cell) {
1881 if (next_cell < 0) {
1896 return xyz->hownear(ireg,x);
1898 if (ireg < nreg-1) {
1900 int ilocal = ireg - cell*ng;
1902 return g->hownear(ilocal,xp);
1906 int ix = (int)(x.
x*dxi + ax);
1910 int iy = (int)(x.
y*dyi + ay);
1914 int iz = (int)(x.
z*dzi + az);
1918 int cell = ix + iy*nx + iz*nxy;
1920 EGS_Float t = g->hownear(-1,xp);
1921 EGS_Float tcell = xyz->hownear(cell,x);
1925 for (
int iix=ix-1; iix<=ix+1; ++iix) {
1926 if (iix >= 0 && iix < nx) {
1927 for (
int iiy=iy-1; iiy<=iy+1; ++iiy) {
1928 if (iiy >= 0 && iiy < ny) {
1929 for (
int iiz=iz-1; iiz<=iz+1; ++iiz) {
1930 if (iiz >= 0 && iiz < nz) {
1931 if (iix != ix || iiy != iy || iiz != iz) {
1932 int cell1 = iix+iiy*nx+iiz*nxy;
1934 EGS_Float t1 = g->hownear(-1,tmp);
1949 return nxyz*(g->getMaxStep() + 1) + 1;
1952 const string &
getType()
const {
1959 xyz->setXYZLabels(input);
1962 virtual void getLabelRegions(
const string &str, vector<int> ®s,
bool sanitize=
true);
1969 EGS_Float dx, dxi, ax;
1970 EGS_Float dy, dyi, ay;
1971 EGS_Float dz, dzi, az;
1972 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 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_rho_scaling
Does this geometry have relative mass density scvaling?
virtual EGS_Float getVolume(int ireg)
Calculates the volume of region ireg.
virtual bool hasRhoScaling()
Does this geometry object have a mass density scaling feature?
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 void getLabelRegions(const string &str, vector< int > ®s, bool sanitize=true)
Get the list of all regions labeled with str.
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