EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_polygon_shape.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ polygon shape
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: Randle Taylor
27 # Reid Townson
28 # Hannah Gallop
29 #
30 ###############################################################################
31 */
32 
33 
39 #include "egs_polygon_shape.h"
40 #include "egs_polygon.h"
41 #include "egs_input.h"
42 #include "egs_functions.h"
43 #include "egs_math.h"
44 
45 static bool EGS_POLYGON_SHAPE_LOCAL inputSet = false;
46 static shared_ptr<EGS_BlockInput> EGS_POLYGON_SHAPE_LOCAL shapeBlockInput = make_shared<EGS_BlockInput>("shape");
47 
48 EGS_TriangleShape::EGS_TriangleShape(const vector<EGS_Float> &points,
49  const string &Name, EGS_ObjectFactory *f) : EGS_SurfaceShape(Name,f) {
50  xo = points[0];
51  yo = points[1];
52  ax = points[2] - xo;
53  ay = points[3] - yo;
54  bx = points[4] - xo;
55  by = points[5] - yo;
56  A = 0.5*fabs(ax*by-ay*bx);
57 }
58 
59 EGS_TriangleShape::EGS_TriangleShape(const EGS_Float *points,
60  const string &Name, EGS_ObjectFactory *f) : EGS_SurfaceShape(Name,f) {
61  xo = points[0];
62  yo = points[1];
63  ax = points[2] - xo;
64  ay = points[3] - yo;
65  bx = points[4] - xo;
66  by = points[5] - yo;
67  A = 0.5*fabs(ax*by-ay*bx);
68 }
69 
70 EGS_PolygonShape::EGS_PolygonShape(const vector<EGS_Float> &points,
71  const string &Name, EGS_ObjectFactory *f) : EGS_SurfaceShape(Name,f) {
72  int np = points.size();
73  n = np/2;
74  EGS_Float auxx = points[np-2] - points[0];
75  EGS_Float auxy = points[np-1] - points[1];
76  EGS_Float *xc, *yc;
77  if (auxx*auxx + auxy*auxy > epsilon) {
78  n++;
79  }
80  xc = new EGS_Float [n];
81  yc = new EGS_Float [n];
82  vector<EGS_2DVector> p1;
83  for (int j=0; j<np/2; j++) {
84  xc[j] = points[2*j];
85  yc[j] = points[2*j+1];
86  p1.push_back(EGS_2DVector(xc[j],yc[j]));
87  }
88  if (n > np/2) {
89  xc[n-1] = points[0];
90  yc[n-1] = points[1];
91  p1.push_back(EGS_2DVector(xc[n-1],yc[n-1]));
92  }
93  EGS_2DPolygon pol(p1);
94  int ntr = 0;
95  triangle = new EGS_TriangleShape* [n-2];
96  np = n;
97  EGS_Float p_tmp[6];
98  while (np > 3) {
99  for (int i=0; i<np-2; i++) {
100  EGS_2DVector aux(0.5*(xc[i+2]+xc[i]),0.5*(yc[i+2]+yc[i]));
101  if (pol.isInside(aux)) {
102  bool is_ok = true;
103  vector<EGS_2DVector> p2;
104  for (int k=0; k<3; k++) {
105  p_tmp[2*k] = xc[i+k];
106  p_tmp[2*k+1] = yc[i+k];
107  p2.push_back(EGS_2DVector(xc[i+k],yc[i+k]));
108  }
109  EGS_2DPolygon tri(p2);
110  for (int j=0; j<np-1; j++) {
111  if (j < i || j > i+2) {
112  EGS_2DVector tmp(xc[j],yc[j]);
113  if (tri.isInside(tmp)) {
114  is_ok = false;
115  break;
116  }
117  }
118  }
119  if (is_ok) {
120  EGS_TriangleShape *t = new EGS_TriangleShape(p_tmp);
121  triangle[ntr++] = t;
122  for (int j=i+1; j<np-1; j++) {
123  xc[j] = xc[j+1];
124  yc[j] = yc[j+1];
125  }
126  }
127  np--;
128  }
129  }
130  }
131  for (int k=0; k<3; k++) {
132  p_tmp[2*k] = xc[k];
133  p_tmp[2*k+1] = yc[k];
134  }
135  triangle[ntr++] = new EGS_TriangleShape(p_tmp);
136  A = 0;
137  for (int i=0; i<ntr; i++) {
138  yc[i] = triangle[i]->area();
139  A += yc[i];
140  }
141  table = new EGS_AliasTable(ntr,xc,yc,0);
142  delete [] xc;
143  delete [] yc;
144 }
145 
146 extern "C" {
147 
148  static void setInputs() {
149  inputSet = true;
150 
151  setShapeInputs(shapeBlockInput);
152  shapeBlockInput->getSingleInput("library")->setValues({"egs_polygon_shape"});
153 
154  shapeBlockInput->addSingleInput("points", true, "A list of at least 3 2D points (at least 6 floating numbers). By default these are in the x-y plane at z=0; use a transformation to adjust.");
155  }
156 
157  EGS_POLYGON_SHAPE_EXPORT string getExample() {
158  string example;
159  example = {
160  R"(
161  # Example of egs_polygon_shape
162  #:start shape:
163  library = egs_polygon_shape
164  points = list of 2D points
165  :stop shape:
166 )"};
167  return example;
168  }
169 
170  EGS_POLYGON_SHAPE_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
171  if(!inputSet) {
172  setInputs();
173  }
174  return shapeBlockInput;
175  }
176 
177  EGS_POLYGON_SHAPE_EXPORT EGS_BaseShape *createShape(EGS_Input *input,
178  EGS_ObjectFactory *f) {
179  if (!input) {
180  egsWarning("createShape(polygon): null input?\n");
181  return 0;
182  }
183  vector<EGS_Float> points;
184  int err = input->getInput("points",points);
185  if (err) {
186  egsWarning("createShape(polygon): no 'points' input\n");
187  return 0;
188  }
189  int np = points.size();
190  if ((np%2) != 0) {
191  egsWarning("createShape(polygon): you must input an even number of"
192  " floating numbers\n");
193  return 0;
194  }
195  if (np < 6) {
196  egsWarning("createShape(polygon): you must input at least 3 2D points"
197  " to form a polygon\n");
198  return 0;
199  }
200  EGS_BaseShape *shape;
201  if (np == 6) {
202  shape = new EGS_TriangleShape(points,"",f);
203  }
204  else {
205  shape = new EGS_PolygonShape(points,"",f);
206  }
207  shape->setName(input);
208  shape->setTransformation(input);
209  return shape;
210  }
211 
212 }
A class to represent a polygon in a plane (a 2D polygon).
Definition: egs_polygon.h:59
A class representing 2D vectors.
A class for sampling random values from a given probability distribution using the alias table techni...
Base shape class. All shapes in the EGSnrc C++ class library are derived from EGS_BaseShape.
Definition: egs_shapes.h:145
void setTransformation(EGS_Input *inp)
Set the transformation attached to this shape.
Definition: egs_shapes.cpp:69
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.
A polygon shape.
A surface shape.
Definition: egs_shapes.h:306
A triangular shape.
Global egspp functions header file.
EGS_Input class header file.
Attempts to fix broken math header files.
EGS_2DPolygon and EGS_PolygonT class header file.
A polygon shape.
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
Definition: egs_functions.h:62
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.