vgl_triangle_scan_iterator.hxx
Go to the documentation of this file.
1 // This is core/vgl/vgl_triangle_scan_iterator.hxx
2 #ifndef vgl_triangle_scan_iterator_hxx_
3 #define vgl_triangle_scan_iterator_hxx_
4 //:
5 // \file
6 // \author fsm
7 
8 #include <cmath>
9 #include <iostream>
11 
12 #ifdef _MSC_VER
13 # include <vcl_msvc_warnings.h>
14 #endif
15 
16 template <class T>
17 static inline
18 void min_n_max(T a, T b, T c, T *min, T *max)
19 {
20  if (a < b) {
21  if (a < c) {
22  *min = a;
23  if (b < c) // a b c
24  *max = c;
25  else // a c b
26  *max = b;
27  }
28  else { // c a b
29  *min = c;
30  *max = b;
31  }
32  }
33  else {
34  if (b < c) {
35  *min = b;
36  if (a < c) // b a c
37  *max = c;
38  else // b c a
39  *max = a;
40  }
41  else { // c b a
42  *min = c;
43  *max = a;
44  }
45  }
46  // that was fun. now do some work.
47 }
48 
49 #if use_polygon_scan_iterator
51 template <class T>
52 struct vgl_triangle_scan_iterator<T>::data_t : public vgl_polygon_scan_iterator<T>
53 {
54  typedef vgl_polygon_scan_iterator<T> base;
55  data_t(vgl_polygon<T> const &p) : base(p) {}
56 };
57 
58 template <class T>
60 {
61  if (data)
62  delete data;
63  data = 0;
64 }
65 #else
66 // w(a, b, c) = det [ a b c ]
67 // [ 1 1 1 ]
68 //# define w(a, b, c) ( b.x*c.y - b.x*a.y - a.x*c.y - c.x*b.y + c.x*a.y + a.x*b.y )
69 #endif
70 
71 template <class T>
73 {
74 #if use_polygon_scan_iterator
75  if (data)
76  delete data;
77  T x[3] = { a.x, b.x, c.x };
78  T y[3] = { a.y, b.y, c.y };
79  vgl_polygon<T> p(x, y, 3);
80  data = new data_t(p);
81  data->reset();
82 #else
83  T min, max;
84 
85  min_n_max(a.x, b.x, c.x, &min, &max);
86  x0 = (int) std::ceil (min);
87  x1 = (int) std::floor(max);
88 #ifdef DEBUG
89  std::cerr << "x0 x1 = " << x0 << ' ' << x1 << '\n';
90 #endif
91 
92  min_n_max(a.y, b.y, c.y, &min, &max);
93  y0 = (int) std::ceil (min);
94  y1 = (int) std::floor(max);
95 #ifdef DEBUG
96  std::cerr << "y0 y1 = " << y0 << ' ' << y1 << '\n';
97 #endif
98 
99  scany_ = y0 - 1;
100 
101  // compute centroid
102  g.x = std::floor((a.x + b.x + c.x)/3);
103  g.y = std::floor((a.y + b.y + c.y)/3);
104 #ifdef DEBUG
105  std::cerr << "g = " << g.x << ' ' << g.y << '\n';
106 #endif
107 
108  //
109  pt ag = { a.x - g.x, a.y - g.y };
110  pt bg = { b.x - g.x, b.y - g.y };
111  pt cg = { c.x - g.x, c.y - g.y };
112 
113  data[0][0] = bg.y - cg.y; data[0][1] = cg.x - bg.x; data[0][2] = bg.x * cg.y - bg.y * cg.x;
114  data[1][0] = cg.y - ag.y; data[1][1] = ag.x - cg.x; data[1][2] = cg.x * ag.y - cg.y * ag.x;
115  data[2][0] = ag.y - bg.y; data[2][1] = bg.x - ag.x; data[2][2] = ag.x * bg.y - ag.y * bg.x;
116 
117  T tmp = ( bg.x*cg.y - bg.x*ag.y - ag.x*cg.y - cg.x*bg.y + cg.x*ag.y + ag.x*bg.y );
118  if (tmp < 0)
119  tmp = -1;
120  else
121  tmp = +1;
122  for (auto & i : data) {
123  T f = tmp; // / sqrt(data[i][0]*data[i][0] + data[i][1]*data[i][1]);
124  for (int j=0; j<3; ++j)
125  i[j] *= f;
126  }
127 #if 0
128  std::cerr << "data:\n";
129  for (int i=0; i<3; ++i) {
130  for (int j=0; j<3; ++j)
131  std::cerr << ' ' << data[i][j];
132  std::cerr << std::endl;
133  }
134  std::cerr << std::endl;
135 #endif
136 #endif // use_polygon_scan_iterator
137 }
138 
139 template <class T>
141 {
142 #if use_polygon_scan_iterator
143  if (data->next()) {
144  scany_ = data->scany();
145  startx_ = data->startx();
146  endx_ = data->endx();
147  return true;
148  }
149  else
150  return false;
151 #else
152  if (++scany_ > y1)
153  return false;
154 
155  T minx = x0 - g.x;
156  T maxx = x1 - g.x;
157 
158 #ifdef DEBUG
159  std::cerr << "minx maxx = " << minx << ' ' << maxx << '\n';
160 #endif
161  for (auto & i : data) {
162  T a_ = i[0];
163  T b_ = i[1] * (scany_ - g.y) + i[2];
164  // ax + b >= 0
165  if (a_ == 0) {
166  // bif bif
167  }
168  else {
169  T x = -b_/a_;
170  if (a_ > 0) {
171  if (x > minx)
172  minx = x;
173  }
174  else {
175  if (x < maxx)
176  maxx = x;
177  }
178  }
179 #ifdef DEBUG
180  std::cerr << "minx maxx = " << minx << ' ' << maxx << '\n';
181 #endif
182  }
183 
184  startx_ = (int) std::ceil (minx + g.x);
185  endx_ = (int) std::floor(maxx + g.x);
186 
187  // can not use (scany_ == y0) || (startx_ <= endx_)
188  // for early scan termination because some triangles may have
189  // (startx_ > endx_) for more than the first scan line
190 
191 
192  return true;
193 #endif
194 }
195 
196 #undef VGL_TRIANGLE_SCAN_ITERATOR_INSTANTIATE
197 #define VGL_TRIANGLE_SCAN_ITERATOR_INSTANTIATE(T) \
198 template class vgl_triangle_scan_iterator<T >
199 
200 #endif // vgl_triangle_scan_iterator_hxx_
bool next() override
Tries to move to the next scan line.
Optimized polygon scan iterator for triangles.
Definition: vgl_fwd.h:34
Optimized polygon scan iterator for triangles.
Fill a polygonal face with interior scan lines.
Definition: vgl_fwd.h:33
void reset() override
Resets the scan iterator to before the first scan line.
Store a polygon.
Definition: vgl_area.h:6