EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_polygon.h
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ polygon 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: Blake Walters
27 # Reid Townson
28 #
29 ###############################################################################
30 */
31 
32 
38 #ifndef EGS_POLYGON_
39 #define EGS_POLYGON_
40 
41 #include "egs_vector.h"
42 #include "egs_projectors.h"
43 #include "egs_math.h"
44 #include "egs_functions.h"
45 
46 #include <vector>
47 
48 using namespace std;
49 
60 
61 public:
62 
70  EGS_2DPolygon(vector<EGS_2DVector> &points, bool Open=false);
71 
73  ~EGS_2DPolygon();
74 
76  int getN() const {
77  return np-1;
78  };
79 
81  bool isConvex() const {
82  return is_convex;
83  };
84 
86  EGS_2DVector getNormal(int j) const {
87  if (j >= 0 && j < np-1) {
88  return a[j];
89  }
90  else {
91  return EGS_2DVector();
92  }
93  };
94 
100  EGS_Float hownear(bool in, const EGS_2DVector &x) const {
101  if (!open) {
102  EGS_Float tperp = veryFar;
103  bool do_it = true;
104  for (int j=0; j<np-1; j++) {
105  EGS_2DVector v(x - p[j]);
106  EGS_Float lam = uj[j]*v;
107  if (lam >= 0 && lam <= uj[j].length2()) {
108  do_it = false;
109  EGS_Float t = fabs(d[j] - x*a[j]);
110  if (t < tperp) {
111  tperp = t;
112  }
113  }
114  else if (lam < 0 && do_it) {
115  EGS_Float t = v.length();
116  if (t < tperp) {
117  tperp = t;
118  }
119  }
120  else {
121  do_it = true;
122  }
123  }
124  return tperp;
125  }
126  EGS_2DVector v(x - p[0]);
127  EGS_Float lam = uj[0]*v;
128  EGS_Float tperp;
129  bool do_it;
130  if (lam <= uj[0].length2()) {
131  do_it = false;
132  tperp = fabs(d[0] - x*a[0]);
133  }
134  else {
135  do_it = true;
136  tperp = veryFar;
137  }
138  v = x - p[1];
139  lam = uj[1]*v;
140  if (lam >= 0) {
141  EGS_Float t = fabs(d[1] - x*a[1]);
142  if (t < tperp) {
143  tperp = t;
144  }
145  }
146  else if (do_it) {
147  EGS_Float t = v.length();
148  if (t < tperp) {
149  tperp = t;
150  }
151  }
152  return tperp;
153  };
154 
156  bool isInside(const EGS_2DVector &x) const {
157  if (!open &&
158  (x.x<xmin+epsilon || x.x+epsilon>xmax || x.y<ymin+epsilon || x.y+epsilon>ymax)) {
159  return false;
160  }
161  if (is_convex) {
162  int nn = open ? np-2 : np-1;
163  for (int j=0; j<nn; j++)
164  if (!inside(j,x)) {
165  return false;
166  }
167  return true;
168  }
169  if (!cpol->isInside(x)) {
170  return false;
171  }
172  for (int j=0; j<ncut; j++) if (cut[j]->isInside(x)) {
173  return false;
174  }
175  return true;
176  };
177 
189  bool howfar(bool in, const EGS_2DVector &x, const EGS_2DVector &u,
190  EGS_Float &t, EGS_2DVector *normal = 0) {
191  EGS_Float xp, up;
192  bool res = false;
193  int nn = open ? np-2 : np-1;
194  if (in) {
195  int jhit=0;
196  for (int j=0; j<nn; j++) {
197  if ((up = u*a[j]) < 0 && (xp = x*a[j])+epsilon > d[j]) {
198  EGS_Float tt = d[j] - xp;
199  if (tt+epsilon >= t*up) {
200  tt /= up;
201  bool ok = is_convex || pc[j];
202  if (!ok) {
203  EGS_Float lam = uj[j]*(x-p[j]+u*tt);
204  if (lam >= 0 && lam < uj[j].length2()) {
205  ok = true;
206  }
207  }
208  if (ok) {
209  t = tt;
210  res = true;
211  jhit = j;
212  //if( normal ) *normal = a[j];
213  }
214  }
215  }
216  }
217  if (res && normal) {
218  *normal = a[jhit];
219  }
220  }
221  else {
222  int jhit=0;
223  if (open) {
224  if ((up = u*a[0]) > 0 && (xp = x*a[0]) < d[0]+epsilon) {
225  EGS_Float tt = (d[0] - xp)/up;
226  if (tt <= t+epsilon) {
227  EGS_Float lam = uj[0]*(x-p[0]+u*tt);
228  if (lam < uj[0].length2()) {
229  t = tt;
230  res = true;
231  jhit = 0;
232  }
233  }
234  }
235  if ((up = u*a[1]) > 0 && (xp = x*a[1]) < d[1]+epsilon) {
236  EGS_Float tt = (d[1] - xp)/up;
237  if (tt <= t+epsilon) {
238  EGS_Float lam = uj[1]*(x-p[1]+u*tt);
239  if (lam > 0) {
240  t = tt;
241  res = true;
242  jhit = 1;
243  }
244  }
245  }
246  }
247  else {
248  for (int j=0; j<nn; j++) {
249  if ((up = u*a[j]) > 0 && (xp = x*a[j]) < d[j]+epsilon) {
250  EGS_Float tt = (d[j] - xp)/up;
251  if (tt <= t+epsilon) {
252  EGS_Float lam = uj[j]*(x-p[j]+u*tt);
253  if (lam >= 0 && lam < uj[j].length2()) {
254  if (tt < 0) {
255  t = 0;
256  }
257  else {
258  t = tt;
259  }
260  res = true;
261  jhit = j;
262  //if( normal ) *normal = a[j]*(-1);
263  }
264  }
265  }
266  }
267  }
268  if (res && normal) {
269  *normal = a[jhit]*(-1);
270  }
271  }
272  return res;
273  };
274 
276  EGS_2DVector getPoint(int j) const {
277  if (j >= 0 && j < np) {
278  return p[j];
279  }
280  else {
281  return EGS_2DVector();
282  }
283  };
284 
285 
286 private:
287 
288  EGS_2DVector *p;
289  EGS_2DVector *a;
290  EGS_2DVector *uj;
291  EGS_Float *d;
292  bool *pc;
293 
294  EGS_Float xmin, xmax, ymin, ymax;
295  int np;
296  bool is_convex;
297  bool open;
300  int ncut;
302  EGS_2DPolygon **cut;
303  EGS_2DPolygon *cpol;
304 
307  static bool checkCCW(const vector<EGS_2DVector> &points);
309  bool inside(int j, const EGS_2DVector &x) const {
310  if (x*a[j]+epsilon >= d[j]) {
311  return true;
312  }
313  else {
314  return false;
315  }
316  };
317 
318 };
319 
334 template <class T>
336 
337 public:
338 
345  EGS_PolygonT(vector<EGS_2DVector> &points, const T &projector,
346  bool Open=false) : p(new EGS_2DPolygon(points,Open)), a(projector) {};
347 
350  delete p;
351  };
352 
354  inline bool isConvex() const {
355  return p->isConvex();
356  };
357 
359  inline int getN() const {
360  return p->getN();
361  };
362 
364  inline EGS_Vector getPoint(int j) const {
365  return a.getPoint(p->getPoint(j));
366  };
367 
369  inline EGS_Vector getNormal() const {
370  return a.normal();
371  };
372 
374  inline EGS_Vector getNormal(const EGS_2DVector &x) const {
375  return a.normal(x);
376  };
377 
379  inline EGS_Vector getNormal(int j) const {
380  return a.normal(p->getNormal(j));
381  };
382 
384  inline EGS_2DVector getProjection(const EGS_Vector &x) const {
385  return a.getProjection(x);
386  };
387 
389  inline EGS_Float distance(const EGS_Vector &x) const {
390  return a.distance(x);
391  };
392 
394  inline bool isInside2D(const EGS_2DVector &xp) const {
395  return p->isInside(xp);
396  };
397 
400  inline bool isInside2D(const EGS_Vector &x) const {
401  return p->isInside(a.getProjection(x));
402  };
403 
406  inline bool isInside(const EGS_Vector &x) const {
407  return (a.distance(x) >= 0);
408  };
409 
412  inline EGS_Float hownear2D(bool in, const EGS_Vector &x) const {
413  return p->hownear(in,a.getProjection(x));
414  };
415 
418  inline EGS_Float hownear(bool in, const EGS_Vector &x) const {
419  EGS_2DVector pos(a.getProjection(x));
420  EGS_Float t1 = fabs(a.distance(x));
421  if (p->isInside(pos)) {
422  return t1;
423  }
424  EGS_Float t2 = p->hownear(true,pos);
425  return sqrt(t1*t1+t2*t2);
426  };
427 
433  inline bool howfar2D(bool in, const EGS_Vector &x, const EGS_Vector &u,
434  EGS_Float &t, EGS_2DVector *normal = 0) const {
435  EGS_2DVector dir(a.getProjection(u));
436  if (u.length2() < epsilon) {
437  return false;
438  }
439  return p->howfar(in,a.getProjection(x),dir,t,normal);
440  };
441 
448  inline bool howfar(bool in, const EGS_Vector &x, const EGS_Vector &u,
449  EGS_Float &t) const {
450  EGS_Float up = a*u;
451  if ((in && up >= 0) || (!in && up <= 0)) {
452  return false;
453  }
454  EGS_Float tt = -a.distance(x)/up;
455  if (tt <= t+epsilon) {
456  EGS_Vector xp(x + u*tt);
457  if (p->isInside(a.getProjection(xp))) {
458  t = tt;
459  return true;
460  }
461  }
462  return false;
463  };
464 
466  const string &getType() const {
467  return a.getType();
468  };
469 
470 private:
471 
472  EGS_2DPolygon *p;
473  T a;
474 
475 };
476 
485 
487 EGS_EXPORT EGS_Polygon *makePolygon(const vector<EGS_Vector> &points);
488 
489 #endif
#define EGS_EXPORT
Export symbols from the egspp library.
Definition: egs_libconfig.h:90
bool isConvex() const
Is the polygon convex ?
Definition: egs_polygon.h:81
EGS_Float hownear(bool in, const EGS_Vector &x) const
Get the nearest distance between x and any point inside the polygon.
Definition: egs_polygon.h:418
EGS_Vector getPoint(int j) const
Get the j&#39;th point.
Definition: egs_polygon.h:364
EGS_PolygonT(vector< EGS_2DVector > &points, const T &projector, bool Open=false)
Construct a 3D polygon defined by the 2D points points in the plane defined by the projector projecto...
Definition: egs_polygon.h:345
A class representing 2D vectors.
bool howfar(bool in, const EGS_Vector &x, const EGS_Vector &u, EGS_Float &t) const
Will the line defined by position x and direction u intersect the polygon plane at a position inside ...
Definition: egs_polygon.h:448
EGS_Vector getNormal(const EGS_2DVector &x) const
Definition: egs_polygon.h:374
bool isConvex() const
Is this polygon convex ?
Definition: egs_polygon.h:354
EGS_Vector methods for the manipulation of 3D vectors in cartesian co-ordinates.
A class representing 3D vectors.
Definition: egs_vector.h:56
const string & getType() const
Get the polygon type.
Definition: egs_polygon.h:466
Global egspp functions header file.
const EGS_Float veryFar
A very large float.
EGS_EXPORT EGS_Polygon * makePolygon(const vector< EGS_Vector > &points)
Make a polygon from the 3D points points.
EGS_Float hownear2D(bool in, const EGS_Vector &x) const
Get the nearest distance between the projection of x and the polygon outline.
Definition: egs_polygon.h:412
EGS_Float hownear(bool in, const EGS_2DVector &x) const
Get the nearest distance from x to the polygon.
Definition: egs_polygon.h:100
EGS_Vector getNormal() const
Get the normal to the polygon plane.
Definition: egs_polygon.h:369
EGS_PolygonT< EGS_XProjector > EGS_PolygonYZ
A 3D polygon in the x-plane.
Definition: egs_polygon.h:478
bool isInside2D(const EGS_2DVector &xp) const
Is the 2D point xp inside the polygon ?
Definition: egs_polygon.h:394
int getN() const
Get the number of polygon points.
Definition: egs_polygon.h:359
EGS_PolygonT< EGS_Projector > EGS_Polygon
A 3D polygon in any plane.
Definition: egs_polygon.h:484
int getN() const
Get the number of points (vertices) in this polygon object.
Definition: egs_polygon.h:76
EGS_2DVector getPoint(int j) const
Get the j&#39;th point of this polygon.
Definition: egs_polygon.h:276
bool howfar2D(bool in, const EGS_Vector &x, const EGS_Vector &u, EGS_Float &t, EGS_2DVector *normal=0) const
Does the projection on the polygon plane of the trajectory defined by position x and direction u inte...
Definition: egs_polygon.h:433
Attempts to fix broken math header files.
EGS_2DVector getProjection(const EGS_Vector &x) const
Get the projection of x on the polygon plane.
Definition: egs_polygon.h:384
bool isInside2D(const EGS_Vector &x) const
Is the projection of the 3D point x on the polygon plane inside the polygon ?
Definition: egs_polygon.h:400
A template class for 3D polygons.
Definition: egs_polygon.h:335
bool howfar(bool in, const EGS_2DVector &x, const EGS_2DVector &u, EGS_Float &t, EGS_2DVector *normal=0)
Will the line defined by position x and direction u intersect the polygon ?
Definition: egs_polygon.h:189
EGS_PolygonT< EGS_ZProjector > EGS_PolygonXY
A 3D polygon in the z-plane.
Definition: egs_polygon.h:482
~EGS_PolygonT()
Destructor.
Definition: egs_polygon.h:349
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
Definition: egs_functions.h:61
bool isInside(const EGS_Vector &x) const
Is the 3D point inside the polygon plane ? (i.e. on than side of the plane to which the plane normal ...
Definition: egs_polygon.h:406
bool isInside(const EGS_2DVector &x) const
Is the 2D point x inside the polygon ?
Definition: egs_polygon.h:156
A class to represent a polygon in a plane (a 2D polygon).
Definition: egs_polygon.h:59
EGS_Projector and EGS_2DVector class header file.
EGS_Float distance(const EGS_Vector &x) const
Get the distance between x and the polygon plane.
Definition: egs_polygon.h:389
EGS_PolygonT< EGS_YProjector > EGS_PolygonXZ
A 3D polygon in the y-plane.
Definition: egs_polygon.h:480
EGS_2DVector getNormal(int j) const
Get a line normal to the j&#39;th polygon edge.
Definition: egs_polygon.h:86
EGS_Vector getNormal(int j) const
Get the normal to the j&#39;th polygon edge.
Definition: egs_polygon.h:379