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 
421  if (ireg >= 0) {
422  // inside.
423  if (ireg < nbase) {
424  // in one of the regions of the base geometry
425  // check if we hit a boundary in the base geometry.
426  // if we do, newmed and normal get set accordingly.
427  int ibase = g->howfar(ireg,x,u,t,newmed,normal);
428  int ij = -1, jg;
429  // check if we will enter any of the inscribed geometries
430  // before entering a new region in the base geometry.
431  for (int j=0; j<n_in; j++) {
432  int ireg_j =
433  geometries[j]->howfar(-1,x,u,t,newmed,normal);
434  if (ireg_j >= 0) {
435  // we do. remember the inscribed geometry index
436  // and local region
437  ij = ireg_j;
438  jg = j;
439  }
440  }
441  if (ij < 0) {
442  return ibase;
443  }
444  // ij<0 implies that we have not hit any of the
445  // inscribed geometries => return the base geometry index.
446  // ij>=0 implies that we entered inscribed geometry
447  // jg in its local region ij.
448  return new_indexing ? local_start[jg] + ij : 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) {
464  return new_indexing ? local_start[jg] + inew : nbase + jg*nmax + inew;
465  }
466  // inew >= 0 implies that we either stay in the same
467  // region (inew=ilocal) or we entered a new region
468  // (inew!=ilocal), which is still inside the inscribed geometry
469  // inew<0 implies that we have exited the inscribed geometry
470  // => check to see in which base geometry region we are.
471  inew = g->isWhere(x+u*t);
472  if (inew >= 0 && newmed) {
473  *newmed = g->medium(inew);
474  }
475  return inew;
476  }
477  // if here, we are outside the base geometry.
478  // check to see if we will enter.
479  int ienter = g->howfar(ireg,x,u,t,newmed,normal);
480  if (ienter >= 0) {
481  // yes, we do. see if we are already inside of one of the
482  // inscribed geometries.
483  for (int j=0; j<n_in; j++) {
484  int i = geometries[j]->isWhere(x+u*t);
485  if (i >= 0) {
486  // yes, we are.
487  if (newmed) {
488  *newmed = geometries[j]->medium(i);
489  }
490  return new_indexing ? local_start[j] + i : 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  if (geometries[j]) {
533  geometries[j]->getNextGeom(rndm);
534  }
535  }
536  if (g) {
537  g->getNextGeom(rndm);
538  }
539  };
540 
541  void updatePosition(EGS_Float time) {
542  // calls updatePosition on its component geometries to update dynamic
543  // geometries in the simulation
544  for (int j=0; j<n_in; j++) {
545  if (geometries[j]) {
546  geometries[j]->updatePosition(time);
547  }
548  }
549  if (g) {
550  g->updatePosition(time);
551  }
552  };
553 
554  void containsDynamic(bool &hasdynamic) {
555  // calls containsDynamic on its component geometries (only calls if
556  // hasDynamic is false, as if it is true we already found one)
557  for (int j=0; j<n_in; j++) {
558  if (!hasdynamic && geometries[j]) {
559  geometries[j]->containsDynamic(hasdynamic);
560  }
561  }
562  if (!hasdynamic && g) {
563  g->containsDynamic(hasdynamic);
564  }
565  };
566 
567  bool hasRhoScaling() override {
568  if (has_rho_scaling) {
569  return has_rho_scaling;
570  }
571 
572  for (int j=0; j<n_in; j++) {
573  bool hasRS = geometries[j]->hasRhoScaling();
574  if (hasRS) {
575  has_rho_scaling = hasRS;
576  return has_rho_scaling;
577  }
578  }
579 
580  return g->hasRhoScaling();
581  };
582 
583  void finishInitialization() {
584  for (int j=0; j<n_in; j++) {
585  geometries[j]->finishInitialization();
586  }
587  g->finishInitialization();
588  };
589 
590  int getMaxStep() const {
591  int nstep = g->getMaxStep();
592  for (int j=0; j<n_in; ++j) {
593  nstep += geometries[j]->getMaxStep();
594  }
595  return nstep+n_in;
596  };
597 
598  bool hasBooleanProperty(int ireg, EGS_BPType prop) const {
599  if (ireg >= 0 && ireg < nreg) {
600  if (ireg < nbase) {
601  return g->hasBooleanProperty(ireg,prop);
602  }
603  int jg = (ireg - nbase)/nmax;
604  int ilocal = ireg - nbase - jg*nmax;
605  return geometries[jg]->hasBooleanProperty(ilocal,prop);
606  }
607  return false;
608  };
609  void setBooleanProperty(EGS_BPType) {
610  setPropertyError("setBooleanProperty()");
611  };
612  void addBooleanProperty(int) {
613  setPropertyError("addBooleanProperty()");
614  };
615  void setBooleanProperty(EGS_BPType,int,int,int step=1) {
616  setPropertyError("setBooleanProperty()");
617  };
618  void addBooleanProperty(int,int,int,int step=1) {
619  setPropertyError("addBooleanProperty()");
620  };
621 
622  const string &getType() const {
623  return type;
624  };
625 
626  EGS_BaseGeometry **getInscribedGeometries(std::size_t &nInscribed) const {
627  nInscribed = n_in;
628  return geometries;
629  }
630 
631  void printInfo() const;
632 
633  void setRelativeRho(int start, int end, EGS_Float rho);
634  void setRelativeRho(EGS_Input *);
635  EGS_Float getRelativeRho(int ireg) const {
636  if (ireg < 0 || ireg >= nreg) {
637  return 1;
638  }
639  if (ireg < nbase) {
640  return g->getRelativeRho(ireg);
641  }
642  int jg = (ireg - nbase)/nmax;
643  return geometries[jg]->getRelativeRho(ireg - nbase - jg*nmax);
644  };
645 
646  void setBScaling(int start, int end, EGS_Float bf);
647  void setBScaling(EGS_Input *);
648  EGS_Float getBScaling(int ireg) const {
649  if (ireg < 0 || ireg >= nreg) {
650  return 1;
651  }
652  if (ireg < nbase) {
653  return g->getBScaling(ireg);
654  }
655  int jg = (ireg - nbase)/nmax;
656  return geometries[jg]->getBScaling(ireg - nbase - jg*nmax);
657  };
658 
659  virtual int getGlobalRegionOffset(const string geomName);
660  virtual void getLabelRegions(const string &str, vector<int> &regs, bool sanitize=true);
661 
662 protected:
663 
666  int n_in;
667  int nbase,
670  static string type;
671 
674  int *local_start;
675 
682  void setMedia(EGS_Input *,int,const int *);
683 
684 private:
685 
686  void setPropertyError(const char *funcname) {
687  egsFatal("EGS_EnvelopeGeometry::%s: don't use this method\n Define "
688  "properties in the constituent geometries instead\n",
689  funcname);
690  };
691 
692 };
693 
694 
695 struct EnvelopeAux;
696 
705 class EGS_ENVELOPEG_EXPORT EGS_FastEnvelope : public EGS_BaseGeometry {
706 
707 public:
708 
710  const vector<EnvelopeAux *> &fgeoms, const string &Name = "",
711  int newindexing=false);
712 
713  ~EGS_FastEnvelope();
714 
715  bool isRealRegion(int ireg) const {
716  if (ireg < 0 || ireg >= nreg) {
717  return false;
718  }
719  if (ireg < nbase) {
720  return g->isRealRegion(ireg);
721  }
722  int jg, ilocal;
723  if (new_indexing) {
724  jg = reg_to_inscr[ireg-nbase];
725  ilocal = ireg - local_start[jg];
726  }
727  else {
728  jg = (ireg - nbase)/nmax;
729  ilocal = ireg - nbase - jg*nmax;
730  }
731  return geometries[jg]->isRealRegion(ilocal);
732  };
733 
734  bool isInside(const EGS_Vector &x) {
735  return g->isInside(x);
736  };
737 
738  int isWhere(const EGS_Vector &x) {
739  int ireg = g->isWhere(x);
740  if (ireg < 0 || n_start[ireg] < 0) {
741  return ireg;
742  }
743  for (int jj=n_start[ireg]; jj<n_start[ireg+1]; jj++) {
744  int j = glist[jj];
745  int i = geometries[j]->isWhere(x);
746  if (i >= 0) {
747  return nbase + nmax*j + i;
748  }
749  }
750  return ireg;
751  };
752 
753  void getNextGeom(EGS_RandomGenerator *rndm) {
754  // calls getNextGeom on its component geometries to update dynamic
755  // geometries in the simulation
756  for (int j=0; j<n_in; j++) {
757  geometries[j]->getNextGeom(rndm);
758  }
759  g->getNextGeom(rndm);
760  };
761 
762  void updatePosition(EGS_Float time) {
763  // calls updatePosition on its component geometries to update dynamic
764  // geometries in the simulation
765  for (int j=0; j<n_in; j++) {
766  geometries[j]->updatePosition(time);
767  }
768  g->updatePosition(time);
769  };
770 
771  void containsDynamic(bool &hasdynamic) {
772  // calls containsDynamic on its component geometries (only calls if
773  // hasDynamic is false, as if it is true we already found one)
774  for (int j=0; j<n_in; j++) {
775  if (!hasdynamic) {
776  geometries[j]->containsDynamic(hasdynamic);
777  }
778  }
779  if (!hasdynamic) {
780  g->containsDynamic(hasdynamic);
781  }
782  };
783 
784  bool hasRhoScaling() override {
785  if (has_rho_scaling) {
786  return has_rho_scaling;
787  }
788 
789  for (int j=0; j<n_in; j++) {
790  bool hasRS = geometries[j]->hasRhoScaling();
791  if (hasRS) {
792  has_rho_scaling = hasRS;
793  return has_rho_scaling;
794  }
795  }
796 
797  return g->hasRhoScaling();
798  };
799 
800  void finishInitialization() override {
801  for (int j=0; j<n_in; j++) {
802  geometries[j]->finishInitialization();
803  }
804  g->finishInitialization();
805  };
806 
807 
808  int inside(const EGS_Vector &x) {
809  return isWhere(x);
810  };
811 
812  int medium(int ireg) const {
813  if (ireg < nbase) {
814  return g->medium(ireg);
815  }
816  int jg = (ireg - nbase)/nmax;
817  int ilocal = ireg - nbase - jg*nmax;
818  return geometries[jg]->medium(ilocal);
819  };
820 
821  int computeIntersections(int ireg, int n, const EGS_Vector &X,
822  const EGS_Vector &u, EGS_GeometryIntersections *isections) {
823  if (n < 1) {
824  return -1;
825  }
826  int ifirst = 0;
827  EGS_Float t, ttot = 0;
828  EGS_Vector x(X);
829  int imed;
830  //egsInformation("computeIntersections: ireg=%d x=(%g,%g,%g) "
831  // "u=(%g,%g,%g)\n",ireg,x.x,x.y,x.z,u.x,u.y,u.z);
832  if (ireg < 0) {
833  t = veryFar;
834  ireg = howfar(ireg,x,u,t,&imed);
835  if (ireg < 0) {
836  return 0;
837  }
838  isections[0].t = t;
839  isections[0].rhof = 1;
840  isections[0].ireg = -1;
841  isections[0].imed = -1;
842  ttot = t;
843  ++ifirst;
844  x += u*t;
845  //egsInformation("entered after t=%g in ireg=%d at x=(%g,%g,%g)\n",
846  // t,ireg,x.x,x.y,x.z);
847  }
848  else {
849  imed = medium(ireg);
850  }
851 
852 
853  int j = ifirst;
854  int ij = -1, ig=0;
855  for (EGS_I64 loopCount=0; loopCount<=loopMax; ++loopCount) {
856  if (loopCount == loopMax) {
857  egsFatal("EGS_FastEnvelope::computeIntersections: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
858  return -1;
859  }
860  //egsInformation("in loop: j=%d ireg=%d imed=%d x=(%g,%g,%g)\n",
861  // j,ireg,imed,x.x,x.y,x.z);
862  if (ireg >= nbase) {
863  ig = (ireg - nbase)/nmax;
864  ij = ireg - nbase - ig*nmax;
865  }
866  isections[j].imed = imed;
867  isections[j].ireg = ireg;
868  isections[j].rhof = getRelativeRho(ireg);
869  if (ireg < nbase) { // in one of the regions of the base geometry
870  t = veryFar;
871  int ibase = g->howfar(ireg,x,u,t,&imed);
872  //egsInformation("In base geometry: t=%g inew=%d\n",t,ibase);
873  ij = -1;
874  for (int ii=n_start[ireg]; ii<n_start[ireg+1]; ii++) {
875  int i = glist[ii];
876  int ireg_i = geometries[i]->howfar(-1,x,u,t,&imed);
877  if (ireg_i >= 0) {
878  ij = ireg_i;
879  ig = i;
880  }
881  }
882  ttot += t;
883  isections[j++].t = ttot;
884  //egsInformation("after inscribed loop: t=%g ij=%d ig=%d"
885  // " ttot=%g\n",t,ij,ig,ttot);
886  if (ij < 0) {
887  ireg = ibase;
888  }
889  else {
890  ireg = nbase + ig*nmax + ij;
891  }
892  if (ireg < 0) {
893  return j;
894  }
895  if (j >= n) {
896  return -1;
897  }
898  x += u*t;
899  }
900  else {
901  int iadd = nbase + ig*nmax;
902  int nsec = geometries[ig]->computeIntersections(ij,n-j,
903  x,u,&isections[j]);
904  //egsInformation("In inscribed %d: got %d intersections\n",ig,
905  // nsec);
906  int nm = nsec >= 0 ? nsec+j : n;
907  for (int i=j; i<nm; i++) {
908  isections[i].ireg += iadd;
909  isections[i].t += ttot;
910  }
911  //egsInformation("last intersection: %g\n",isections[nm-1].t);
912  if (nsec < 0) {
913  return nsec;
914  }
915  j += nsec;
916  if (j >= n) {
917  return -1;
918  }
919  t = isections[j-1].t - ttot;
920  x += u*t;
921  ttot = isections[j-1].t;
922  ireg = g->isWhere(x);
923  //egsInformation("new region: %d\n",ireg);
924  if (ireg < 0) {
925  return j;
926  }
927  imed = g->medium(ireg);
928  }
929  }
930  return -1;
931  }
932 
933  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
934  const EGS_Vector &u) {
935  if (ireg < 0) {
936  return 0;
937  }
938  EGS_Float d;
939  if (ireg < nbase) {
940  d = g->howfarToOutside(ireg,x,u);
941  }
942  else if (g->regions() == 1) {
943  d = g->howfarToOutside(0,x,u);
944  }
945  else {
946  int ir = g->isWhere(x);
947  d = g->howfarToOutside(ir,x,u);
948  }
949  return d;
950  };
951 
952  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
953  EGS_Float &t, int *newmed = 0, EGS_Vector *normal = 0) {
954  if (ireg >= 0) {
955  // inside.
956  if (ireg < nbase) {
957  // in one of the regions of the base geometry
958  // check if we hit a boundary in the base geometry.
959  // if we do, newmed and normal get set accordingly.
960  int ibase = g->howfar(ireg,x,u,t,newmed,normal);
961  int ij = -1, jg;
962  // check if we will enter any of the inscribed geometries
963  // before entering a new region in the base geometry.
964  for (int jj=n_start[ireg]; jj<n_start[ireg+1]; jj++) {
965  int j = glist[jj];
966  int ireg_j =
967  geometries[j]->howfar(-1,x,u,t,newmed,normal);
968  if (ireg_j >= 0) {
969  // we do. remember the inscribed geometry index
970  // and local region
971  ij = ireg_j;
972  jg = j;
973  }
974  }
975  if (ij < 0) {
976  return ibase;
977  }
978  // ij<0 implies that we have not hit any of the
979  // inscribed geometries => return the base geometry index.
980  // ij>=0 implies that we entered inscribed geometry
981  // jg in its local region ij.
982  return nbase + jg*nmax + ij;
983  }
984  // if here, we are in an inscribed geometry.
985  // calculate its index (jg) and its local region (ilocal).
986  int jg = (ireg - nbase)/nmax;
987  int ilocal = ireg - nbase - jg*nmax;
988  // and then check if we will hit a boundary in this geometry.
989  int inew = geometries[jg]->howfar(ilocal,x,u,t,newmed,normal);
990  if (inew >= 0) {
991  return nbase + jg*nmax + inew;
992  }
993  // inew >= 0 implies that we either stay in the same
994  // region (inew=ilocal) or we entered a new region
995  // (inew!=ilocal), which is still inside the inscribed geometry
996  // inew<0 implies that we have exited the inscribed geometry
997  // => check to see in which base geometry region we are.
998  inew = g->isWhere(x+u*t);
999  if (inew >= 0 && newmed) {
1000  *newmed = g->medium(inew);
1001  }
1002  return inew;
1003  }
1004  // if here, we are outside the base geometry.
1005  // check to see if we will enter.
1006  int ienter = g->howfar(ireg,x,u,t,newmed,normal);
1007  if (ienter >= 0) {
1008  // yes, we do. see if we are already inside of one of the
1009  // inscribed geometries.
1010  //if( n_start[ienter] < 0 ) return ienter;
1011  for (int jj=n_start[ienter]; jj<n_start[ienter+1]; jj++) {
1012  int j = glist[jj];
1013  int i = geometries[j]->isWhere(x+u*t);
1014  if (i >= 0) {
1015  // yes, we are.
1016  if (newmed) {
1017  *newmed = geometries[j]->medium(i);
1018  }
1019  return nbase + nmax*j + i;
1020  }
1021  }
1022  }
1023  return ienter;
1024  };
1025 
1026  EGS_Float hownear(int ireg, const EGS_Vector &x) {
1027  if (ireg >= 0) {
1028  EGS_Float tmin;
1029  if (ireg < nbase) { // in one of the regions of the base geom.
1030  tmin = g->hownear(ireg,x);
1031  if (tmin <= 0) {
1032  return tmin;
1033  }
1034  for (int jj=n_start[ireg]; jj<n_start[ireg+1]; jj++) {
1035  int j = glist[jj];
1036  EGS_Float tj = geometries[j]->hownear(-1,x);
1037  if (tj < tmin) {
1038  tmin = tj;
1039  if (tmin <= 0) {
1040  return tmin;
1041  }
1042  }
1043  }
1044  return tmin;
1045  }
1046  int jg = (ireg - nbase)/nmax;
1047  int ilocal = ireg - nbase - jg*nmax;
1048  return geometries[jg]->hownear(ilocal,x);
1049  }
1050  return g->hownear(ireg,x);
1051  };
1052 
1053  bool hasBooleanProperty(int ireg, EGS_BPType prop) const {
1054  if (ireg >= 0 && ireg < nreg) {
1055  if (ireg < nbase) {
1056  return g->hasBooleanProperty(ireg,prop);
1057  }
1058  int jg = (ireg - nbase)/nmax;
1059  int ilocal = ireg - nbase - jg*nmax;
1060  return geometries[jg]->hasBooleanProperty(ilocal,prop);
1061  }
1062  return false;
1063  };
1064  void setBooleanProperty(EGS_BPType) {
1065  setPropertyError("setBooleanProperty()");
1066  };
1067  void addBooleanProperty(int) {
1068  setPropertyError("addBooleanProperty()");
1069  };
1070  void setBooleanProperty(EGS_BPType,int,int,int step=1) {
1071  setPropertyError("setBooleanProperty()");
1072  };
1073  void addBooleanProperty(int,int,int,int step=1) {
1074  setPropertyError("addBooleanProperty()");
1075  };
1076 
1077  int getMaxStep() const {
1078  int nstep = g->getMaxStep();
1079  for (int j=0; j<n_in; ++j) {
1080  nstep += geometries[j]->getMaxStep();
1081  }
1082  return nstep+n_in;
1083  };
1084 
1085  const string &getType() const {
1086  return type;
1087  };
1088 
1089  void printInfo() const;
1090 
1091  void setRelativeRho(int start, int end, EGS_Float rho);
1092  void setRelativeRho(EGS_Input *);
1093  EGS_Float getRelativeRho(int ireg) const {
1094  if (ireg < 0 || ireg >= nreg) {
1095  return 1;
1096  }
1097  if (ireg < nbase) {
1098  return g->getRelativeRho(ireg);
1099  }
1100  int jg = (ireg - nbase)/nmax;
1101  return geometries[jg]->getRelativeRho(ireg - nbase - jg*nmax);
1102  };
1103 
1104  void setBScaling(int start, int end, EGS_Float bf);
1105  void setBScaling(EGS_Input *);
1106  EGS_Float getBScaling(int ireg) const {
1107  if (ireg < 0 || ireg >= nreg) {
1108  return 1;
1109  }
1110  if (ireg < nbase) {
1111  return g->getBScaling(ireg);
1112  }
1113  int jg = (ireg - nbase)/nmax;
1114  return geometries[jg]->getBScaling(ireg - nbase - jg*nmax);
1115  };
1116 
1117  virtual int getGlobalRegionOffset(const string geomName);
1118  virtual void getLabelRegions(const string &str, vector<int> &regs, bool sanitize=true);
1119 
1120 protected:
1121 
1124  int n_in;
1125  int nbase,
1128  int *glist;
1129  int *n_start;
1130  static string type;
1131 
1135 
1142  void setMedia(EGS_Input *,int,const int *);
1143 
1144 private:
1145 
1146  void setPropertyError(const char *funcname) {
1147  egsFatal("EGS_FastEnvelope::%s: don't use this method\n Define "
1148  "properties in the constituent geometries instead\n",
1149  funcname);
1150  };
1151 
1152 
1153 };
1154 
1155 #endif
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
virtual int getGlobalRegionOffset(const string geomName)
Get the global region number for the first region in the geometry.
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.
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?
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:90
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