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