EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_polygon.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ polygon
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 #
28 ###############################################################################
29 */
30 
31 
37 #include "egs_polygon.h"
38 
39 bool EGS_2DPolygon::checkCCW(const vector<EGS_2DVector> &points) {
40  double A = 0;
41  for (int j=0; j<points.size()-1; j++) {
42  A += (points[j].x*points[j+1].y - points[j+1].x*points[j].y);
43  }
44  if (A > 0) {
45  return true;
46  }
47  else {
48  return false;
49  }
50 }
51 
53  delete [] a;
54  delete [] p;
55  delete [] d;
56  delete [] pc;
57  delete [] uj;
58  if (!is_convex) {
59  delete cpol;
60  for (int j=0; j<ncut; j++) {
61  delete cut[j];
62  }
63  delete [] cut;
64  }
65 }
66 
67 EGS_2DPolygon::EGS_2DPolygon(vector<EGS_2DVector> &points, bool Open) {
68  int n = points.size();
69  open = Open;
70  EGS_2DVector test(points[0]-points[n-1]);
71  if (test.length2() > epsilon) {
72  points.push_back(points[0]);
73  n++;
74  }
75  bool ccw = checkCCW(points);
76  // Remove points that are too close to each other.
77  EGS_2DVector *pp = new EGS_2DVector [n];
78  pp[0] = points[0];
79  int jj=1;
80  int j;
81  for (j=1; j<n; j++) {
82  EGS_2DVector aux(points[j]-pp[jj-1]);
83  if (aux.length2() > epsilon) {
84  pp[jj++] = points[j];
85  }
86  }
87  n = jj;
88  // now check for points on a line
89  for (j=0; j<n-2; j++) {
90  EGS_2DVector aa(pp[j+1]-pp[j]), bb(pp[j+2]-pp[j]);
91  if (fabs(aa%bb) < epsilon) {
92  pp[j+1] = pp[j+2];
93  for (int i=j+2; i<n; i++) {
94  pp[i] = pp[i+1];
95  }
96  n--;
97  }
98  }
99  np = n;
100  p = new EGS_2DVector [np];
101  for (j=0; j<n; j++) {
102  p[j] = pp[j];
103  }
104  delete [] pp;
105  // now make line normals pointing inwards.
106  a = new EGS_2DVector [np-1];
107  d = new EGS_Float [np-1];
108  uj = new EGS_2DVector [np-1];
109  pc = new bool [np-1];
110  xmin = veryFar, xmax = -veryFar;
111  ymin = veryFar, ymax = -veryFar;
112  for (j=0; j<np-1; j++) {
113  pc[j] = true;
114  if (p[j].x < xmin) {
115  xmin = p[j].x;
116  }
117  if (p[j].x > xmax) {
118  xmax = p[j].x;
119  }
120  if (p[j].y < ymin) {
121  ymin = p[j].y;
122  }
123  if (p[j].y > ymax) {
124  ymax = p[j].y;
125  }
126  uj[j] = p[j+1]-p[j];
127  if (ccw) {
128  a[j] = EGS_2DVector(-uj[j].y,uj[j].x);
129  }
130  else {
131  a[j] = EGS_2DVector(uj[j].y,-uj[j].x);
132  }
133  a[j].normalize();
134  d[j] = a[j]*p[j];
135  }
136  // now see if the polygon is convex
137  is_convex = true;
138  if (np == 4) {
139  return; // triangles are always convex.
140  }
141  open = false; // we can not have open polygons
142  for (j=0; j<np-1; j++) {
143  int j1 = j+1;
144  if (j1 == np-1) {
145  j1=0;
146  }
147  bool is_ok = true;
148  for (int i=0; i<np-1; i++) {
149  if (i != j && i != j1) {
150  if (!inside(j,p[i])) {
151  is_ok=false;
152  break;
153  }
154  }
155  }
156  if (!is_ok) {
157  is_convex = false;
158  pc[j] = false;
159  } //break; }
160  }
161 
162  if (is_convex) {
163  return;
164  }
165 
166  // find a point that is part of the convex hull of this polygon
167  for (j=0; j<np-1; j++) {
168  bool is_ok = true;
169  for (int i=0; i<np; i++) {
170  if (i < j || i > j+1) if (!inside(j,p[i])) {
171  is_ok=false;
172  break;
173  }
174  }
175  if (is_ok) { // found the point
176  pp = new EGS_2DVector [np];
177  int jj=0;
178  int i;
179  for (i=j; i<np-1; i++) {
180  pp[jj++] = p[i];
181  }
182  for (i=0; i<=j; i++) {
183  pp[jj++] = p[i];
184  }
185  break;
186  }
187  }
188 
189  vector<EGS_2DVector> chull;
190  vector<EGS_2DVector> ipol;
191  vector<EGS_2DPolygon *> tmp_pol;
192  chull.push_back(pp[0]);
193  chull.push_back(pp[1]);
194  int nc=2;
195  j=2;
196  bool doing_chull=true;
197  for (EGS_I64 loopCount=0; loopCount<=loopMax; ++loopCount) {
198  if (loopCount == loopMax) {
199  egsFatal("EGS_2DPolygon::EGS_2DPolygon: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
200  return;
201  }
202  EGS_2DVector s(pp[j]-chull[nc-1]);
203  EGS_2DVector sperp(-s.y,s.x);
204  if (!ccw) {
205  sperp *= (-1.);
206  }
207  EGS_Float ds = sperp*chull[nc-1];
208  bool all_inside=true;
209  for (int i=j+1; i<n; i++) {
210  if (sperp*pp[i] < ds) {
211  all_inside=false;
212  break;
213  }
214  }
215  if (all_inside) {
216  if (!doing_chull) {
217  ipol.push_back(pp[j]);
218  EGS_2DPolygon *newp = new EGS_2DPolygon(ipol);
219  tmp_pol.push_back(newp);
220  ipol.clear();
221  }
222  doing_chull = true;
223  chull.push_back(pp[j]);
224  nc++;
225  }
226  else {
227  if (doing_chull) {
228  doing_chull = false;
229  ipol.push_back(chull[nc-1]);
230  }
231  ipol.push_back(pp[j]);
232  }
233  j++;
234  if (j >= n) {
235  break;
236  }
237  }
238  cpol = new EGS_2DPolygon(chull);
239  ncut = tmp_pol.size();
240  cut = new EGS_2DPolygon* [ncut];
241  for (j=0; j<ncut; j++) {
242  cut[j] = tmp_pol[j];
243  }
244  delete [] pp;
245 }
const EGS_I64 loopMax
The maximum number of iterations for near-infinite loops.
Definition: egs_functions.h:95
A class representing 2D vectors.
~EGS_2DPolygon()
Destructor.
Definition: egs_polygon.cpp:52
const EGS_Float veryFar
A very large float.
EGS_2DPolygon and EGS_PolygonT class header file.
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
Definition: egs_functions.h:61
A class to represent a polygon in a plane (a 2D polygon).
Definition: egs_polygon.h:59
EGS_2DPolygon(vector< EGS_2DVector > &points, bool Open=false)
Construct a polygon from the 2D points points.
Definition: egs_polygon.cpp:67