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