EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_spherical_shell.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ spherical shell shape
5 # Copyright (C) 2016 Randle E. P. Taylor, Rowan M. Thomson,
6 # Marc J. P. Chamberland, D. W. O. Rogers
7 #
8 # This file is part of EGSnrc.
9 #
10 # EGSnrc is free software: you can redistribute it and/or modify it under
11 # the terms of the GNU Affero General Public License as published by the
12 # Free Software Foundation, either version 3 of the License, or (at your
13 # option) any later version.
14 #
15 # EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY
16 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
18 # more details.
19 #
20 # You should have received a copy of the GNU Affero General Public License
21 # along with EGSnrc. If not, see <http://www.gnu.org/licenses/>.
22 #
23 ###############################################################################
24 #
25 # Author: Randle Taylor, 2016
26 #
27 # Contributors: Marc Chamberland
28 # Rowan Thomson
29 # Dave Rogers
30 # Hannah Gallop
31 #
32 ###############################################################################
33 #
34 # egs_spherical_shell was developed for the Carleton Laboratory for
35 # Radiotherapy Physics.
36 #
37 ###############################################################################
38 */
39 
40 
46 #include "egs_spherical_shell.h"
47 #include "egs_input.h"
48 #include "egs_functions.h"
49 
50 static bool EGS_SPHERICAL_SHELL_LOCAL inputSet = false;
51 static shared_ptr<EGS_BlockInput> EGS_SPHERICAL_SHELL_LOCAL shapeBlockInput = make_shared<EGS_BlockInput>("shape");
52 
53 EGS_SphericalShellShape::EGS_SphericalShellShape(EGS_Float ri, EGS_Float ro, int hemisph, EGS_Float halfangle, const EGS_Vector &Xo,
54  const string &Name,EGS_ObjectFactory *f) :
55  EGS_BaseShape(Name, f), r_inner(ri), r_outer(ro), hemisphere(hemisph), half_angle(halfangle), xo(Xo) {
56  otype = "sphericalShell";
57  if (half_angle < 0) {
58  sgn = -1;
59  half_angle = fabs(half_angle);
60  }
61  else {
62  sgn = 1;
63  }
64 };
65 
66 
69 
70  EGS_Float rnd1 = rndm->getUniform();
71  EGS_Float rnd2 = rndm->getUniform();
72 
73  EGS_Float rad = r_inner + (r_outer - r_inner)*pow(rnd1, 1/3.);
74 
75  EGS_Float cos_max, cos_min;
76  EGS_Float cos_th;
77 
78  if (fabs(half_angle) < 1E-4) {
79  cos_th = 2*rnd2 -1;
80  }
81  else {
82  /* conical section */
83  cos_min = cos(half_angle);
84  cos_th = cos_min + rnd2*(1 - cos_min);
85  rad *= sgn;
86  }
87 
88  EGS_Float sin_th = sqrt(1-cos_th*cos_th);
89 
90  EGS_Float cos_phi, sin_phi;
91  rndm->getAzimuth(cos_phi, sin_phi);
92 
93  EGS_Float x = rad*sin_th*cos_phi;
94  EGS_Float y = rad*sin_th*sin_phi;
95  EGS_Float z = rad*cos_th;
96 
97  if (hemisphere != 0) {
98  z = hemisphere*fabs(z);
99  }
100 
101  return xo + EGS_Vector(x, y, z);
102 
103 };
104 
105 
107  EGS_RandomGenerator *rndm, EGS_Vector &u, EGS_Float &wt) {
108  EGS_Vector xo = T ? Xo*(*T) : Xo;
109  EGS_Float cost = 2*rndm->getUniform()-1;
110  EGS_Float sint = 1-cost*cost;
111  EGS_Vector x;
112  if (sint > 1e-10) {
113  EGS_Float cphi, sphi;
114  rndm->getAzimuth(cphi,sphi);
115  sint = r_outer*sqrt(sint);
116  x.x = sint*cphi;
117  x.y = sint*sphi;
118  x.z = r_outer*cost;
119  }
120  else {
121  x.z = r_outer*cost;
122  }
123  u = (x + this->xo) - xo;
124  EGS_Float di = 1/u.length();
125  u *= di;
126  wt = u*x*4*M_PI*r_outer*di*di;
127 };
128 
129 EGS_Float EGS_SphericalShellShape::area() const {
130  return 4*M_PI*r_outer*r_outer;
131 };
132 
133 extern "C" {
134 
135  static void setInputs() {
136  inputSet = true;
137 
138  setShapeInputs(shapeBlockInput);
139  shapeBlockInput->getSingleInput("library")->setValues({"egs_spherical_shell"});
140 
141  shapeBlockInput->addSingleInput("midpoint", false, "The midpoint of the shape, (x y z). Defaults to '0 0 0'.");
142  shapeBlockInput->addSingleInput("inner radius", true, "The inner radius");
143  shapeBlockInput->addSingleInput("outer radius", true, "The outer radius");
144  auto hemiPtr = shapeBlockInput->addSingleInput("hemisphere", false, "Truncates the sphere to a hemisphere in positive or negative z, by setting to 1 or -1, respectively.", {"1", "-1"});
145  auto halfAngPtr = shapeBlockInput->addSingleInput("half angle", false, "The half angle, in degrees. The shell is truncated by a conical section with the half angle specified. If 'half angle' is negative, the points will sampled with negative z coordinates.");
146 
147  hemiPtr->addDependency(halfAngPtr, "", true);
148  halfAngPtr->addDependency(hemiPtr, "", true);
149  }
150 
151  EGS_SPHERICAL_SHELL_EXPORT string getExample() {
152  string example;
153  example = {
154  R"(
155  # Example of egs_spherical_shell
156  #:start shape:
157  library = egs_spherical_shell
158  midpoint = 0 0 0
159  inner radius = 0.5
160  outer radius = 1
161  hemisphere = 1
162  half angle = 35
163  :stop shape:
164 )"};
165  return example;
166  }
167 
168  EGS_SPHERICAL_SHELL_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
169  if(!inputSet) {
170  setInputs();
171  }
172  return shapeBlockInput;
173  }
174 
175  EGS_SPHERICAL_SHELL_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) {
176 
177  if (!input) {
178  egsWarning("createShape(sphericalShell): null input?\n");
179  return 0;
180  }
181 
182  EGS_Float ri, ro;
183  int err = input->getInput("inner radius", ri);
184  if (err) {
185  egsWarning("createShape(sphericalShell): no 'inner radius' input\n");
186  return 0;
187  }
188  else if (ri < 0) {
189  egsWarning("createShape(sphericalShell): 'inner radius' must be >= 0\n");
190  return 0;
191  }
192 
193  err = input->getInput("outer radius", ro);
194  if (err) {
195  egsWarning("createShape(sphericalShell): no 'outer radius' input\n");
196  return 0;
197  }
198  else if (ro < 0) {
199  egsWarning("createShape(sphericalShell): 'outer radius' must be >= 0\n");
200  return 0;
201  }
202  else if (ri > ro) {
203  egsWarning("createShape(sphericalShell): 'inner radius' must be less than 'outer radius'\n");
204  return 0;
205  }
206 
207  int hemisphere;
208  err = input->getInput("hemisphere", hemisphere);
209  if (err) {
210  hemisphere = 0;
211  }
212  else if ((hemisphere != 0) && (hemisphere != -1) && (hemisphere != 1)) {
213  egsWarning("createShape(sphericalShell): 'hemisphere' must be 1, -1, 0\n");
214  return 0;
215  }
216 
217  EGS_Float half_angle=0, half_angle_deg= 0;
218  err = input->getInput("half angle", half_angle_deg);
219  if (err) {
220  half_angle = 0;
221  }
222  else {
223  half_angle = M_PI/180.*half_angle_deg;
224  }
225 
226  if (half_angle && hemisphere) {
227  egsWarning("createShape(sphericalShell): Hemisphere and half angle specified! Remove one and try again.");
228  return 0;
229  }
230 
231 
232  EGS_SphericalShellShape *result;
233 
234  vector<EGS_Float> xo;
235  err = input->getInput("midpoint",xo);
236  if (err || xo.size() != 3) {
237  xo.clear();
238  xo.push_back(0);
239  xo.push_back(0);
240  xo.push_back(0);
241  }
242 
243  result = new EGS_SphericalShellShape(ri, ro, hemisphere, half_angle, EGS_Vector(xo[0],xo[1],xo[2]));
244  result->setName(input);
245  return result;
246  }
247 
248 }
Base shape class. All shapes in the EGSnrc C++ class library are derived from EGS_BaseShape.
Definition: egs_shapes.h:145
EGS_AffineTransform * T
The affine transformation attached to the shape.
Definition: egs_shapes.h:288
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
int getInput(const string &key, vector< string > &values) const
Assign values to an array of strings from an input identified by key.
Definition: egs_input.cpp:341
An object factory.
void setName(EGS_Input *inp)
Set the name of the object from the information provided by inp.
string otype
The object type.
Base random number generator class. All random number generators should be derived from this class.
Definition: egs_rndm.h:90
void getAzimuth(EGS_Float &cphi, EGS_Float &sphi)
Sets cphi and sphi to the cosine and sine of a random angle uniformely distributed between 0 and .
Definition: egs_rndm.h:161
EGS_Float getUniform()
Returns a random number uniformly distributed between zero (inclusive) and 1 (exclusive).
Definition: egs_rndm.h:126
A spherical shell shape.
EGS_Float area() const
Returns the sphere surface area.
EGS_SphericalShellShape(EGS_Float ri, EGS_Float ro, int hemisph=0, EGS_Float halfangle=0, const EGS_Vector &Xo=EGS_Vector(0, 0, 0), const string &Name="", EGS_ObjectFactory *f=0)
Construct a sphere of radius r with midpoint Xo.
void getPointSourceDirection(const EGS_Vector &Xo, EGS_RandomGenerator *rndm, EGS_Vector &u, EGS_Float &wt)
Sets the direction u by picking a random point uniformely on the sphere surface.
EGS_Vector xo
The sphere midpoint.
EGS_Vector getPoint(EGS_RandomGenerator *rndm)
Returns a random point within the spherical shell.
EGS_Float sgn
The sphere radius.
EGS_Float half_angle
Half angle of conical section.
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
Global egspp functions header file.
EGS_Input class header file.
a spherical shell shape
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.