EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_envelope_geometry.h
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ envelope 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: Ernesto Mainegra-Hing
27 # Frederic Tessier
28 # Reid Townson
29 # Max Orok
30 # Alexandre Demelo
31 #
32 ###############################################################################
33 */
34 
35 
41 #ifndef EGS_ENVELOPE_GEOMETRY_
42 #define EGS_ENVELOPE_GEOMETRY_
43 
44 #ifdef WIN32
45 
46  #ifdef BUILD_ENVELOPEG_DLL
47  #define EGS_ENVELOPEG_EXPORT __declspec(dllexport)
48  #else
49  #define EGS_ENVELOPEG_EXPORT __declspec(dllimport)
50  #endif
51  #define EGS_ENVELOPEG_LOCAL
52 
53 #else
54 
55  #ifdef HAVE_VISIBILITY
56  #define EGS_ENVELOPEG_EXPORT __attribute__ ((visibility ("default")))
57  #define EGS_ENVELOPEG_LOCAL __attribute__ ((visibility ("hidden")))
58  #else
59  #define EGS_ENVELOPEG_EXPORT
60  #define EGS_ENVELOPEG_LOCAL
61  #endif
62 
63 #endif
64 
65 
66 #include "egs_base_geometry.h"
67 #include "egs_functions.h"
68 
69 #include<vector>
70 using std::vector;
71 
230 class EGS_ENVELOPEG_EXPORT EGS_EnvelopeGeometry : public EGS_BaseGeometry {
231 
232 public:
233 
235  const vector<EGS_BaseGeometry *> &geoms, const string &Name = "",
236  bool newindexing=false);
237 
239 
240  bool isRealRegion(int ireg) const {
241  if (ireg < 0 || ireg >= nreg) {
242  return false;
243  }
244  if (ireg < nbase) {
245  return g->isRealRegion(ireg);
246  }
247  int jg, ilocal;
248  if (new_indexing) {
249  jg = reg_to_inscr[ireg-nbase];
250  ilocal = ireg - local_start[jg];
251  }
252  else {
253  jg = (ireg - nbase)/nmax;
254  ilocal = ireg - nbase - jg*nmax;
255  }
256  return geometries[jg]->isRealRegion(ilocal);
257  };
258 
259  bool isInside(const EGS_Vector &x) {
260  return g->isInside(x);
261  };
262 
263  int isWhere(const EGS_Vector &x) {
264  int ireg = g->isWhere(x);
265  if (ireg < 0) {
266  return ireg;
267  }
268  for (int j=0; j<n_in; j++) {
269  int i = geometries[j]->isWhere(x);
270  if (i >= 0) return new_indexing ? local_start[j] + i :
271  nbase + nmax*j + i;
272  }
273  return ireg;
274  };
275 
276  int inside(const EGS_Vector &x) {
277  return isWhere(x);
278  };
279 
280  int medium(int ireg) const {
281  if (ireg < nbase) {
282  return g->medium(ireg);
283  }
284  int jg, ilocal;
285  if (new_indexing) {
286  jg = reg_to_inscr[ireg-nbase];
287  ilocal = ireg - local_start[jg];
288  }
289  else {
290  jg = (ireg - nbase)/nmax;
291  ilocal = ireg - nbase - jg*nmax;
292  }
293  return geometries[jg]->medium(ilocal);
294  };
295 
296  int computeIntersections(int ireg, int n, const EGS_Vector &X,
297  const EGS_Vector &u, EGS_GeometryIntersections *isections) {
298  if (n < 1) {
299  return -1;
300  }
301  int ifirst = 0;
302  EGS_Float t, ttot = 0;
303  EGS_Vector x(X);
304  int imed;
305  if (ireg < 0) {
306  t = veryFar;
307  ireg = howfar(ireg,x,u,t,&imed);
308  if (ireg < 0) {
309  return 0;
310  }
311  isections[0].t = t;
312  isections[0].rhof = 1;
313  isections[0].ireg = -1;
314  isections[0].imed = -1;
315  ttot = t;
316  ++ifirst;
317  x += u*t;
318  }
319  else {
320  imed = medium(ireg);
321  }
322 
323 
324  int j = ifirst;
325  int ij = -1, ig=0;
326  for (EGS_I64 loopCount=0; loopCount<=loopMax; ++loopCount) {
327  if (loopCount == loopMax) {
328  egsFatal("EGS_EnvelopeGeometry::computeIntersections: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
329  return -1;
330  }
331  if (ireg >= nbase) {
332  if (new_indexing) {
333  ig = reg_to_inscr[ireg-nbase];
334  ij = ireg - local_start[ig];
335  }
336  else {
337  ig = (ireg - nbase)/nmax;
338  ij = ireg - nbase - ig*nmax;
339  }
340  }
341  isections[j].imed = imed;
342  isections[j].ireg = ireg;
343  isections[j].rhof = getRelativeRho(ireg);
344  if (ireg < nbase) { // in one of the regions of the base geometry
345  t = veryFar;
346  int ibase = g->howfar(ireg,x,u,t,&imed);
347  ij = -1;
348  for (int i=0; i<n_in; i++) {
349  int ireg_i = geometries[i]->howfar(-1,x,u,t,&imed);
350  if (ireg_i >= 0) {
351  ij = ireg_i;
352  ig = i;
353  }
354  }
355  ttot += t;
356  isections[j++].t = ttot;
357  if (ij < 0) {
358  ireg = ibase;
359  }
360  else ireg = new_indexing ? local_start[ig] + ij :
361  nbase + ig*nmax + ij;
362  if (ireg < 0) {
363  return j;
364  }
365  if (j >= n) {
366  return -1;
367  }
368  x += u*t;
369  }
370  else {
371  int iadd = new_indexing ? local_start[ig] : nbase + ig*nmax;
372  int nsec = geometries[ig]->computeIntersections(ij,n-j,
373  x,u,&isections[j]);
374  int nm = nsec >= 0 ? nsec+j : n;
375  for (int i=j; i<nm; i++) {
376  isections[i].ireg += iadd;
377  isections[i].t += ttot;
378  }
379  if (nsec < 0) {
380  return nsec;
381  }
382  j += nsec;
383  if (j >= n) {
384  return -1;
385  }
386  t = isections[j-1].t - ttot;
387  x += u*t;
388  ttot = isections[j-1].t;
389  ireg = g->isWhere(x);
390  if (ireg < 0) {
391  return j;
392  }
393  imed = g->medium(ireg);
394  }
395  }
396  return -1;
397  }
398 
399  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
400  const EGS_Vector &u) {
401  if (ireg < 0) {
402  return 0;
403  }
404  EGS_Float d;
405  if (ireg < nbase) {
406  d = g->howfarToOutside(ireg,x,u);
407  }
408  else if (g->regions() == 1) {
409  d = g->howfarToOutside(0,x,u);
410  }
411  else {
412  int ir = g->isWhere(x);
413  d = g->howfarToOutside(ir,x,u);
414  }
415  return d;
416  };
417 
418  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
419  EGS_Float &t, int *newmed = 0, EGS_Vector *normal = 0) {
420  if (ireg >= 0) {
421  // inside.
422  if (ireg < nbase) {
423  // in one of the regions of the base geometry
424  // check if we hit a boundary in the base geometry.
425  // if we do, newmed and normal get set accordingly.
426  int ibase = g->howfar(ireg,x,u,t,newmed,normal);
427  int ij = -1, jg;
428  // check if we will enter any of the inscribed geometries
429  // before entering a new region in the base geometry.
430  for (int j=0; j<n_in; j++) {
431  int ireg_j =
432  geometries[j]->howfar(-1,x,u,t,newmed,normal);
433  if (ireg_j >= 0) {
434  // we do. remember the inscribed geometry index
435  // and local region
436  ij = ireg_j;
437  jg = j;
438  }
439  }
440  if (ij < 0) {
441  return ibase;
442  }
443  // ij<0 implies that we have not hit any of the
444  // inscribed geometries => return the base geometry index.
445  // ij>=0 implies that we entered inscribed geometry
446  // jg in its local region ij.
447  return new_indexing ? local_start[jg] + ij :
448  nbase + jg*nmax + ij;
449  }
450  // if here, we are in an inscribed geometry.
451  // calculate its index (jg) and its local region (ilocal).
452  int jg, ilocal;
453  if (new_indexing) {
454  jg = reg_to_inscr[ireg-nbase];
455  ilocal = ireg-local_start[jg];
456  }
457  else {
458  jg = (ireg - nbase)/nmax;
459  ilocal = ireg - nbase - jg*nmax;
460  }
461  // and then check if we will hit a boundary in this geometry.
462  int inew = geometries[jg]->howfar(ilocal,x,u,t,newmed,normal);
463  if (inew >= 0) return new_indexing ? local_start[jg] + inew :
464  nbase + jg*nmax + inew;
465  // inew >= 0 implies that we either stay in the same
466  // region (inew=ilocal) or we entered a new region
467  // (inew!=ilocal), which is still inside the inscribed geometry
468  // inew<0 implies that we have exited the inscribed geometry
469  // => check to see in which base geometry region we are.
470  inew = g->isWhere(x+u*t);
471  if (inew >= 0 && newmed) {
472  *newmed = g->medium(inew);
473  }
474  return inew;
475  }
476  // if here, we are outside the base geometry.
477  // check to see if we will enter.
478  int ienter = g->howfar(ireg,x,u,t,newmed,normal);
479  if (ienter >= 0) {
480  // yes, we do. see if we are already inside of one of the
481  // inscribed geometries.
482  for (int j=0; j<n_in; j++) {
483  int i = geometries[j]->isWhere(x+u*t);
484  if (i >= 0) {
485  // yes, we are.
486  if (newmed) {
487  *newmed = geometries[j]->medium(i);
488  }
489  return new_indexing ? local_start[j] + i :
490  nbase + nmax*j + i;
491  }
492  }
493  }
494  return ienter;
495  };
496 
497  EGS_Float hownear(int ireg, const EGS_Vector &x) {
498  if (ireg >= 0) {
499  EGS_Float tmin;
500  if (ireg < nbase) { // in one of the regions of the base geom.
501  tmin = g->hownear(ireg,x);
502  for (int j=0; j<n_in; j++) {
503  EGS_Float tj = geometries[j]->hownear(-1,x);
504  if (tj < tmin) {
505  tmin = tj;
506  if (tmin <= 0) {
507  return tmin;
508  }
509  }
510  }
511  return tmin;
512  }
513  int jg, ilocal;
514  if (new_indexing) {
515  jg = reg_to_inscr[ireg-nbase];
516  ilocal = ireg-local_start[jg];
517  }
518  else {
519  jg = (ireg - nbase)/nmax;
520  ilocal = ireg - nbase - jg*nmax;
521  }
522  return geometries[jg]->hownear(ilocal,x);
523  }
524  return g->hownear(ireg,x);
525  };
526 
527 
528  void getNextGeom(EGS_RandomGenerator *rndm) {
529  // calls getNextGeom on its component geometries to update dynamic
530  // geometries in the simulation
531  for (int j=0; j<n_in; j++) {
532  geometries[j]->getNextGeom(rndm);
533  }
534  g->getNextGeom(rndm);
535  };
536 
537  void updatePosition(EGS_Float time) {
538  // calls updatePosition on its component geometries to update dynamic
539  // geometries in the simulation
540  for (int j=0; j<n_in; j++) {
541  geometries[j]->updatePosition(time);
542  }
543  g->updatePosition(time);
544  };
545 
546  void containsDynamic(bool &hasdynamic) {
547  // calls containsDynamic on its component geometries (only calls if
548  // hasDynamic is false, as if it is true we already found one)
549  for (int j=0; j<n_in; j++) {
550  if (!hasdynamic) {
551  geometries[j]->containsDynamic(hasdynamic);
552  }
553  }
554  if (!hasdynamic) {
555  g->containsDynamic(hasdynamic);
556  }
557  };
558 
559 
560 
561  int getMaxStep() const {
562  int nstep = g->getMaxStep();
563  for (int j=0; j<n_in; ++j) {
564  nstep += geometries[j]->getMaxStep();
565  }
566  return nstep+n_in;
567  };
568 
569  bool hasBooleanProperty(int ireg, EGS_BPType prop) const {
570  if (ireg >= 0 && ireg < nreg) {
571  if (ireg < nbase) {
572  return g->hasBooleanProperty(ireg,prop);
573  }
574  int jg = (ireg - nbase)/nmax;
575  int ilocal = ireg - nbase - jg*nmax;
576  return geometries[jg]->hasBooleanProperty(ilocal,prop);
577  }
578  return false;
579  };
580  void setBooleanProperty(EGS_BPType) {
581  setPropertyError("setBooleanProperty()");
582  };
583  void addBooleanProperty(int) {
584  setPropertyError("addBooleanProperty()");
585  };
586  void setBooleanProperty(EGS_BPType,int,int,int step=1) {
587  setPropertyError("setBooleanProperty()");
588  };
589  void addBooleanProperty(int,int,int,int step=1) {
590  setPropertyError("addBooleanProperty()");
591  };
592 
593  const string &getType() const {
594  return type;
595  };
596 
597  EGS_BaseGeometry **getInscribedGeometries(std::size_t &nInscribed) const {
598  nInscribed = n_in;
599  return geometries;
600  }
601 
602  void printInfo() const;
603 
604  void setRelativeRho(int start, int end, EGS_Float rho);
605  void setRelativeRho(EGS_Input *);
606  EGS_Float getRelativeRho(int ireg) const {
607  if (ireg < 0 || ireg >= nreg) {
608  return 1;
609  }
610  if (ireg < nbase) {
611  return g->getRelativeRho(ireg);
612  }
613  int jg = (ireg - nbase)/nmax;
614  return geometries[jg]->getRelativeRho(ireg - nbase - jg*nmax);
615  };
616 
617  void setBScaling(int start, int end, EGS_Float bf);
618  void setBScaling(EGS_Input *);
619  EGS_Float getBScaling(int ireg) const {
620  if (ireg < 0 || ireg >= nreg) {
621  return 1;
622  }
623  if (ireg < nbase) {
624  return g->getBScaling(ireg);
625  }
626  int jg = (ireg - nbase)/nmax;
627  return geometries[jg]->getBScaling(ireg - nbase - jg*nmax);
628  };
629 
630  virtual void getLabelRegions(const string &str, vector<int> &regs);
631 
632 protected:
633 
636  int n_in;
637  int nbase,
640  static string type;
641 
644  int *local_start;
645 
652  void setMedia(EGS_Input *,int,const int *);
653 
654 private:
655 
656  void setPropertyError(const char *funcname) {
657  egsFatal("EGS_EnvelopeGeometry::%s: don't use this method\n Define "
658  "properties in the constituent geometries instead\n",
659  funcname);
660  };
661 
662 };
663 
664 
665 struct EnvelopeAux;
666 
675 class EGS_ENVELOPEG_EXPORT EGS_FastEnvelope : public EGS_BaseGeometry {
676 
677 public:
678 
680  const vector<EnvelopeAux *> &fgeoms, const string &Name = "",
681  int newindexing=false);
682 
683  ~EGS_FastEnvelope();
684 
685  bool isRealRegion(int ireg) const {
686  if (ireg < 0 || ireg >= nreg) {
687  return false;
688  }
689  if (ireg < nbase) {
690  return g->isRealRegion(ireg);
691  }
692  int jg, ilocal;
693  if (new_indexing) {
694  jg = reg_to_inscr[ireg-nbase];
695  ilocal = ireg - local_start[jg];
696  }
697  else {
698  jg = (ireg - nbase)/nmax;
699  ilocal = ireg - nbase - jg*nmax;
700  }
701  return geometries[jg]->isRealRegion(ilocal);
702  };
703 
704  bool isInside(const EGS_Vector &x) {
705  return g->isInside(x);
706  };
707 
708  int isWhere(const EGS_Vector &x) {
709  int ireg = g->isWhere(x);
710  if (ireg < 0 || n_start[ireg] < 0) {
711  return ireg;
712  }
713  for (int jj=n_start[ireg]; jj<n_start[ireg+1]; jj++) {
714  int j = glist[jj];
715  int i = geometries[j]->isWhere(x);
716  if (i >= 0) {
717  return nbase + nmax*j + i;
718  }
719  }
720  return ireg;
721  };
722 
723  void getNextGeom(EGS_RandomGenerator *rndm) {
724  // calls getNextGeom on its component geometries to update dynamic
725  // geometries in the simulation
726  for (int j=0; j<n_in; j++) {
727  geometries[j]->getNextGeom(rndm);
728  }
729  g->getNextGeom(rndm);
730  };
731 
732  void updatePosition(EGS_Float time) {
733  // calls updatePosition on its component geometries to update dynamic
734  // geometries in the simulation
735  for (int j=0; j<n_in; j++) {
736  geometries[j]->updatePosition(time);
737  }
738  g->updatePosition(time);
739  };
740 
741  void containsDynamic(bool &hasdynamic) {
742  // calls containsDynamic on its component geometries (only calls if
743  // hasDynamic is false, as if it is true we already found one)
744  for (int j=0; j<n_in; j++) {
745  if (!hasdynamic) {
746  geometries[j]->containsDynamic(hasdynamic);
747  }
748  }
749  if (!hasdynamic) {
750  g->containsDynamic(hasdynamic);
751  }
752  };
753 
754 
755  int inside(const EGS_Vector &x) {
756  return isWhere(x);
757  };
758 
759  int medium(int ireg) const {
760  if (ireg < nbase) {
761  return g->medium(ireg);
762  }
763  int jg = (ireg - nbase)/nmax;
764  int ilocal = ireg - nbase - jg*nmax;
765  return geometries[jg]->medium(ilocal);
766  };
767 
768  int computeIntersections(int ireg, int n, const EGS_Vector &X,
769  const EGS_Vector &u, EGS_GeometryIntersections *isections) {
770  if (n < 1) {
771  return -1;
772  }
773  int ifirst = 0;
774  EGS_Float t, ttot = 0;
775  EGS_Vector x(X);
776  int imed;
777  //egsInformation("computeIntersections: ireg=%d x=(%g,%g,%g) "
778  // "u=(%g,%g,%g)\n",ireg,x.x,x.y,x.z,u.x,u.y,u.z);
779  if (ireg < 0) {
780  t = veryFar;
781  ireg = howfar(ireg,x,u,t,&imed);
782  if (ireg < 0) {
783  return 0;
784  }
785  isections[0].t = t;
786  isections[0].rhof = 1;
787  isections[0].ireg = -1;
788  isections[0].imed = -1;
789  ttot = t;
790  ++ifirst;
791  x += u*t;
792  //egsInformation("entered after t=%g in ireg=%d at x=(%g,%g,%g)\n",
793  // t,ireg,x.x,x.y,x.z);
794  }
795  else {
796  imed = medium(ireg);
797  }
798 
799 
800  int j = ifirst;
801  int ij = -1, ig=0;
802  for (EGS_I64 loopCount=0; loopCount<=loopMax; ++loopCount) {
803  if (loopCount == loopMax) {
804  egsFatal("EGS_FastEnvelope::computeIntersections: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
805  return -1;
806  }
807  //egsInformation("in loop: j=%d ireg=%d imed=%d x=(%g,%g,%g)\n",
808  // j,ireg,imed,x.x,x.y,x.z);
809  if (ireg >= nbase) {
810  ig = (ireg - nbase)/nmax;
811  ij = ireg - nbase - ig*nmax;
812  }
813  isections[j].imed = imed;
814  isections[j].ireg = ireg;
815  isections[j].rhof = getRelativeRho(ireg);
816  if (ireg < nbase) { // in one of the regions of the base geometry
817  t = veryFar;
818  int ibase = g->howfar(ireg,x,u,t,&imed);
819  //egsInformation("In base geometry: t=%g inew=%d\n",t,ibase);
820  ij = -1;
821  for (int ii=n_start[ireg]; ii<n_start[ireg+1]; ii++) {
822  int i = glist[ii];
823  int ireg_i = geometries[i]->howfar(-1,x,u,t,&imed);
824  if (ireg_i >= 0) {
825  ij = ireg_i;
826  ig = i;
827  }
828  }
829  ttot += t;
830  isections[j++].t = ttot;
831  //egsInformation("after inscribed loop: t=%g ij=%d ig=%d"
832  // " ttot=%g\n",t,ij,ig,ttot);
833  if (ij < 0) {
834  ireg = ibase;
835  }
836  else {
837  ireg = nbase + ig*nmax + ij;
838  }
839  if (ireg < 0) {
840  return j;
841  }
842  if (j >= n) {
843  return -1;
844  }
845  x += u*t;
846  }
847  else {
848  int iadd = nbase + ig*nmax;
849  int nsec = geometries[ig]->computeIntersections(ij,n-j,
850  x,u,&isections[j]);
851  //egsInformation("In inscribed %d: got %d intersections\n",ig,
852  // nsec);
853  int nm = nsec >= 0 ? nsec+j : n;
854  for (int i=j; i<nm; i++) {
855  isections[i].ireg += iadd;
856  isections[i].t += ttot;
857  }
858  //egsInformation("last intersection: %g\n",isections[nm-1].t);
859  if (nsec < 0) {
860  return nsec;
861  }
862  j += nsec;
863  if (j >= n) {
864  return -1;
865  }
866  t = isections[j-1].t - ttot;
867  x += u*t;
868  ttot = isections[j-1].t;
869  ireg = g->isWhere(x);
870  //egsInformation("new region: %d\n",ireg);
871  if (ireg < 0) {
872  return j;
873  }
874  imed = g->medium(ireg);
875  }
876  }
877  return -1;
878  }
879 
880  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
881  const EGS_Vector &u) {
882  if (ireg < 0) {
883  return 0;
884  }
885  EGS_Float d;
886  if (ireg < nbase) {
887  d = g->howfarToOutside(ireg,x,u);
888  }
889  else if (g->regions() == 1) {
890  d = g->howfarToOutside(0,x,u);
891  }
892  else {
893  int ir = g->isWhere(x);
894  d = g->howfarToOutside(ir,x,u);
895  }
896  return d;
897  };
898 
899  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
900  EGS_Float &t, int *newmed = 0, EGS_Vector *normal = 0) {
901  if (ireg >= 0) {
902  // inside.
903  if (ireg < nbase) {
904  // in one of the regions of the base geometry
905  // check if we hit a boundary in the base geometry.
906  // if we do, newmed and normal get set accordingly.
907  int ibase = g->howfar(ireg,x,u,t,newmed,normal);
908  int ij = -1, jg;
909  // check if we will enter any of the inscribed geometries
910  // before entering a new region in the base geometry.
911  for (int jj=n_start[ireg]; jj<n_start[ireg+1]; jj++) {
912  int j = glist[jj];
913  int ireg_j =
914  geometries[j]->howfar(-1,x,u,t,newmed,normal);
915  if (ireg_j >= 0) {
916  // we do. remember the inscribed geometry index
917  // and local region
918  ij = ireg_j;
919  jg = j;
920  }
921  }
922  if (ij < 0) {
923  return ibase;
924  }
925  // ij<0 implies that we have not hit any of the
926  // inscribed geometries => return the base geometry index.
927  // ij>=0 implies that we entered inscribed geometry
928  // jg in its local region ij.
929  return nbase + jg*nmax + ij;
930  }
931  // if here, we are in an inscribed geometry.
932  // calculate its index (jg) and its local region (ilocal).
933  int jg = (ireg - nbase)/nmax;
934  int ilocal = ireg - nbase - jg*nmax;
935  // and then check if we will hit a boundary in this geometry.
936  int inew = geometries[jg]->howfar(ilocal,x,u,t,newmed,normal);
937  if (inew >= 0) {
938  return nbase + jg*nmax + inew;
939  }
940  // inew >= 0 implies that we either stay in the same
941  // region (inew=ilocal) or we entered a new region
942  // (inew!=ilocal), which is still inside the inscribed geometry
943  // inew<0 implies that we have exited the inscribed geometry
944  // => check to see in which base geometry region we are.
945  inew = g->isWhere(x+u*t);
946  if (inew >= 0 && newmed) {
947  *newmed = g->medium(inew);
948  }
949  return inew;
950  }
951  // if here, we are outside the base geometry.
952  // check to see if we will enter.
953  int ienter = g->howfar(ireg,x,u,t,newmed,normal);
954  if (ienter >= 0) {
955  // yes, we do. see if we are already inside of one of the
956  // inscribed geometries.
957  //if( n_start[ienter] < 0 ) return ienter;
958  for (int jj=n_start[ienter]; jj<n_start[ienter+1]; jj++) {
959  int j = glist[jj];
960  int i = geometries[j]->isWhere(x+u*t);
961  if (i >= 0) {
962  // yes, we are.
963  if (newmed) {
964  *newmed = geometries[j]->medium(i);
965  }
966  return nbase + nmax*j + i;
967  }
968  }
969  }
970  return ienter;
971  };
972 
973  EGS_Float hownear(int ireg, const EGS_Vector &x) {
974  if (ireg >= 0) {
975  EGS_Float tmin;
976  if (ireg < nbase) { // in one of the regions of the base geom.
977  tmin = g->hownear(ireg,x);
978  if (tmin <= 0) {
979  return tmin;
980  }
981  for (int jj=n_start[ireg]; jj<n_start[ireg+1]; jj++) {
982  int j = glist[jj];
983  EGS_Float tj = geometries[j]->hownear(-1,x);
984  if (tj < tmin) {
985  tmin = tj;
986  if (tmin <= 0) {
987  return tmin;
988  }
989  }
990  }
991  return tmin;
992  }
993  int jg = (ireg - nbase)/nmax;
994  int ilocal = ireg - nbase - jg*nmax;
995  return geometries[jg]->hownear(ilocal,x);
996  }
997  return g->hownear(ireg,x);
998  };
999 
1000  bool hasBooleanProperty(int ireg, EGS_BPType prop) const {
1001  if (ireg >= 0 && ireg < nreg) {
1002  if (ireg < nbase) {
1003  return g->hasBooleanProperty(ireg,prop);
1004  }
1005  int jg = (ireg - nbase)/nmax;
1006  int ilocal = ireg - nbase - jg*nmax;
1007  return geometries[jg]->hasBooleanProperty(ilocal,prop);
1008  }
1009  return false;
1010  };
1011  void setBooleanProperty(EGS_BPType) {
1012  setPropertyError("setBooleanProperty()");
1013  };
1014  void addBooleanProperty(int) {
1015  setPropertyError("addBooleanProperty()");
1016  };
1017  void setBooleanProperty(EGS_BPType,int,int,int step=1) {
1018  setPropertyError("setBooleanProperty()");
1019  };
1020  void addBooleanProperty(int,int,int,int step=1) {
1021  setPropertyError("addBooleanProperty()");
1022  };
1023 
1024  int getMaxStep() const {
1025  int nstep = g->getMaxStep();
1026  for (int j=0; j<n_in; ++j) {
1027  nstep += geometries[j]->getMaxStep();
1028  }
1029  return nstep+n_in;
1030  };
1031 
1032  const string &getType() const {
1033  return type;
1034  };
1035 
1036  void printInfo() const;
1037 
1038  void setRelativeRho(int start, int end, EGS_Float rho);
1039  void setRelativeRho(EGS_Input *);
1040  EGS_Float getRelativeRho(int ireg) const {
1041  if (ireg < 0 || ireg >= nreg) {
1042  return 1;
1043  }
1044  if (ireg < nbase) {
1045  return g->getRelativeRho(ireg);
1046  }
1047  int jg = (ireg - nbase)/nmax;
1048  return geometries[jg]->getRelativeRho(ireg - nbase - jg*nmax);
1049  };
1050 
1051  void setBScaling(int start, int end, EGS_Float bf);
1052  void setBScaling(EGS_Input *);
1053  EGS_Float getBScaling(int ireg) const {
1054  if (ireg < 0 || ireg >= nreg) {
1055  return 1;
1056  }
1057  if (ireg < nbase) {
1058  return g->getBScaling(ireg);
1059  }
1060  int jg = (ireg - nbase)/nmax;
1061  return geometries[jg]->getBScaling(ireg - nbase - jg*nmax);
1062  };
1063 
1064  virtual void getLabelRegions(const string &str, vector<int> &regs);
1065 
1066 protected:
1067 
1070  int n_in;
1071  int nbase,
1074  int *glist;
1075  int *n_start;
1076  static string type;
1077 
1081 
1088  void setMedia(EGS_Input *,int,const int *);
1089 
1090 private:
1091 
1092  void setPropertyError(const char *funcname) {
1093  egsFatal("EGS_FastEnvelope::%s: don't use this method\n Define "
1094  "properties in the constituent geometries instead\n",
1095  funcname);
1096  };
1097 
1098 
1099 };
1100 
1101 #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 void getLabelRegions(const string &str, vector< int > &regs)
Get the list of all regions labeled with str.
virtual int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u, EGS_Float &t, int *newmed=0, EGS_Vector *normal=0)=0
Calculate the distance to a boundary from x along the direction u.
virtual 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.
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 int isWhere(const EGS_Vector &x)=0
In which region is poisition x?
An envelope geometry class.
EGS_BaseGeometry * g
The envelope geometry.
int n_in
Number of inscribed geometries.
static string type
Geometry type.
int * local_start
First region for each inscribed geometry.
int nbase
Number of regions in the base geometry.
bool new_indexing
If true, use new indexing style.
EGS_BaseGeometry ** geometries
The inscribed geometries.
int * reg_to_inscr
Region to inscribed geometry conversion.
An envelope geometry class.
int nbase
Number of regions in the base geometry.
EGS_BaseGeometry ** geometries
The inscribed geometries.
int * local_start
First region for each inscribed geometry.
int n_in
Number of inscribed geometries.
int * reg_to_inscr
Region to inscribed geometry conversion.
EGS_BaseGeometry * g
The envelope geometry.
static string type
Geometry type.
bool new_indexing
If true, use new indexing style.
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
Base random number generator class. All random number generators should be derived from this class.
Definition: egs_rndm.h:67
A class representing 3D vectors.
Definition: egs_vector.h:57
EGS_BaseGeometry class header file.
Global egspp functions 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
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