42 #ifndef EGS_ND_GEOMETRY_
43 #define EGS_ND_GEOMETRY_
48 #define EGS_NDG_EXPORT __declspec(dllexport)
50 #define EGS_NDG_EXPORT __declspec(dllimport)
56 #ifdef HAVE_VISIBILITY
57 #define EGS_NDG_EXPORT __attribute__ ((visibility ("default")))
58 #define EGS_NDG_LOCAL __attribute__ ((visibility ("hidden")))
60 #define EGS_NDG_EXPORT
322 EGS_NDGeometry(vector<EGS_BaseGeometry *> &G,
const string &Name =
"",
328 for (
int j=0; j<N; j++)
if (!g[j]->
isInside(x)) {
336 for (
int j=0; j<N; j++) {
337 int ij = g[j]->isWhere(x);
357 for (
int j=N-1; j>=0; j--) {
359 EGS_Float t = g[j]->howfarToOutside(l,x,u);
371 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
374 int inext = -1, idelta, lnew_j=0;
375 for (
int j=N-1; j>=0; j--) {
377 int lnew = g[j]->howfar(l,x,u,t,0,normal);
388 int inew = lnew_j >= 0 ? ireg + idelta*n[inext] : lnew_j;
392 *newmed = inew >= 0 ?
medium(inew) : -1;
396 for (
int j=0; j<N; j++) {
398 bool is_in = g[j]->isInside(x);
405 int i = g[j]->howfar(ireg,x,u,tj,0,np);
410 for (
int k=0; k<N; k++) {
412 int check = g[k]->isWhere(tmp);
440 int ii = g[j]->isWhere(x);
442 for (EGS_I64 loopCount=0; loopCount<=
loopMax; ++loopCount) {
444 egsFatal(
"EGS_NDGeometry::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
447 EGS_Float tt = tleft;
448 int inew = g[j]->howfar(ii,tmp,u,tt);
464 EGS_Float tt = tleft;
465 int inew = g[j]->howfar(ii,tmp,u,tt,0,np);
471 for (
int k=0; k<N; k++) {
473 int check = g[k]->isWhere(tmp);
503 for (
int j=N-1; j>=0; j--) {
505 EGS_Float t = g[j]->hownear(l,x);
518 EGS_Float s1=0, s2=0;
519 for (
int j=0; j<N; j++) {
521 EGS_Float t = g[j]->hownear(-1,x);
534 for (
int j=0; j<N; j++) {
536 int i = g[j]->isWhere(x);
537 t = g[j]->hownear(i,x);
551 for (
int j=0; j<N; ++j) {
552 nstep += g[j]->getMaxStep();
557 const string &
getType()
const {
564 void ndRegions(
int r,
int dim,
int dimk,
int k, vector<int> ®s);
586 void setM(
int ib,
int idim,
const vector<int> &ranges,
int medium);
590 #include "../egs_planes/egs_planes.h"
745 const string &Name =
"");
750 if (!xp->isInside(x)) {
753 if (!yp->isInside(x)) {
756 if (!zp->isInside(x)) {
763 int ix = xp->isWhere(x);
767 int iy = yp->isWhere(x);
771 int iz = zp->isWhere(x);
775 return ix + iy*nx + iz*nxy;
788 EGS_Float t, t_ini = 0;
793 ireg =
howfar(ireg,x,u,t,&imed);
798 isections[0].
rhof = 1;
799 isections[0].
ireg = -1;
800 isections[0].
imed = -1;
808 EGS_Float *px = xp->getPositions(),
809 *py = yp->getPositions(),
810 *pz = zp->getPositions();
812 int ir = ireg - iz*nxy;
815 EGS_Float uxi, uyi, uzi, nextx, nexty, nextz;
816 int dirx, icx, diry, icy, dirz, icz;
862 nextx = (px[ix+icx] - x.
x)*uxi + t_ini;
863 nexty = (py[iy+icy] - x.
y)*uyi + t_ini;
864 nextz = (pz[iz+icz] - x.
z)*uzi + t_ini;
865 for (
int j=ifirst; j<n; j++) {
866 isections[j].
imed = imed;
867 isections[j].
ireg = ireg;
870 if (nextx < nexty && nextx < nextz) {
873 if (ix < 0 || ix >= nx) {
878 nextx = (px[ix+icx] - x.
x)*uxi + t_ini;
881 else if (nexty < nextz) {
884 if (iy < 0 || iy >= ny) {
888 inew = ireg + nx*diry;
889 nexty = (py[iy+icy] - x.
y)*uyi + t_ini;
895 if (iz < 0 || iz >= nz) {
899 inew = ireg + nxy*dirz;
900 nextz = (pz[iz+icz] - x.
z)*uzi + t_ini;
910 return ireg >= 0 ? -1 : n;
919 int ir = ireg - iz*nxy;
922 EGS_Float d = xp->howfarToOutside(ix,x,u);
923 EGS_Float ty = yp->howfarToOutside(iy,x,u);
927 EGS_Float tz = zp->howfarToOutside(iz,x,u);
935 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
938 int ir = ireg - iz*nxy;
943 EGS_Float d = (xpos[ix+1]-x.
x)/u.
x;
945 if (d <= boundaryTolerance) {
948 t = halfBoundaryTolerance;
965 EGS_Float d = (xpos[ix]-x.
x)/u.
x;
967 if (d <= boundaryTolerance) {
968 t = halfBoundaryTolerance;
985 EGS_Float d = (ypos[iy+1]-x.
y)/u.
y;
987 if (d <= boundaryTolerance) {
988 t = halfBoundaryTolerance;
1005 EGS_Float d = (ypos[iy]-x.
y)/u.
y;
1007 if (d <= boundaryTolerance) {
1008 t = halfBoundaryTolerance;
1025 EGS_Float d = (zpos[iz+1]-x.
z)/u.
z;
1027 if (d <= boundaryTolerance) {
1028 t = halfBoundaryTolerance;
1045 EGS_Float d = (zpos[iz]-x.
z)/u.
z;
1047 if (d <= boundaryTolerance) {
1048 t = halfBoundaryTolerance;
1064 if (newmed && inew >= 0) {
1070 int inew = howfarFromOut(x,u,t,ix,iy,iz,face,normal);
1071 if (inew >= 0 && newmed) {
1080 int ir = ireg - iz*nxy;
1082 int ix = ir - iy*nx;
1083 EGS_Float t = xp->hownear(ix,x);
1084 EGS_Float t1 = yp->hownear(iy,x);
1088 t1 = zp->hownear(iz,x);
1095 EGS_Float s1=0, s2=0;
1096 if (!xp->isInside(x)) {
1097 EGS_Float t = xp->hownear(-1,x);
1102 if (!yp->isInside(x)) {
1103 EGS_Float t = yp->hownear(-1,x);
1108 if (!zp->isInside(x)) {
1109 EGS_Float t = zp->hownear(-1,x);
1123 int ir = ireg - iz*nxy;
1125 int ix = ir - iy*nx;
1126 return (xpos[ix+1]-xpos[ix])*(ypos[iy+1]-ypos[iy])*(zpos[iz+1]-zpos[iz]);
1129 EGS_Float
getBound(
int idir,
int ind) {
1132 if (ind>=0 && ind<=nx) {
1136 egsWarning(
"Error in getBound: Looking for X bound out of range %d\n"
1137 "Will set this to zero.\n",ind);
1141 else if (idir == 1) {
1142 if (ind>=0 && ind<=ny) {
1146 egsWarning(
"Error in getBound: Looking for Y bound out of range %d\n"
1147 "Will set this to zero.\n",ind);
1151 else if (idir == 2) {
1152 if (ind>=0 && ind<=nz) {
1156 egsWarning(
"Error in getBound: Looking for Z bound out of range %d\n"
1157 "Will set this to zero.\n",ind);
1162 egsWarning(
"Error in getBound: Dimension %d undefined in EGS_XYZGeometry.\n",idir);
1179 egsWarning(
"Error in getNregDir: Dimension %d undefined in EGS_XYZGeometry.\n",
1200 EGS_Float *getXPositions() {
1201 return xp->getPositions();
1203 EGS_Float *getYPositions() {
1204 return yp->getPositions();
1206 EGS_Float *getZPositions() {
1207 return zp->getPositions();
1210 static int getDigits(
int i);
1212 const string &
getType()
const {
1218 static EGS_XYZGeometry *constructGeometry(
const char *dens_or_egphant_file,
1219 const char *ramp_file,
int dens_or_egphant=0);
1220 static EGS_XYZGeometry *constructCTGeometry(
const char *dens_or_egphant_file);
1222 void voxelizeGeometry(
EGS_Input *input);
1227 void getXLabelRegions(
const string &str, vector<int> ®s) {
1228 xp->getLabelRegions(str, regs);
1230 void getYLabelRegions(
const string &str, vector<int> ®s) {
1231 yp->getLabelRegions(str, regs);
1233 void getZLabelRegions(
const string &str, vector<int> ®s) {
1234 zp->getLabelRegions(str, regs);
1245 int nx, ny, nz, nxy;
1253 EGS_Float &t,
int &ix,
int &iy,
int &iz,
1257 if (x.
x <= xpos[0] && u.
x > 0) {
1258 t1 = (xpos[0]-x.
x)/u.
x;
1262 else if (x.
x >= xpos[nx] && u.
x < 0) {
1263 t1 = (xpos[nx]-x.
x)/u.
x;
1267 if (ix >= 0 && t1 <= t) {
1269 iy = yp->isWhere(tmp);
1271 iz = zp->isWhere(tmp);
1273 int inew = ix + iy*nx + iz*nxy;
1274 if (t1 < boundaryTolerance) {
1275 int itest =
howfar(inew, tmp, u, t1);
1276 if (itest == -1 && t1 < boundaryTolerance) {
1280 if (normal) *normal = face == 0 ?
EGS_Vector(-1,0,0) :
1288 if (x.
y <= ypos[0] && u.
y > 0) {
1289 t1 = (ypos[0]-x.
y)/u.
y;
1293 else if (x.
y >= ypos[ny] && u.
y < 0) {
1294 t1 = (ypos[ny]-x.
y)/u.
y;
1298 if (iy >= 0 && t1 <= t) {
1300 ix = xp->isWhere(tmp);
1302 iz = zp->isWhere(tmp);
1304 int inew = ix + iy*nx + iz*nxy;
1305 if (t1 < boundaryTolerance) {
1306 int itest =
howfar(inew, tmp, u, t1);
1307 if (itest == -1 && t1 < boundaryTolerance) {
1311 if (normal) *normal = face == 2 ?
EGS_Vector(0,-1,0) :
1319 if (x.
z <= zpos[0] && u.
z > 0) {
1320 t1 = (zpos[0]-x.
z)/u.
z;
1324 else if (x.
z >= zpos[nz] && u.
z < 0) {
1325 t1 = (zpos[nz]-x.
z)/u.
z;
1329 if (iz >= 0 && t1 <= t) {
1331 ix = xp->isWhere(tmp);
1333 iy = yp->isWhere(tmp);
1335 int inew = ix + iy*nx + iz*nxy;
1336 if (t1 < boundaryTolerance) {
1337 int itest =
howfar(inew, tmp, u, t1);
1338 if (itest == -1 && t1 < boundaryTolerance) {
1342 if (normal) *normal = face == 4 ?
EGS_Vector(0,0,-1) :
1372 const char *defFile,
const string &Name =
"");
1377 int ireg = EGS_XYZGeometry::isWhere(x);
1378 if (ireg >= 0)
egsFatal(
"EGS_DeformedXYZ::isWhere(): this geometry "
1379 "does not allow the use of this method with position inside\n");
1387 int medium(
int ireg)
const {
1392 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
1394 int ir = ireg/6, tetra = ireg - 6*ir, tetra4 = 4*tetra;
1397 ind[1] = (ir - ind[2]*nxy)/nx;
1398 ind[0] = ir - ind[2]*nxy - ind[1]*nx;
1399 int edge = ir + ind[1] + ind[2]*nxyp1;
1401 n1(vectors[edge+tnodes[tetra4+1]]-n0),
1402 n2(vectors[edge+tnodes[tetra4+2]]-n0),
1403 n3(vectors[edge+tnodes[tetra4+3]]-n0);
1405 EGS_Float disti[4],dpi[4];
1409 disti[0]=normvec*n0x;
1412 disti[2]=normvec*n0x;
1415 disti[1]=normvec*n0x;
1416 normvec = (n3-n1)%(n2-n1);
1418 disti[3] = normvec*(n0x+n1);
1420 EGS_Float mindist = t, mindp=1;
1421 for (
int i=0; i<4; ++i) {
1422 if (dpi[i] > 0 && disti[i]*mindp < mindist*dpi[i]) {
1428 if (nextplane == 4) {
1432 int j = 12*tetra + 3*nextplane;
1433 int next = tetra_data[j];
1436 ind[next] += tetra_data[j+1];
1437 if (ind[next] < 0 || ind[next] >= np[next]) {
1440 irnew = ind[0] + ind[1]*nx + ind[2]*nxy;
1446 switch (nextplane) {
1457 *normal = (n2-n1)%(n3-n1);
1460 return 6*irnew + tetra_data[j+2];
1463 int inew = howfarFromOut(x,u,t,ix,iy,iz,face,normal);
1471 int edge = inew + iy + iz*nxyp1;
1473 int tetra1 = enter_tetra1[face], plane1 = enter_plane1[face];
1474 int node1 = tnodes[4*tetra1 + plane_order[3*plane1]],
1475 node2 = tnodes[4*tetra1 + plane_order[3*plane1+1]],
1476 node3 = tnodes[4*tetra1 + plane_order[3*plane1+2]];
1477 if (inTriangle(vectors[edge+node1],vectors[edge+node2],
1478 vectors[edge+node3],tmp)) {
1479 return 6*inew + tetra1;
1481 int tetra2 = enter_tetra2[face], plane2 = enter_plane2[face];
1482 int node1a = tnodes[4*tetra2 + plane_order[3*plane2]],
1483 node2a = tnodes[4*tetra2 + plane_order[3*plane2+1]],
1484 node3a = tnodes[4*tetra2 + plane_order[3*plane2+2]];
1485 if (inTriangle(vectors[edge+node1a],vectors[edge+node2a],
1486 vectors[edge+node3a],tmp)) {
1487 return 6*inew + tetra2;
1490 egsWarning(
"deformed geometry: entering from face %d but inTriangle()"
1491 " fails for both triangles\n",face);
1492 egsWarning(
"x_enter=(%16.10f,%16.10f,%16.10f)\n",tmp.
x,tmp.
y,tmp.
z);
1496 EGS_Float hownear(
int ireg,
const EGS_Vector &x) {
1498 return EGS_XYZGeometry::hownear(ireg,x);
1500 int ir = ireg/6, tetra = ireg - 6*ir, tetra4 = 4*tetra;
1503 ind[1] = (ir - ind[2]*nxy)/nx;
1504 ind[0] = ir - ind[2]*nxy - ind[1]*nx;
1505 int edge = ir + ind[1] + ind[2]*nxyp1;
1507 n1(vectors[edge+tnodes[tetra4+1]]-n0),
1508 n2(vectors[edge+tnodes[tetra4+2]]-n0),
1509 n3(vectors[edge+tnodes[tetra4+3]]-n0);
1511 EGS_Float disti[4],dpi[4];
1514 dpi[0]=normvec.length2();
1515 disti[0]=normvec*n0x;
1517 dpi[2]=normvec.length2();
1518 disti[2]=normvec*n0x;
1520 dpi[1]=normvec.length2();
1521 disti[1]=normvec*n0x;
1522 normvec = (n3-n1)%(n2-n1);
1523 dpi[3] = normvec.length2();
1524 disti[3] = normvec*(n0x+n1);
1525 EGS_Float mindist =
veryFar, mindp=1;
1526 for (
int i=0; i<4; ++i) {
1527 if (disti[i]*mindp < mindist*dpi[i]) {
1532 return mindist/mindp;
1535 int computeIntersections(
int ireg,
int n,
const EGS_Vector &X,
1540 EGS_Float howfarToOutside(
int ireg,
const EGS_Vector &x,
1547 int ir1 = ir - iz*nxy;
1549 int ix = ir1 - iy*nx;
1550 EGS_Float d = xp->howfarToOutside(ix,x,u);
1551 EGS_Float ty = yp->howfarToOutside(iy,x,u);
1555 EGS_Float tz = zp->howfarToOutside(iz,x,u);
1562 int getMaxStep()
const {
1563 return 6*(nx+ny+nz) + 1;
1566 const string &getType()
const {
1570 void printInfo()
const {};
1583 int setDeformations(
const char *defFile);
1588 EGS_Float a=u1.length2(), b=u1*u2, c=u2.length2(), b1=xp*u1, b2=xp*u2;
1589 EGS_Float D=a*c-b*b;
1590 EGS_Float u=b1*c-b2*b;
1594 EGS_Float v=b2*a-b1*b;
1611 static string def_type;
1613 static char tetrahedra[];
1615 static char plane_order[];
1617 static char tetra_data[];
1619 static char enter_tetra1[];
1620 static char enter_plane1[];
1621 static char enter_tetra2[];
1622 static char enter_plane2[];
1703 EGS_Float Ymin, EGS_Float Ymax,
1704 EGS_Float Zmin, EGS_Float Zmax,
1706 const string &Name =
"");
1711 int cell = xyz->isWhere(x);
1717 int ir = g->isWhere(xp);
1719 return ir >= 0 ? cell*ng + ir : nreg-1;
1723 return xyz->isInside(x);
1730 int medium(
int ireg)
const {
1731 if (ireg == nreg-1) {
1735 int ilocal = ireg - ng*cell;
1736 return g->medium(ilocal);
1744 return xyz->howfarToOutside(0,x,u);
1748 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
1753 int cell = xyz->howfar(ireg,x,u,t,0,normal);
1764 if (ireg < nreg-1) {
1766 int ilocal = ireg - cell*ng;
1768 int inew = g->howfar(ilocal,xp,u,t,newmed,normal);
1772 return cell*ng + inew;
1782 int ix = (int)(x.
x*dxi + ax);
1786 int iy = (int)(x.
y*dyi + ay);
1790 int iz = (int)(x.
z*dzi + az);
1794 int cell = ix + iy*nx + iz*nxy;
1796 EGS_Float t_left = t;
1799 for (EGS_I64 loopCount=0; loopCount<=
loopMax; ++loopCount) {
1801 egsFatal(
"EGS_XYZRepeater::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
1804 EGS_Float this_t = t_left;
1806 int inew = g->howfar(-1,xp,u,this_t,newmed,normal);
1811 return cell*ng + inew;
1813 int next_cell = xyz->howfar(cell,xtmp,u,this_t,0,normal);
1815 if (next_cell == cell) {
1818 if (next_cell < 0) {
1833 return xyz->hownear(ireg,x);
1835 if (ireg < nreg-1) {
1837 int ilocal = ireg - cell*ng;
1839 return g->hownear(ilocal,xp);
1843 int ix = (int)(x.
x*dxi + ax);
1847 int iy = (int)(x.
y*dyi + ay);
1851 int iz = (int)(x.
z*dzi + az);
1855 int cell = ix + iy*nx + iz*nxy;
1857 EGS_Float t = g->hownear(-1,xp);
1858 EGS_Float tcell = xyz->hownear(cell,x);
1862 for (
int iix=ix-1; iix<=ix+1; ++iix) {
1863 if (iix >= 0 && iix < nx) {
1864 for (
int iiy=iy-1; iiy<=iy+1; ++iiy) {
1865 if (iiy >= 0 && iiy < ny) {
1866 for (
int iiz=iz-1; iiz<=iz+1; ++iiz) {
1867 if (iiz >= 0 && iiz < nz) {
1868 if (iix != ix || iiy != iy || iiz != iz) {
1869 int cell1 = iix+iiy*nx+iiz*nz;
1871 EGS_Float t1 = g->hownear(-1,tmp);
1886 return nxyz*(g->getMaxStep() + 1) + 1;
1889 const string &
getType()
const {
1896 xyz->setXYZLabels(input);
1906 EGS_Float dx, dxi, ax;
1907 EGS_Float dy, dyi, ay;
1908 EGS_Float dz, dzi, az;
1909 int nx, ny, nz, nxy, nxyz, ng;
virtual const string & getType() const =0
Get the geometry type.
virtual bool isInside(const EGS_Vector &x)=0
Is the position x inside the geometry?
const EGS_I64 loopMax
The maximum number of iterations for near-infinite loops.
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 t
distance to next region boundary
int N
Number of dimensions.
virtual EGS_Float howfarToOutside(int ireg, const EGS_Vector &x, const EGS_Vector &u)
EGS_Float rhof
relative mass density in that region
virtual int getMaxStep() const
Returns the maximum number of steps through the geometry.
A class representing 3D vectors.
virtual EGS_Float getVolume(int ireg)
Calculates the volume of region ireg.
virtual int isWhere(const EGS_Vector &x)=0
In which region is poisition x?
int * n
Used for calculating region indeces.
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.
const EGS_Float veryFar
A very large float.
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.
bool isConvex() const
Is the geometry convex?
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
virtual void getLabelRegions(const string &str, vector< int > ®s)
Get the list of all regions labeled with str.
void setMedia(EGS_Input *inp)
Set the media in the geometry from the input pointed to by inp.
virtual int inside(const EGS_Vector &x)=0
Returns the region index, if inside, or -1 if outside (obsolete)
A set of parallel planes.
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 EGS_Float getRelativeRho(int ireg) const
Get the relative mass density in region ireg.
A geometry repeated on a regular XYZ grid.
A class modeling a N-dimensional geometry.
EGS_BaseGeometry ** g
The dimensions.
EGS_BaseGeometry class header file.
bool ortho
Is the geometry orthogonal ?
static string type
The geometry type.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.