EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_lattice.h
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ lattice geometry headers
5 # Copyright (C) 2019 Rowan Thomson and Martin Martinov
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: Martin Martinov, 2019
25 #
26 # Contributors: Frederic Tessier
27 # Ernesto Mainegra-Hing
28 #
29 ###############################################################################
30 #
31 # When egs_lattice is used for publications, please cite the following paper:
32 #
33 # Martinov, Martin P., and Rowan M. Thomson. Taking EGSnrc to new lows:
34 # Development of egs++ lattice geometry and testing with microscopic
35 # geometries. Medical Physics 47, 3225-3232 (2020).
36 #
37 ###############################################################################
38 */
39 
40 
45 #include "egs_base_geometry.h"
46 #include "../egs_gtransformed/egs_gtransformed.h"
47 
48 #ifndef EGS_LATTICE_GEOMETRY_
49 #define EGS_LATTICE_GEOMETRY_
50 
51 #ifdef WIN32
52 
53  #ifdef BUILD_LATTICE_DLL
54  #define EGS_LATTICE_EXPORT __declspec(dllexport)
55  #else
56  #define EGS_LATTICE_EXPORT __declspec(dllimport)
57  #endif
58  #define EGS_LATTICE_LOCAL
59 
60 #else
61 
62  #ifdef HAVE_VISIBILITY
63  #define EGS_LATTICE_EXPORT __attribute__ ((visibility ("default")))
64  #define EGS_LATTICE_LOCAL __attribute__ ((visibility ("hidden")))
65  #else
66  #define EGS_LATTICE_EXPORT
67  #define EGS_LATTICE_LOCAL
68  #endif
69 
70 #endif
71 
146 class EGS_LATTICE_EXPORT EGS_Lattice : public EGS_BaseGeometry {
147 protected:
148 
151  int ind;
152  int maxStep;
153  EGS_Float a, b, c;
154  string type;
155 
156 public:
157 
158  EGS_Lattice(EGS_BaseGeometry *B, EGS_BaseGeometry *S, int i, EGS_Float x,
159  EGS_Float y, EGS_Float z, const string &Name = "");
160  ~EGS_Lattice();
161 
162  EGS_Vector closestPoint(const EGS_Vector &x) {
163  return EGS_Vector(int(round(x.x/a))*a,
164  int(round(x.y/b))*b,
165  int(round(x.z/c))*c);
166  };
167 
168  int computeIntersections(int ireg, int n, const EGS_Vector &x,
169  const EGS_Vector &u, EGS_GeometryIntersections *isections) {
170  return base->computeIntersections(ireg,n,x,u,isections);
171  };
172 
173  bool isRealRegion(int ireg) const {
174  if (ireg < base->regions()) { // If ireg is less than base regions
175  return base->isRealRegion(ireg); // check against base regions
176  }
177  return sub->isRealRegion(ireg - base->regions()); // then check sub regions
178  };
179 
180  bool isInside(const EGS_Vector &x) {
181  return base->isInside(x);
182  };
183 
184  int isWhere(const EGS_Vector &x) {
185  int temp = base->isWhere(x);
186  if (temp == ind) {// Are we in the subgeom?
187  sub->setTransformation(closestPoint(x));
188  if (sub->isInside(x)) {
189  return sub->isWhere(x) + base->regions();
190  }
191  }
192  return temp; // otherwise base geom
193  };
194 
195  int inside(const EGS_Vector &x) {
196  return isWhere(x);
197  };
198 
199  int medium(int ireg) const {
200  if (ireg >= base->regions()) { // If ireg is greater than base regions
201  return sub->medium(ireg-base->regions());
202  }
203  return base->medium(ireg); // If in base region
204  };
205 
206  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x, const EGS_Vector &u) {
207  if (ireg < 0) { // Error catch, not inside
208  return 0;
209  }
210 
211  // Are we in the subgeom
212  if (ireg >= base->regions()) {
213  return base->howfarToOutside(ind,x,u);
214  }
215  return base->howfarToOutside(ireg,x,u);
216  };
217 
218  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
219  EGS_Float &t,int *newmed=0, EGS_Vector *normal=0) {
220  // Catch t=0 exception, which sometimes causes issues when ind is the region neighboring -1
221  if (t < epsilon) {
222  t = 0.0;
223  return ireg;
224  }
225 
226  if (ireg >= base->regions()) { // Are we in the subgeom?
227  sub->setTransformation(closestPoint(x));
228 
229  // Do the howfar call
230  EGS_Float tempT = t;
231  int tempReg = sub->howfar(ireg-base->regions(),x,u,tempT,newmed,normal);
232 
233  // If we do leave the subgeom, we want to return the index
234  // of the region of the base geometry we would be entering,
235  // which is not necessarily ind if subgeom is at a boundary
236  EGS_Vector newX = u;
237  newX.normalize();
238  newX = x + (newX * tempT);
239 
240  if (base->isWhere(newX) != ind) {// If we leave ind region of base
241  t = tempT;
242 
243  tempReg = base->howfar(ind,x,u,t,0,normal);
244  if (newmed && tempReg >= 0) {
245  *newmed = base->medium(tempReg);
246  }
247 
248  //if (t<0) {
249  // egsWarning("Returning negative t from subgeom of %s\n",getName().c_str());
250  // egsWarning("howfar(%7d,[%e,%e,%e],[%e,%e,%e],%e)\n",ireg, x.x, x.y, x.z, u.x, u.y, u.z, t);
251  //}
252  return tempReg;
253  }
254 
255  if (!(tempReg+1)) {// If we leave sub geom back into ind
256  if (newmed) {
257  *newmed = base->medium(ind);
258  }
259  t = tempT;
260  return ind;
261  }
262 
263  // else we stay in sub geom
264  t = tempT;
265  //if (t<0) {
266  // egsWarning("Returning negative t from subgeom of %s\n",getName().c_str());
267  // egsWarning("howfar(%7d,[%e,%e,%e],[%e,%e,%e],%e)\n",ireg, x.x, x.y, x.z, u.x, u.y, u.z, t);
268  //}
269  return tempReg+base->regions();
270  }
271  else if (ireg == ind) {// If we are in the region that could contain subgeoms
272  // Determine the path travelled ------------------------------------------------ //
273  EGS_Float tempT = t;
274  base->howfar(ireg,x,u,tempT); // Get how far it is in temp
275  EGS_Float max = tempT;
276 
277  // Iterate through the lattice ------------------------------------------------- //
278  EGS_Float min = max, minX = max, minY = max, minZ = max; // Distance to closest subgeom for three different cases
279  EGS_Vector unit = u;
280  unit.normalize();
281  EGS_Vector xInt = unit*(a/4.0/fabs(unit.x)), yInt = unit*(b/4.0/fabs(unit.y)), zInt = unit*(c/4.0/fabs(unit.z));
282  EGS_Vector tempP; // Temporarily hold indices of subgeom we are testing against
283  EGS_Vector finalP, finalX, finalY, finalZ; // Current closest intersecting subgeom
284 
285  EGS_Vector x0;
286  EGS_Float max2 = max*max;
287 
288  x0 = x;
289  while ((x-x0).length2() < max2) {// Quit as soon as our testing position is beyond current closest intersection (which could be tempT)
290  tempT = minX;
291  tempP = closestPoint(x0);
292  sub->setTransformation(tempP);
293  if (sub->howfar(-1,x,u,tempT)+1) // Intersection!
294  if (tempT < max && tempT > 0) {
295  finalX = tempP;
296  minX = tempT;
297  break;
298  }
299  x0 += xInt;
300  }
301 
302  x0 = x;
303  while ((x-x0).length2() < max2) {// Quit as soon as our testing position is beyond current closest intersection (which could be tempT)
304  tempT = minY;
305  tempP = closestPoint(x0);
306  sub->setTransformation(tempP);
307  if (sub->howfar(-1,x,u,tempT)+1) // Intersection!
308  if (tempT < max && tempT > 0) {
309  finalY = tempP;
310  minY = tempT;
311  break;
312  }
313  x0 += yInt;
314  }
315 
316  x0 = x;
317  while ((x-x0).length2() < max2) {// Quit as soon as our testing position is beyond current closest intersection (which could be tempT)
318  tempT = minZ;
319  tempP = closestPoint(x0);
320  sub->setTransformation(tempP);
321  if (sub->howfar(-1,x,u,tempT)+1) // Intersection!
322  if (tempT < max && tempT > 0) {
323  finalZ = tempP;
324  minZ = tempT;
325  break;
326  }
327  x0 += zInt;
328  }
329 
330  finalP = finalX;
331  min = minX;
332  if (min > minY) {
333  min = minY;
334  finalP = finalY;
335  }
336  if (min > minZ) {
337  min = minZ;
338  finalP = finalZ;
339  }
340 
341  // Check last point
342  tempT = max;
343  sub->setTransformation(closestPoint(x+unit*tempT));
344  sub->howfar(-1,x,u,tempT);
345  if (tempT < min && tempT > 0) {
346  min = tempT;
347  finalP = closestPoint(x+unit*tempT);
348  }
349 
350  // We did intersect subgeom
351  if (min < max) {
352  tempT = t;
353  sub->setTransformation(finalP);
354  int tempReg = sub->howfar(-1,x,u,tempT,newmed,normal);
355  if (tempReg+1) {
356  if (newmed && tempReg >= 0) {
357  *newmed = sub->medium(tempReg);
358  }
359  t = tempT;
360 
361  //if (t<0) {
362  // egsWarning("Returning negative t from region %d in base geom of %s\n", ind, getName().c_str());
363  // egsWarning("howfar(%7d,[%e,%e,%e],[%e,%e,%e],%e)\n",ireg, x.x, x.y, x.z, u.x, u.y, u.z, t);
364  //}
365  return tempReg+base->regions();
366  }
367  }
368 
369  // We didn't intersect subgeom
370  int tempReg = base->howfar(ireg,x,u,t,newmed,normal);
371  //if (t<0) {
372  // egsWarning("Returning negative t from region %d in base geom of %s\n", ind, getName().c_str());
373  // egsWarning("howfar(%7d,[%e,%e,%e],[%e,%e,%e],%e)\n",ireg, x.x, x.y, x.z, u.x, u.y, u.z, t);
374  //}
375  if (newmed && tempReg >= 0) {
376  *newmed = base->medium(tempReg);
377  }
378 
379  return tempReg;
380  }
381  else {// Not in region containing subgeoms, then it is quite easy
382  // unless we enter directly into a subgeom when entering
383  // region ind
384  int tempReg = base->howfar(ireg,x,u,t,newmed,normal);
385 
386  // If we enter region ind
387  if (tempReg == ind) {
388  // newX is the point of entrance
389  EGS_Vector newX = u;
390  newX.normalize();
391  newX = x + (newX * t);
392 
393  sub->setTransformation(closestPoint(newX));
394  int newReg = sub->isWhere(newX);
395  if (newReg+1) { // see what region we are in
396  if (newmed && newReg >= 0) { // in subgeom, if its not -1
397  *newmed = sub->medium(newReg); // then return the proper
398  }
399  //if (t<0) { // media and region
400  // egsWarning("Returning negative t from region %d (not ind) in base geom of %s\n", ireg, getName().c_str());
401  // egsWarning("howfar(%7d,[%e,%e,%e],[%e,%e,%e],%e)\n",ireg, x.x, x.y, x.z, u.x, u.y, u.z, t);
402  //}
403  return newReg + base->regions();
404  }
405  }
406 
407  if (newmed && tempReg >= 0) {
408  *newmed = base->medium(tempReg);
409  }
410  //if (t<0) {
411  // egsWarning("Returning negative t from region %d (not ind) in base geom of %s\n", ireg, getName().c_str());
412  // egsWarning("howfar(%7d,[%e,%e,%e],[%e,%e,%e],%e)\n",ireg, x.x, x.y, x.z, u.x, u.y, u.z, t);
413  //}
414  return tempReg;
415  }
416  };
417 
418  EGS_Float hownear(int ireg, const EGS_Vector &x) {
419  EGS_Float temp, dist = base->hownear(ind,x);
420  if (ireg >= base->regions()) {
421  sub->setTransformation(closestPoint(x));
422  temp = sub->hownear(ireg-base->regions(),x);
423  dist=(temp<dist)?temp:dist;
424  }
425  else if (ireg == ind) {
426  // Check all nearby geometries
427  EGS_Float xa = floor(x.x/a)*a, yb = floor(x.y/b)*b, zc = floor(x.z/c)*c;
428  EGS_Vector x0[8] = {EGS_Vector(xa, yb, zc),
429  EGS_Vector(xa+a,yb, zc),
430  EGS_Vector(xa, yb+b,zc),
431  EGS_Vector(xa+a,yb+b,zc),
432  EGS_Vector(xa, yb, zc+c),
433  EGS_Vector(xa+a,yb, zc+c),
434  EGS_Vector(xa, yb+b,zc+c),
435  EGS_Vector(xa+a,yb+b,zc+c)
436  };
437  for (int i = 0; i < 8; i++) {
438  sub->setTransformation(x0[i]);
439  temp = sub->hownear(-1,x);
440  if (temp < dist) {
441  dist = temp;
442  }
443  }
444  }
445  else {
446  dist = base->hownear(ireg,x);
447  }
448  return dist;
449  };
450 
451  int regions() {
452  return base->regions() + sub->regions();
453  }
454 
455  int getMaxStep() const {
456  return maxStep;
457  };
458 
459  const string &getType() const {
460  return type;
461  };
462 
463  void printInfo() const;
464 
465  // I have no idea what this boolean stuff is for
466  bool hasBooleanProperty(int ireg, EGS_BPType prop) const {
467  if (ireg < base->regions()) { // If ireg is less than base regions
468  return base->hasBooleanProperty(ireg, prop); // check against base regions
469  }
470  return sub->hasBooleanProperty(ireg - base->regions(), prop); // then check sub regions
471  };
472  void setBooleanProperty(EGS_BPType prop) {
473  base->setBooleanProperty(prop);
474  };
475  void addBooleanProperty(int bit) {
476  base->addBooleanProperty(bit);
477  };
478  void setBooleanProperty(EGS_BPType prop, int start, int end, int step=1) {
479  base->setBooleanProperty(prop,start,end,step);
480  };
481  void addBooleanProperty(int bit, int start, int end, int step=1) {
482  base->addBooleanProperty(bit,start,end,step);
483  };
484 
485  EGS_Float getRelativeRho(int ireg) const {
486  if (ireg < base->regions()) { // If ireg is less than base regions
487  return base->getRelativeRho(ireg); // check against base regions
488  }
489  return sub->getRelativeRho(ireg - base->regions()); // then check sub regions
490  };
491  void setRelativeRho(int start, int end, EGS_Float rho);
492  void setRelativeRho(EGS_Input *);
493 
494  void setBScaling(int start, int end, EGS_Float rho);
495  void setBScaling(EGS_Input *);
496  EGS_Float getBScaling(int ireg) const {
497  if (ireg < base->regions()) { // If ireg is less than base regions
498  return base->getBScaling(ireg); // check against base regions
499  }
500  return sub->getBScaling(ireg - base->regions()); // then check sub regions
501  };
502 
503  bool hasRhoScaling() override {
504  if (has_rho_scaling) {
505  return has_rho_scaling;
506  }
507 
508  bool hasRS = sub->hasRhoScaling();
509  if (hasRS) {
510  has_rho_scaling = hasRS;
511  return has_rho_scaling;
512  }
513  else {
514  hasRS = base->hasRhoScaling();
515  has_rho_scaling = hasRS;
516  return has_rho_scaling;
517  }
518  };
519 
520  void finishInitialization() override {
521  sub->finishInitialization();
522  base->finishInitialization();
523  };
524 
525  virtual void getLabelRegions(const string &str, vector<int> &regs, bool sanitize=true);
526 
527 protected:
528  void setMedia(EGS_Input *inp,int,const int *);
529 };
530 
531 class EGS_LATTICE_EXPORT EGS_Hexagonal_Lattice : public EGS_BaseGeometry {
532 protected:
533 
536  int ind;
537  int maxStep;
538  EGS_Float a;
539  vector<EGS_Float> d;
540  string type;
541  EGS_Float gap;
542  // y and z have a shorter recurrence scale than a
543 public:
544 
545  EGS_Hexagonal_Lattice(EGS_BaseGeometry *B, EGS_BaseGeometry *S, int i, EGS_Float x, const string &Name = "");
547 
548  // Based off the closestPoint() function in the egs_lattice definition, here we check against the four
549  // Bravais lattices that make up the hexagonal lattice to find the closest point
550  EGS_Vector closestPoint(const EGS_Vector &x) {
551  EGS_Float i1,j1,k1,i2,j2,j3,k3,j4;
552  EGS_Float r3a = 2.0*gap;
553 
554  i1 = a*(round(x.x/a));
555  j1 = r3a*(round(x.y/r3a));
556  k1 = r3a*(round(x.z/r3a));
557 
558  i2 = a*(0.5+round(x.x/a-0.5));
559  j2 = r3a*(0.5+round(x.y/r3a-0.5));
560 
561  j3 = r3a*(0.25+round(x.y/r3a-0.25));
562  k3 = r3a*(0.5+round(x.z/r3a-0.5));
563 
564  j4 = r3a*(-0.25+round(x.y/r3a+0.25));
565 
566  EGS_Vector p1(i1,j1,k1);
567  EGS_Vector p2(i2,j2,k1);
568  EGS_Vector p3(i1,j3,k3);
569  EGS_Vector p4(i2,j4,k3);
570 
571  d[0] = (x-p1).length2();
572  d[1] = (x-p2).length2();
573  d[2] = (x-p3).length2();
574  d[3] = (x-p4).length2();
575 
576  if (d[0] < d[1] && d[0] < d[2] && d[0] < d[3]) {
577  return p1;
578  }
579  if (d[1] < d[2] && d[1] < d[3]) {
580  return p2;
581  }
582  if (d[2] < d[3]) {
583  return p3;
584  }
585  return p4;
586  };
587 
588  int computeIntersections(int ireg, int n, const EGS_Vector &x,
589  const EGS_Vector &u, EGS_GeometryIntersections *isections) {
590  return base->computeIntersections(ireg,n,x,u,isections);
591  };
592 
593  bool isRealRegion(int ireg) const {
594  if (ireg < base->regions()) { // If ireg is less than base regions
595  return base->isRealRegion(ireg); // check against base regions
596  }
597  return sub->isRealRegion(ireg - base->regions()); // then check sub regions
598  };
599 
600  bool isInside(const EGS_Vector &x) {
601  return base->isInside(x);
602  };
603 
604  int isWhere(const EGS_Vector &x) {
605  int temp = base->isWhere(x);
606  if (temp == ind) {// Are we in the subgeom?
607  sub->setTransformation(closestPoint(x));
608  if (sub->isInside(x)) {
609  return sub->isWhere(x) + base->regions();
610  }
611  }
612  return temp; // otherwise base geom
613  };
614 
615  int inside(const EGS_Vector &x) {
616  return isWhere(x);
617  };
618 
619  int medium(int ireg) const {
620  if (ireg >= base->regions()) { // If ireg is greater than base regions
621  return sub->medium(ireg-base->regions());
622  }
623  return base->medium(ireg); // If in base region
624  };
625 
626  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x, const EGS_Vector &u) {
627  if (ireg < 0) { // Error catch, not inside
628  return 0;
629  }
630 
631  // Are we in the subgeom
632  if (ireg >= base->regions()) {
633  return base->howfarToOutside(ind,x,u);
634  }
635  return base->howfarToOutside(ireg,x,u);
636  };
637 
638  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
639  EGS_Float &t,int *newmed=0, EGS_Vector *normal=0) {
640  // Catch t=0 exception, which sometimes causes issues when ind is the region neighboring -1
641  if (t < epsilon) {
642  t = 0.0;
643  return ireg;
644  }
645 
646  if (ireg >= base->regions()) { // Are we in the subgeom?
647  sub->setTransformation(closestPoint(x));
648 
649  // Do the howfar call
650  EGS_Float tempT = t;
651  int tempReg = sub->howfar(ireg-base->regions(),x,u,tempT,newmed,normal);
652 
653  // If we do leave the subgeom, we want to return the index
654  // of the region of the base geometry we would be entering,
655  // which is not necessarily ind if subgeom is at a boundary
656  EGS_Vector newX = u;
657  newX.normalize();
658  newX = x + (newX * tempT);
659 
660  if (base->isWhere(newX) != ind) {// If we leave ind region of base
661  t = tempT;
662 
663  tempReg = base->howfar(ind,x,u,t,0,normal);
664  if (newmed && tempReg >= 0) {
665  *newmed = base->medium(tempReg);
666  }
667 
668  //if (t<0) {
669  // egsWarning("Returning negative t from subgeom of %s\n",getName().c_str());
670  // egsWarning("howfar(%7d,[%e,%e,%e],[%e,%e,%e],%e)\n",ireg, x.x, x.y, x.z, u.x, u.y, u.z, t);
671  //}
672  return tempReg;
673  }
674 
675  if (!(tempReg+1)) {// If we leave sub geom back into ind
676  if (newmed) {
677  *newmed = base->medium(ind);
678  }
679  t = tempT;
680  return ind;
681  }
682 
683  // else we stay in sub geom
684  t = tempT;
685  //if (t<0) {
686  // egsWarning("Returning negative t from subgeom of %s\n",getName().c_str());
687  // egsWarning("howfar(%7d,[%e,%e,%e],[%e,%e,%e],%e)\n",ireg, x.x, x.y, x.z, u.x, u.y, u.z, t);
688  //}
689  return tempReg+base->regions();
690  }
691  else if (ireg == ind) {// If we are in the region that could contain subgeoms
692  // Determine the path travelled ------------------------------------------------ //
693  EGS_Float tempT = t;
694  base->howfar(ireg,x,u,tempT); // Get how far it is in temp
695  EGS_Float max = tempT;
696 
697  // Iterate through the lattice ------------------------------------------------- //
698  EGS_Float min = max, minX = max, minY = max, minZ = max; // Distance to closest subgeom for three different cases
699  EGS_Vector unit = u;
700  unit.normalize();
701  EGS_Vector xInt = unit*(a/8.0/fabs(unit.x)), yInt = unit*(gap/8.0/fabs(unit.y)), zInt = unit*(gap/8.0/fabs(unit.z));
702  EGS_Vector tempP; // Temporarily hold indices of subgeom we are testing against
703  EGS_Vector finalP, finalX, finalY, finalZ; // Current closest intersecting subgeom
704 
705  EGS_Vector x0;
706  EGS_Float max2 = max*max;
707 
708  x0 = x;
709  while ((x-x0).length2() < max2) {// Quit as soon as our testing position is beyond current closest intersection (which could be tempT)
710  tempT = minX;
711  tempP = closestPoint(x0);
712  sub->setTransformation(tempP);
713  if (sub->howfar(-1,x,u,tempT)+1) // Intersection!
714  if (tempT < max && tempT > 0) {
715  finalX = tempP;
716  minX = tempT;
717  break;
718  }
719  x0 += xInt;
720  }
721 
722  x0 = x;
723  while ((x-x0).length2() < max2) {// Quit as soon as our testing position is beyond current closest intersection (which could be tempT)
724  tempT = minY;
725  tempP = closestPoint(x0);
726  sub->setTransformation(tempP);
727  if (sub->howfar(-1,x,u,tempT)+1) // Intersection!
728  if (tempT < max && tempT > 0) {
729  finalY = tempP;
730  minY = tempT;
731  break;
732  }
733  x0 += yInt;
734  }
735 
736  x0 = x;
737  while ((x-x0).length2() < max2) {// Quit as soon as our testing position is beyond current closest intersection (which could be tempT)
738  tempT = minZ;
739  tempP = closestPoint(x0);
740  sub->setTransformation(tempP);
741  if (sub->howfar(-1,x,u,tempT)+1) // Intersection!
742  if (tempT < max && tempT > 0) {
743  finalZ = tempP;
744  minZ = tempT;
745  break;
746  }
747  x0 += zInt;
748  }
749 
750  finalP = finalX;
751  min = minX;
752  if (min > minY) {
753  min = minY;
754  finalP = finalY;
755  }
756  if (min > minZ) {
757  min = minZ;
758  finalP = finalZ;
759  }
760 
761  // Check last point
762  tempT = max;
763  sub->setTransformation(closestPoint(x+unit*tempT));
764  sub->howfar(-1,x,u,tempT);
765  if (tempT < min && tempT > 0) {
766  min = tempT;
767  finalP = closestPoint(x+unit*tempT);
768  }
769 
770  // We did intersect subgeom
771  if (min < max) {
772  tempT = t;
773  sub->setTransformation(finalP);
774  int tempReg = sub->howfar(-1,x,u,tempT,newmed,normal);
775  if (tempReg+1) {
776  if (newmed && tempReg >= 0) {
777  *newmed = sub->medium(tempReg);
778  }
779  t = tempT;
780 
781  //if (t<0) {
782  // egsWarning("Returning negative t from region %d in base geom of %s\n", ind, getName().c_str());
783  // egsWarning("howfar(%7d,[%e,%e,%e],[%e,%e,%e],%e)\n",ireg, x.x, x.y, x.z, u.x, u.y, u.z, t);
784  //}
785  return tempReg+base->regions();
786  }
787  }
788 
789  // We didn't intersect subgeom
790  int tempReg = base->howfar(ireg,x,u,t,newmed,normal);
791  //if (t<0) {
792  // egsWarning("Returning negative t from region %d in base geom of %s\n", ind, getName().c_str());
793  // egsWarning("howfar(%7d,[%e,%e,%e],[%e,%e,%e],%e)\n",ireg, x.x, x.y, x.z, u.x, u.y, u.z, t);
794  //}
795  if (newmed && tempReg >= 0) {
796  *newmed = base->medium(tempReg);
797  }
798 
799  return tempReg;
800  }
801  else {// Not in region containing subgeoms, then it is quite easy
802  // unless we enter directly into a subgeom when entering
803  // region ind
804  int tempReg = base->howfar(ireg,x,u,t,newmed,normal);
805 
806  // If we enter region ind
807  if (tempReg == ind) {
808  // newX is the point of entrance
809  EGS_Vector newX = u;
810  newX.normalize();
811  newX = x + (newX * t);
812 
813  sub->setTransformation(closestPoint(newX));
814  int newReg = sub->isWhere(newX);
815  if (newReg+1) { // see what region we are in
816  if (newmed && newReg >= 0) { // in subgeom, if its not -1
817  *newmed = sub->medium(newReg); // then return the proper
818  }
819  //if (t<0) { // media and region
820  // egsWarning("Returning negative t from region %d (not ind) in base geom of %s\n", ireg, getName().c_str());
821  // egsWarning("howfar(%7d,[%e,%e,%e],[%e,%e,%e],%e)\n", ireg, x.x, x.y, x.z, u.x, u.y, u.z, t);
822  //}
823  return newReg + base->regions();
824  }
825  }
826 
827  if (newmed && tempReg >= 0) {
828  *newmed = base->medium(tempReg);
829  }
830  //if (t<0) {
831  // egsWarning("Returning negative t from region %d (not ind) in base geom of %s\n", ireg, getName().c_str());
832  // egsWarning("howfar(%7d,[%e,%e,%e],[%e,%e,%e],%e)\n", ireg, x.x, x.y, x.z, u.x, u.y, u.z, t);
833  //}
834  return tempReg;
835  }
836  };
837 
838  EGS_Float hownear(int ireg, const EGS_Vector &x) {
839  EGS_Float temp, dist = base->hownear(ireg>=base->regions()?ind:ireg,x);
840  if (ireg >= base->regions()) {
841  sub->setTransformation(closestPoint(x));
842  temp = sub->hownear(ireg-base->regions(),x);
843  dist=(temp<dist)?temp:dist;
844  }
845  else if (ireg == ind) {
846  // Check all nearby geometries, making use of the 4 Bravais lattice substructure of the geometry
847  EGS_Float i,j,k;
848  EGS_Float r3a = 2.0*gap, hgap = gap/2.0, ha = a/2.0;
849  EGS_Vector x0[8];
850 
851  // Calculate the edge of an oblique rhombic prism formed around x
852  i = a*(floor(x.x/a));
853  j = r3a*(round(x.y/r3a));
854  k = r3a*(round(x.z/r3a));
855 
856  // One of the following 4 trigonal trapezohedrons must enclose x, they all share an edge defined
857  // as (i,j,k) to (i+a,j,k) and can recurse through all space
858  if (x.y<=j && x.z<=k)
859  EGS_Vector x0[8] = {EGS_Vector(i,j,k),
860  EGS_Vector(i-ha,j-gap,k),
861  EGS_Vector(i,j-gap-hgap,k-gap),
862  EGS_Vector(i+ha,j-hgap,k-gap),
863  EGS_Vector(i+a,j,k),
864  EGS_Vector(i+ha,j-gap,k),
865  EGS_Vector(i+a,j-gap-hgap,k-gap),
866  EGS_Vector(i+a+ha,j-hgap,k-gap)
867  };
868  else if (x.y>j && x.z<=k)
869  EGS_Vector x0[8] = {EGS_Vector(i,j,k),
870  EGS_Vector(i+ha,j+gap,k),
871  EGS_Vector(i+a,j+hgap,k-gap),
872  EGS_Vector(i+ha,j-hgap,k-gap),
873  EGS_Vector(i+a,j,k),
874  EGS_Vector(i+a+ha,j+gap,k),
875  EGS_Vector(i+a+a,j+hgap,k-gap),
876  EGS_Vector(i+a+ha,j-hgap,k-gap)
877  };
878  else if (x.y<j && x.z>k)
879  EGS_Vector x0[8] = {EGS_Vector(i,j,k),
880  EGS_Vector(i+ha,j-gap,k),
881  EGS_Vector(i,j-gap-hgap,k+gap),
882  EGS_Vector(i-ha,j-hgap,k+gap),
883  EGS_Vector(i+a,j,k),
884  EGS_Vector(i+a+ha,j-gap,k),
885  EGS_Vector(i+a,j-gap-hgap,k+gap),
886  EGS_Vector(i+ha,j-hgap,k+gap)
887  };
888  else //(x.y>j && x.z>k)
889  EGS_Vector x0[8] = {EGS_Vector(i,j,k),
890  EGS_Vector(i-ha,j+gap,k),
891  EGS_Vector(i-a,j+hgap,k+gap),
892  EGS_Vector(i-ha,j-hgap,k+gap),
893  EGS_Vector(i+a,j,k),
894  EGS_Vector(i+ha,j+gap,k),
895  EGS_Vector(i,j+hgap,k+gap),
896  EGS_Vector(i+ha,j-hgap,k+gap)
897  };
898  for (int i = 0; i < 8; i++) {
899  sub->setTransformation(x0[i]);
900  temp = sub->hownear(-1,x);
901  if (temp < dist) {
902  dist = temp;
903  }
904  }
905  }
906  return dist;
907  };
908 
909  int regions() {
910  return base->regions() + sub->regions();
911  }
912 
913  int getMaxStep() const {
914  return maxStep;
915  };
916 
917  const string &getType() const {
918  return type;
919  };
920 
921  void printInfo() const;
922 
923  // I have no idea what this boolean stuff is for
924  bool hasBooleanProperty(int ireg, EGS_BPType prop) const {
925  if (ireg < base->regions()) { // If ireg is less than base regions
926  return base->hasBooleanProperty(ireg, prop); // check against base regions
927  }
928  return sub->hasBooleanProperty(ireg - base->regions(), prop); // then check sub regions
929  };
930  void setBooleanProperty(EGS_BPType prop) {
931  base->setBooleanProperty(prop);
932  };
933  void addBooleanProperty(int bit) {
934  base->addBooleanProperty(bit);
935  };
936  void setBooleanProperty(EGS_BPType prop, int start, int end, int step=1) {
937  base->setBooleanProperty(prop,start,end,step);
938  };
939  void addBooleanProperty(int bit, int start, int end, int step=1) {
940  base->addBooleanProperty(bit,start,end,step);
941  };
942 
943  EGS_Float getRelativeRho(int ireg) const {
944  if (ireg < base->regions()) { // If ireg is less than base regions
945  return base->getRelativeRho(ireg); // check against base regions
946  }
947  return sub->getRelativeRho(ireg - base->regions()); // then check sub regions
948  };
949  void setRelativeRho(int start, int end, EGS_Float rho);
950  void setRelativeRho(EGS_Input *);
951 
952  void setBScaling(int start, int end, EGS_Float rho);
953  void setBScaling(EGS_Input *);
954  EGS_Float getBScaling(int ireg) const {
955  if (ireg < base->regions()) { // If ireg is less than base regions
956  return base->getBScaling(ireg); // check against base regions
957  }
958  return sub->getBScaling(ireg - base->regions()); // then check sub regions
959  };
960 
961  virtual void getLabelRegions(const string &str, vector<int> &regs, bool sanitize=true);
962 
963 protected:
964  void setMedia(EGS_Input *inp,int,const int *);
965 };
966 
967 #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 bool hasBooleanProperty(int ireg, EGS_BPType prop) const
Is the boolean property prop set for region ireg ?
virtual EGS_Float howfarToOutside(int ireg, const EGS_Vector &x, const EGS_Vector &u)
virtual EGS_Float getBScaling(int ireg) const
Get the B field scaling factor in region ireg.
virtual void setBScaling(int start, int end, EGS_Float bf)
Set the B field scaling factor in regions.
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 bool hasRhoScaling()
Does this geometry object have a mass density scaling feature?
virtual bool isRealRegion(int ireg) const
Returnes true if ireg is a real region, false otherwise.
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.
virtual void setBooleanProperty(EGS_BPType prop)
Set the boolean properties of the entire geometry to prop.
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.
int regions() const
Returns the number of local regions in this geometry.
virtual void setRelativeRho(int start, int end, EGS_Float rho)
Set the relative mass density in regions.
virtual void printInfo() const
Print information about this geometry.
virtual void addBooleanProperty(int bit)
Add a boolean property for the entire geometry by setting the bit'th bit.
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?
EGS_Float a
The center-to-center distance to the nearest 12 neighbours.
Definition: egs_lattice.h:538
vector< EGS_Float > d
Don't redefine 4 dists in closestPoint each invocation.
Definition: egs_lattice.h:539
EGS_BaseGeometry * base
The geometry within which the sub geometry appears.
Definition: egs_lattice.h:534
EGS_Float gap
Translating the hexagonal lattice to xyz coordinate,.
Definition: egs_lattice.h:541
EGS_TransformedGeometry * sub
The sub geometry that could appear within base.
Definition: egs_lattice.h:535
int maxStep
The maximum number of steps.
Definition: egs_lattice.h:537
int ind
The region in base geom where we could encounter sub geom.
Definition: egs_lattice.h:536
string type
The geometry type.
Definition: egs_lattice.h:540
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 Bravais, cubic, and hexagonal lattice geometry.
Definition: egs_lattice.h:146
EGS_TransformedGeometry * sub
The sub geometry that could appear within base.
Definition: egs_lattice.h:150
string type
The geometry type.
Definition: egs_lattice.h:154
EGS_BaseGeometry * base
The geometry within which the sub geometry appears.
Definition: egs_lattice.h:149
EGS_Float c
The center-to-center distance along x, y, and z.
Definition: egs_lattice.h:153
int maxStep
The maximum number of steps.
Definition: egs_lattice.h:152
int ind
The region in base geom where we could encounter sub geom.
Definition: egs_lattice.h:151
A transformed geometry.
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
EGS_BaseGeometry class header file.
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
Definition: egs_functions.h:62