EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_cd_geometry.h
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ cd 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 # Marc Chamberland
30 # Alexandre Demelo
31 #
32 ###############################################################################
33 */
34 
35 
41 #ifndef EGS_CD_GEOMETRY_
42 #define EGS_CD_GEOMETRY_
43 
44 #include "egs_base_geometry.h"
45 #include "egs_functions.h"
46 
47 #ifdef WIN32
48 
49  #ifdef BUILD_CDGEOMETRY_DLL
50  #define EGS_CDGEOMETRY_EXPORT __declspec(dllexport)
51  #else
52  #define EGS_CDGEOMETRY_EXPORT __declspec(dllimport)
53  #endif
54  #define EGS_CDGEOMETRY_LOCAL
55 
56 #else
57 
58  #ifdef HAVE_VISIBILITY
59  #define EGS_CDGEOMETRY_EXPORT __attribute__ ((visibility ("default")))
60  #define EGS_CDGEOMETRY_LOCAL __attribute__ ((visibility ("hidden")))
61  #else
62  #define EGS_CDGEOMETRY_EXPORT
63  #define EGS_CDGEOMETRY_LOCAL
64  #endif
65 
66 #endif
67 
68 #include <vector>
69 using std::vector;
70 
265 class EGS_CDGEOMETRY_EXPORT EGS_CDGeometry : public EGS_BaseGeometry {
266 
267 public:
268 
269 
271  const string &Name = "", int indexing=0) : EGS_BaseGeometry(Name) {
272  nmax = 0;
273  new_indexing = false;
274  reg_to_base = 0;
275  local_start = 0;
276  nbase = G1->regions();
277  g = new EGS_BaseGeometry* [nbase];
278  bg = G1; //bg->ref();
279  for (int j=0; j<nbase; j++) {
280  g[j] = G[j];
281  if (g[j]) {
282  //g[j]->ref();
283  int n = g[j]->regions();
284  if (n > nmax) {
285  nmax = n;
286  }
287  }
288  }
289  if (!nmax) {
290  nmax = 1;
291  }
292  nreg = nbase*nmax;
293  is_convex = false;
294  if (indexing) {
295  setUpIndexing();
296  }
297  setHasRhoScaling();
298  setHasBScaling();
299  };
300 
301  EGS_CDGeometry(EGS_BaseGeometry *G1, const vector<EGS_BaseGeometry *> &G,
302  const string &Name = "",int indexing=0) : EGS_BaseGeometry(Name) {
303  if (!G1) egsFatal("EGS_CDGeometry: got a null pointer to the"
304  " base geometry?\n");
305  nbase = G1->regions();
306  new_indexing = false;
307  reg_to_base = 0;
308  local_start = 0;
309  if (nbase != G.size()) egsFatal("EGS_CDGeometry: number of passed"
310  " geometries (%d) is not the same as the number of regions (%d)\n",
311  nbase,G.size());
312  nmax = 0;
313  g = new EGS_BaseGeometry* [nbase];
314  bg = G1; //bg->ref();
315  for (int j=0; j<nbase; j++) {
316  g[j] = G[j];
317  if (g[j]) {
318  //g[j]->ref();
319  int n = g[j]->regions();
320  if (n > nmax) {
321  nmax = n;
322  }
323  }
324  }
325  if (!nmax) {
326  nmax = 1;
327  }
328  nreg = nbase*nmax;
329  is_convex = false;
330  if (indexing) {
331  setUpIndexing();
332  }
333  setHasRhoScaling();
334  setHasBScaling();
335  };
336 
337 
338  ~EGS_CDGeometry() {
339  for (int j=0; j<nbase; j++) {
340  if (g[j]) {
341  if (!g[j]->deref()) {
342  delete g[j];
343  }
344  }
345  }
346  delete [] g;
347  if (!bg->deref()) {
348  delete bg;
349  }
350  if (new_indexing) {
351  if (reg_to_base) {
352  delete [] reg_to_base;
353  }
354  if (local_start) {
355  delete [] local_start;
356  }
357  }
358  };
359 
360  int medium(int ireg) const {
361  /*
362  int ibase = ireg/nmax;
363  if( g[ibase] ) return g[ibase]->medium(ireg-ibase*nmax);
364  return bg->medium(ibase);
365  */
366  int ibase, ilocal;
367  if (new_indexing) {
368  ibase = reg_to_base[ireg];
369  ilocal = ireg - local_start[ibase];
370  }
371  else {
372  ibase = ireg/nmax;
373  ilocal = ireg-ibase*nmax;
374  }
375  return g[ibase] ? g[ibase]->medium(ilocal) : bg->medium(ibase);
376  };
377 
378  bool isRealRegion(int ireg) const {
379  if (ireg < 0 || ireg >= nreg) {
380  return false;
381  }
382  int ibase, icd;
383  if (new_indexing) {
384  ibase = reg_to_base[ireg];
385  icd = ireg-local_start[ibase];
386  }
387  else {
388  ibase = ireg/nmax;
389  icd = ireg - ibase*nmax;
390  }
391  return g[ibase] ? g[ibase]->isRealRegion(icd) :
392  bg->isRealRegion(ibase);
393  };
394 
395  bool isInside(const EGS_Vector &x) {
396  int ibase = bg->isWhere(x);
397  if (ibase < 0) {
398  return false;
399  }
400  if (g[ibase]) {
401  return g[ibase]->isInside(x);
402  }
403  return true;
404  };
405 
406  int isWhere(const EGS_Vector &x) {
407  int ibase = bg->isWhere(x);
408  if (ibase < 0) {
409  return ibase;
410  }
411  int ir = 0;
412  if (g[ibase]) {
413  ir = g[ibase]->isWhere(x);
414  if (ir < 0) {
415  return ir;
416  }
417  }
418  return new_indexing ? local_start[ibase] + ir : ibase*nmax + ir;
419  };
420 
421  int inside(const EGS_Vector &x) {
422  return isWhere(x);
423  };
424 
425  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
426  EGS_Float &t, int *newmed = 0, EGS_Vector *normal = 0) {
427  if (ireg >= 0) {
428  //
429  // *** We are inside and ibase is the current base geometry
430  // region and icd the local region of the geometry inscribed
431  // in ibase (if any)
432  int ibase, icd;
433  if (new_indexing) {
434  ibase = reg_to_base[ireg];
435  icd = ireg-local_start[ibase];
436  }
437  else {
438  ibase = ireg/nmax;
439  icd = ireg - ibase*nmax;
440  }
441  //
442  // *** See if we will hit a boundary in the base geometry.
443  // If we do, newmed and normal will get set accordingly.
444  //
445  int ibase_new = bg->howfar(ibase,x,u,t,newmed,normal);
446  if (g[ibase]) {
447  //
448  // *** There is another geometry in this base geometry region.
449  // See if will hit one of its boundaries first.
450  //
451  int icd_new = g[ibase]->howfar(icd,x,u,t,newmed,normal);
452  if (icd_new < 0) {
453  return icd_new;
454  }
455  // above: yes we do but the new region is outside
456  // => we exit the entire geometry. newmed and normal
457  // must have been set accordingly.
458  if (icd_new != icd)
459  return new_indexing ? local_start[ibase] + icd_new :
460  ibase*nmax + icd_new;
461  // above: yes we do and we enter the local region icd_new
462  // => calculate the new region and return
463  // newmed and normal must have been set in g[ibase]->howfar
464  }
465  if (ibase_new != ibase) {
466  // we have entered a new base geometry region.
467  if (ibase_new < 0) {
468  return ibase_new;
469  }
470  // but this region is outside => just return.
471  if (g[ibase_new]) {
472  // there is a geometry in this new base geometry region.
473  // are we already inside?
474  EGS_Vector tmp(x + u*t);
475  int icd_new = g[ibase_new]->isWhere(tmp);
476  if (icd_new < 0) {
477  return icd_new;
478  }
479  // above: no, we are not => we exit the entire geometry.
480  // below: yes, we are in local region icd_new
481  // simply calculate the new global region and return
482  // newmed and normal have been set in bg->howfar above
483  if (newmed) {
484  *newmed = g[ibase_new]->medium(icd_new);
485  }
486  return new_indexing ? local_start[ibase_new] + icd_new :
487  ibase_new*nmax + icd_new;
488  }
489  // there is no cd geometry in this base geometry region
490  // => simply calculate the new global region and return
491  // newmed and normal have been set in bg->howfar above
492  return new_indexing ? local_start[ibase_new] : ibase_new*nmax;
493  }
494  // new region is the same as old region (i.e. we don't reach
495  // a boundary => simply return the old region.
496  return ireg;
497  }
498 
499  //
500  // *** If here, we are outside.
501  // Are we already inside the base geometry ?
502  //
503  int ibase = bg->isWhere(x);
504  EGS_Float tb=0, ttot=0;
505  bool first_time = true;// first time checking base geometry?
506  EGS_Vector n;
507  int mednew;
508  EGS_Vector *pn = normal ? &n : 0;
509  int *pmednew = newmed ? &mednew : 0;
510  if (ibase >= 0) {
511  //
512  // IK Feb 22 2007:
513  // The following seems flawed. Yes, if there is no inscribed
514  // geometry we can assume that ibase>=0 is due to roundoff,
515  // but if there is, we might as well be about to enter this
516  // geometry (but isInside() thinks that we are already inside).
517  // What would be the best way to check? Don't know yet.
518  //
519  // already inside the base geometry.
520  // unfortunately, due to roundoff we may think that
521  // we are inside the base geometry but we are actually
522  // outside. To make the logic below work, we need to
523  // check if we are inside the geometry inscribed in region
524  // ibase.
525  int icd = g[ibase] ? g[ibase]->isWhere(x) : 0;
526  if (icd >= 0) {
527 
528  // We think we are outside, but isWhere(x) reports that we are
529  // inside. This can be caused by numerical roundoff.
530  // There are 2 possibilities:
531  // a) The particle has just left geometry, but due to roundoff
532  // we still find it inside for the next step. This possibility
533  // can be checked by checking the distance to the exit point
534  // b) The particle is approaching the geometry but due to roundoff
535  // we already find it inside. This possibility can be checked
536  // by determining the distance to exit point moving along the
537  // direction oposite to the particle direction.
538  //***********************************************************************
539  // EMH April 12 2013: Check 0 for (b) below was ambiguosly defined as there
540  // will be situations where u and -u will not hit the geometry. An univocally
541  // defined test is to check whether particle actually enters the geometry from
542  // the boundary or a location near it (round-off).
543  // REMEMBER: - isWhere will return ir >= 0 when particle seats at a boundary.
544  // - We are here either due to roundoff or just at the boundary
545  //
546  // 0. Proper check for a and b)
547  int ixold = new_indexing ? local_start[ibase] + icd :
548  ibase*nmax + icd;
549  //EGS_Float tb_neg = 1e30; int ixnew_neg = howfar(ixold,x,u*(-1),tb_neg,0,pn);
550  //EGS_Float tb_pos = 1e30; int ixnew_pos = howfar(ixold,x,u,tb_pos,0,pn);
551  // Call to CD geometry howfar with updated region ixold. If it is aimed away from
552  // geometry, it will return ixnew = -1 and assumption a) was correct. If it is
553  // aimed into geometry, it will return ixnew >=0 and assumption b) was correct.
554  tb = veryFar;
555  int ixnew = howfar(ixold,x,u,tb,0,pn);
556  // Enters geometry and at a boundary or very close to one.
557  //if( ixnew_pos >= 0 && ixnew_neg < 0 && tb_neg <= boundaryTolerance && tb_pos <= boundaryTolerance) {
558  if (ixnew >= 0 && tb <= boundaryTolerance) { // (b) is true
559  t = 0;
560  if (newmed) *newmed = g[ibase] ? g[ibase]->medium(icd) :
561  bg->medium(ibase);
562  //if( normal ) *normal = (*pn)*(-1);
563  if (normal) {
564  *normal = *pn;
565  }
566  return ixold;
567  }
568  // Skip for concave geometries: particles can reenter the CD geometry after leaving.
569  // Check 2. below will catch these cases.
570  // This follow has been commented out because it fails in cases
571  // where the inscribe geometries are themselves convex but
572  // form a concave shape. Instead, just continue to do more checks.
573 // else if ((ixnew < 0 && tb <= boundaryTolerance) && (bg->isConvex() &&
574 // (g[ibase] && g[ibase]->isConvex()))) {
575 // // (a) is true
576 // return ixnew;
577 // }
578 
579  // If a particle approaching the geometry sits on a boundary, we look back to see
580  // if we just entered the geometry (the previous checks fail to catch this case).
581  EGS_Float tb_neg = veryFar;
582  int ixnew_neg = howfar(ixold,x,u*(-1),tb_neg,0,pn);
583  if (ixnew_neg < 0 && tb_neg <= epsilon) { // (b) is true
584  t = 0;
585  if (newmed) {
586  *newmed = g[ibase] ? g[ibase]->medium(icd) : bg->medium(ibase);
587  }
588  if (normal) {
589  *normal = (*pn)*(-1);
590  }
591  return ixold;
592  }
593 
594  //***********************************************************************
595 
596  // 1. Check if we exit the base geometry after a sufficiently small
597  // distance.
598  EGS_Float t1=veryFar, t2 = veryFar;
599  int ibase_n, ic_n=0;
600  ibase_n = bg->howfar(ibase,x,u,t1);
601  if (ibase_n < 0 && t1 < boundaryTolerance) {
602  // Yes we do => we assume that it was a roundoff problem
603  // and in reality the particle was outside the base geometry.
604  // We then check if it will enter the base geometry.
605  EGS_Vector xtmp(x + u*t1);
606  tb = t-t1;
607  ibase_n = bg->howfar(ibase_n,xtmp,u,tb,pmednew,pn);
608  if (ibase_n < 0) {
609  return ibase_n; // no, so just return.
610  }
611  // yes, so transport to entry point and follow normal outside logic
612  tb += t1;
613  ttot = tb;
614  ibase = ibase_n;
615  first_time = false;
616  goto do_checks;
617  }
618  // If here, particle is inside base geometry and also doesn't exit base geometry
619  // very soon. So, we must do check 2.:
620  // 2. Check if we exit the inscribed geometry after a sufficiently small
621  // distance.
622  if (g[ibase]) {
623  ic_n = g[ibase]->howfar(icd,x,u,t2);
624  if (ic_n < 0 && t2 < boundaryTolerance) {
625  // Yes we do => we assume that it was a roundoff problem
626  // and in reality the particle was outside the inscribed geometry.
627  // We move to the boundary and check again the base geometry.
628  EGS_Vector xtmp(x + u*t2);
629  ibase = bg->isWhere(xtmp);
630  if (ibase < 0) {
631  tb = t - t2;
632  ibase = bg->howfar(ibase,xtmp,u,tb,pmednew,pn);
633  if (ibase < 0) {
634  return ibase;
635  }
636  tb += t2;
637  ttot = tb;
638  first_time = false;
639  }
640  else {
641  tb = t2;
642  ttot = tb;
643  }
644  goto do_checks;
645  }
646  }
647  if (t1 < boundaryTolerance && ibase_n >= 0 && g[ibase_n]) {
648  // last resort.
649  EGS_Vector xtmp(x + u*t1);
650  int icdx = g[ibase_n]->isWhere(xtmp);
651  if (icdx < 0) {
652  tb = t1;
653  ttot = tb;
654  ibase = ibase_n;
655  first_time = true;
656  goto do_checks;
657  }
658  }
659  if (t1 > boundaryTolerance && t2 > boundaryTolerance) {
660  error_flag = 1;
661  egsWarning("EGS_CDGeometry::howfar: ireg<0, but position appears inside\n");
662  egsWarning(" name=%s base name=%s inscribed name=%s\n",name.c_str(),
663  bg->getName().c_str(),g[ibase] ? g[ibase]->getName().c_str() : "none");
664  egsWarning(" x=(%g,%g,%g) u=(%g,%g,%g) ibase=%d icd=%d\n",
665  x.x,x.y,x.z,u.x,u.y,u.z,ibase,icd);
666  egsWarning(" distance to boundaries: base=(%d,%g) inscribed=(%d,%g)\n",
667  ibase_n,t1,ic_n,t2);
668  }
669  }
670  if (icd >= 0) {
671  return ireg;
672  }
673  tb = 0;
674  ttot = 0;
675  } // yes, we are.
676  else {
677  // no, we are not. Check if we will enter the base geometry.
678  first_time = false;
679  tb = t;
680  ibase = bg->howfar(ireg,x,u,tb,pmednew,pn);
681  if (ibase < 0) {
682  return ibase; // no, we will not.
683  }
684  ttot = tb; // i.e. we enter the base geometry after a
685  // path-length of tb (wich is less than t).
686  // if this happens, newmed and normal are set
687  // by the bg->howfar call.
688  }
689 
690 do_checks:
691  EGS_Vector tmp(x + u*tb); // position at which we are inside
692  // the base geometry
693  for (EGS_I64 loopCount=0; loopCount<=loopMax; ++loopCount) {
694  if (loopCount == loopMax) {
695  egsFatal("EGS_CDGeometry::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
696  return -1;
697  }
698  if (!g[ibase]) { // no inscribed geometry in this base geometry region
699  t = ttot;
700  if (newmed) {
701  *newmed = mednew;
702  }
703  if (normal) {
704  *normal = n;
705  }
706  return new_indexing ? local_start[ibase] : ibase*nmax;
707  }
708  // => we have entered.
709  int icd = -1;
710  if (!first_time) { // already howfar-checked base geometry
711  icd = g[ibase]->isWhere(tmp);
712  if (icd >= 0) {
713  // already inside of the geometry of this base geometry
714  // region.
715  t = ttot;
716  if (newmed) {
717  *newmed = g[ibase]->medium(icd);
718  }
719  if (normal) {
720  *normal = n;
721  }
722  return new_indexing ? local_start[ibase] + icd :
723  ibase*nmax + icd;
724  }
725  first_time = false;
726  }
727 
728  // see if we will enter a new base geometry region before t
729  EGS_Float tnew = t - ttot;
730  int ibase_new = bg->howfar(ibase,tmp,u,tnew,pmednew,pn);
731  // see if we will enter the cd geometry of this base geometry
732  // region.
733  int icd_new = g[ibase]->howfar(-1,tmp,u,tnew,pmednew,pn);
734  if (icd_new >= 0) {
735  // yes, we will.
736  t = ttot + tnew;
737  if (newmed) {
738  *newmed = mednew;
739  }
740  if (normal) {
741  *normal = n;
742  }
743  return new_indexing ? local_start[ibase] + icd_new :
744  ibase*nmax + icd_new;
745  }
746  // if the base region is the same or we have exited the
747  // base geometry, the particle never enters.
748 
749  //if( ibase_new == ibase || ibase_new < 0 ) return -1;
750  if (ibase_new == ibase) {
751  return -1;
752  }
753  if (ibase_new < 0) {
754  tmp += u*tnew;
755  ttot += tnew;
756  tnew = t - ttot;
757  ibase_new = bg->howfar(-1,tmp,u,tnew,pmednew,pn);
758  if (ibase_new < 0) {
759  return -1;
760  }
761  //tb = tnew; ttot += tnew; first_time = false;
762  //goto do_checks;
763  }
764  // OK, we are in a new base geometry now, adjust
765  // position and path-length so-far and retry.
766  if (tnew < boundaryTolerance) {
767  tnew = boundaryTolerance;
768  }
769  tmp += u*tnew;
770  ttot += tnew;
771  ibase = ibase_new;
772  first_time = false;
773  }
774 
775  return ireg;
776  };
777 
778  EGS_Float hownear(int ireg, const EGS_Vector &x) {
779  if (ireg >= 0) {
780  int ibase, icd;
781  if (new_indexing) {
782  ibase = reg_to_base[ireg];
783  icd = ireg - local_start[ibase];
784  }
785  else {
786  ibase = ireg/nmax;
787  icd = ireg - ibase*nmax;
788  }
789  EGS_Float t = bg->hownear(ibase,x);
790  if (!g[ibase] || t <= 0) {
791  return t;
792  }
793  EGS_Float t1 = g[ibase]->hownear(icd,x);
794  return (t1 < t ? t1 : t);
795  }
796  int ibase = bg->isWhere(x);
797  if (ibase < 0) {
798  EGS_Float tt = bg->hownear(ireg,x);
799  return tt;
800  }
801  EGS_Float t = bg->hownear(ibase,x);
802  if (g[ibase]) {
803  EGS_Float t1 = g[ibase]->hownear(-1,x);
804  if (t1 < t) {
805  t = t1;
806  }
807  }
808  return t;
809  };
810 
811  int getMaxStep() const {
812  int nstep = 0;
813  for (int j=0; j<bg->regions(); ++j) {
814  if (g[j]) {
815  nstep += g[j]->getMaxStep();
816  }
817  else {
818  ++nstep;
819  }
820  }
821  return nstep + 1;
822  }
823 
824  void getNextGeom(EGS_RandomGenerator *rndm) { //calls getNextGeom on its component geometries to update dynamic geometries in the simulation
825  for (int j=0; j<bg->regions(); ++j) {
826  g[j]->getNextGeom(rndm);
827  }
828  bg->getNextGeom(rndm);
829  };
830 
831  void updatePosition(EGS_Float time) {//calls updatePosition on its component geometries to update dynamic geometries in the simulation
832  for (int j=0; j<bg->regions(); j++) {
833  g[j]->updatePosition(time);
834  }
835  bg->updatePosition(time);
836  };
837 
838  void containsDynamic(bool &hasdynamic) {//calls containsDynamic on its component geometries (only calls if hasDynamic is false, as if it is true we already found one)
839  for (int j=0; j<bg->regions(); j++) {
840  if (!hasdynamic) {
841  g[j]->containsDynamic(hasdynamic);
842  }
843  }
844  if (!hasdynamic) {
845  bg->containsDynamic(hasdynamic);
846  }
847  };
848 
849 
850  bool hasBooleanProperty(int ireg, EGS_BPType prop) const {
851  if (ireg >= 0 && ireg < nreg) {
852  int ibase = ireg/nmax;
853  return g[ibase] ?
854  g[ibase]->hasBooleanProperty(ireg - ibase*nmax,prop) :
855  bg->hasBooleanProperty(ibase,prop);
856  }
857  return false;
858  };
859  void setBooleanProperty(EGS_BPType) {
860  setPropertError("setBooleanProperty()");
861  };
862  void addBooleanProperty(int) {
863  setPropertError("addBooleanProperty()");
864  };
865  void setBooleanProperty(EGS_BPType,int,int,int step=1) {
866  setPropertError("setBooleanProperty()");
867  };
868  void addBooleanProperty(int,int,int,int step=1) {
869  setPropertError("addBooleanProperty()");
870  };
871 
872  const string &getType() const {
873  return type;
874  };
875 
876  void setRelativeRho(int start, int end, EGS_Float rho);
877  void setRelativeRho(EGS_Input *);
878  EGS_Float getRelativeRho(int ireg) const {
879  if (ireg < 0 || ireg >= nbase*nmax) {
880  return 1;
881  }
882  int ibase = ireg/nmax;
883  return g[ibase] ? g[ibase]->getRelativeRho(ireg-ibase*nmax) :
884  bg->getRelativeRho(ibase);
885  };
886 
887  void setBScaling(int start, int end, EGS_Float bf);
888  void setBScaling(EGS_Input *);
889  EGS_Float getBScaling(int ireg) const {
890  if (ireg < 0 || ireg >= nbase*nmax) {
891  return 1;
892  }
893  int ibase = ireg/nmax;
894  return g[ibase] ? g[ibase]->getBScaling(ireg-ibase*nmax) :
895  bg->getBScaling(ibase);
896  };
897 
898  virtual void getLabelRegions(const string &str, vector<int> &regs);
899 
900 protected:
901 
902  EGS_BaseGeometry *bg;
903  EGS_BaseGeometry **g;
904  int nbase, nmax;
905  static string type;
906 
907  /* New indexing style:
908 
909  If the base geometry has \f$N_B\f$ regions and the inscribed
910  geometries \f$G_j\f$ have \f$n_j\f$ regions, then the CD geometry
911  will have \f$n_1 + n_2 + \cdots n_{N_B}\f$ regions
912  (if there is no inscribed geometry is some region, then
913  \f$n_j = 1\f$). Then, for a CD geometry region \f$i\f$
914  the base region \f$i_B\f$ is given by reg_to_base[i] and
915  the local region in the inscribed geometry (if any) is
916  \f$i\f$ - local_start[\f$i_B\f$].
917  */
918 
927 
928  void setMedia(EGS_Input *inp, int, const int *);
929 
930 private:
931 
932  void setPropertError(const char *funcname) {
933  egsFatal("EGS_CDGeometry::%s: don't use this method\n Define "
934  "properties in the constituent geometries instead\n");
935  };
936 
937  void setHasRhoScaling() {
938  has_rho_scaling = false;
939  if (bg->hasRhoScaling()) {
940  has_rho_scaling = true;
941  return;
942  }
943  for (int j=0; j<nbase; j++) {
944  if (g[j]) {
945  if (g[j]->hasRhoScaling()) {
946  has_rho_scaling = true;
947  return;
948  }
949  }
950  }
951  };
952 
953  void setHasBScaling() {
954  has_B_scaling = false;
955  if (bg->hasBScaling()) {
956  has_B_scaling = true;
957  return;
958  }
959  for (int j=0; j<nbase; j++) {
960  if (g[j]) {
961  if (g[j]->hasBScaling()) {
962  has_B_scaling = true;
963  return;
964  }
965  }
966  }
967  };
968 
969  void setUpIndexing();
970 };
971 
972 #endif
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
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)
int deref()
Decrease the reference count to this geometry.
virtual bool hasBooleanProperty(int ireg, EGS_BPType prop) const
Is the boolean property prop set for region ireg ?
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.
EGS_Float boundaryTolerance
Boundary tolerance for geometries that need it.
bool hasBScaling() const
Does this geometry object have a B field 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.
bool hasRhoScaling() const
Does this geometry object have a mass density scaling feature?
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 addBooleanProperty(int bit)
Add a boolean property for the entire geometry by setting the bit'th bit.
EGS_BaseGeometry(const string &Name)
Construct a geometry named Name.
virtual int isWhere(const EGS_Vector &x)=0
In which region is poisition x?
A "combinatorial dimension" geometry.
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
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_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.
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 epsilon
The epsilon constant for floating point comparisons.
Definition: egs_functions.h:62
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.
const EGS_Float veryFar
A very large float.