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 #
32 ###############################################################################
33 */
34 
35 
42 #ifndef EGS_ND_GEOMETRY_
43 #define EGS_ND_GEOMETRY_
44 
45 #ifdef WIN32
46 
47  #ifdef BUILD_NDG_DLL
48  #define EGS_NDG_EXPORT __declspec(dllexport)
49  #else
50  #define EGS_NDG_EXPORT __declspec(dllimport)
51  #endif
52  #define EGS_NDG_LOCAL
53 
54 #else
55 
56  #ifdef HAVE_VISIBILITY
57  #define EGS_NDG_EXPORT __attribute__ ((visibility ("default")))
58  #define EGS_NDG_LOCAL __attribute__ ((visibility ("hidden")))
59  #else
60  #define EGS_NDG_EXPORT
61  #define EGS_NDG_LOCAL
62  #endif
63 
64 #endif
65 
66 
67 #include "egs_base_geometry.h"
68 
69 #include<vector>
70 #include <iomanip>
71 using std::vector;
72 
312 class EGS_NDG_EXPORT EGS_NDGeometry : public EGS_BaseGeometry {
313 
314 public:
315 
318  EGS_NDGeometry(int ng, EGS_BaseGeometry **G, const string &Name = "",
319  bool O=true);
320 
322  EGS_NDGeometry(vector<EGS_BaseGeometry *> &G, const string &Name = "",
323  bool O=true);
324 
325  ~EGS_NDGeometry();
326 
327  bool isInside(const EGS_Vector &x) {
328  for (int j=0; j<N; j++) if (!g[j]->isInside(x)) {
329  return false;
330  }
331  return true;
332  };
333 
334  int isWhere(const EGS_Vector &x) {
335  int ireg = 0;
336  for (int j=0; j<N; j++) {
337  int ij = g[j]->isWhere(x);
338  if (ij < 0) {
339  return -1;
340  }
341  ireg += ij*n[j];
342  }
343  return ireg;
344  };
345 
346  int inside(const EGS_Vector &x) {
347  return isWhere(x);
348  };
349 
350  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
351  const EGS_Vector &u) {
352  if (ireg < 0) {
353  return 0;
354  }
355  int itmp = ireg;
356  EGS_Float d = veryFar;
357  for (int j=N-1; j>=0; j--) {
358  int l = itmp/n[j];
359  EGS_Float t = g[j]->howfarToOutside(l,x,u);
360  if (t <= 0) {
361  return t;
362  }
363  if (t < d) {
364  d = t;
365  }
366  }
367  return d;
368  };
369 
370  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
371  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
372  if (ireg >= 0) {
373  int itmp = ireg;
374  int inext = -1, idelta, lnew_j=0;
375  for (int j=N-1; j>=0; j--) {
376  int l = itmp/n[j];
377  int lnew = g[j]->howfar(l,x,u,t,0,normal);
378  if (lnew != l) {
379  inext = j;
380  idelta = lnew - l;
381  lnew_j = lnew;
382  }
383  itmp -= l*n[j];
384  }
385  if (inext < 0) {
386  return ireg;
387  }
388  int inew = lnew_j >= 0 ? ireg + idelta*n[inext] : lnew_j;
389  //if( lnew_j < 0 ) return lnew_j;
390  //int inew = ireg + idelta*n[inext];
391  if (newmed) {
392  *newmed = inew >= 0 ? medium(inew) : -1;
393  }
394  return inew;
395  }
396  for (int j=0; j<N; j++) {
397  EGS_Float tj = t;
398  bool is_in = g[j]->isInside(x);
399  // Note: this logic fails if the geometry is not convex!
400  if (!is_in) {
401  EGS_Vector nn, *np=0;
402  if (normal) {
403  np = &nn;
404  }
405  int i = g[j]->howfar(ireg,x,u,tj,0,np);
406  if (i >= 0) {
407  EGS_Vector tmp(x + u*tj);
408  bool is_ok = true;
409  int res = 0;
410  for (int k=0; k<N; k++) {
411  if (k != j) {
412  int check = g[k]->isWhere(tmp);
413  if (check < 0) {
414  is_ok = false;
415  break;
416  }
417  res += check*n[k];
418  }
419  }
420  if (is_ok) {
421  t = tj;
422  res += i*n[j];
423  if (newmed) {
424  *newmed = medium(res);
425  }
426  if (normal) {
427  *normal = nn;
428  }
429  return res;
430  }
431  }
432  }
433  // and so, to fix it, we do the following for non-convex
434  // dimensions. But this only works if and only if there
435  // is not more than 1 non-convex dimension and this
436  // dimension is last in the list.
437  else if (!g[j]->isConvex()) {
438  EGS_Vector tmp(x);
439  EGS_Float tleft = t;
440  int ii = g[j]->isWhere(x);
441  EGS_Float ttot = 0;
442  for (EGS_I64 loopCount=0; loopCount<=loopMax; ++loopCount) {
443  if (loopCount == loopMax) {
444  egsFatal("EGS_NDGeometry::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
445  return -1;
446  }
447  EGS_Float tt = tleft;
448  int inew = g[j]->howfar(ii,tmp,u,tt);
449  if (inew == ii) {
450  break;
451  }
452  tleft -= tt;
453  tmp += u*tt;
454  ii = inew;
455  ttot += tt;
456  //egsWarning(" inew = %d tt = %g ttot = %g tmp = (%g,%g,%g)\n",inew,tt,ttot,tmp.x,tmp.y,tmp.z);
457  if (ii < 0) {
458  break;
459  }
460  }
461  //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);
462  if (ii < 0) {
463  EGS_Vector nn, *np = normal ? &nn : 0;
464  EGS_Float tt = tleft;
465  int inew = g[j]->howfar(ii,tmp,u,tt,0,np);
466  //egsWarning(" exited and tried to reenter: %d %g\n",inew,ttot+tt);
467  if (inew >= 0) {
468  tmp += u*tt;
469  bool is_ok = true;
470  int res = 0;
471  for (int k=0; k<N; k++) {
472  if (k != j) {
473  int check = g[k]->isWhere(tmp);
474  if (check < 0) {
475  is_ok = false;
476  break;
477  }
478  res += check*n[k];
479  }
480  }
481  if (is_ok) {
482  t = ttot + tt;
483  res += inew*n[j];
484  if (newmed) {
485  *newmed = medium(res);
486  }
487  if (normal) {
488  *normal = nn;
489  }
490  return res;
491  }
492  }
493  }
494  }
495  }
496  return -1;
497  };
498 
499  EGS_Float hownear(int ireg, const EGS_Vector &x) {
500  EGS_Float tmin = veryFar;
501  if (ireg >= 0) {
502  int itmp = ireg;
503  for (int j=N-1; j>=0; j--) {
504  int l = itmp/n[j];
505  EGS_Float t = g[j]->hownear(l,x);
506  if (t < tmin) {
507  tmin = t;
508  if (tmin <= 0) {
509  return 0;
510  }
511  }
512  itmp -= l*n[j];
513  }
514  return tmin;
515  }
516  if (ortho) {
517  int nc = 0;
518  EGS_Float s1=0, s2=0;
519  for (int j=0; j<N; j++) {
520  if (!g[j]->isInside(x)) {
521  EGS_Float t = g[j]->hownear(-1,x);
522  nc++;
523  s1 += t;
524  s2 += t*t;
525  }
526  }
527  if (nc == 1) {
528  return s1;
529  }
530  return sqrt(s2);
531  }
532  else {
533  EGS_Float tmin = veryFar;
534  for (int j=0; j<N; j++) {
535  EGS_Float t;
536  int i = g[j]->isWhere(x);
537  t = g[j]->hownear(i,x);
538  if (t < tmin) {
539  tmin = t;
540  if (tmin <= 0) {
541  return 0;
542  }
543  }
544  }
545  return tmin;
546  }
547  };
548 
549  int getMaxStep() const {
550  int nstep = 1;
551  for (int j=0; j<N; ++j) {
552  nstep += g[j]->getMaxStep();
553  }
554  return nstep;
555  };
556 
557  const string &getType() const {
558  return type;
559  };
560 
561  void printInfo() const;
562 
563  virtual void getLabelRegions(const string &str, vector<int> &regs);
564  void ndRegions(int r, int dim, int dimk, int k, vector<int> &regs);
565 
566 protected:
567 
568  int N;
570  int *n;
571  static string type;
572  bool ortho;
573 
574  void setup();
575 
582  void setMedia(EGS_Input *inp, int nmed, const int *med_ind);
583 
584 private:
585 
586  void setM(int ib, int idim, const vector<int> &ranges, int medium);
587 };
588 
589 #ifdef EXPLICIT_XYZ
590 #include "../egs_planes/egs_planes.h"
591 
740 class EGS_NDG_EXPORT EGS_XYZGeometry : public EGS_BaseGeometry {
741 
742 public:
743 
745  const string &Name = "");
746 
747  ~EGS_XYZGeometry();
748 
749  bool isInside(const EGS_Vector &x) {
750  if (!xp->isInside(x)) {
751  return false;
752  }
753  if (!yp->isInside(x)) {
754  return false;
755  }
756  if (!zp->isInside(x)) {
757  return false;
758  }
759  return true;
760  };
761 
762  int isWhere(const EGS_Vector &x) {
763  int ix = xp->isWhere(x);
764  if (ix < 0) {
765  return ix;
766  }
767  int iy = yp->isWhere(x);
768  if (iy < 0) {
769  return iy;
770  }
771  int iz = zp->isWhere(x);
772  if (iz < 0) {
773  return iz;
774  }
775  return ix + iy*nx + iz*nxy;
776  };
777 
778  int inside(const EGS_Vector &x) {
779  return isWhere(x);
780  };
781 
782  int computeIntersections(int ireg, int n, const EGS_Vector &X,
783  const EGS_Vector &u, EGS_GeometryIntersections *isections) {
784  if (n < 1) {
785  return -1;
786  }
787  int ifirst = 0;
788  EGS_Float t, t_ini = 0;
789  EGS_Vector x(X);
790  int imed;
791  if (ireg < 0) {
792  t = veryFar;
793  ireg = howfar(ireg,x,u,t,&imed);
794  if (ireg < 0) {
795  return 0;
796  }
797  isections[0].t = t;
798  isections[0].rhof = 1;
799  isections[0].ireg = -1;
800  isections[0].imed = -1;
801  t_ini = t;
802  ++ifirst;
803  x += u*t;
804  }
805  else {
806  imed = medium(ireg);
807  }
808  EGS_Float *px = xp->getPositions(),
809  *py = yp->getPositions(),
810  *pz = zp->getPositions();
811  int iz = ireg/nxy;
812  int ir = ireg - iz*nxy;
813  int iy = ir/nx;
814  int ix = ir - iy*nx;
815  EGS_Float uxi, uyi, uzi, nextx, nexty, nextz;
816  int dirx, icx, diry, icy, dirz, icz;
817  if (u.x > 0) {
818  uxi = 1/u.x;
819  dirx = 1;
820  icx = 1;
821  }
822  else if (u.x < 0) {
823  uxi = 1/u.x;
824  dirx = -1;
825  icx = 0;
826  }
827  else {
828  uxi = veryFar*1e3;
829  dirx = 1;
830  icx = 1;
831  }
832  if (u.y > 0) {
833  uyi = 1/u.y;
834  diry = 1;
835  icy = 1;
836  }
837  else if (u.y < 0) {
838  uyi = 1/u.y;
839  diry = -1;
840  icy = 0;
841  }
842  else {
843  uyi = veryFar*1e3;
844  diry = 1;
845  icy = 1;
846  }
847  if (u.z > 0) {
848  uzi = 1/u.z;
849  dirz = 1;
850  icz = 1;
851  }
852  else if (u.z < 0) {
853  uzi = 1/u.z;
854  dirz = -1;
855  icz = 0;
856  }
857  else {
858  uzi = veryFar*1e3;
859  dirz = 1;
860  icz = 1;
861  }
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;
868  isections[j].rhof = getRelativeRho(ireg);
869  int inew;
870  if (nextx < nexty && nextx < nextz) {
871  t = nextx;
872  ix += dirx;
873  if (ix < 0 || ix >= nx) {
874  inew = -1;
875  }
876  else {
877  inew = ireg + dirx;
878  nextx = (px[ix+icx] - x.x)*uxi + t_ini;
879  }
880  }
881  else if (nexty < nextz) {
882  t = nexty;
883  iy += diry;
884  if (iy < 0 || iy >= ny) {
885  inew = -1;
886  }
887  else {
888  inew = ireg + nx*diry;
889  nexty = (py[iy+icy] - x.y)*uyi + t_ini;
890  }
891  }
892  else {
893  t = nextz;
894  iz += dirz;
895  if (iz < 0 || iz >= nz) {
896  inew = -1;
897  }
898  else {
899  inew = ireg + nxy*dirz;
900  nextz = (pz[iz+icz] - x.z)*uzi + t_ini;
901  }
902  }
903  isections[j].t = t;
904  if (inew < 0) {
905  return j+1;
906  }
907  ireg = inew;
908  imed = medium(ireg);
909  }
910  return ireg >= 0 ? -1 : n;
911  };
912 
913  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
914  const EGS_Vector &u) {
915  if (ireg < 0) {
916  return 0;
917  }
918  int iz = ireg/nxy;
919  int ir = ireg - iz*nxy;
920  int iy = ir/nx;
921  int ix = ir - iy*nx;
922  EGS_Float d = xp->howfarToOutside(ix,x,u);
923  EGS_Float ty = yp->howfarToOutside(iy,x,u);
924  if (ty < d) {
925  d = ty;
926  }
927  EGS_Float tz = zp->howfarToOutside(iz,x,u);
928  if (tz < d) {
929  d = tz;
930  }
931  return d;
932  };
933 
934  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
935  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
936  if (ireg >= 0) {
937  int iz = ireg/nxy;
938  int ir = ireg - iz*nxy;
939  int iy = ir/nx;
940  int ix = ir - iy*nx;
941  int inew = ireg;
942  if (u.x > 0) {
943  EGS_Float d = (xpos[ix+1]-x.x)/u.x;
944  if (d <= t) {
945  if (d <= boundaryTolerance) {
946  // t=0 works on most cases but can result in
947  // getting stuck on an edge, so use boundaryTolerance
948  t = halfBoundaryTolerance;
949  }
950  else {
951  t = d;
952  }
953  if ((++ix) < nx) {
954  inew = ireg + 1;
955  }
956  else {
957  inew = -1;
958  }
959  if (normal) {
960  *normal = EGS_Vector(-1,0,0);
961  }
962  }
963  }
964  else if (u.x < 0) {
965  EGS_Float d = (xpos[ix]-x.x)/u.x;
966  if (d <= t) {
967  if (d <= boundaryTolerance) {
968  t = halfBoundaryTolerance;
969  }
970  else {
971  t = d;
972  }
973  if ((--ix) >= 0) {
974  inew = ireg - 1;
975  }
976  else {
977  inew = -1;
978  }
979  if (normal) {
980  *normal = EGS_Vector(1,0,0);
981  }
982  }
983  }
984  if (u.y > 0) {
985  EGS_Float d = (ypos[iy+1]-x.y)/u.y;
986  if (d <= t) {
987  if (d <= boundaryTolerance) {
988  t = halfBoundaryTolerance;
989  }
990  else {
991  t = d;
992  }
993  if ((++iy) < ny) {
994  inew = ireg + nx;
995  }
996  else {
997  inew = -1;
998  }
999  if (normal) {
1000  *normal = EGS_Vector(0,-1,0);
1001  }
1002  }
1003  }
1004  else if (u.y < 0) {
1005  EGS_Float d = (ypos[iy]-x.y)/u.y;
1006  if (d <= t) {
1007  if (d <= boundaryTolerance) {
1008  t = halfBoundaryTolerance;
1009  }
1010  else {
1011  t = d;
1012  }
1013  if ((--iy) >= 0) {
1014  inew = ireg - nx;
1015  }
1016  else {
1017  inew = -1;
1018  }
1019  if (normal) {
1020  *normal = EGS_Vector(0,1,0);
1021  }
1022  }
1023  }
1024  if (u.z > 0) {
1025  EGS_Float d = (zpos[iz+1]-x.z)/u.z;
1026  if (d <= t) {
1027  if (d <= boundaryTolerance) {
1028  t = halfBoundaryTolerance;
1029  }
1030  else {
1031  t = d;
1032  }
1033  if ((++iz) < nz) {
1034  inew = ireg+nxy;
1035  }
1036  else {
1037  inew = -1;
1038  }
1039  if (normal) {
1040  *normal = EGS_Vector(0,0,-1);
1041  }
1042  }
1043  }
1044  else if (u.z < 0) {
1045  EGS_Float d = (zpos[iz]-x.z)/u.z;
1046  if (d <= t) {
1047  if (d <= boundaryTolerance) {
1048  t = halfBoundaryTolerance;
1049  }
1050  else {
1051  t = d;
1052  }
1053  if ((--iz) >= 0) {
1054  inew = ireg-nxy;
1055  }
1056  else {
1057  inew = -1;
1058  }
1059  if (normal) {
1060  *normal = EGS_Vector(0,0,1);
1061  }
1062  }
1063  }
1064  if (newmed && inew >= 0) {
1065  *newmed = medium(inew);
1066  }
1067  return inew;
1068  }
1069  int face,ix,iy,iz;
1070  int inew = howfarFromOut(x,u,t,ix,iy,iz,face,normal);
1071  if (inew >= 0 && newmed) {
1072  *newmed = medium(inew);
1073  }
1074  return inew;
1075  };
1076 
1077  EGS_Float hownear(int ireg, const EGS_Vector &x) {
1078  if (ireg >= 0) {
1079  int iz = ireg/nxy;
1080  int ir = ireg - iz*nxy;
1081  int iy = ir/nx;
1082  int ix = ir - iy*nx;
1083  EGS_Float t = xp->hownear(ix,x);
1084  EGS_Float t1 = yp->hownear(iy,x);
1085  if (t1 < t) {
1086  t = t1;
1087  }
1088  t1 = zp->hownear(iz,x);
1089  if (t1 < t) {
1090  t = t1;
1091  }
1092  return t;
1093  }
1094  int nc = 0;
1095  EGS_Float s1=0, s2=0;
1096  if (!xp->isInside(x)) {
1097  EGS_Float t = xp->hownear(-1,x);
1098  nc++;
1099  s1 += t;
1100  s2 += t*t;
1101  }
1102  if (!yp->isInside(x)) {
1103  EGS_Float t = yp->hownear(-1,x);
1104  nc++;
1105  s1 += t;
1106  s2 += t*t;
1107  }
1108  if (!zp->isInside(x)) {
1109  EGS_Float t = zp->hownear(-1,x);
1110  nc++;
1111  s1 += t;
1112  s2 += t*t;
1113  }
1114  if (nc == 1) {
1115  return s1;
1116  }
1117  return sqrt(s2);
1118  };
1119 
1120 
1121  EGS_Float getVolume(int ireg) {
1122  int iz = ireg/nxy;
1123  int ir = ireg - iz*nxy;
1124  int iy = ir/nx;
1125  int ix = ir - iy*nx;
1126  return (xpos[ix+1]-xpos[ix])*(ypos[iy+1]-ypos[iy])*(zpos[iz+1]-zpos[iz]);
1127  }
1128 
1129  EGS_Float getBound(int idir, int ind) {
1130  EGS_Float bound;
1131  if (idir == 0) {
1132  if (ind>=0 && ind<=nx) {
1133  bound = xpos[ind];
1134  }
1135  else {
1136  egsWarning("Error in getBound: Looking for X bound out of range %d\n"
1137  "Will set this to zero.\n",ind);
1138  bound = 0.0;
1139  }
1140  }
1141  else if (idir == 1) {
1142  if (ind>=0 && ind<=ny) {
1143  bound = ypos[ind];
1144  }
1145  else {
1146  egsWarning("Error in getBound: Looking for Y bound out of range %d\n"
1147  "Will set this to zero.\n",ind);
1148  bound = 0.0;
1149  }
1150  }
1151  else if (idir == 2) {
1152  if (ind>=0 && ind<=nz) {
1153  bound = zpos[ind];
1154  }
1155  else {
1156  egsWarning("Error in getBound: Looking for Z bound out of range %d\n"
1157  "Will set this to zero.\n",ind);
1158  bound = 0.0;
1159  }
1160  }
1161  else {
1162  egsWarning("Error in getBound: Dimension %d undefined in EGS_XYZGeometry.\n",idir);
1163  bound = 0.0;
1164  }
1165  return bound;
1166  }
1167 
1168  int getNRegDir(int idir) {
1169  if (idir==0) {
1170  return nx;
1171  }
1172  else if (idir==1) {
1173  return ny;
1174  }
1175  else if (idir==2) {
1176  return nz;
1177  }
1178  else {
1179  egsWarning("Error in getNregDir: Dimension %d undefined in EGS_XYZGeometry.\n",
1180  idir);
1181  return 0;
1182  }
1183  }
1184 
1185 
1186  int getMaxStep() const {
1187  return nx+ny+nz+1;
1188  };
1189 
1190  int getNx() const {
1191  return nx;
1192  };
1193  int getNy() const {
1194  return ny;
1195  };
1196  int getNz() const {
1197  return nz;
1198  };
1199 
1200  EGS_Float *getXPositions() {
1201  return xp->getPositions();
1202  };
1203  EGS_Float *getYPositions() {
1204  return yp->getPositions();
1205  };
1206  EGS_Float *getZPositions() {
1207  return zp->getPositions();
1208  };
1209 
1210  static int getDigits(int i);
1211 
1212  const string &getType() const {
1213  return type;
1214  };
1215 
1216  void printInfo() const;
1217 
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);
1221 
1222  void voxelizeGeometry(EGS_Input *input);
1223 
1224  void setXYZLabels(EGS_Input *input);
1225 
1226  virtual void getLabelRegions(const string &str, vector<int> &regs);
1227  void getXLabelRegions(const string &str, vector<int> &regs) {
1228  xp->getLabelRegions(str, regs);
1229  }
1230  void getYLabelRegions(const string &str, vector<int> &regs) {
1231  yp->getLabelRegions(str, regs);
1232  }
1233  void getZLabelRegions(const string &str, vector<int> &regs) {
1234  zp->getLabelRegions(str, regs);
1235  }
1236 
1237 protected:
1238 
1239  EGS_PlanesX *xp;
1240  EGS_PlanesY *yp;
1241  EGS_PlanesZ *zp;
1242  EGS_Float *xpos;
1243  EGS_Float *ypos;
1244  EGS_Float *zpos;
1245  int nx, ny, nz, nxy;
1246  static string type;
1247 
1248  void setup();
1249 
1250  void setMedia(EGS_Input *inp, int nmed, const int *med_ind);
1251 
1252  int howfarFromOut(const EGS_Vector &x, const EGS_Vector &u,
1253  EGS_Float &t, int &ix, int &iy, int &iz,
1254  int &face, EGS_Vector *normal=0) {
1255  ix = -1;
1256  EGS_Float t1;
1257  if (x.x <= xpos[0] && u.x > 0) {
1258  t1 = (xpos[0]-x.x)/u.x;
1259  ix = 0;
1260  face = 0;
1261  }
1262  else if (x.x >= xpos[nx] && u.x < 0) {
1263  t1 = (xpos[nx]-x.x)/u.x;
1264  ix = nx-1;
1265  face = 1;
1266  }
1267  if (ix >= 0 && t1 <= t) {
1268  EGS_Vector tmp(x + u*t1);
1269  iy = yp->isWhere(tmp);
1270  if (iy >= 0) {
1271  iz = zp->isWhere(tmp);
1272  if (iz >= 0) {
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) {
1277  return -1;
1278  }
1279  }
1280  if (normal) *normal = face == 0 ? EGS_Vector(-1,0,0) :
1281  EGS_Vector(1,0,0);
1282  t = t1;
1283  return inew;
1284  }
1285  }
1286  }
1287  iy = -1;
1288  if (x.y <= ypos[0] && u.y > 0) {
1289  t1 = (ypos[0]-x.y)/u.y;
1290  iy = 0;
1291  face = 2;
1292  }
1293  else if (x.y >= ypos[ny] && u.y < 0) {
1294  t1 = (ypos[ny]-x.y)/u.y;
1295  iy = ny-1;
1296  face = 3;
1297  }
1298  if (iy >= 0 && t1 <= t) {
1299  EGS_Vector tmp(x + u*t1);
1300  ix = xp->isWhere(tmp);
1301  if (ix >= 0) {
1302  iz = zp->isWhere(tmp);
1303  if (iz >= 0) {
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) {
1308  return -1;
1309  }
1310  }
1311  if (normal) *normal = face == 2 ? EGS_Vector(0,-1,0) :
1312  EGS_Vector(0, 1,0);
1313  t = t1;
1314  return inew;
1315  }
1316  }
1317  }
1318  iz = -1;
1319  if (x.z <= zpos[0] && u.z > 0) {
1320  t1 = (zpos[0]-x.z)/u.z;
1321  iz = 0;
1322  face = 4;
1323  }
1324  else if (x.z >= zpos[nz] && u.z < 0) {
1325  t1 = (zpos[nz]-x.z)/u.z;
1326  iz = nz-1;
1327  face = 5;
1328  }
1329  if (iz >= 0 && t1 <= t) {
1330  EGS_Vector tmp(x + u*t1);
1331  ix = xp->isWhere(tmp);
1332  if (ix >= 0) {
1333  iy = yp->isWhere(tmp);
1334  if (iy >= 0) {
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) {
1339  return -1;
1340  }
1341  }
1342  if (normal) *normal = face == 4 ? EGS_Vector(0,0,-1) :
1343  EGS_Vector(0,0, 1);
1344  t = t1;
1345  return inew;
1346  }
1347  }
1348  }
1349  return -1;
1350  };
1351 };
1352 
1367 class EGS_NDG_EXPORT EGS_DeformedXYZ : public EGS_XYZGeometry {
1368 
1369 public:
1370 
1372  const char *defFile, const string &Name = "");
1373 
1374  ~EGS_DeformedXYZ();
1375 
1376  int isWhere(const EGS_Vector &x) {
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");
1380  return ireg;
1381  };
1382 
1383  int inside(const EGS_Vector &x) {
1384  return isWhere(x);
1385  };
1386 
1387  int medium(int ireg) const {
1388  return EGS_XYZGeometry::medium(ireg/6);
1389  };
1390 
1391  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
1392  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
1393  if (ireg >= 0) {
1394  int ir = ireg/6, tetra = ireg - 6*ir, tetra4 = 4*tetra;
1395  int ind[3];
1396  ind[2] = ir/nxy;
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;
1400  EGS_Vector n0(vectors[edge+tnodes[tetra4]]),
1401  n1(vectors[edge+tnodes[tetra4+1]]-n0),
1402  n2(vectors[edge+tnodes[tetra4+2]]-n0),
1403  n3(vectors[edge+tnodes[tetra4+3]]-n0);
1404  EGS_Vector n0x(n0-x);
1405  EGS_Float disti[4],dpi[4];
1406  EGS_Vector normvec;
1407  normvec = n1%n2;
1408  dpi[0]=normvec*u;
1409  disti[0]=normvec*n0x;
1410  normvec = n3%n1;
1411  dpi[2]=normvec*u;
1412  disti[2]=normvec*n0x;
1413  normvec = n2%n3;
1414  dpi[1]=normvec*u;
1415  disti[1]=normvec*n0x;
1416  normvec = (n3-n1)%(n2-n1);
1417  dpi[3] = normvec*u;
1418  disti[3] = normvec*(n0x+n1);
1419  int nextplane = 4;
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]) {
1423  mindist = disti[i];
1424  mindp=dpi[i];
1425  nextplane=i;
1426  }
1427  }
1428  if (nextplane == 4) {
1429  return ireg;
1430  }
1431  t = mindist/mindp;
1432  int j = 12*tetra + 3*nextplane;
1433  int next = tetra_data[j];
1434  int irnew = ir;
1435  if (next >= 0) {
1436  ind[next] += tetra_data[j+1];
1437  if (ind[next] < 0 || ind[next] >= np[next]) {
1438  return -1;
1439  }
1440  irnew = ind[0] + ind[1]*nx + ind[2]*nxy;
1441  }
1442  if (newmed) {
1443  *newmed = EGS_XYZGeometry::medium(irnew);
1444  }
1445  if (normal) {
1446  switch (nextplane) {
1447  case 0:
1448  *normal = n2%n1;
1449  break;
1450  case 1:
1451  *normal = n1%n3;
1452  break;
1453  case 2:
1454  *normal = n3%n2;
1455  break;
1456  case 3:
1457  *normal = (n2-n1)%(n3-n1);
1458  }
1459  }
1460  return 6*irnew + tetra_data[j+2];
1461  }
1462  int ix,iy,iz,face;
1463  int inew = howfarFromOut(x,u,t,ix,iy,iz,face,normal);
1464  if (inew < 0) {
1465  return inew;
1466  }
1467  if (newmed) {
1468  *newmed = EGS_XYZGeometry::medium(inew);
1469  }
1470  // need to determine the tetrahedron we are entering.
1471  int edge = inew + iy + iz*nxyp1;
1472  EGS_Vector tmp(x + u*t);
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;
1480  }
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;
1488  }
1489  // roundoff problem
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);
1493  return -1;
1494  };
1495 
1496  EGS_Float hownear(int ireg, const EGS_Vector &x) {
1497  if (ireg < 0) {
1498  return EGS_XYZGeometry::hownear(ireg,x);
1499  }
1500  int ir = ireg/6, tetra = ireg - 6*ir, tetra4 = 4*tetra;
1501  int ind[3];
1502  ind[2] = ir/nxy;
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;
1506  EGS_Vector n0(vectors[edge+tnodes[tetra4]]),
1507  n1(vectors[edge+tnodes[tetra4+1]]-n0),
1508  n2(vectors[edge+tnodes[tetra4+2]]-n0),
1509  n3(vectors[edge+tnodes[tetra4+3]]-n0);
1510  EGS_Vector n0x(n0-x);
1511  EGS_Float disti[4],dpi[4];
1512  EGS_Vector normvec;
1513  normvec = n1%n2;
1514  dpi[0]=normvec.length2();
1515  disti[0]=normvec*n0x;
1516  normvec = n3%n1;
1517  dpi[2]=normvec.length2();
1518  disti[2]=normvec*n0x;
1519  normvec = n2%n3;
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]) {
1528  mindist = disti[i];
1529  mindp=dpi[i];
1530  }
1531  }
1532  return mindist/mindp;
1533  };
1534 
1535  int computeIntersections(int ireg, int n, const EGS_Vector &X,
1536  const EGS_Vector &u, EGS_GeometryIntersections *isections) {
1537  return EGS_BaseGeometry::computeIntersections(ireg,n,X,u,isections);
1538  };
1539 
1540  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
1541  const EGS_Vector &u) {
1542  if (ireg < 0) {
1543  return 0;
1544  }
1545  int ir = ireg/6;
1546  int iz = ir/nxy;
1547  int ir1 = ir - iz*nxy;
1548  int iy = ir1/nx;
1549  int ix = ir1 - iy*nx;
1550  EGS_Float d = xp->howfarToOutside(ix,x,u);
1551  EGS_Float ty = yp->howfarToOutside(iy,x,u);
1552  if (ty < d) {
1553  d = ty;
1554  }
1555  EGS_Float tz = zp->howfarToOutside(iz,x,u);
1556  if (tz < d) {
1557  d = tz;
1558  }
1559  return d;
1560  };
1561 
1562  int getMaxStep() const {
1563  return 6*(nx+ny+nz) + 1;
1564  };
1565 
1566  const string &getType() const {
1567  return def_type;
1568  };
1569 
1570  void printInfo() const {};
1571 
1583  int setDeformations(const char *defFile);
1584 
1585  bool inTriangle(const EGS_Vector &n0, const EGS_Vector &n1,
1586  const EGS_Vector &n2, const EGS_Vector &x) {
1587  EGS_Vector u1(n1-n0), u2(n2-n0), xp(x-n0);
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;
1591  if (u<0||u>D) {
1592  return false;
1593  }
1594  EGS_Float v=b2*a-b1*b;
1595  if (v<0||u+v>D) {
1596  return false;
1597  }
1598  return true;
1599  };
1600 
1601 protected:
1602 
1603  EGS_Vector *vectors;
1604 
1605  int tnodes[24];
1606 
1607  int np[3];
1608 
1609  int nxyp1;
1610 
1611  static string def_type;
1612 
1613  static char tetrahedra[];
1614 
1615  static char plane_order[];
1616 
1617  static char tetra_data[];
1618 
1619  static char enter_tetra1[];
1620  static char enter_plane1[];
1621  static char enter_tetra2[];
1622  static char enter_plane2[];
1623 
1624 
1625 };
1626 
1698 class EGS_NDG_EXPORT EGS_XYZRepeater : public EGS_BaseGeometry {
1699 
1700 public:
1701 
1702  EGS_XYZRepeater(EGS_Float Xmin, EGS_Float Xmax,
1703  EGS_Float Ymin, EGS_Float Ymax,
1704  EGS_Float Zmin, EGS_Float Zmax,
1705  int Nx, int Ny, int Nz, EGS_BaseGeometry *G,
1706  const string &Name = "");
1707 
1708  ~EGS_XYZRepeater();
1709 
1710  int isWhere(const EGS_Vector &x) {
1711  int cell = xyz->isWhere(x);
1712  //egsWarning("isInside(%g,%g,%g): cell=%d\n",x.x,x.y,x.z,cell);
1713  if (cell < 0) {
1714  return cell;
1715  }
1716  EGS_Vector xp(x - translation[cell]);
1717  int ir = g->isWhere(xp);
1718  //egsWarning("xp=(%g,%g,%g) ir=%d\n",xp.x,xp.y,xp.z,ir);
1719  return ir >= 0 ? cell*ng + ir : nreg-1;
1720  };
1721 
1722  bool isInside(const EGS_Vector &x) {
1723  return xyz->isInside(x);
1724  };
1725 
1726  int inside(const EGS_Vector &x) {
1727  return isWhere(x);
1728  };
1729 
1730  int medium(int ireg) const {
1731  if (ireg == nreg-1) {
1732  return med;
1733  }
1734  int cell = ireg/ng;
1735  int ilocal = ireg - ng*cell;
1736  return g->medium(ilocal);
1737  };
1738 
1739  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
1740  const EGS_Vector &u) {
1741  if (ireg < 0) {
1742  return 0;
1743  }
1744  return xyz->howfarToOutside(0,x,u);
1745  };
1746 
1747  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
1748  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
1749  //egsWarning("\n***howfar(reg=%d,x=(%g,%g,%g),u=(%g,%g,%g),t=%g)\n",
1750  // ireg,x.x,x.y,x.z,u.x,u.y,u.z,t);
1751  if (ireg < 0) {
1752  // outside of the box.
1753  int cell = xyz->howfar(ireg,x,u,t,0,normal);
1754  //egsWarning("entering: cell=%d t=%g\n",cell,t);
1755  if (cell >= 0) {
1756  if (newmed) {
1757  *newmed = med;
1758  }
1759  return nreg-1;
1760  }
1761  return -1;
1762  }
1763  if (ireg >= 0) {
1764  if (ireg < nreg-1) { // in one of the repetitions
1765  int cell = ireg/ng;
1766  int ilocal = ireg - cell*ng;
1767  EGS_Vector xp(x - translation[cell]);
1768  int inew = g->howfar(ilocal,xp,u,t,newmed,normal);
1769  //egsWarning("cell=%d il=%d inew=%d t=%g xp=(%g,%g,%g)\n",
1770  // cell,ilocal,inew,t,xp.x,xp.y,xp.z);
1771  if (inew >= 0) {
1772  return cell*ng + inew;
1773  }
1774  if (newmed) {
1775  *newmed = med;
1776  }
1777  return nreg-1;
1778  }
1779  }
1780  // if here, we are in the box outside of all repetitions
1781  // find the cell we are in
1782  int ix = (int)(x.x*dxi + ax);
1783  if (ix >= nx) {
1784  ix = nx-1;
1785  }
1786  int iy = (int)(x.y*dyi + ay);
1787  if (iy >= ny) {
1788  iy = ny-1;
1789  }
1790  int iz = (int)(x.z*dzi + az);
1791  if (iz >= nz) {
1792  iz = nz-1;
1793  }
1794  int cell = ix + iy*nx + iz*nxy;
1795  //egsWarning("in box: ix=%d iy=%d iz=%d\n",ix,iy,iz);
1796  EGS_Float t_left = t;
1797  EGS_Vector xtmp(x);
1798  EGS_Float ttot = 0;
1799  for (EGS_I64 loopCount=0; loopCount<=loopMax; ++loopCount) {
1800  if (loopCount == loopMax) {
1801  egsFatal("EGS_XYZRepeater::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
1802  return -1;
1803  }
1804  EGS_Float this_t = t_left;
1805  EGS_Vector xp(xtmp - translation[cell]);
1806  int inew = g->howfar(-1,xp,u,this_t,newmed,normal);
1807  //egsWarning("cell=%d tleft=%g xp=(%g,%g,%g) inew=%d this_t=%g\n",
1808  // cell,t_left,xp.x,xp.y,xp.z,inew,this_t);
1809  if (inew >= 0) {
1810  t = ttot + this_t;
1811  return cell*ng + inew;
1812  }
1813  int next_cell = xyz->howfar(cell,xtmp,u,this_t,0,normal);
1814  //egsWarning("next: %d %g\n",next_cell,this_t);
1815  if (next_cell == cell) {
1816  return ireg;
1817  }
1818  if (next_cell < 0) {
1819  t = ttot + this_t;
1820  return -1;
1821  }
1822  ttot += this_t;
1823  t_left -= this_t;
1824  xtmp += u*this_t;
1825  cell = next_cell;
1826  }
1827 
1828  return ireg;
1829  };
1830 
1831  EGS_Float hownear(int ireg, const EGS_Vector &x) {
1832  if (ireg < 0) {
1833  return xyz->hownear(ireg,x);
1834  }
1835  if (ireg < nreg-1) {
1836  int cell = ireg/ng;
1837  int ilocal = ireg - cell*ng;
1838  EGS_Vector xp(x - translation[cell]);
1839  return g->hownear(ilocal,xp);
1840  }
1841  // if here, we are in the box outside of all repetitions
1842  // find the cell we are in
1843  int ix = (int)(x.x*dxi + ax);
1844  if (ix >= nx) {
1845  ix = nx-1;
1846  }
1847  int iy = (int)(x.y*dyi + ay);
1848  if (iy >= ny) {
1849  iy = ny-1;
1850  }
1851  int iz = (int)(x.z*dzi + az);
1852  if (iz >= nz) {
1853  iz = nz-1;
1854  }
1855  int cell = ix + iy*nx + iz*nxy;
1856  EGS_Vector xp(x - translation[cell]);
1857  EGS_Float t = g->hownear(-1,xp);
1858  EGS_Float tcell = xyz->hownear(cell,x);
1859  if (t < tcell) {
1860  return t;
1861  }
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;
1870  EGS_Vector tmp(x-translation[cell1]);
1871  EGS_Float t1 = g->hownear(-1,tmp);
1872  if (t1 < t) {
1873  t = t1;
1874  }
1875  }
1876  }
1877  }
1878  }
1879  }
1880  }
1881  }
1882  return t;
1883  };
1884 
1885  int getMaxStep() const {
1886  return nxyz*(g->getMaxStep() + 1) + 1;
1887  };
1888 
1889  const string &getType() const {
1890  return type;
1891  };
1892 
1893  void printInfo() const;
1894 
1895  void setXYZLabels(EGS_Input *input) {
1896  xyz->setXYZLabels(input);
1897  }
1898 
1899  virtual void getLabelRegions(const string &str, vector<int> &regs);
1900 
1901 protected:
1902 
1903  EGS_XYZGeometry *xyz;
1904  EGS_BaseGeometry *g;
1905  EGS_Vector *translation;
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;
1910 
1911  static string type;
1912 
1913 };
1914 
1915 #endif
1916 
1917 #endif
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.
Definition: egs_functions.h:95
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
EGS_Float y
y-component
Definition: egs_vector.h:61
virtual int getMaxStep() const
Returns the maximum number of steps through the geometry.
A class representing 3D vectors.
Definition: egs_vector.h:56
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.
EGS_I32 imed
medium index
int med
Medium index.
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_Float z
z-component
Definition: egs_vector.h:62
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
virtual void getLabelRegions(const string &str, vector< int > &regs)
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.
Definition: egs_planes.h:166
virtual int computeIntersections(int ireg, int n, const EGS_Vector &x, const EGS_Vector &u, EGS_GeometryIntersections *isections)
Calculates intersection distances to region boundaries.
A deformed XYZ-geometry.
virtual EGS_Float hownear(int ireg, const EGS_Vector &x)=0
Calculate the distance to a boundary for position x in any direction.
An XYZ-geometry.
virtual EGS_Float getRelativeRho(int ireg) const
Get the relative mass density in region ireg.
A geometry repeated on a regular XYZ grid.
EGS_Float x
x-component
Definition: egs_vector.h:60
EGS_I32 ireg
region index
A class modeling a N-dimensional 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
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.