EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_roundrect_cylinders.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ roundrect cylinders geometry
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: Manuel Stoeckl, 2016
25 #
26 # Contributors: Hannah Gallop
27 #
28 ###############################################################################
29 #
30 # A set of concentric rounded rectangle cylinders.
31 #
32 ###############################################################################
33 */
34 
35 
42 #include "egs_input.h"
43 
44 static bool EGS_ROUNDRECT_CYLINDERS_LOCAL inputSet = false;
45 
46 extern "C" {
47  static void setInputs() {
48  inputSet = true;
49 
50  setBaseGeometryInputs();
51 
52  geomBlockInput->getSingleInput("library")->setValues({"egs_roundrect_cylinders"});
53 
54  // Format: name, isRequired, description, vector string of allowed inputs
55  auto typePtr = geomBlockInput->addSingleInput("type", true, "The type of rounded rectangle cylinder", {"EGS_RoundRectCylinders", "EGS_RoundRectCylindersXY", "EGS_RoundRectCylindersYZ", "EGS_RoundRectCylindersXZ"});
56 
57  geomBlockInput->addSingleInput("x-widths", true, "A list of cylinder half-widths in the x-direction, must be in increasing order");
58  geomBlockInput->addSingleInput("y-widths", true, "A list of cylinder half-widths in the y-direction, must be in increasing order");
59  geomBlockInput->addSingleInput("radii", true, "A list of fillet radii, must be in increasing order");
60  geomBlockInput->addSingleInput("midpoint", false, "The position of the midpoint (x, y, z)");
61 
62  // EGS_RoundRectCylinders
63  auto inpPtr = geomBlockInput->addSingleInput("x-axis", true, "x-axis of rounded rectangle (x, y, z)");
64  inpPtr->addDependency(typePtr, "EGS_RoundRectCylinders");
65  auto yinpPtr = geomBlockInput->addSingleInput("y-axis", true, "y-axis of rounded rectangle (x, y, z)");
66  yinpPtr->addDependency(typePtr, "EGS_RoundRectCylinders");
67  }
68 
69  EGS_ROUNDRECT_CYLINDERS_EXPORT string getExample() {
70  string example;
71  example = {
72  R"(
73  # Example of rounded reactangle cylinder
74  #:start geometry:
75  name = my_roundedrectcylinder
76  library = egs_roundrect_cylinders
77  type = EGS_RoundRectCylindersXY
78  x-widths = 1 2
79  y-widths = 0.5 1
80  radii = 0.1 0.5
81  :start media input:
82  media = air water
83  set medium = 1 1
84  :stop media input:
85  :stop geometry:
86 )"};
87  return example;
88  }
89 
90  EGS_ROUNDRECT_CYLINDERS_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
91  if(!inputSet) {
92  setInputs();
93  }
94  return geomBlockInput;
95  }
96 
97  EGS_ROUNDRECT_CYLINDERS_EXPORT
99  // check for valid input
100  if (!input) {
101  egsWarning("createGeometry(round rectangular cylinders): null input?\n");
102  return 0;
103  }
104  string type;
105  int err = input->getInput("type",type);
106  if (err) {
107  egsWarning("createGeometry(round rectangular cylinders): missing type key\n");
108  return 0;
109  }
110 
111  // point on cylinder axis
112  EGS_Vector xo;
113  vector<EGS_Float> Xo;
114  err = input->getInput("midpoint",Xo);
115  if (!err && Xo.size() == 3) {
116  xo = EGS_Vector(Xo[0],Xo[1],Xo[2]);
117  }
118 
119  // cylinder radii
120  vector<EGS_Float> x_widths, y_widths, radii;
121  err = input->getInput("x-widths",x_widths);
122  if (err) {
123  egsWarning("createGeometry(round rectangular cylinders): wrong/missing "
124  "'x-widths' input\n");
125  return 0;
126  }
127  err = input->getInput("y-widths",y_widths);
128  if (err) {
129  egsWarning("createGeometry(round rectangular cylinders): wrong/missing "
130  "'y-widths' input\n");
131  return 0;
132  }
133  err = input->getInput("radii",radii);
134  if (err) {
135  egsWarning("createGeometry(round rectangular cylinders): wrong/missing "
136  "'radii' input\n");
137  return 0;
138  }
139  if (x_widths.size() != y_widths.size() || x_widths.size() != radii.size()) {
140  egsWarning("createGeometry(round rectangular cylinders): expecting the same "
141  "number of x- and y-widths and radii, your input is %d %d %d\n",
142  x_widths.size(),y_widths.size(), radii.size());
143  return 0;
144  }
145 
146  for (int i=0; i<x_widths.size(); i++) {
147  if (i >= 1) {
148  if (x_widths[i-1] > x_widths[i] || x_widths[i] <= 0 || x_widths[i-1] <= 0) {
149  egsWarning("createGeometry(round rectangular cylinders): x-widths must all be positive and in sorted order\n");
150  return 0;
151  }
152  if (y_widths[i-1] > y_widths[i] || y_widths[i] <= 0 || y_widths[i-1] <= 0) {
153  egsWarning("createGeometry(round rectangular cylinders): y-widths must all be positive and in sorted order\n");
154  return 0;
155  }
156  if (radii[i] > radii[i-1]) {
157  if (x_widths[i] - radii[i] >= x_widths[i-1] - radii[i-1]) {
158  }
159  else if (x_widths[i] - radii[i] >= x_widths[i-1] - radii[i-1]) {
160  }
161  else {
162  // We have an intersection if the furthest distance on the
163  // smaller circle away from the center of the larger is more
164  // than the larger radius
165  EGS_Float dx = (x_widths[i] - radii[i]) - (x_widths[i-1] - radii[i-1]);
166  EGS_Float dy = (y_widths[i] - radii[i]) - (y_widths[i-1] - radii[i-1]);
167  EGS_Float maxdist = sqrt(dx*dx+dy*dy);
168  if (radii[i] - radii[i-1] < maxdist) {
169  egsWarning("createGeometry(round rectangular cylinders): rounded rectangles may not intersect (but (hx,hy,r) = (%f,%f,%f) and (%f,%f,%f) do)\n",
170  x_widths[i-1], y_widths[i-1], radii[i-1],
171  x_widths[i], y_widths[i], radii[i]);
172  return 0;
173  }
174  }
175  }
176  }
177  if (radii[i] < 0) {
178  egsWarning("createGeometry(round rectangular cylinders): radii must all be positive\n");
179  return 0;
180  }
181  if (radii[i] > x_widths[i] || radii[i] > y_widths[i]) {
182  egsWarning("createGeometry(round rectangular cylinders): radii cannot be larger than half-widths\n");
183  return 0;
184  }
185  }
186 
187  // select geometry
188  EGS_BaseGeometry *g;
189  if (type == "EGS_RoundRectCylindersXY")
190  g = new EGS_RoundRectCylindersT<EGS_XProjector,EGS_YProjector>(x_widths,y_widths,radii,xo,"",
191  EGS_XProjector("X"),EGS_YProjector("Y"));
192  else if (type == "EGS_RoundRectCylindersXZ")
193  g = new EGS_RoundRectCylindersT<EGS_XProjector,EGS_ZProjector>(x_widths,y_widths,radii,xo,"",
194  EGS_XProjector("X"),EGS_ZProjector("Z"));
195  else if (type == "EGS_RoundRectCylindersYZ")
196  g = new EGS_RoundRectCylindersT<EGS_YProjector,EGS_ZProjector>(x_widths,y_widths,radii,xo,"",
197  EGS_YProjector("Y"),EGS_ZProjector("Z"));
198  else {
199  vector<EGS_Float> ax, ay;
200  err = input->getInput("x-axis",ax);
201  if (err || ax.size() != 3) {
202  egsWarning("createGeometry(round rectangular cylinders): missing/wrong "
203  "'x-axis' input\n");
204  return 0;
205  }
206  err = input->getInput("y-axis",ay);
207  if (err || ay.size() != 3) {
208  egsWarning("createGeometry(round rectangular cylinders): missing/wrong "
209  "'y-axis' input\n");
210  return 0;
211  }
212  g = new EGS_RoundRectCylindersT<EGS_Projector,EGS_Projector>(x_widths,y_widths,radii,xo,"",
213  EGS_Projector(EGS_Vector(ax[0],ax[1],ax[2]),"Any"),
214  EGS_Projector(EGS_Vector(ay[0],ay[1],ay[2]),""));
215  }
216  g->setName(input);
217  g->setLabels(input);
218  g->setMedia(input);
219  return g;
220  }
221 
222 }
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
void setMedia(EGS_Input *inp)
Set the media in the geometry from the input pointed to by inp.
void setName(EGS_Input *inp)
Set the name of the geometry from the input inp.
int setLabels(EGS_Input *input)
Set the labels from an input block.
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
A projector into any plane.
A set of concentric rounded rectangles.
A class representing 3D vectors.
Definition: egs_vector.h:57
A projector into the x-plane.
A projector into the y-plane.
A projector into the z-plane.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
Definition: egs_glib.cpp:84
EGS_Input class header file.
A set of concentric rounded rectangular cylinders: header.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.