EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_planes.h
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ planes 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: Reid Townson
27 # Hubert Ho
28 # Marc Chamberland
29 #
30 ###############################################################################
31 */
32 
33 
39 #ifndef EGS_PLANES_
40 #define EGS_PLANES_
41 
42 #include "egs_base_geometry.h"
43 #include "egs_functions.h"
44 #include "egs_projectors.h"
45 
46 #include <vector>
47 using std::vector;
48 
49 #ifdef WIN32
50 
51  #ifdef BUILD_PLANES_DLL
52  #define EGS_PLANES_EXPORT __declspec(dllexport)
53  #else
54  #define EGS_PLANES_EXPORT __declspec(dllimport)
55  #endif
56  #define EGS_PLANES_LOCAL
57 
58 #else
59 
60  #ifdef HAVE_VISIBILITY
61  #define EGS_PLANES_EXPORT __attribute__ ((visibility ("default")))
62  #define EGS_PLANES_LOCAL __attribute__ ((visibility ("hidden")))
63  #else
64  #define EGS_PLANES_EXPORT
65  #define EGS_PLANES_LOCAL
66  #endif
67 
68 #endif
69 
166 template <class T>
167 class EGS_PLANES_EXPORT EGS_PlanesT : public EGS_BaseGeometry {
168 
169 protected:
170 
171  EGS_Float *p;
172  EGS_Float p_last;
173  EGS_Float dp;
174  int n_plane;
175  bool is_uniform;
176  T a;
177  //EGS_Vector last_x, last_u;
178  //EGS_Float last_d;
179  //int last_ir, last_irnew;
180 
181  void checkIfUniform() {
182  is_uniform = true;
183  if (nreg == 1) {
184  dp = p_last - p[0];
185  return;
186  }
187  dp = p[1] - p[0];
188  for (int j=1; j<nreg; j++) {
189  EGS_Float dpj = p[j+1] - p[j];
190  if (fabs(dpj/dp-1) > boundaryTolerance) {
191  is_uniform = false;
192  break;
193  }
194  }
195  };
196 
197 public:
198 
201  if (nreg) {
202  delete [] p;
203  }
204  };
205 
209  EGS_PlanesT(int np, const EGS_Float *pos, const string &Name,
210  const T &A) : EGS_BaseGeometry(Name), a(A) {
211  if (np > 0) {
212  p = new EGS_Float [np];
213  for (int j=0; j<np; j++) {
214  p[j] = pos[j]/a.length();
215  if (j > 0) {
216  if (p[j] < p[j-1]) egsFatal("EGS_PlanesT::EGS_PlanesT: "
217  " plane positions must be in increasing order\n");
218  }
219  }
220  if (np > 1) {
221  nreg = np-1;
222  p_last = p[nreg];
223  n_plane = np-1;
224  }
225  else {
226  nreg = 1;
227  p_last = veryFar*1e-15;
228  n_plane = 0;
229  }
230  }
231  else egsFatal("EGS_PlanesT::EGS_PlanesT: attempt to construct a "
232  "plane set with %d plane positions\n",np);
233  checkIfUniform();
234  };
238  EGS_PlanesT(const vector<EGS_Float> &pos, const string &Name, const T &A) :
239  EGS_BaseGeometry(Name), a(A) {
240  int np = pos.size();
241  if (np > 0) {
242  p = new EGS_Float [np];
243  for (int j=0; j<np; j++) {
244  p[j] = pos[j]/a.length();
245  if (j > 0) {
246  if (p[j] < p[j-1]) egsFatal("EGS_PlanesT::EGS_PlanesT: "
247  " plane positions must be in increasing order\n");
248  }
249  }
250  if (np > 1) {
251  nreg = np-1;
252  p_last = p[nreg];
253  n_plane = np-1;
254  }
255  else {
256  nreg = 1;
257  p_last = veryFar*1e-15;
258  n_plane = 0;
259  }
260  }
261  else egsFatal("EGS_PlanesT::EGS_PlanesT: attempt to construct a "
262  "plane set with %d plane positions\n",np);
263  checkIfUniform();
264  };
268  EGS_PlanesT(EGS_Float xo, EGS_Float dx, int np, const string &Name,
269  const T &A) : EGS_BaseGeometry(Name), a(A) {
270  if (np < 1) egsFatal("EGS_PlanesT::EGS_PlanesT: attempt to construct"
271  " a plane set with %d plane positions\n",np);
272  if (dx <= 0) egsFatal("EGS_PlanesT::EGS_PlanesT: attempt to construct"
273  " a plane set with a non-positive slice thickness %g\n",dx);
274  p = new EGS_Float [np+1];
275  p[0] = xo;
276  for (int j=0; j<np; j++) {
277  p[j+1] = p[j] + dx;
278  }
279  nreg = np;
280  p_last = p[nreg];
281  n_plane = np;
282  is_uniform = true;
283  dp = dx;
284  };
285 
286  EGS_Float *getPositions() {
287  return p;
288  };
289 
293  bool isInside(const EGS_Vector &x) {
294  EGS_Float xp = a*x;
295  if (xp < p[0] || xp > p_last) {
296  return false;
297  }
298  return true;
299  };
300 
301  int isWhere(const EGS_Vector &x) {
302  EGS_Float xp = a*x;
303  if (xp < p[0] || xp > p_last) {
304  return -1;
305  }
306  if (nreg == 1) {
307  return 0;
308  }
309  //if( is_uniform ) { int res = (int) ((xp-p[0])/dp); return res; }
310  return findRegion(xp,nreg,p);
311  };
312 
313  int inside(const EGS_Vector &x) {
314  return isWhere(x);
315  };
316 
317  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
318  const EGS_Vector &u) {
319  if (ireg < 0) {
320  return 0;
321  }
322  double xp = a*x, up = a*u;
323  EGS_Float t = veryFar;
324  if (up > 0) {
325  t = (p_last-xp)/up;
326  }
327  else if (up < 0) {
328  t = (p[0]-xp)/up;
329  }
330  return t;
331  };
332 
333  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
334  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
335  //EGS_Float d = veryFar; int res=ireg;
336  //EGS_Float xp = a*x, up = a*u;
337  double d = veryFar*1e5;
338  int res=ireg;
339  double xp = a*x, up = a*u;
340  if (ireg >= 0) {
341  int dir = 0;
342 // bool warn=false;
343 // EGS_Float dist;
344  if (up > 0 && ireg < n_plane) {
345  d = (p[ireg+1]-xp)/up;
346  //if( xp <= p[ireg+1] ) d = (p[ireg+1]-xp)/up;
347  //else {
348  // dist = xp - p[ireg+1]; d = 0;
349  // if( dist > 2e-5 ) warn = true;
350  //}
351  dir = 1;
352  }
353  else if (up < 0) {
354  d = (p[ireg]-xp)/up;
355  //if( xp >= p[ireg] ) d = (p[ireg]-xp)/up;
356  //else {
357  // dist = p[ireg] - xp; d = 0;
358  // if( dist > 2e-5 ) warn = true;
359  //}
360  dir = -1;
361  }
362  /*
363  if( warn ) {
364  egsWarning("In EGS_Planes::howfar(%s): particle is not"
365  " in region we think it is:\n",a.getType().c_str());
366  //egsWarning("x=(%g,%g,%g) region=%d distance to plane=%g\n",
367  // x.x,x.y,x.z,ireg,dist);
368  egsWarning("x=%g u=%g region=%d distance to plane=%g\n",
369  xp,up,ireg,dist);
370  }
371  */
372  if (d > t) {
373  res = ireg;
374  }
375  else {
376  t = d;
377  res = ireg + dir;
378  if (res >= nreg) {
379  res = -1;
380  }
381  if (newmed) {
382  if (res >= 0) {
383  *newmed = medium(res);
384  }
385  else {
386  *newmed=-1;
387  }
388  }
389  if (normal) {
390  *normal = a.normal()*(-dir);
391  }
392  }
393  return res;
394  }
395  if (xp <= p[0] && up > 0) {
396  d = (p[0] - xp)/up;
397  res = 0;
398  }
399  else if (xp >= p_last && up < 0) {
400  d = (p_last - xp)/up;
401  res = nreg-1;
402  }
403  else if (xp > p[0] && xp < p_last) {
404  // we think we are outside but we are inside.
405  // hopefully a truncation problem with a particle
406  // backscattered at a boundary
407  if (xp-p[0] < boundaryTolerance && up > 0) {
408  d = 0;
409  res = 0;
410  }
411  else if (p_last-xp < boundaryTolerance && up < 0) {
412  d = 0;
413  res = nreg-1;
414  }
415  }
416  if (d <= t) {
417  t = d;
418  if (newmed) {
419  *newmed = medium(res);
420  }
421  if (normal) {
422  if (up > 0) {
423  *normal = a.normal()*(-1.);
424  }
425  else {
426  *normal = a.normal();
427  }
428  }
429  }
430  else {
431  res = -1;
432  }
433  return res;
434  };
435 
436  EGS_Float hownear(int ireg, const EGS_Vector &x) {
437  EGS_Float xp = a*x;
438  if (ireg >= 0) {
439  EGS_Float t = xp - p[ireg];
440  if (ireg+1 <= n_plane) {
441  EGS_Float t2 = p[ireg+1] - xp;
442  if (t2 < t) {
443  t = t2;
444  }
445  }
446  return t;
447  }
448  if (xp <= p[0]) {
449  return p[0] - xp;
450  }
451  if (xp >= p_last) {
452  return xp - p_last;
453  }
454  return 0; // this should not happen.
455  };
456 
457  const string &getType() const {
458  return a.getType();
459  };
460 
461  void printInfo() const {
463  a.printInfo();
464  if (is_uniform)
465  egsInformation(" first plane at %g, %d slices of %g thickness\n",
466  p[0],nreg,dp);
467  else {
468  egsInformation(" plane positions = ");
469  for (int j=0; j<nreg; j++) {
470  egsInformation("%g ",p[j]);
471  }
472  if (n_plane == nreg) {
473  egsInformation("%g ",p[n_plane]);
474  }
475  egsInformation("\n");
476  }
478  "=======================================================\n");
479  };
480 
481  EGS_Float position(int j) const {
482  return p[j];
483  };
484 
485  EGS_Vector normal() const {
486  return a.normal();
487  };
488 
489 };
490 
495 
575 class EGS_PLANES_EXPORT EGS_PlaneCollection : public EGS_BaseGeometry {
576 
577 protected:
578 
579  EGS_Planes **planes; // the planes.
580  int np; // number of planes.
581  static string type;
582 
583 public:
584 
585  EGS_PlaneCollection(int Np, const EGS_Float *pos, const EGS_Vector *norm,
586  const string &Name = "");
588  bool isInside(const EGS_Vector &x) {
589  return (planes[0]->isInside(x) && !planes[np-1]->isInside(x));
590  };
591  int isWhere(const EGS_Vector &x) {
592  if (!planes[0]->isInside(x)) {
593  return -1;
594  }
595  if (planes[np-1]->isInside(x)) {
596  return -1;
597  }
598  for (int j=0; j<np-1; j++)
599  if (planes[j]->isInside(x) && !planes[j+1]->isInside(x)) {
600  return j;
601  }
602  return -1; // this should not happen.
603  };
604  int inside(const EGS_Vector &x) {
605  return isInside(x);
606  };
607  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
608  EGS_Float &t, int *newmed=0, EGS_Vector *normal=0) {
609  if (ireg >= 0) {
610  int m1, m2;
611  EGS_Vector n1, n2;
612  EGS_Float t1 = t;
613  int i1=planes[ireg]->howfar(0,x,u,t1,&m1,&n1);
614  EGS_Float t2 = t;
615  int i2=planes[ireg+1]->howfar(-1,x,u,t2,&m2,&n2);
616  int res = ireg;
617  if (i1 == -1 && i2 == 0) {
618  if (t1 < t2) {
619  t = t1;
620  res = ireg-1;
621  if (normal) {
622  *normal = n1;
623  }
624  }
625  else {
626  t = t2;
627  res = ireg+1;
628  if (res > nreg-1) {
629  res = -1;
630  }
631  if (normal) {
632  *normal = n2;
633  }
634  }
635  }
636  else if (i1 == -1) {
637  t = t1;
638  res = ireg-1;
639  if (normal) {
640  *normal = n1;
641  }
642  }
643  else if (i2 == 0) {
644  t = t2;
645  res=ireg+1;
646  if (res > nreg-1) {
647  res = -1;
648  }
649  if (normal) {
650  *normal = n2;
651  }
652  }
653  if (newmed && res != ireg) {
654  if (res >= 0) {
655  *newmed = medium(res);
656  }
657  else {
658  *newmed = -1;
659  }
660  }
661  return res;
662  }
663  if (!planes[0]->isInside(x)) {
664  int iaux = planes[0]->howfar(-1,x,u,t,newmed,normal);
665  return iaux;
666  }
667  int i1 = planes[nreg]->howfar(0,x,u,t,newmed,normal);
668  if (i1 < 0) {
669  return nreg-1;
670  }
671  return -1;
672  };
673  EGS_Float hownear(int ireg,const EGS_Vector &x) {
674  if (ireg >= 0) {
675  EGS_Float t1 = planes[ireg]->hownear(0,x);
676  EGS_Float t2 = planes[ireg+1]->hownear(-1,x);
677  if (t1 < t2) {
678  return t1;
679  }
680  else {
681  return t2;
682  }
683  }
684  if (!planes[0]->isInside(x)) {
685  return planes[0]->hownear(-1,x);
686  }
687  return planes[np-1]->hownear(0,x);
688  };
689  const string &getType() const {
690  return type;
691  };
692 
693  void printInfo() const;
694 
695 };
696 
697 #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)
virtual EGS_Float howfarToOutside(int ireg, const EGS_Vector &x, const EGS_Vector &u)
virtual const string & getType() const =0
Get the geometry type.
static int findRegion(EGS_Float xp, int np, const EGS_Float *p)
Find the bin to which xp belongs, given np bin edges p.
int nreg
Number of local regions in this geometry.
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 isInside(const EGS_Vector &x)=0
Is the position x inside the geometry?
virtual int medium(int ireg) const
Returns the medium index in region ireg.
virtual void printInfo() const
Print information about this geometry.
virtual int isWhere(const EGS_Vector &x)=0
In which region is poisition x?
A collection of non-parallel planes.
Definition: egs_planes.h:575
A set of parallel planes.
Definition: egs_planes.h:167
int n_plane
Number of planes - 1.
Definition: egs_planes.h:174
EGS_Float p_last
The last plane.
Definition: egs_planes.h:172
EGS_PlanesT(int np, const EGS_Float *pos, const string &Name, const T &A)
Construct a parallel plane set with np planes at positions pos.
Definition: egs_planes.h:209
T a
The projection operator.
Definition: egs_planes.h:176
bool isInside(const EGS_Vector &x)
Definition: egs_planes.h:293
EGS_PlanesT(const vector< EGS_Float > &pos, const string &Name, const T &A)
Construct a parallel plane set from the positions given by pos.
Definition: egs_planes.h:238
EGS_PlanesT(EGS_Float xo, EGS_Float dx, int np, const string &Name, const T &A)
Construct a parallel plane set starting at xo with uniform distance between the np+1 planes given by ...
Definition: egs_planes.h:268
EGS_Float * p
Plane positions.
Definition: egs_planes.h:171
A class representing 3D vectors.
Definition: egs_vector.h:57
EGS_BaseGeometry class header file.
Global egspp functions header file.
EGS_Projector and EGS_2DVector class header file.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
const EGS_Float veryFar
A very large float.