Pottu
Gate2D.hpp
Go to the documentation of this file.
1 
8 #ifndef H_GATE2D
9 #define H_GATE2D
10 
11 #include <vector>
12 #include <fstream>
13 #include <cstdio>
14 #include <iostream>
15 
16 
17 namespace pottu {
18 
19 
23  struct Gate2D {
24 
27  struct point_t {
28  double x;
29  double y;
30  };
31 
32  // Points of the polygon gate. The very last point is the same
33  // as the very first. This is to speed up the test.
34  std::vector<point_t> points;
35 
36  // One point which is outside the polygon. Needed in the test.
37  point_t pointOutside{0,0};
38  // Bounding box low corner
39  point_t c00{0};
40  // Bounding box high corner
41  point_t c11{0};
42 
50  void update() {
51  if( points.size() < 4 )
52  throw std::runtime_error("Too few points in points");
53  c00 = points.front();
54  c11 = points.front();
55  for( const auto &p : points ) {
56  if( p.x < c00.x )
57  c00.x = p.x;
58  if( p.y < c00.y )
59  c00.y = p.y;
60  if( p.x > c11.x )
61  c11.x = p.x;
62  if( p.y > c11.y )
63  c11.y = p.y;
64  }
65  pointOutside.x = c00.x - 0.5*(c11.x-c00.x);
66  pointOutside.x = c00.y - (c11.y-c00.y);
67  }
68 
69 
70 
77  bool operator()( double x, double y ) const noexcept {
78  if( points.size()<4 )
79  return false;
80 
81  const point_t p1{x,y};
82  int ret{0};
83  auto prev = points.begin();
84  auto next = prev+1;
85  while( next != points.end() ) {
86  ret += hasIntersection( p1, pointOutside, *prev, *next );
87  prev++;
88  next++;
89  }
90  return ret & 1;
91  }
92 
93 
100  static Gate2D createFromAsciiFile( const std::string &filename ) {
101  Gate2D gate;
102  std::ifstream f( filename );
103  if( !f.is_open() )
104  throw std::runtime_error( "Gate2D::readFromAsciiFile(): Couldnot open the file." );
105 
106  unsigned int row = 0;
107  double x, y;
108  int tmp;
109 
110  std::string s_line, s_tmp;
111  while( !f.eof() ) {
112  ++row;
113  std::getline( f, s_line );
114 
115  tmp = sscanf( s_line.c_str(), " %lf %lf", &x, &y );
116  if( tmp == 2 ) {
117  gate.points.push_back( {x,y} );
118  }
119  if( tmp != 2 && tmp != 0 && tmp != EOF ) {
120  std::cerr << "Gate2D::readFromAsciiFile(): \n"
121  << " Error on file \'" << filename << "\' on line " << row << "!\n"
122  << " Line \'" << s_line << "\'\n"
123  << " tmp = " << tmp << "\n";
124  throw std::runtime_error( "Syntax error when reading Gate2D from an ascii file" );
125  }
126  }
127  if( gate.points.size() < 3 )
128  throw std::runtime_error( "Gate2D: Too few points in polygon." );
129  gate.points.push_back( gate.points.front() );
130  gate.update();
131  return gate;
132  }
133 
134 
135  // Helper function
136  static int hasIntersection( point_t p0, point_t p1, point_t p2, point_t p3 ) noexcept {
137  const point_t s1{ p1.x - p0.x, p1.y - p0.y };
138  const point_t s2{ p3.x - p2.x, p3.y - p2.y };
139 
140  point_t st{
141  (-s1.y * (p0.x - p2.x) + s1.x * (p0.y - p2.y)) / (-s2.x * s1.y + s1.x * s2.y),
142  ( s2.x * (p0.y - p2.y) - s2.y * (p0.x - p2.x)) / (-s2.x * s1.y + s1.x * s2.y) };
143 
144  return st.x >= 0 && st.x <= 1 && st.y >=0 && st.y <= 1;
145  }
146 
147  };
148 
149 }
150 
151 #endif
Definition: mainpage.dox:6
Point type.
Definition: Gate2D.hpp:27
Defines 2D polygon for 2D gating.
Definition: Gate2D.hpp:23
static Gate2D createFromAsciiFile(const std::string &filename)
Reads the polygon from a file.
Definition: Gate2D.hpp:100
bool operator()(double x, double y) const noexcept
Tests if a given point is inside the gate.
Definition: Gate2D.hpp:77
void update()
updates the other important fields after modifying points.
Definition: Gate2D.hpp:50