EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_nd_geometry.h
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ nd geometry headers
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: Blake Walters
27 # Ernesto Mainegra-Hing
28 # Frederic Tessier
29 # Reid Townson
30 # Randle Taylor
31 # Marc Chamberland
32 # Martin Martinov
33 # Alexandre Demelo
34 #
35 ###############################################################################
36 */
37 
38 
45 #ifndef EGS_ND_GEOMETRY_
46 #define EGS_ND_GEOMETRY_
47 
48 #ifdef WIN32
49 
50  #ifdef BUILD_NDG_DLL
51  #define EGS_NDG_EXPORT __declspec(dllexport)
52  #else
53  #define EGS_NDG_EXPORT __declspec(dllimport)
54  #endif
55  #define EGS_NDG_LOCAL
56 
57 #else
58 
59  #ifdef HAVE_VISIBILITY
60  #define EGS_NDG_EXPORT __attribute__ ((visibility ("default")))
61  #define EGS_NDG_LOCAL __attribute__ ((visibility ("hidden")))
62  #else
63  #define EGS_NDG_EXPORT
64  #define EGS_NDG_LOCAL
65  #endif
66 
67 #endif
68 
69 
70 #include "egs_base_geometry.h"
71 
72 #include<vector>
73 #include <iomanip>
74 using std::vector;
75 
315 class EGS_NDG_EXPORT EGS_NDGeometry : public EGS_BaseGeometry {
316 
317 public:
318 
321  EGS_NDGeometry(int ng, EGS_BaseGeometry **G, const string &Name = "",
322  bool O=true);
323 
325  EGS_NDGeometry(vector<EGS_BaseGeometry *> &G, const string &Name = "",
326  bool O=true);
327 
328  ~EGS_NDGeometry();
329 
330  bool isInside(const EGS_Vector &x) {
331  for (int j=0; j<N; j++) if (!g[j]->isInside(x)) {
332  return false;
333  }
334  return true;
335  };
336 
337  int isWhere(const EGS_Vector &x) {
338  int ireg = 0;
339  for (int j=0; j<N; j++) {
340  int ij = g[j]->isWhere(x);
341  if (ij < 0) {
342  return -1;
343  }
344  ireg += ij*n[j];
345  }
346  return ireg;
347  };
348 
349  int inside(const EGS_Vector &x) {
350  return isWhere(x);
351  };
352 
353  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
354  const EGS_Vector &u) {
355  if (ireg < 0) {
356  return 0;
357  }
358  int itmp = ireg;
359  EGS_Float d = veryFar;
360  for (int j=N-1; j>=0; j--) {
361  int l = itmp/n[j];
362  EGS_Float t = g[j]->howfarToOutside(l,x,u);
363  if (t <= 0) {
364  return t;
365  }
366  if (t < d) {
367  d = t;
368  }
369  }
370  return d;
371  };
372 
373  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
374  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
375  if (ireg >= 0) {
376  int itmp = ireg;
377  int inext = -1, idelta=0, lnew_j=0;
378  for (int j=N-1; j>=0; j--) {
379  int l = itmp/n[j];
380  int lnew = g[j]->howfar(l,x,u,t,0,normal);
381  if (lnew != l) {
382  inext = j;
383  idelta = lnew - l;
384  lnew_j = lnew;
385  }
386  itmp -= l*n[j];
387  }
388  if (inext < 0) {
389  return ireg;
390  }
391  int inew = lnew_j >= 0 ? ireg + idelta*n[inext] : lnew_j;
392  //if( lnew_j < 0 ) return lnew_j;
393  //int inew = ireg + idelta*n[inext];
394  if (newmed) {
395  *newmed = inew >= 0 ? medium(inew) : -1;
396  }
397  return inew;
398  }
399  for (int j=0; j<N; j++) {
400  EGS_Float tj = t;
401  bool is_in = g[j]->isInside(x);
402  // Note: this logic fails if the geometry is not convex!
403  if (!is_in) {
404  EGS_Vector nn, *np=0;
405  if (normal) {
406  np = &nn;
407  }
408  int i = g[j]->howfar(ireg,x,u,tj,0,np);
409  if (i >= 0) {
410  EGS_Vector tmp(x + u*tj);
411  bool is_ok = true;
412  int res = 0;
413  for (int k=0; k<N; k++) {
414  if (k != j) {
415  int check = g[k]->isWhere(tmp);
416  if (check < 0) {
417  is_ok = false;
418  break;
419  }
420  res += check*n[k];
421  }
422  }
423  if (is_ok) {
424  t = tj;
425  res += i*n[j];
426  if (newmed) {
427  *newmed = medium(res);
428  }
429  if (normal) {
430  *normal = nn;
431  }
432  return res;
433  }
434  }
435  }
436  // and so, to fix it, we do the following for non-convex
437  // dimensions. But this only works if and only if there
438  // is not more than 1 non-convex dimension and this
439  // dimension is last in the list.
440  else if (!g[j]->isConvex()) {
441  EGS_Vector tmp(x);
442  EGS_Float tleft = t;
443  int ii = g[j]->isWhere(x);
444  EGS_Float ttot = 0;
445  for (EGS_I64 loopCount=0; loopCount<=loopMax; ++loopCount) {
446  if (loopCount == loopMax) {
447  egsFatal("EGS_NDGeometry::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
448  return -1;
449  }
450  EGS_Float tt = tleft;
451  int inew = g[j]->howfar(ii,tmp,u,tt);
452  if (inew == ii) {
453  break;
454  }
455  tleft -= tt;
456  tmp += u*tt;
457  ii = inew;
458  ttot += tt;
459  //egsWarning(" inew = %d tt = %g ttot = %g tmp = (%g,%g,%g)\n",inew,tt,ttot,tmp.x,tmp.y,tmp.z);
460  if (ii < 0) {
461  break;
462  }
463  }
464  //egsWarning("doing non-convex part: x = (%g,%g,%g) ii = %d t = %g ttot = %g\n",x.x,x.y,x.z,ii,t,ttot);
465  if (ii < 0) {
466  EGS_Vector nn, *np = normal ? &nn : 0;
467  EGS_Float tt = tleft;
468  int inew = g[j]->howfar(ii,tmp,u,tt,0,np);
469  //egsWarning(" exited and tried to reenter: %d %g\n",inew,ttot+tt);
470  if (inew >= 0) {
471  tmp += u*tt;
472  bool is_ok = true;
473  int res = 0;
474  for (int k=0; k<N; k++) {
475  if (k != j) {
476  int check = g[k]->isWhere(tmp);
477  if (check < 0) {
478  is_ok = false;
479  break;
480  }
481  res += check*n[k];
482  }
483  }
484  if (is_ok) {
485  t = ttot + tt;
486  res += inew*n[j];
487  if (newmed) {
488  *newmed = medium(res);
489  }
490  if (normal) {
491  *normal = nn;
492  }
493  return res;
494  }
495  }
496  }
497  }
498  }
499  return -1;
500  };
501 
502  EGS_Float hownear(int ireg, const EGS_Vector &x) {
503  EGS_Float tmin = veryFar;
504  if (ireg >= 0) {
505  int itmp = ireg;
506  for (int j=N-1; j>=0; j--) {
507  int l = itmp/n[j];
508  EGS_Float t = g[j]->hownear(l,x);
509  if (t < tmin) {
510  tmin = t;
511  if (tmin <= 0) {
512  return 0;
513  }
514  }
515  itmp -= l*n[j];
516  }
517  return tmin;
518  }
519  if (ortho) {
520  int nc = 0;
521  EGS_Float s1=0, s2=0;
522  for (int j=0; j<N; j++) {
523  if (!g[j]->isInside(x)) {
524  EGS_Float t = g[j]->hownear(-1,x);
525  nc++;
526  s1 += t;
527  s2 += t*t;
528  }
529  }
530  if (nc == 1) {
531  return s1;
532  }
533  return sqrt(s2);
534  }
535  else {
536  EGS_Float tmin = veryFar;
537  for (int j=0; j<N; j++) {
538  EGS_Float t;
539  int i = g[j]->isWhere(x);
540  t = g[j]->hownear(i,x);
541  if (t < tmin) {
542  tmin = t;
543  if (tmin <= 0) {
544  return 0;
545  }
546  }
547  }
548  return tmin;
549  }
550  };
551 
552  int getMaxStep() const {
553  int nstep = 1;
554  for (int j=0; j<N; ++j) {
555  nstep += g[j]->getMaxStep();
556  }
557  return nstep;
558  };
559 
560  void getNextGeom(EGS_RandomGenerator *rndm) {
561  // calls getNextGeom on its component geometries to update dynamic
562  // geometries in the simulation
563  for (int j=0; j<N; j++) {
564  g[j]->getNextGeom(rndm);
565  }
566  };
567 
568  void updatePosition(EGS_Float time) {
569  // calls updatePosition on its component geometries to update dynamic
570  // geometries in the simulation
571  for (int j=0; j<N; j++) {
572  g[j]->updatePosition(time);
573  }
574  };
575 
576  void containsDynamic(bool &hasdynamic) {
577  // calls containsDynamic on its component geometries (only calls if
578  // hasDynamic is false, as if it is true we already found one)
579  for (int j=0; j<N; j++) {
580  if (!hasdynamic) {
581  g[j]->containsDynamic(hasdynamic);
582  }
583  }
584  };
585 
586  const string &getType() const {
587  return type;
588  };
589 
590  void printInfo() const;
591 
592  virtual void getLabelRegions(const string &str, vector<int> &regs);
593  void ndRegions(int r, int dim, int dimk, int k, vector<int> &regs);
594 
595 protected:
596 
597  int N;
599  int *n;
600  static string type;
601  bool ortho;
602 
603  void setup();
604 
611  void setMedia(EGS_Input *inp, int nmed, const int *med_ind);
612 
613 private:
614 
615  void setM(int ib, int idim, const vector<int> &ranges, int medium);
616 };
617 
618 #ifdef EXPLICIT_XYZ
619 #include "../egs_planes/egs_planes.h"
620 
769 class EGS_NDG_EXPORT EGS_XYZGeometry : public EGS_BaseGeometry {
770 
771 public:
772 
774  const string &Name = "");
775 
776  ~EGS_XYZGeometry();
777 
778  bool isInside(const EGS_Vector &x) {
779  if (!xp->isInside(x)) {
780  return false;
781  }
782  if (!yp->isInside(x)) {
783  return false;
784  }
785  if (!zp->isInside(x)) {
786  return false;
787  }
788  return true;
789  };
790 
791  int isWhere(const EGS_Vector &x) {
792  int ix = xp->isWhere(x);
793  if (ix < 0) {
794  return ix;
795  }
796  int iy = yp->isWhere(x);
797  if (iy < 0) {
798  return iy;
799  }
800  int iz = zp->isWhere(x);
801  if (iz < 0) {
802  return iz;
803  }
804  return ix + iy*nx + iz*nxy;
805  };
806 
807  int inside(const EGS_Vector &x) {
808  return isWhere(x);
809  };
810 
811  int computeIntersections(int ireg, int n, const EGS_Vector &X,
812  const EGS_Vector &u, EGS_GeometryIntersections *isections) {
813  if (n < 1) {
814  return -1;
815  }
816  int ifirst = 0;
817  EGS_Float t, t_ini = 0;
818  EGS_Vector x(X);
819  int imed;
820  if (ireg < 0) {
821  t = veryFar;
822  ireg = howfar(ireg,x,u,t,&imed);
823  if (ireg < 0) {
824  return 0;
825  }
826  isections[0].t = t;
827  isections[0].rhof = 1;
828  isections[0].ireg = -1;
829  isections[0].imed = -1;
830  t_ini = t;
831  ++ifirst;
832  x += u*t;
833  }
834  else {
835  imed = medium(ireg);
836  }
837  EGS_Float *px = xp->getPositions(),
838  *py = yp->getPositions(),
839  *pz = zp->getPositions();
840  int iz = ireg/nxy;
841  int ir = ireg - iz*nxy;
842  int iy = ir/nx;
843  int ix = ir - iy*nx;
844  EGS_Float uxi, uyi, uzi, nextx, nexty, nextz;
845  int dirx, icx, diry, icy, dirz, icz;
846  if (u.x > 0) {
847  uxi = 1/u.x;
848  dirx = 1;
849  icx = 1;
850  }
851  else if (u.x < 0) {
852  uxi = 1/u.x;
853  dirx = -1;
854  icx = 0;
855  }
856  else {
857  uxi = veryFar*1e3;
858  dirx = 1;
859  icx = 1;
860  }
861  if (u.y > 0) {
862  uyi = 1/u.y;
863  diry = 1;
864  icy = 1;
865  }
866  else if (u.y < 0) {
867  uyi = 1/u.y;
868  diry = -1;
869  icy = 0;
870  }
871  else {
872  uyi = veryFar*1e3;
873  diry = 1;
874  icy = 1;
875  }
876  if (u.z > 0) {
877  uzi = 1/u.z;
878  dirz = 1;
879  icz = 1;
880  }
881  else if (u.z < 0) {
882  uzi = 1/u.z;
883  dirz = -1;
884  icz = 0;
885  }
886  else {
887  uzi = veryFar*1e3;
888  dirz = 1;
889  icz = 1;
890  }
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;
897  isections[j].rhof = getRelativeRho(ireg);
898  int inew;
899  if (nextx < nexty && nextx < nextz) {
900  t = nextx;
901  ix += dirx;
902  if (ix < 0 || ix >= nx) {
903  inew = -1;
904  }
905  else {
906  inew = ireg + dirx;
907  nextx = (px[ix+icx] - x.x)*uxi + t_ini;
908  }
909  }
910  else if (nexty < nextz) {
911  t = nexty;
912  iy += diry;
913  if (iy < 0 || iy >= ny) {
914  inew = -1;
915  }
916  else {
917  inew = ireg + nx*diry;
918  nexty = (py[iy+icy] - x.y)*uyi + t_ini;
919  }
920  }
921  else {
922  t = nextz;
923  iz += dirz;
924  if (iz < 0 || iz >= nz) {
925  inew = -1;
926  }
927  else {
928  inew = ireg + nxy*dirz;
929  nextz = (pz[iz+icz] - x.z)*uzi + t_ini;
930  }
931  }
932  isections[j].t = t;
933  if (inew < 0) {
934  return j+1;
935  }
936  ireg = inew;
937  imed = medium(ireg);
938  }
939  return ireg >= 0 ? -1 : n;
940  };
941 
942  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
943  const EGS_Vector &u) {
944  if (ireg < 0) {
945  return 0;
946  }
947  int iz = ireg/nxy;
948  int ir = ireg - iz*nxy;
949  int iy = ir/nx;
950  int ix = ir - iy*nx;
951  EGS_Float d = xp->howfarToOutside(ix,x,u);
952  EGS_Float ty = yp->howfarToOutside(iy,x,u);
953  if (ty < d) {
954  d = ty;
955  }
956  EGS_Float tz = zp->howfarToOutside(iz,x,u);
957  if (tz < d) {
958  d = tz;
959  }
960  return d;
961  };
962 
963  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
964  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
965  if (ireg >= 0) {
966  int iz = ireg/nxy;
967  int ir = ireg - iz*nxy;
968  int iy = ir/nx;
969  int ix = ir - iy*nx;
970  int inew = ireg;
971  if (u.x > 0) {
972  EGS_Float d = (xpos[ix+1]-x.x)/u.x;
973  if (d <= t) {
974  if (d <= boundaryTolerance) {
975  // t=0 works on most cases but can result in
976  // getting stuck on an edge, so use boundaryTolerance
977  t = halfBoundaryTolerance;
978  }
979  else {
980  t = d;
981  }
982  if ((++ix) < nx) {
983  inew = ireg + 1;
984  }
985  else {
986  inew = -1;
987  }
988  if (normal) {
989  *normal = EGS_Vector(-1,0,0);
990  }
991  }
992  }
993  else if (u.x < 0) {
994  EGS_Float d = (xpos[ix]-x.x)/u.x;
995  if (d <= t) {
996  if (d <= boundaryTolerance) {
997  t = halfBoundaryTolerance;
998  }
999  else {
1000  t = d;
1001  }
1002  if ((--ix) >= 0) {
1003  inew = ireg - 1;
1004  }
1005  else {
1006  inew = -1;
1007  }
1008  if (normal) {
1009  *normal = EGS_Vector(1,0,0);
1010  }
1011  }
1012  }
1013  if (u.y > 0) {
1014  EGS_Float d = (ypos[iy+1]-x.y)/u.y;
1015  if (d <= t) {
1016  if (d <= boundaryTolerance) {
1017  t = halfBoundaryTolerance;
1018  }
1019  else {
1020  t = d;
1021  }
1022  if ((++iy) < ny) {
1023  inew = ireg + nx;
1024  }
1025  else {
1026  inew = -1;
1027  }
1028  if (normal) {
1029  *normal = EGS_Vector(0,-1,0);
1030  }
1031  }
1032  }
1033  else if (u.y < 0) {
1034  EGS_Float d = (ypos[iy]-x.y)/u.y;
1035  if (d <= t) {
1036  if (d <= boundaryTolerance) {
1037  t = halfBoundaryTolerance;
1038  }
1039  else {
1040  t = d;
1041  }
1042  if ((--iy) >= 0) {
1043  inew = ireg - nx;
1044  }
1045  else {
1046  inew = -1;
1047  }
1048  if (normal) {
1049  *normal = EGS_Vector(0,1,0);
1050  }
1051  }
1052  }
1053  if (u.z > 0) {
1054  EGS_Float d = (zpos[iz+1]-x.z)/u.z;
1055  if (d <= t) {
1056  if (d <= boundaryTolerance) {
1057  t = halfBoundaryTolerance;
1058  }
1059  else {
1060  t = d;
1061  }
1062  if ((++iz) < nz) {
1063  inew = ireg+nxy;
1064  }
1065  else {
1066  inew = -1;
1067  }
1068  if (normal) {
1069  *normal = EGS_Vector(0,0,-1);
1070  }
1071  }
1072  }
1073  else if (u.z < 0) {
1074  EGS_Float d = (zpos[iz]-x.z)/u.z;
1075  if (d <= t) {
1076  if (d <= boundaryTolerance) {
1077  t = halfBoundaryTolerance;
1078  }
1079  else {
1080  t = d;
1081  }
1082  if ((--iz) >= 0) {
1083  inew = ireg-nxy;
1084  }
1085  else {
1086  inew = -1;
1087  }
1088  if (normal) {
1089  *normal = EGS_Vector(0,0,1);
1090  }
1091  }
1092  }
1093  if (newmed && inew >= 0) {
1094  *newmed = medium(inew);
1095  }
1096  return inew;
1097  }
1098  int face,ix,iy,iz;
1099  int inew = howfarFromOut(x,u,t,ix,iy,iz,face,normal);
1100  if (inew >= 0 && newmed) {
1101  *newmed = medium(inew);
1102  }
1103  return inew;
1104  };
1105 
1106  EGS_Float hownear(int ireg, const EGS_Vector &x) {
1107  if (ireg >= 0) {
1108  int iz = ireg/nxy;
1109  int ir = ireg - iz*nxy;
1110  int iy = ir/nx;
1111  int ix = ir - iy*nx;
1112  EGS_Float t = xp->hownear(ix,x);
1113  EGS_Float t1 = yp->hownear(iy,x);
1114  if (t1 < t) {
1115  t = t1;
1116  }
1117  t1 = zp->hownear(iz,x);
1118  if (t1 < t) {
1119  t = t1;
1120  }
1121  return t;
1122  }
1123  int nc = 0;
1124  EGS_Float s1=0, s2=0;
1125  if (!xp->isInside(x)) {
1126  EGS_Float t = xp->hownear(-1,x);
1127  nc++;
1128  s1 += t;
1129  s2 += t*t;
1130  }
1131  if (!yp->isInside(x)) {
1132  EGS_Float t = yp->hownear(-1,x);
1133  nc++;
1134  s1 += t;
1135  s2 += t*t;
1136  }
1137  if (!zp->isInside(x)) {
1138  EGS_Float t = zp->hownear(-1,x);
1139  nc++;
1140  s1 += t;
1141  s2 += t*t;
1142  }
1143  if (nc == 1) {
1144  return s1;
1145  }
1146  return sqrt(s2);
1147  };
1148 
1149 
1150  EGS_Float getVolume(int ireg) {
1151  int iz = ireg/nxy;
1152  int ir = ireg - iz*nxy;
1153  int iy = ir/nx;
1154  int ix = ir - iy*nx;
1155  return (xpos[ix+1]-xpos[ix])*(ypos[iy+1]-ypos[iy])*(zpos[iz+1]-zpos[iz]);
1156  }
1157 
1158  EGS_Float getBound(int idir, int ind) {
1159  EGS_Float bound;
1160  if (idir == 0) {
1161  if (ind>=0 && ind<=nx) {
1162  bound = xpos[ind];
1163  }
1164  else {
1165  egsWarning("Error in getBound: Looking for X bound out of range %d\n"
1166  "Will set this to zero.\n",ind);
1167  bound = 0.0;
1168  }
1169  }
1170  else if (idir == 1) {
1171  if (ind>=0 && ind<=ny) {
1172  bound = ypos[ind];
1173  }
1174  else {
1175  egsWarning("Error in getBound: Looking for Y bound out of range %d\n"
1176  "Will set this to zero.\n",ind);
1177  bound = 0.0;
1178  }
1179  }
1180  else if (idir == 2) {
1181  if (ind>=0 && ind<=nz) {
1182  bound = zpos[ind];
1183  }
1184  else {
1185  egsWarning("Error in getBound: Looking for Z bound out of range %d\n"
1186  "Will set this to zero.\n",ind);
1187  bound = 0.0;
1188  }
1189  }
1190  else {
1191  egsWarning("Error in getBound: Dimension %d undefined in EGS_XYZGeometry.\n",idir);
1192  bound = 0.0;
1193  }
1194  return bound;
1195  }
1196 
1197  int getNRegDir(int idir) {
1198  if (idir==0) {
1199  return nx;
1200  }
1201  else if (idir==1) {
1202  return ny;
1203  }
1204  else if (idir==2) {
1205  return nz;
1206  }
1207  else {
1208  egsWarning("Error in getNregDir: Dimension %d undefined in EGS_XYZGeometry.\n",
1209  idir);
1210  return 0;
1211  }
1212  }
1213 
1214 
1215  int getMaxStep() const {
1216  return nx+ny+nz+1;
1217  };
1218 
1219  int getNx() const {
1220  return nx;
1221  };
1222  int getNy() const {
1223  return ny;
1224  };
1225  int getNz() const {
1226  return nz;
1227  };
1228 
1229  EGS_Float *getXPositions() {
1230  return xp->getPositions();
1231  };
1232  EGS_Float *getYPositions() {
1233  return yp->getPositions();
1234  };
1235  EGS_Float *getZPositions() {
1236  return zp->getPositions();
1237  };
1238 
1239  static int getDigits(int i);
1240 
1241  const string &getType() const {
1242  return type;
1243  };
1244 
1245  void printInfo() const;
1246 
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);
1250 
1251  void voxelizeGeometry(EGS_Input *input);
1252 
1253  void setXYZLabels(EGS_Input *input);
1254 
1255  virtual void getLabelRegions(const string &str, vector<int> &regs);
1256  void getXLabelRegions(const string &str, vector<int> &regs) {
1257  xp->getLabelRegions(str, regs);
1258  }
1259  void getYLabelRegions(const string &str, vector<int> &regs) {
1260  yp->getLabelRegions(str, regs);
1261  }
1262  void getZLabelRegions(const string &str, vector<int> &regs) {
1263  zp->getLabelRegions(str, regs);
1264  }
1265 
1266 protected:
1267 
1268  EGS_PlanesX *xp;
1269  EGS_PlanesY *yp;
1270  EGS_PlanesZ *zp;
1271  EGS_Float *xpos;
1272  EGS_Float *ypos;
1273  EGS_Float *zpos;
1274  int nx, ny, nz, nxy;
1275  static string type;
1276 
1277  void setup();
1278 
1279  void setMedia(EGS_Input *inp, int nmed, const int *med_ind);
1280 
1281  int howfarFromOut(const EGS_Vector &x, const EGS_Vector &u,
1282  EGS_Float &t, int &ix, int &iy, int &iz,
1283  int &face, EGS_Vector *normal=0) {
1284  ix = -1;
1285  EGS_Float t1;
1286  if (x.x <= xpos[0] && u.x > 0) {
1287  t1 = (xpos[0]-x.x)/u.x;
1288  ix = 0;
1289  face = 0;
1290  }
1291  else if (x.x >= xpos[nx] && u.x < 0) {
1292  t1 = (xpos[nx]-x.x)/u.x;
1293  ix = nx-1;
1294  face = 1;
1295  }
1296  if (ix >= 0 && t1 <= t) {
1297  EGS_Vector tmp(x + u*t1);
1298  iy = yp->isWhere(tmp);
1299  if (iy >= 0) {
1300  iz = zp->isWhere(tmp);
1301  if (iz >= 0) {
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) {
1306  return -1;
1307  }
1308  }
1309  if (normal) *normal = face == 0 ? EGS_Vector(-1,0,0) :
1310  EGS_Vector(1,0,0);
1311  t = t1;
1312  return inew;
1313  }
1314  }
1315  }
1316  iy = -1;
1317  if (x.y <= ypos[0] && u.y > 0) {
1318  t1 = (ypos[0]-x.y)/u.y;
1319  iy = 0;
1320  face = 2;
1321  }
1322  else if (x.y >= ypos[ny] && u.y < 0) {
1323  t1 = (ypos[ny]-x.y)/u.y;
1324  iy = ny-1;
1325  face = 3;
1326  }
1327  if (iy >= 0 && t1 <= t) {
1328  EGS_Vector tmp(x + u*t1);
1329  ix = xp->isWhere(tmp);
1330  if (ix >= 0) {
1331  iz = zp->isWhere(tmp);
1332  if (iz >= 0) {
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) {
1337  return -1;
1338  }
1339  }
1340  if (normal) *normal = face == 2 ? EGS_Vector(0,-1,0) :
1341  EGS_Vector(0, 1,0);
1342  t = t1;
1343  return inew;
1344  }
1345  }
1346  }
1347  iz = -1;
1348  if (x.z <= zpos[0] && u.z > 0) {
1349  t1 = (zpos[0]-x.z)/u.z;
1350  iz = 0;
1351  face = 4;
1352  }
1353  else if (x.z >= zpos[nz] && u.z < 0) {
1354  t1 = (zpos[nz]-x.z)/u.z;
1355  iz = nz-1;
1356  face = 5;
1357  }
1358  if (iz >= 0 && t1 <= t) {
1359  EGS_Vector tmp(x + u*t1);
1360  ix = xp->isWhere(tmp);
1361  if (ix >= 0) {
1362  iy = yp->isWhere(tmp);
1363  if (iy >= 0) {
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) {
1368  return -1;
1369  }
1370  }
1371  if (normal) *normal = face == 4 ? EGS_Vector(0,0,-1) :
1372  EGS_Vector(0,0, 1);
1373  t = t1;
1374  return inew;
1375  }
1376  }
1377  }
1378  return -1;
1379  };
1380 };
1381 
1396 class EGS_NDG_EXPORT EGS_DeformedXYZ : public EGS_XYZGeometry {
1397 
1398 public:
1399 
1401  const char *defFile, const string &Name = "");
1402 
1403  ~EGS_DeformedXYZ();
1404 
1405  int isWhere(const EGS_Vector &x) {
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");
1409  return ireg;
1410  };
1411 
1412  int inside(const EGS_Vector &x) {
1413  return isWhere(x);
1414  };
1415 
1416  int medium(int ireg) const {
1417  return EGS_XYZGeometry::medium(ireg/6);
1418  };
1419 
1420  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
1421  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
1422  if (ireg >= 0) {
1423  int ir = ireg/6, tetra = ireg - 6*ir, tetra4 = 4*tetra;
1424  int ind[3];
1425  ind[2] = ir/nxy;
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;
1429  EGS_Vector n0(vectors[edge+tnodes[tetra4]]),
1430  n1(vectors[edge+tnodes[tetra4+1]]-n0),
1431  n2(vectors[edge+tnodes[tetra4+2]]-n0),
1432  n3(vectors[edge+tnodes[tetra4+3]]-n0);
1433  EGS_Vector n0x(n0-x);
1434  EGS_Float disti[4],dpi[4];
1435  EGS_Vector normvec;
1436  normvec = n1%n2;
1437  dpi[0]=normvec*u;
1438  disti[0]=normvec*n0x;
1439  normvec = n3%n1;
1440  dpi[2]=normvec*u;
1441  disti[2]=normvec*n0x;
1442  normvec = n2%n3;
1443  dpi[1]=normvec*u;
1444  disti[1]=normvec*n0x;
1445  normvec = (n3-n1)%(n2-n1);
1446  dpi[3] = normvec*u;
1447  disti[3] = normvec*(n0x+n1);
1448  int nextplane = 4;
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]) {
1452  mindist = disti[i];
1453  mindp=dpi[i];
1454  nextplane=i;
1455  }
1456  }
1457  if (nextplane == 4) {
1458  return ireg;
1459  }
1460  t = mindist/mindp;
1461  int j = 12*tetra + 3*nextplane;
1462  int next = tetra_data[j];
1463  int irnew = ir;
1464  if (next >= 0) {
1465  ind[next] += tetra_data[j+1];
1466  if (ind[next] < 0 || ind[next] >= np[next]) {
1467  return -1;
1468  }
1469  irnew = ind[0] + ind[1]*nx + ind[2]*nxy;
1470  }
1471  if (newmed) {
1472  *newmed = EGS_XYZGeometry::medium(irnew);
1473  }
1474  if (normal) {
1475  switch (nextplane) {
1476  case 0:
1477  *normal = n2%n1;
1478  break;
1479  case 1:
1480  *normal = n1%n3;
1481  break;
1482  case 2:
1483  *normal = n3%n2;
1484  break;
1485  case 3:
1486  *normal = (n2-n1)%(n3-n1);
1487  }
1488  }
1489  return 6*irnew + tetra_data[j+2];
1490  }
1491  int ix,iy,iz,face;
1492  int inew = howfarFromOut(x,u,t,ix,iy,iz,face,normal);
1493  if (inew < 0) {
1494  return inew;
1495  }
1496  if (newmed) {
1497  *newmed = EGS_XYZGeometry::medium(inew);
1498  }
1499  // need to determine the tetrahedron we are entering.
1500  int edge = inew + iy + iz*nxyp1;
1501  EGS_Vector tmp(x + u*t);
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;
1509  }
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;
1517  }
1518  // roundoff problem
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);
1522  return -1;
1523  };
1524 
1525  EGS_Float hownear(int ireg, const EGS_Vector &x) {
1526  if (ireg < 0) {
1527  return EGS_XYZGeometry::hownear(ireg,x);
1528  }
1529  int ir = ireg/6, tetra = ireg - 6*ir, tetra4 = 4*tetra;
1530  int ind[3];
1531  ind[2] = ir/nxy;
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;
1535  EGS_Vector n0(vectors[edge+tnodes[tetra4]]),
1536  n1(vectors[edge+tnodes[tetra4+1]]-n0),
1537  n2(vectors[edge+tnodes[tetra4+2]]-n0),
1538  n3(vectors[edge+tnodes[tetra4+3]]-n0);
1539  EGS_Vector n0x(n0-x);
1540  EGS_Float disti[4],dpi[4];
1541  EGS_Vector normvec;
1542  normvec = n1%n2;
1543  dpi[0]=normvec.length2();
1544  disti[0]=normvec*n0x;
1545  normvec = n3%n1;
1546  dpi[2]=normvec.length2();
1547  disti[2]=normvec*n0x;
1548  normvec = n2%n3;
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]) {
1557  mindist = disti[i];
1558  mindp=dpi[i];
1559  }
1560  }
1561  return mindist/mindp;
1562  };
1563 
1564  int computeIntersections(int ireg, int n, const EGS_Vector &X,
1565  const EGS_Vector &u, EGS_GeometryIntersections *isections) {
1566  return EGS_BaseGeometry::computeIntersections(ireg,n,X,u,isections);
1567  };
1568 
1569  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
1570  const EGS_Vector &u) {
1571  if (ireg < 0) {
1572  return 0;
1573  }
1574  int ir = ireg/6;
1575  int iz = ir/nxy;
1576  int ir1 = ir - iz*nxy;
1577  int iy = ir1/nx;
1578  int ix = ir1 - iy*nx;
1579  EGS_Float d = xp->howfarToOutside(ix,x,u);
1580  EGS_Float ty = yp->howfarToOutside(iy,x,u);
1581  if (ty < d) {
1582  d = ty;
1583  }
1584  EGS_Float tz = zp->howfarToOutside(iz,x,u);
1585  if (tz < d) {
1586  d = tz;
1587  }
1588  return d;
1589  };
1590 
1591  int getMaxStep() const {
1592  return 6*(nx+ny+nz) + 1;
1593  };
1594 
1595  const string &getType() const {
1596  return def_type;
1597  };
1598 
1599  void printInfo() const {};
1600 
1612  int setDeformations(const char *defFile);
1613 
1614  bool inTriangle(const EGS_Vector &n0, const EGS_Vector &n1,
1615  const EGS_Vector &n2, const EGS_Vector &x) {
1616  EGS_Vector u1(n1-n0), u2(n2-n0), xp(x-n0);
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;
1620  if (u<0||u>D) {
1621  return false;
1622  }
1623  EGS_Float v=b2*a-b1*b;
1624  if (v<0||u+v>D) {
1625  return false;
1626  }
1627  return true;
1628  };
1629 
1630 protected:
1631 
1632  EGS_Vector *vectors;
1633 
1634  int tnodes[24];
1635 
1636  int np[3];
1637 
1638  int nxyp1;
1639 
1640  static string def_type;
1641 
1642  static char tetrahedra[];
1643 
1644  static char plane_order[];
1645 
1646  static char tetra_data[];
1647 
1648  static char enter_tetra1[];
1649  static char enter_plane1[];
1650  static char enter_tetra2[];
1651  static char enter_plane2[];
1652 
1653 
1654 };
1655 
1727 class EGS_NDG_EXPORT EGS_XYZRepeater : public EGS_BaseGeometry {
1728 
1729 public:
1730 
1731  EGS_XYZRepeater(EGS_Float Xmin, EGS_Float Xmax,
1732  EGS_Float Ymin, EGS_Float Ymax,
1733  EGS_Float Zmin, EGS_Float Zmax,
1734  int Nx, int Ny, int Nz, EGS_BaseGeometry *G,
1735  const string &Name = "");
1736 
1737  ~EGS_XYZRepeater();
1738 
1739  int isWhere(const EGS_Vector &x) {
1740  int cell = xyz->isWhere(x);
1741  //egsWarning("isInside(%g,%g,%g): cell=%d\n",x.x,x.y,x.z,cell);
1742  if (cell < 0) {
1743  return cell;
1744  }
1745  EGS_Vector xp(x - translation[cell]);
1746  int ir = g->isWhere(xp);
1747  //egsWarning("xp=(%g,%g,%g) ir=%d\n",xp.x,xp.y,xp.z,ir);
1748  return ir >= 0 ? cell*ng + ir : nreg-1;
1749  };
1750 
1751  bool isInside(const EGS_Vector &x) {
1752  return xyz->isInside(x);
1753  };
1754 
1755  int inside(const EGS_Vector &x) {
1756  return isWhere(x);
1757  };
1758 
1759  int medium(int ireg) const {
1760  if (ireg == nreg-1) {
1761  return med;
1762  }
1763  int cell = ireg/ng;
1764  int ilocal = ireg - ng*cell;
1765  return g->medium(ilocal);
1766  };
1767 
1768  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
1769  const EGS_Vector &u) {
1770  if (ireg < 0) {
1771  return 0;
1772  }
1773  return xyz->howfarToOutside(0,x,u);
1774  };
1775 
1776  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
1777  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
1778  //egsWarning("\n***howfar(reg=%d,x=(%g,%g,%g),u=(%g,%g,%g),t=%g)\n",
1779  // ireg,x.x,x.y,x.z,u.x,u.y,u.z,t);
1780  if (ireg < 0) {
1781  // outside of the box.
1782  int cell = xyz->howfar(ireg,x,u,t,0,normal);
1783  //egsWarning("entering: cell=%d t=%g\n",cell,t);
1784  if (cell >= 0) {
1785  if (newmed) {
1786  *newmed = med;
1787  }
1788  return nreg-1;
1789  }
1790  return -1;
1791  }
1792  if (ireg >= 0) {
1793  if (ireg < nreg-1) { // in one of the repetitions
1794  int cell = ireg/ng;
1795  int ilocal = ireg - cell*ng;
1796  EGS_Vector xp(x - translation[cell]);
1797  int inew = g->howfar(ilocal,xp,u,t,newmed,normal);
1798  //egsWarning("cell=%d il=%d inew=%d t=%g xp=(%g,%g,%g)\n",
1799  // cell,ilocal,inew,t,xp.x,xp.y,xp.z);
1800  if (inew >= 0) {
1801  return cell*ng + inew;
1802  }
1803  if (newmed) {
1804  *newmed = med;
1805  }
1806  return nreg-1;
1807  }
1808  }
1809  // if here, we are in the box outside of all repetitions
1810  // find the cell we are in
1811  int ix = (int)(x.x*dxi + ax);
1812  if (ix >= nx) {
1813  ix = nx-1;
1814  }
1815  int iy = (int)(x.y*dyi + ay);
1816  if (iy >= ny) {
1817  iy = ny-1;
1818  }
1819  int iz = (int)(x.z*dzi + az);
1820  if (iz >= nz) {
1821  iz = nz-1;
1822  }
1823  int cell = ix + iy*nx + iz*nxy;
1824  //egsWarning("in box: ix=%d iy=%d iz=%d\n",ix,iy,iz);
1825  EGS_Float t_left = t;
1826  EGS_Vector xtmp(x);
1827  EGS_Float ttot = 0;
1828  for (EGS_I64 loopCount=0; loopCount<=loopMax; ++loopCount) {
1829  if (loopCount == loopMax) {
1830  egsFatal("EGS_XYZRepeater::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
1831  return -1;
1832  }
1833  EGS_Float this_t = t_left;
1834  EGS_Vector xp(xtmp - translation[cell]);
1835  int inew = g->howfar(-1,xp,u,this_t,newmed,normal);
1836  //egsWarning("cell=%d tleft=%g xp=(%g,%g,%g) inew=%d this_t=%g\n",
1837  // cell,t_left,xp.x,xp.y,xp.z,inew,this_t);
1838  if (inew >= 0) {
1839  t = ttot + this_t;
1840  return cell*ng + inew;
1841  }
1842  int next_cell = xyz->howfar(cell,xtmp,u,this_t,0,normal);
1843  //egsWarning("next: %d %g\n",next_cell,this_t);
1844  if (next_cell == cell) {
1845  return ireg;
1846  }
1847  if (next_cell < 0) {
1848  t = ttot + this_t;
1849  return -1;
1850  }
1851  ttot += this_t;
1852  t_left -= this_t;
1853  xtmp += u*this_t;
1854  cell = next_cell;
1855  }
1856 
1857  return ireg;
1858  };
1859 
1860  EGS_Float hownear(int ireg, const EGS_Vector &x) {
1861  if (ireg < 0) {
1862  return xyz->hownear(ireg,x);
1863  }
1864  if (ireg < nreg-1) {
1865  int cell = ireg/ng;
1866  int ilocal = ireg - cell*ng;
1867  EGS_Vector xp(x - translation[cell]);
1868  return g->hownear(ilocal,xp);
1869  }
1870  // if here, we are in the box outside of all repetitions
1871  // find the cell we are in
1872  int ix = (int)(x.x*dxi + ax);
1873  if (ix >= nx) {
1874  ix = nx-1;
1875  }
1876  int iy = (int)(x.y*dyi + ay);
1877  if (iy >= ny) {
1878  iy = ny-1;
1879  }
1880  int iz = (int)(x.z*dzi + az);
1881  if (iz >= nz) {
1882  iz = nz-1;
1883  }
1884  int cell = ix + iy*nx + iz*nxy;
1885  EGS_Vector xp(x - translation[cell]);
1886  EGS_Float t = g->hownear(-1,xp);
1887  EGS_Float tcell = xyz->hownear(cell,x);
1888  if (t < tcell) {
1889  return t;
1890  }
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;
1899  EGS_Vector tmp(x-translation[cell1]);
1900  EGS_Float t1 = g->hownear(-1,tmp);
1901  if (t1 < t) {
1902  t = t1;
1903  }
1904  }
1905  }
1906  }
1907  }
1908  }
1909  }
1910  }
1911  return t;
1912  };
1913 
1914  int getMaxStep() const {
1915  return nxyz*(g->getMaxStep() + 1) + 1;
1916  };
1917 
1918  const string &getType() const {
1919  return type;
1920  };
1921 
1922  void printInfo() const;
1923 
1924  void setXYZLabels(EGS_Input *input) {
1925  xyz->setXYZLabels(input);
1926  }
1927 
1928  virtual void getLabelRegions(const string &str, vector<int> &regs);
1929 
1930 protected:
1931 
1932  EGS_XYZGeometry *xyz;
1933  EGS_BaseGeometry *g;
1934  EGS_Vector *translation;
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;
1939 
1940  static string type;
1941 
1942 };
1943 
1944 #endif
1945 
1946 #endif
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 > &regs)
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?
int med
Medium index.
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 deformed XYZ-geometry.
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
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.
Definition: egs_planes.h:167
Base random number generator class. All random number generators should be derived from this class.
Definition: egs_rndm.h:67
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
An XYZ-geometry.
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.
Definition: egs_functions.h:96
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.
const EGS_Float veryFar
A very large float.
EGS_I32 ireg
region index
EGS_Float t
distance to next region boundary
EGS_Float rhof
relative mass density in that region
EGS_I32 imed
medium index