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  if (g[j]) {
565  g[j]->getNextGeom(rndm);
566  }
567  }
568  };
569 
570  void updatePosition(EGS_Float time) {
571  // calls updatePosition on its component geometries to update dynamic
572  // geometries in the simulation
573  for (int j=0; j<N; j++) {
574  if (g[j]) {
575  g[j]->updatePosition(time);
576  }
577  }
578  };
579 
580  void containsDynamic(bool &hasdynamic) {
581  // calls containsDynamic on its component geometries (only calls if
582  // hasDynamic is false, as if it is true we already found one)
583  for (int j=0; j<N; j++) {
584  if (!hasdynamic && g[j]) {
585  g[j]->containsDynamic(hasdynamic);
586  }
587  }
588  };
589 
590  bool hasRhoScaling() override {
591  if (has_rho_scaling) {
592  return has_rho_scaling;
593  }
594 
595  for (int j=0; j<N; j++) {
596  bool hasRS = g[j]->hasRhoScaling();
597  if (hasRS) {
598  has_rho_scaling = hasRS;
599  return has_rho_scaling;
600  }
601  }
602 
603  return false;
604  };
605 
606  void finishInitialization() override {
607  for (int j=0; j<N; j++) {
608  g[j]->finishInitialization();
609  }
610  };
611 
612  const string &getType() const {
613  return type;
614  };
615 
616  void printInfo() const;
617 
618  virtual void getLabelRegions(const string &str, vector<int> &regs, bool sanitize=true);
619  void ndRegions(int r, int dim, int dimk, int k, vector<int> &regs);
620 
621 protected:
622 
623  int N;
625  int *n;
626  static string type;
627  bool ortho;
628 
629  void setup();
630 
637  void setMedia(EGS_Input *inp, int nmed, const int *med_ind);
638 
639 private:
640 
641  void setM(int ib, int idim, const vector<int> &ranges, int medium);
642 };
643 
644 #ifdef EXPLICIT_XYZ
645 #include "../egs_planes/egs_planes.h"
646 
794 class EGS_NDG_EXPORT EGS_XYZGeometry : public EGS_BaseGeometry {
795 
796 public:
797 
799  const string &Name = "");
800 
801  ~EGS_XYZGeometry();
802 
803  int medIndex(char medium);
804 
805  bool isInside(const EGS_Vector &x) {
806  if (!xp->isInside(x)) {
807  return false;
808  }
809  if (!yp->isInside(x)) {
810  return false;
811  }
812  if (!zp->isInside(x)) {
813  return false;
814  }
815  return true;
816  };
817 
818  int isWhere(const EGS_Vector &x) {
819  int ix = xp->isWhere(x);
820  if (ix < 0) {
821  return ix;
822  }
823  int iy = yp->isWhere(x);
824  if (iy < 0) {
825  return iy;
826  }
827  int iz = zp->isWhere(x);
828  if (iz < 0) {
829  return iz;
830  }
831  return ix + iy*nx + iz*nxy;
832  };
833 
834  int inside(const EGS_Vector &x) {
835  return isWhere(x);
836  };
837 
838  int computeIntersections(int ireg, int n, const EGS_Vector &X,
839  const EGS_Vector &u, EGS_GeometryIntersections *isections) {
840  if (n < 1) {
841  return -1;
842  }
843  int ifirst = 0;
844  EGS_Float t, t_ini = 0;
845  EGS_Vector x(X);
846  int imed;
847  if (ireg < 0) {
848  t = veryFar;
849  ireg = howfar(ireg,x,u,t,&imed);
850  if (ireg < 0) {
851  return 0;
852  }
853  isections[0].t = t;
854  isections[0].rhof = 1;
855  isections[0].ireg = -1;
856  isections[0].imed = -1;
857  t_ini = t;
858  ++ifirst;
859  x += u*t;
860  }
861  else {
862  imed = medium(ireg);
863  }
864  EGS_Float *px = xp->getPositions(),
865  *py = yp->getPositions(),
866  *pz = zp->getPositions();
867  int iz = ireg/nxy;
868  int ir = ireg - iz*nxy;
869  int iy = ir/nx;
870  int ix = ir - iy*nx;
871  EGS_Float uxi, uyi, uzi, nextx, nexty, nextz;
872  int dirx, icx, diry, icy, dirz, icz;
873  if (u.x > 0) {
874  uxi = 1/u.x;
875  dirx = 1;
876  icx = 1;
877  }
878  else if (u.x < 0) {
879  uxi = 1/u.x;
880  dirx = -1;
881  icx = 0;
882  }
883  else {
884  uxi = veryFar*1e3;
885  dirx = 1;
886  icx = 1;
887  }
888  if (u.y > 0) {
889  uyi = 1/u.y;
890  diry = 1;
891  icy = 1;
892  }
893  else if (u.y < 0) {
894  uyi = 1/u.y;
895  diry = -1;
896  icy = 0;
897  }
898  else {
899  uyi = veryFar*1e3;
900  diry = 1;
901  icy = 1;
902  }
903  if (u.z > 0) {
904  uzi = 1/u.z;
905  dirz = 1;
906  icz = 1;
907  }
908  else if (u.z < 0) {
909  uzi = 1/u.z;
910  dirz = -1;
911  icz = 0;
912  }
913  else {
914  uzi = veryFar*1e3;
915  dirz = 1;
916  icz = 1;
917  }
918  nextx = (px[ix+icx] - x.x)*uxi + t_ini;
919  nexty = (py[iy+icy] - x.y)*uyi + t_ini;
920  nextz = (pz[iz+icz] - x.z)*uzi + t_ini;
921  for (int j=ifirst; j<n; j++) {
922  isections[j].imed = imed;
923  isections[j].ireg = ireg;
924  isections[j].rhof = getRelativeRho(ireg);
925  int inew;
926  if (nextx < nexty && nextx < nextz) {
927  t = nextx;
928  ix += dirx;
929  if (ix < 0 || ix >= nx) {
930  inew = -1;
931  }
932  else {
933  inew = ireg + dirx;
934  nextx = (px[ix+icx] - x.x)*uxi + t_ini;
935  }
936  }
937  else if (nexty < nextz) {
938  t = nexty;
939  iy += diry;
940  if (iy < 0 || iy >= ny) {
941  inew = -1;
942  }
943  else {
944  inew = ireg + nx*diry;
945  nexty = (py[iy+icy] - x.y)*uyi + t_ini;
946  }
947  }
948  else {
949  t = nextz;
950  iz += dirz;
951  if (iz < 0 || iz >= nz) {
952  inew = -1;
953  }
954  else {
955  inew = ireg + nxy*dirz;
956  nextz = (pz[iz+icz] - x.z)*uzi + t_ini;
957  }
958  }
959  isections[j].t = t;
960  if (inew < 0) {
961  return j+1;
962  }
963  ireg = inew;
964  imed = medium(ireg);
965  }
966  return ireg >= 0 ? -1 : n;
967  };
968 
969  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
970  const EGS_Vector &u) {
971  if (ireg < 0) {
972  return 0;
973  }
974  int iz = ireg/nxy;
975  int ir = ireg - iz*nxy;
976  int iy = ir/nx;
977  int ix = ir - iy*nx;
978  EGS_Float d = xp->howfarToOutside(ix,x,u);
979  EGS_Float ty = yp->howfarToOutside(iy,x,u);
980  if (ty < d) {
981  d = ty;
982  }
983  EGS_Float tz = zp->howfarToOutside(iz,x,u);
984  if (tz < d) {
985  d = tz;
986  }
987  return d;
988  };
989 
990  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
991  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
992  if (ireg >= 0) {
993  int iz = ireg/nxy;
994  int ir = ireg - iz*nxy;
995  int iy = ir/nx;
996  int ix = ir - iy*nx;
997  int inew = ireg;
998  if (u.x > 0) {
999  EGS_Float d = (xpos[ix+1]-x.x)/u.x;
1000  if (d <= t) {
1001  if (d <= boundaryTolerance) {
1002  // t=0 works on most cases but can result in
1003  // getting stuck on an edge, so use boundaryTolerance
1004  t = halfBoundaryTolerance;
1005  }
1006  else {
1007  t = d;
1008  }
1009  if ((++ix) < nx) {
1010  inew = ireg + 1;
1011  }
1012  else {
1013  inew = -1;
1014  }
1015  if (normal) {
1016  *normal = EGS_Vector(-1,0,0);
1017  }
1018  }
1019  }
1020  else if (u.x < 0) {
1021  EGS_Float d = (xpos[ix]-x.x)/u.x;
1022  if (d <= t) {
1023  if (d <= boundaryTolerance) {
1024  t = halfBoundaryTolerance;
1025  }
1026  else {
1027  t = d;
1028  }
1029  if ((--ix) >= 0) {
1030  inew = ireg - 1;
1031  }
1032  else {
1033  inew = -1;
1034  }
1035  if (normal) {
1036  *normal = EGS_Vector(1,0,0);
1037  }
1038  }
1039  }
1040  if (u.y > 0) {
1041  EGS_Float d = (ypos[iy+1]-x.y)/u.y;
1042  if (d <= t) {
1043  if (d <= boundaryTolerance) {
1044  t = halfBoundaryTolerance;
1045  }
1046  else {
1047  t = d;
1048  }
1049  if ((++iy) < ny) {
1050  inew = ireg + nx;
1051  }
1052  else {
1053  inew = -1;
1054  }
1055  if (normal) {
1056  *normal = EGS_Vector(0,-1,0);
1057  }
1058  }
1059  }
1060  else if (u.y < 0) {
1061  EGS_Float d = (ypos[iy]-x.y)/u.y;
1062  if (d <= t) {
1063  if (d <= boundaryTolerance) {
1064  t = halfBoundaryTolerance;
1065  }
1066  else {
1067  t = d;
1068  }
1069  if ((--iy) >= 0) {
1070  inew = ireg - nx;
1071  }
1072  else {
1073  inew = -1;
1074  }
1075  if (normal) {
1076  *normal = EGS_Vector(0,1,0);
1077  }
1078  }
1079  }
1080  if (u.z > 0) {
1081  EGS_Float d = (zpos[iz+1]-x.z)/u.z;
1082  if (d <= t) {
1083  if (d <= boundaryTolerance) {
1084  t = halfBoundaryTolerance;
1085  }
1086  else {
1087  t = d;
1088  }
1089  if ((++iz) < nz) {
1090  inew = ireg+nxy;
1091  }
1092  else {
1093  inew = -1;
1094  }
1095  if (normal) {
1096  *normal = EGS_Vector(0,0,-1);
1097  }
1098  }
1099  }
1100  else if (u.z < 0) {
1101  EGS_Float d = (zpos[iz]-x.z)/u.z;
1102  if (d <= t) {
1103  if (d <= boundaryTolerance) {
1104  t = halfBoundaryTolerance;
1105  }
1106  else {
1107  t = d;
1108  }
1109  if ((--iz) >= 0) {
1110  inew = ireg-nxy;
1111  }
1112  else {
1113  inew = -1;
1114  }
1115  if (normal) {
1116  *normal = EGS_Vector(0,0,1);
1117  }
1118  }
1119  }
1120  if (newmed && inew >= 0) {
1121  *newmed = medium(inew);
1122  }
1123  return inew;
1124  }
1125  int face,ix,iy,iz;
1126  int inew = howfarFromOut(x,u,t,ix,iy,iz,face,normal);
1127  if (inew >= 0 && newmed) {
1128  *newmed = medium(inew);
1129  }
1130  return inew;
1131  };
1132 
1133  EGS_Float hownear(int ireg, const EGS_Vector &x) {
1134  if (ireg >= 0) {
1135  int iz = ireg/nxy;
1136  int ir = ireg - iz*nxy;
1137  int iy = ir/nx;
1138  int ix = ir - iy*nx;
1139  EGS_Float t = xp->hownear(ix,x);
1140  EGS_Float t1 = yp->hownear(iy,x);
1141  if (t1 < t) {
1142  t = t1;
1143  }
1144  t1 = zp->hownear(iz,x);
1145  if (t1 < t) {
1146  t = t1;
1147  }
1148  return t;
1149  }
1150  int nc = 0;
1151  EGS_Float s1=0, s2=0;
1152  if (!xp->isInside(x)) {
1153  EGS_Float t = xp->hownear(-1,x);
1154  nc++;
1155  s1 += t;
1156  s2 += t*t;
1157  }
1158  if (!yp->isInside(x)) {
1159  EGS_Float t = yp->hownear(-1,x);
1160  nc++;
1161  s1 += t;
1162  s2 += t*t;
1163  }
1164  if (!zp->isInside(x)) {
1165  EGS_Float t = zp->hownear(-1,x);
1166  nc++;
1167  s1 += t;
1168  s2 += t*t;
1169  }
1170  if (nc == 1) {
1171  return s1;
1172  }
1173  return sqrt(s2);
1174  };
1175 
1176 
1177  EGS_Float getVolume(int ireg) {
1178  int iz = ireg/nxy;
1179  int ir = ireg - iz*nxy;
1180  int iy = ir/nx;
1181  int ix = ir - iy*nx;
1182  return (xpos[ix+1]-xpos[ix])*(ypos[iy+1]-ypos[iy])*(zpos[iz+1]-zpos[iz]);
1183  }
1184 
1185  EGS_Float getBound(int idir, int ind) {
1186  EGS_Float bound;
1187  if (idir == 0) {
1188  if (ind>=0 && ind<=nx) {
1189  bound = xpos[ind];
1190  }
1191  else {
1192  egsWarning("Error in getBound: Looking for X bound out of range %d\n"
1193  "Will set this to zero.\n",ind);
1194  bound = 0.0;
1195  }
1196  }
1197  else if (idir == 1) {
1198  if (ind>=0 && ind<=ny) {
1199  bound = ypos[ind];
1200  }
1201  else {
1202  egsWarning("Error in getBound: Looking for Y bound out of range %d\n"
1203  "Will set this to zero.\n",ind);
1204  bound = 0.0;
1205  }
1206  }
1207  else if (idir == 2) {
1208  if (ind>=0 && ind<=nz) {
1209  bound = zpos[ind];
1210  }
1211  else {
1212  egsWarning("Error in getBound: Looking for Z bound out of range %d\n"
1213  "Will set this to zero.\n",ind);
1214  bound = 0.0;
1215  }
1216  }
1217  else {
1218  egsWarning("Error in getBound: Dimension %d undefined in EGS_XYZGeometry.\n",idir);
1219  bound = 0.0;
1220  }
1221  return bound;
1222  }
1223 
1224  int getNRegDir(int idir) {
1225  if (idir==0) {
1226  return nx;
1227  }
1228  else if (idir==1) {
1229  return ny;
1230  }
1231  else if (idir==2) {
1232  return nz;
1233  }
1234  else {
1235  egsWarning("Error in getNregDir: Dimension %d undefined in EGS_XYZGeometry.\n",
1236  idir);
1237  return 0;
1238  }
1239  }
1240 
1241 
1242  int getMaxStep() const {
1243  return nx+ny+nz+1;
1244  };
1245 
1246  int getNx() const {
1247  return nx;
1248  };
1249  int getNy() const {
1250  return ny;
1251  };
1252  int getNz() const {
1253  return nz;
1254  };
1255 
1256  EGS_Float *getXPositions() {
1257  return xp->getPositions();
1258  };
1259  EGS_Float *getYPositions() {
1260  return yp->getPositions();
1261  };
1262  EGS_Float *getZPositions() {
1263  return zp->getPositions();
1264  };
1265 
1266  static int getDigits(int i);
1267 
1268  const string &getType() const {
1269  return type;
1270  };
1271 
1272  void printInfo() const;
1273 
1274  static EGS_XYZGeometry *constructGeometry(const char *dens_or_egphant_file,
1275  const char *ramp_file, int dens_or_egphant=0);
1276  static EGS_XYZGeometry *constructCTGeometry(const char *dens_or_egphant_file);
1277 
1278  void voxelizeGeometry(EGS_Input *input);
1279 
1280  void setXYZLabels(EGS_Input *input);
1281 
1282  virtual void getLabelRegions(const string &str, vector<int> &regs, bool sanitize=true);
1283  void getXLabelRegions(const string &str, vector<int> &regs, bool sanitize=true) {
1284  xp->getLabelRegions(str, regs, sanitize);
1285  }
1286  void getYLabelRegions(const string &str, vector<int> &regs, bool sanitize=true) {
1287  yp->getLabelRegions(str, regs, sanitize);
1288  }
1289  void getZLabelRegions(const string &str, vector<int> &regs, bool sanitize=true) {
1290  zp->getLabelRegions(str, regs, sanitize);
1291  }
1292 
1293  void finishInitialization();
1294 
1295 protected:
1296 
1297  EGS_PlanesX *xp;
1298  EGS_PlanesY *yp;
1299  EGS_PlanesZ *zp;
1300  EGS_Float *xpos;
1301  EGS_Float *ypos;
1302  EGS_Float *zpos;
1303  int nx, ny, nz, nxy;
1304  static string type;
1305 
1306  void setup();
1307 
1308  void setMedia(EGS_Input *inp, int nmed, const int *med_ind);
1309 
1310  int howfarFromOut(const EGS_Vector &x, const EGS_Vector &u,
1311  EGS_Float &t, int &ix, int &iy, int &iz,
1312  int &face, EGS_Vector *normal=0) {
1313  ix = -1;
1314  EGS_Float t1;
1315  if (x.x <= xpos[0] && u.x > 0) {
1316  t1 = (xpos[0]-x.x)/u.x;
1317  ix = 0;
1318  face = 0;
1319  }
1320  else if (x.x >= xpos[nx] && u.x < 0) {
1321  t1 = (xpos[nx]-x.x)/u.x;
1322  ix = nx-1;
1323  face = 1;
1324  }
1325  if (ix >= 0 && t1 <= t) {
1326  EGS_Vector tmp(x + u*t1);
1327  iy = yp->isWhere(tmp);
1328  if (iy >= 0) {
1329  iz = zp->isWhere(tmp);
1330  if (iz >= 0) {
1331  int inew = ix + iy*nx + iz*nxy;
1332  if (t1 < boundaryTolerance) {
1333  int itest = howfar(inew, tmp, u, t1);
1334  if (itest == -1 && t1 < boundaryTolerance) {
1335  return -1;
1336  }
1337  }
1338  if (normal) *normal = face == 0 ? EGS_Vector(-1,0,0) :
1339  EGS_Vector(1,0,0);
1340  t = t1;
1341  return inew;
1342  }
1343  }
1344  }
1345  iy = -1;
1346  if (x.y <= ypos[0] && u.y > 0) {
1347  t1 = (ypos[0]-x.y)/u.y;
1348  iy = 0;
1349  face = 2;
1350  }
1351  else if (x.y >= ypos[ny] && u.y < 0) {
1352  t1 = (ypos[ny]-x.y)/u.y;
1353  iy = ny-1;
1354  face = 3;
1355  }
1356  if (iy >= 0 && t1 <= t) {
1357  EGS_Vector tmp(x + u*t1);
1358  ix = xp->isWhere(tmp);
1359  if (ix >= 0) {
1360  iz = zp->isWhere(tmp);
1361  if (iz >= 0) {
1362  int inew = ix + iy*nx + iz*nxy;
1363  if (t1 < boundaryTolerance) {
1364  int itest = howfar(inew, tmp, u, t1);
1365  if (itest == -1 && t1 < boundaryTolerance) {
1366  return -1;
1367  }
1368  }
1369  if (normal) *normal = face == 2 ? EGS_Vector(0,-1,0) :
1370  EGS_Vector(0, 1,0);
1371  t = t1;
1372  return inew;
1373  }
1374  }
1375  }
1376  iz = -1;
1377  if (x.z <= zpos[0] && u.z > 0) {
1378  t1 = (zpos[0]-x.z)/u.z;
1379  iz = 0;
1380  face = 4;
1381  }
1382  else if (x.z >= zpos[nz] && u.z < 0) {
1383  t1 = (zpos[nz]-x.z)/u.z;
1384  iz = nz-1;
1385  face = 5;
1386  }
1387  if (iz >= 0 && t1 <= t) {
1388  EGS_Vector tmp(x + u*t1);
1389  ix = xp->isWhere(tmp);
1390  if (ix >= 0) {
1391  iy = yp->isWhere(tmp);
1392  if (iy >= 0) {
1393  int inew = ix + iy*nx + iz*nxy;
1394  if (t1 < boundaryTolerance) {
1395  int itest = howfar(inew, tmp, u, t1);
1396  if (itest == -1 && t1 < boundaryTolerance) {
1397  return -1;
1398  }
1399  }
1400  if (normal) *normal = face == 4 ? EGS_Vector(0,0,-1) :
1401  EGS_Vector(0,0, 1);
1402  t = t1;
1403  return inew;
1404  }
1405  }
1406  }
1407  return -1;
1408  };
1409 
1410 public:
1411  string dens_file;
1412  int dens_or_egsphant_or_interfile;
1413  bool useEgsphantDensities;
1414 };
1415 
1430 class EGS_NDG_EXPORT EGS_DeformedXYZ : public EGS_XYZGeometry {
1431 
1432 public:
1433 
1435  const char *defFile, const string &Name = "");
1436 
1437  ~EGS_DeformedXYZ();
1438 
1439  int isWhere(const EGS_Vector &x) {
1440  int ireg = EGS_XYZGeometry::isWhere(x);
1441  if (ireg >= 0) egsFatal("EGS_DeformedXYZ::isWhere(): this geometry "
1442  "does not allow the use of this method with position inside\n");
1443  return ireg;
1444  };
1445 
1446  int inside(const EGS_Vector &x) {
1447  return isWhere(x);
1448  };
1449 
1450  int medium(int ireg) const {
1451  return EGS_XYZGeometry::medium(ireg/6);
1452  };
1453 
1454  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
1455  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
1456  if (ireg >= 0) {
1457  int ir = ireg/6, tetra = ireg - 6*ir, tetra4 = 4*tetra;
1458  int ind[3];
1459  ind[2] = ir/nxy;
1460  ind[1] = (ir - ind[2]*nxy)/nx;
1461  ind[0] = ir - ind[2]*nxy - ind[1]*nx;
1462  int edge = ir + ind[1] + ind[2]*nxyp1;
1463  EGS_Vector n0(vectors[edge+tnodes[tetra4]]),
1464  n1(vectors[edge+tnodes[tetra4+1]]-n0),
1465  n2(vectors[edge+tnodes[tetra4+2]]-n0),
1466  n3(vectors[edge+tnodes[tetra4+3]]-n0);
1467  EGS_Vector n0x(n0-x);
1468  EGS_Float disti[4],dpi[4];
1469  EGS_Vector normvec;
1470  normvec = n1%n2;
1471  dpi[0]=normvec*u;
1472  disti[0]=normvec*n0x;
1473  normvec = n3%n1;
1474  dpi[2]=normvec*u;
1475  disti[2]=normvec*n0x;
1476  normvec = n2%n3;
1477  dpi[1]=normvec*u;
1478  disti[1]=normvec*n0x;
1479  normvec = (n3-n1)%(n2-n1);
1480  dpi[3] = normvec*u;
1481  disti[3] = normvec*(n0x+n1);
1482  int nextplane = 4;
1483  EGS_Float mindist = t, mindp=1;
1484  for (int i=0; i<4; ++i) {
1485  if (dpi[i] > 0 && disti[i]*mindp < mindist*dpi[i]) {
1486  mindist = disti[i];
1487  mindp=dpi[i];
1488  nextplane=i;
1489  }
1490  }
1491  if (nextplane == 4) {
1492  return ireg;
1493  }
1494  t = mindist/mindp;
1495  int j = 12*tetra + 3*nextplane;
1496  int next = tetra_data[j];
1497  int irnew = ir;
1498  if (next >= 0) {
1499  ind[next] += tetra_data[j+1];
1500  if (ind[next] < 0 || ind[next] >= np[next]) {
1501  return -1;
1502  }
1503  irnew = ind[0] + ind[1]*nx + ind[2]*nxy;
1504  }
1505  if (newmed) {
1506  *newmed = EGS_XYZGeometry::medium(irnew);
1507  }
1508  if (normal) {
1509  switch (nextplane) {
1510  case 0:
1511  *normal = n2%n1;
1512  break;
1513  case 1:
1514  *normal = n1%n3;
1515  break;
1516  case 2:
1517  *normal = n3%n2;
1518  break;
1519  case 3:
1520  *normal = (n2-n1)%(n3-n1);
1521  }
1522  }
1523  return 6*irnew + tetra_data[j+2];
1524  }
1525  int ix,iy,iz,face;
1526  int inew = howfarFromOut(x,u,t,ix,iy,iz,face,normal);
1527  if (inew < 0) {
1528  return inew;
1529  }
1530  if (newmed) {
1531  *newmed = EGS_XYZGeometry::medium(inew);
1532  }
1533  // need to determine the tetrahedron we are entering.
1534  int edge = inew + iy + iz*nxyp1;
1535  EGS_Vector tmp(x + u*t);
1536  int tetra1 = enter_tetra1[face], plane1 = enter_plane1[face];
1537  int node1 = tnodes[4*tetra1 + plane_order[3*plane1]],
1538  node2 = tnodes[4*tetra1 + plane_order[3*plane1+1]],
1539  node3 = tnodes[4*tetra1 + plane_order[3*plane1+2]];
1540  if (inTriangle(vectors[edge+node1],vectors[edge+node2],
1541  vectors[edge+node3],tmp)) {
1542  return 6*inew + tetra1;
1543  }
1544  int tetra2 = enter_tetra2[face], plane2 = enter_plane2[face];
1545  int node1a = tnodes[4*tetra2 + plane_order[3*plane2]],
1546  node2a = tnodes[4*tetra2 + plane_order[3*plane2+1]],
1547  node3a = tnodes[4*tetra2 + plane_order[3*plane2+2]];
1548  if (inTriangle(vectors[edge+node1a],vectors[edge+node2a],
1549  vectors[edge+node3a],tmp)) {
1550  return 6*inew + tetra2;
1551  }
1552  // roundoff problem
1553  egsWarning("deformed geometry: entering from face %d but inTriangle()"
1554  " fails for both triangles\n",face);
1555  egsWarning("x_enter=(%16.10f,%16.10f,%16.10f)\n",tmp.x,tmp.y,tmp.z);
1556  return -1;
1557  };
1558 
1559  EGS_Float hownear(int ireg, const EGS_Vector &x) {
1560  if (ireg < 0) {
1561  return EGS_XYZGeometry::hownear(ireg,x);
1562  }
1563  int ir = ireg/6, tetra = ireg - 6*ir, tetra4 = 4*tetra;
1564  int ind[3];
1565  ind[2] = ir/nxy;
1566  ind[1] = (ir - ind[2]*nxy)/nx;
1567  ind[0] = ir - ind[2]*nxy - ind[1]*nx;
1568  int edge = ir + ind[1] + ind[2]*nxyp1;
1569  EGS_Vector n0(vectors[edge+tnodes[tetra4]]),
1570  n1(vectors[edge+tnodes[tetra4+1]]-n0),
1571  n2(vectors[edge+tnodes[tetra4+2]]-n0),
1572  n3(vectors[edge+tnodes[tetra4+3]]-n0);
1573  EGS_Vector n0x(n0-x);
1574  EGS_Float disti[4],dpi[4];
1575  EGS_Vector normvec;
1576  normvec = n1%n2;
1577  dpi[0]=normvec.length2();
1578  disti[0]=normvec*n0x;
1579  normvec = n3%n1;
1580  dpi[2]=normvec.length2();
1581  disti[2]=normvec*n0x;
1582  normvec = n2%n3;
1583  dpi[1]=normvec.length2();
1584  disti[1]=normvec*n0x;
1585  normvec = (n3-n1)%(n2-n1);
1586  dpi[3] = normvec.length2();
1587  disti[3] = normvec*(n0x+n1);
1588  EGS_Float mindist = veryFar, mindp=1;
1589  for (int i=0; i<4; ++i) {
1590  if (disti[i]*mindp < mindist*dpi[i]) {
1591  mindist = disti[i];
1592  mindp=dpi[i];
1593  }
1594  }
1595  return mindist/mindp;
1596  };
1597 
1598  int computeIntersections(int ireg, int n, const EGS_Vector &X,
1599  const EGS_Vector &u, EGS_GeometryIntersections *isections) {
1600  return EGS_BaseGeometry::computeIntersections(ireg,n,X,u,isections);
1601  };
1602 
1603  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
1604  const EGS_Vector &u) {
1605  if (ireg < 0) {
1606  return 0;
1607  }
1608  int ir = ireg/6;
1609  int iz = ir/nxy;
1610  int ir1 = ir - iz*nxy;
1611  int iy = ir1/nx;
1612  int ix = ir1 - iy*nx;
1613  EGS_Float d = xp->howfarToOutside(ix,x,u);
1614  EGS_Float ty = yp->howfarToOutside(iy,x,u);
1615  if (ty < d) {
1616  d = ty;
1617  }
1618  EGS_Float tz = zp->howfarToOutside(iz,x,u);
1619  if (tz < d) {
1620  d = tz;
1621  }
1622  return d;
1623  };
1624 
1625  int getMaxStep() const {
1626  return 6*(nx+ny+nz) + 1;
1627  };
1628 
1629  const string &getType() const {
1630  return def_type;
1631  };
1632 
1633  void printInfo() const {};
1634 
1646  int setDeformations(const char *defFile);
1647 
1648  bool inTriangle(const EGS_Vector &n0, const EGS_Vector &n1,
1649  const EGS_Vector &n2, const EGS_Vector &x) {
1650  EGS_Vector u1(n1-n0), u2(n2-n0), xp(x-n0);
1651  EGS_Float a=u1.length2(), b=u1*u2, c=u2.length2(), b1=xp*u1, b2=xp*u2;
1652  EGS_Float D=a*c-b*b;
1653  EGS_Float u=b1*c-b2*b;
1654  if (u<0||u>D) {
1655  return false;
1656  }
1657  EGS_Float v=b2*a-b1*b;
1658  if (v<0||u+v>D) {
1659  return false;
1660  }
1661  return true;
1662  };
1663 
1664 protected:
1665 
1666  EGS_Vector *vectors;
1667 
1668  int tnodes[24];
1669 
1670  int np[3];
1671 
1672  int nxyp1;
1673 
1674  static string def_type;
1675 
1676  static char tetrahedra[];
1677 
1678  static char plane_order[];
1679 
1680  static char tetra_data[];
1681 
1682  static char enter_tetra1[];
1683  static char enter_plane1[];
1684  static char enter_tetra2[];
1685  static char enter_plane2[];
1686 
1687 
1688 };
1689 
1761 class EGS_NDG_EXPORT EGS_XYZRepeater : public EGS_BaseGeometry {
1762 
1763 public:
1764 
1765  EGS_XYZRepeater(EGS_Float Xmin, EGS_Float Xmax,
1766  EGS_Float Ymin, EGS_Float Ymax,
1767  EGS_Float Zmin, EGS_Float Zmax,
1768  int Nx, int Ny, int Nz, EGS_BaseGeometry *G,
1769  const string &Name = "");
1770 
1771  ~EGS_XYZRepeater();
1772 
1773  int isWhere(const EGS_Vector &x) {
1774  int cell = xyz->isWhere(x);
1775  //egsWarning("isInside(%g,%g,%g): cell=%d\n",x.x,x.y,x.z,cell);
1776  if (cell < 0) {
1777  return cell;
1778  }
1779  EGS_Vector xp(x - translation[cell]);
1780  int ir = g->isWhere(xp);
1781  //egsWarning("xp=(%g,%g,%g) ir=%d\n",xp.x,xp.y,xp.z,ir);
1782  return ir >= 0 ? cell*ng + ir : nreg-1;
1783  };
1784 
1785  bool isInside(const EGS_Vector &x) {
1786  return xyz->isInside(x);
1787  };
1788 
1789  int inside(const EGS_Vector &x) {
1790  return isWhere(x);
1791  };
1792 
1793  int medium(int ireg) const {
1794  if (ireg == nreg-1) {
1795  return med;
1796  }
1797  int cell = ireg/ng;
1798  int ilocal = ireg - ng*cell;
1799  return g->medium(ilocal);
1800  };
1801 
1802  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
1803  const EGS_Vector &u) {
1804  if (ireg < 0) {
1805  return 0;
1806  }
1807  return xyz->howfarToOutside(0,x,u);
1808  };
1809 
1810  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
1811  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
1812  //egsWarning("\n***howfar(reg=%d,x=(%g,%g,%g),u=(%g,%g,%g),t=%g)\n",
1813  // ireg,x.x,x.y,x.z,u.x,u.y,u.z,t);
1814  if (ireg < 0) {
1815  // outside of the box.
1816  int cell = xyz->howfar(ireg,x,u,t,0,normal);
1817  //egsWarning("entering: cell=%d t=%g\n",cell,t);
1818  if (cell >= 0) {
1819  if (newmed) {
1820  *newmed = med;
1821  }
1822  return nreg-1;
1823  }
1824  return -1;
1825  }
1826  if (ireg >= 0) {
1827  if (ireg < nreg-1) { // in one of the repetitions
1828  int cell = ireg/ng;
1829  int ilocal = ireg - cell*ng;
1830  EGS_Vector xp(x - translation[cell]);
1831  int inew = g->howfar(ilocal,xp,u,t,newmed,normal);
1832  //egsWarning("cell=%d il=%d inew=%d t=%g xp=(%g,%g,%g)\n",
1833  // cell,ilocal,inew,t,xp.x,xp.y,xp.z);
1834  if (inew >= 0) {
1835  return cell*ng + inew;
1836  }
1837  if (newmed) {
1838  *newmed = med;
1839  }
1840  return nreg-1;
1841  }
1842  }
1843  // if here, we are in the box outside of all repetitions
1844  // find the cell we are in
1845  int ix = (int)(x.x*dxi + ax);
1846  if (ix >= nx) {
1847  ix = nx-1;
1848  }
1849  int iy = (int)(x.y*dyi + ay);
1850  if (iy >= ny) {
1851  iy = ny-1;
1852  }
1853  int iz = (int)(x.z*dzi + az);
1854  if (iz >= nz) {
1855  iz = nz-1;
1856  }
1857  int cell = ix + iy*nx + iz*nxy;
1858  //egsWarning("in box: ix=%d iy=%d iz=%d\n",ix,iy,iz);
1859  EGS_Float t_left = t;
1860  EGS_Vector xtmp(x);
1861  EGS_Float ttot = 0;
1862  for (EGS_I64 loopCount=0; loopCount<=loopMax; ++loopCount) {
1863  if (loopCount == loopMax) {
1864  egsFatal("EGS_XYZRepeater::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
1865  return -1;
1866  }
1867  EGS_Float this_t = t_left;
1868  EGS_Vector xp(xtmp - translation[cell]);
1869  int inew = g->howfar(-1,xp,u,this_t,newmed,normal);
1870  //egsWarning("cell=%d tleft=%g xp=(%g,%g,%g) inew=%d this_t=%g\n",
1871  // cell,t_left,xp.x,xp.y,xp.z,inew,this_t);
1872  if (inew >= 0) {
1873  t = ttot + this_t;
1874  return cell*ng + inew;
1875  }
1876  int next_cell = xyz->howfar(cell,xtmp,u,this_t,0,normal);
1877  //egsWarning("next: %d %g\n",next_cell,this_t);
1878  if (next_cell == cell) {
1879  return ireg;
1880  }
1881  if (next_cell < 0) {
1882  t = ttot + this_t;
1883  return -1;
1884  }
1885  ttot += this_t;
1886  t_left -= this_t;
1887  xtmp += u*this_t;
1888  cell = next_cell;
1889  }
1890 
1891  return ireg;
1892  };
1893 
1894  EGS_Float hownear(int ireg, const EGS_Vector &x) {
1895  if (ireg < 0) {
1896  return xyz->hownear(ireg,x);
1897  }
1898  if (ireg < nreg-1) {
1899  int cell = ireg/ng;
1900  int ilocal = ireg - cell*ng;
1901  EGS_Vector xp(x - translation[cell]);
1902  return g->hownear(ilocal,xp);
1903  }
1904  // if here, we are in the box outside of all repetitions
1905  // find the cell we are in
1906  int ix = (int)(x.x*dxi + ax);
1907  if (ix >= nx) {
1908  ix = nx-1;
1909  }
1910  int iy = (int)(x.y*dyi + ay);
1911  if (iy >= ny) {
1912  iy = ny-1;
1913  }
1914  int iz = (int)(x.z*dzi + az);
1915  if (iz >= nz) {
1916  iz = nz-1;
1917  }
1918  int cell = ix + iy*nx + iz*nxy;
1919  EGS_Vector xp(x - translation[cell]);
1920  EGS_Float t = g->hownear(-1,xp);
1921  EGS_Float tcell = xyz->hownear(cell,x);
1922  if (t < tcell) {
1923  return t;
1924  }
1925  for (int iix=ix-1; iix<=ix+1; ++iix) {
1926  if (iix >= 0 && iix < nx) {
1927  for (int iiy=iy-1; iiy<=iy+1; ++iiy) {
1928  if (iiy >= 0 && iiy < ny) {
1929  for (int iiz=iz-1; iiz<=iz+1; ++iiz) {
1930  if (iiz >= 0 && iiz < nz) {
1931  if (iix != ix || iiy != iy || iiz != iz) {
1932  int cell1 = iix+iiy*nx+iiz*nxy;
1933  EGS_Vector tmp(x-translation[cell1]);
1934  EGS_Float t1 = g->hownear(-1,tmp);
1935  if (t1 < t) {
1936  t = t1;
1937  }
1938  }
1939  }
1940  }
1941  }
1942  }
1943  }
1944  }
1945  return t;
1946  };
1947 
1948  int getMaxStep() const {
1949  return nxyz*(g->getMaxStep() + 1) + 1;
1950  };
1951 
1952  const string &getType() const {
1953  return type;
1954  };
1955 
1956  void printInfo() const;
1957 
1958  void setXYZLabels(EGS_Input *input) {
1959  xyz->setXYZLabels(input);
1960  }
1961 
1962  virtual void getLabelRegions(const string &str, vector<int> &regs, bool sanitize=true);
1963 
1964 protected:
1965 
1966  EGS_XYZGeometry *xyz;
1967  EGS_BaseGeometry *g;
1968  EGS_Vector *translation;
1969  EGS_Float dx, dxi, ax;
1970  EGS_Float dy, dyi, ay;
1971  EGS_Float dz, dzi, az;
1972  int nx, ny, nz, nxy, nxyz, ng;
1973 
1974  static string type;
1975 
1976 };
1977 
1978 #endif
1979 
1980 #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 int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u, EGS_Float &t, int *newmed=0, EGS_Vector *normal=0)=0
Calculate the distance to a boundary from x along the direction u.
bool has_rho_scaling
Does this geometry have relative mass density scvaling?
virtual EGS_Float getVolume(int ireg)
Calculates the volume of region ireg.
virtual bool hasRhoScaling()
Does this geometry object have a mass density scaling feature?
virtual bool isInside(const EGS_Vector &x)=0
Is the position x inside the geometry?
virtual EGS_Float getRelativeRho(int ireg) const
Get the relative mass density in region ireg.
bool isConvex() const
Is the geometry convex?
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 void getLabelRegions(const string &str, vector< int > &regs, bool sanitize=true)
Get the list of all regions labeled with str.
virtual int isWhere(const EGS_Vector &x)=0
In which region is poisition x?
A 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:90
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