Go to the documentation of this file.00001
00002 #ifndef vgl_polygon_scan_iterator_txx_
00003 #define vgl_polygon_scan_iterator_txx_
00004
00005
00006
00007 #include "vgl_polygon_scan_iterator.h"
00008 #include <vcl_cstring.h>
00009 #include <vcl_cmath.h>
00010 #include <vcl_iostream.h>
00011 #include <vcl_algorithm.h>
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 static const float vgl_polygon_scan_iterator_offset = 0.0f;
00033
00034
00035 #undef MIN
00036 #define MIN(a,b) (((a)<(b))?(a):(b))
00037
00038
00039 #undef MAX
00040 #define MAX(a,b) (((a)>(b))?(a):(b))
00041
00042 template <class T>
00043 struct compare_vertind
00044 {
00045 compare_vertind(typename vgl_polygon<T>::sheet_t* chs) : chs_(chs)
00046 {}
00047
00048 inline bool operator()(const typename vgl_polygon_scan_iterator<T>::vertind &u,
00049 const typename vgl_polygon_scan_iterator<T>::vertind &v) const
00050 {
00051 return chs_[u.chainnum][u.vertnum].y() < chs_[v.chainnum][v.vertnum].y();
00052 }
00053
00054 typename vgl_polygon<T>::sheet_t* chs_;
00055 };
00056
00057 template <class T>
00058 struct compare_crossedges
00059 {
00060 inline bool operator()(const typename vgl_polygon_scan_iterator<T>::crossedge &u,
00061 const typename vgl_polygon_scan_iterator<T>::crossedge &v) const
00062 {
00063 return u.x < v.x;
00064 }
00065 };
00066
00067 template <class T>
00068 inline static void local_qsort(typename vgl_polygon_scan_iterator<T>::vertind* yverts, int numverts, vgl_polygon<T>& p)
00069 {
00070 vcl_sort(yverts, yverts + numverts, compare_vertind<T>(&p[0]));
00071 }
00072
00073 template <class T>
00074 inline static void local_qsort(typename vgl_polygon_scan_iterator<T>::crossedge* crossedges, int numcrossedges)
00075 {
00076 vcl_sort(crossedges, crossedges + numcrossedges, compare_crossedges<T>());
00077 }
00078
00079
00080
00081
00082 template <class T>
00083 vgl_polygon_scan_iterator<T>::~vgl_polygon_scan_iterator()
00084 {
00085 delete [] crossedges;
00086 delete [] yverts;
00087 }
00088
00089
00090
00091
00092 template <class T>
00093 vgl_polygon_scan_iterator<T>::vgl_polygon_scan_iterator(vgl_polygon<T> const& face,
00094 bool boundaryp):
00095 poly_(face)
00096 {
00097 boundp = boundaryp;
00098 have_window = false;
00099 init();
00100 }
00101
00102
00103
00104
00105 template <class T>
00106 vgl_polygon_scan_iterator<T>::vgl_polygon_scan_iterator(vgl_polygon<T> const& face, bool boundaryp, vgl_box_2d<T> const& window):
00107 poly_(face)
00108 {
00109 boundp = boundaryp;
00110 have_window = true;
00111 win = window;
00112 init();
00113 }
00114
00115
00116
00117
00118
00119
00120 template <class T>
00121 void vgl_polygon_scan_iterator<T>::init()
00122 {
00123
00124 numverts = 0;
00125 for (unsigned int s = 0; s < poly_.num_sheets(); ++s)
00126 numverts += int(poly_[s].size());
00127
00128 unsigned int numchains = poly_.num_sheets();
00129
00130 if ( numverts == 0 ) {
00131
00132 y0 = 0;
00133 y1 = -1;
00134 crossedges = 0;
00135 yverts = 0;
00136 return;
00137 }
00138
00139
00140 crossedges = new crossedge[ numverts ];
00141
00142
00143 yverts = new vertind[ numverts ];
00144 int i = 0;
00145 for (unsigned int j = 0; j < numchains; j++ )
00146 for (unsigned int h = 0; h < poly_[ j ].size(); h++ )
00147 {
00148 yverts[ i ].chainnum = j;
00149 yverts[ i ].vertnum = h;
00150 i++;
00151 }
00152 if ( i != numverts )
00153 vcl_cout << "Error: i does not equal numverts!\n";
00154
00155
00156 local_qsort<T>(yverts, numverts, poly_);
00157
00158 T miny, maxy;
00159 miny = get_y( yverts[ 0 ] );
00160 maxy = get_y( yverts[ numverts - 1 ] );
00161
00162
00163 if (have_window)
00164 {
00165 if (boundp)
00166 y0 = (int)MAX(win.min_y(), vcl_floor( miny - vgl_polygon_scan_iterator_offset));
00167 else
00168 y0 = (int)MAX(win.min_y(), vcl_ceil( miny - vgl_polygon_scan_iterator_offset));
00169
00170 if (boundp)
00171 y1 = (int)MIN(win.max_y()-1, vcl_ceil( maxy - vgl_polygon_scan_iterator_offset));
00172 else
00173 y1 = (int)MIN(win.max_y()-1, vcl_floor( maxy - vgl_polygon_scan_iterator_offset));
00174 }
00175 else
00176 {
00177 if (boundp)
00178 y0 = (int)vcl_floor( miny - vgl_polygon_scan_iterator_offset);
00179 else
00180 y0 = (int)vcl_ceil( miny - vgl_polygon_scan_iterator_offset);
00181
00182 if (boundp)
00183 y1 = (int)vcl_ceil( maxy - vgl_polygon_scan_iterator_offset);
00184 else
00185 y1 = (int)vcl_floor( maxy - vgl_polygon_scan_iterator_offset);
00186 }
00187 }
00188
00189
00190
00191
00192 template <class T>
00193 void vgl_polygon_scan_iterator<T>::delete_edge( vertind v )
00194 {
00195 int j;
00196 for ( j = 0; j < numcrossedges &&
00197 !( crossedges[j].v.chainnum == v.chainnum &&
00198 crossedges[j].v.vertnum == v.vertnum ); ++j )
00199 ;
00200
00201
00202 if ( j >= numcrossedges ) return;
00203
00204 numcrossedges--;
00205 vcl_memmove(&crossedges[j], &crossedges[j+1],
00206 (numcrossedges-j)*sizeof( crossedges[0] ));
00207 }
00208
00209
00210
00211
00212 template <class T>
00213 void vgl_polygon_scan_iterator<T>::insert_edge( vertind v )
00214 {
00215 vertind nextvert;
00216 T dx;
00217 Point2 p, q;
00218
00219 get_next_vert( v, nextvert );
00220 if ( get_y( v ) < get_y( nextvert ) )
00221 {
00222 p = get_pt( v );
00223 q = get_pt( nextvert );
00224 }
00225 else
00226 {
00227 p = get_pt( nextvert );
00228 q = get_pt( v );
00229 }
00230
00231
00232 crossedges[numcrossedges].dx = dx = (q.x() - p.x()) / (q.y() - p.y());
00233 crossedges[numcrossedges].x = dx * ( fy + vgl_polygon_scan_iterator_offset - p.y() ) + p.x();
00234 crossedges[numcrossedges].v = v;
00235 numcrossedges++;
00236 }
00237
00238
00239
00240
00241
00242 template <class T>
00243 void vgl_polygon_scan_iterator<T>::reset()
00244 {
00245 y = y0;
00246 numcrossedges = 0;
00247 curcrossedge = 0;
00248 k = 0;
00249 xl = 0;
00250 xr = 0;
00251 fxl = 0;
00252 fxr = 0;
00253 }
00254
00255
00256
00257
00258 template <class T>
00259 static inline int irnd(T x)
00260 {
00261 return (int)vcl_floor(x + 0.5);
00262 }
00263
00264 template <class T>
00265 void vgl_polygon_scan_iterator<T>::get_crossedge_vertices(int * &chainnum, int * &vertnum, int & num_crossedges)
00266 {
00267 num_crossedges=numcrossedges;
00268 int current=0;
00269 chainnum=new int[num_crossedges];
00270 vertnum=new int[num_crossedges];
00271 while ( current < numcrossedges )
00272 {
00273 chainnum[current] = crossedges[current].v.chainnum;
00274 vertnum[current] = crossedges[current].v.vertnum;
00275 current++;
00276 }
00277 }
00278
00279
00280
00281
00282
00283
00284
00285 template <class T>
00286 bool vgl_polygon_scan_iterator<T>::next( )
00287 {
00288 do {
00289
00290 while ( curcrossedge < numcrossedges )
00291 {
00292 fxl = crossedges[curcrossedge].x;
00293 fxr = crossedges[curcrossedge+1].x;
00294 if (boundp)
00295
00296 xl = (int)vcl_floor( crossedges[curcrossedge].x - vgl_polygon_scan_iterator_offset);
00297 else
00298
00299 xl = (int)vcl_ceil( crossedges[curcrossedge].x - vgl_polygon_scan_iterator_offset);
00300
00301 if ( have_window && xl < irnd(win.min_x()) )
00302 {
00303 fxl = win.min_x();
00304 xl = irnd(fxl);
00305 }
00306
00307 if ( boundp )
00308
00309 xr = (int)vcl_ceil( crossedges[curcrossedge+1].x - vgl_polygon_scan_iterator_offset);
00310 else
00311
00312 xr = (int)vcl_floor( crossedges[curcrossedge+1].x - vgl_polygon_scan_iterator_offset);
00313
00314 if ( have_window && xr >= irnd(win.max_x()) )
00315 {
00316 fxr = win.max_x() -1;
00317 xr = irnd(fxr);
00318 }
00319 #if 0 // TODO: added by Vishal Jain (Brown U) but breaks the tests - please fix!
00320 if (xr==crossedges[curcrossedge+1].x)
00321 --xr;
00322 #endif // 0
00323
00324
00325 crossedges[curcrossedge].x += crossedges[curcrossedge].dx;
00326 crossedges[curcrossedge+1].x += crossedges[curcrossedge+1].dx;
00327 curcrossedge+=2;
00328 if ( xl <= xr )
00329 return true;
00330 }
00331
00332
00333
00334 vertind curvert, prevvert, nextvert;
00335 if ( y > y1 )
00336 return false;
00337 else
00338 {
00339
00340 bool not_last = true;
00341
00342
00343
00344
00345
00346 if ( boundp ) {
00347 if ( y == y0 )
00348 fy = vcl_floor(get_y( yverts[ 0 ] ));
00349 else if ( y == y1 ) {
00350 fy = vcl_ceil(get_y( yverts[ numverts - 1 ] ));
00351 not_last = false;
00352 }
00353 else
00354 fy = T(y);
00355 }
00356 else
00357 fy = T(y);
00358
00359 for (; k<numverts && get_y(yverts[k]) <= fy+vgl_polygon_scan_iterator_offset && not_last; k++)
00360 {
00361 curvert = yverts[ k ];
00362
00363
00364
00365 get_prev_vert( curvert, prevvert );
00366
00367 if ( get_y( prevvert ) <= fy-vgl_polygon_scan_iterator_offset)
00368 delete_edge( prevvert );
00369 else if ( get_y( prevvert ) > fy+vgl_polygon_scan_iterator_offset)
00370 insert_edge( prevvert );
00371
00372 get_next_vert( curvert, nextvert );
00373
00374 if ( get_y( nextvert ) <= fy-vgl_polygon_scan_iterator_offset)
00375 delete_edge( curvert );
00376 else if ( get_y( nextvert ) > fy+vgl_polygon_scan_iterator_offset)
00377 insert_edge( curvert );
00378 }
00379
00380
00381 local_qsort<T>(crossedges, numcrossedges);
00382
00383 curcrossedge = 0;
00384 y++;
00385 }
00386 } while ( true );
00387 }
00388
00389
00390
00391
00392
00393
00394 template <class T>
00395 void vgl_polygon_scan_iterator<T>::get_next_vert( vertind v, vertind & nextvert )
00396 {
00397 nextvert = v;
00398 nextvert.vertnum += 1;
00399 if ( nextvert.vertnum == int(poly_[nextvert.chainnum].size()) )
00400 nextvert.vertnum = 0;
00401 }
00402
00403
00404
00405
00406
00407 template <class T>
00408 void vgl_polygon_scan_iterator<T>::get_prev_vert( vertind v, vertind & prevvert )
00409 {
00410 prevvert = v;
00411 prevvert.vertnum = prevvert.vertnum - 1;
00412 if ( prevvert.vertnum == -1 )
00413 prevvert.vertnum = int(poly_[prevvert.chainnum].size() - 1);
00414 }
00415
00416
00417
00418
00419 template <class T>
00420 void vgl_polygon_scan_iterator<T>::display_chains()
00421 {
00422 vcl_cout << "Number of Chains: " << poly_.num_sheets() << vcl_endl
00423 << "Number of Vertices: " << numverts << vcl_endl;
00424 for (unsigned int c = 0; c < poly_.num_sheets(); ++c )
00425 {
00426 vcl_cout << "---- Chain # " << c << " ----\n"
00427 << " Length: " << poly_[ c ].size() << vcl_endl;
00428 for (unsigned int v = 0; v < poly_[ c ].size(); v++ )
00429 {
00430 vcl_cout << " [ " << poly_[ c ][ v ].x()
00431 << ' ' << poly_[ c ][ v ].y() << " ]\n";
00432 }
00433 }
00434 vcl_cout << vcl_flush;
00435 }
00436
00437
00438
00439
00440 template <class T>
00441 void vgl_polygon_scan_iterator<T>::display_crossedges()
00442 {
00443 vcl_cout << "----- CROSSEDGES -----\n"
00444 << "numcrossedges: " << numcrossedges << vcl_endl;
00445 for (int i = 0; i< numcrossedges; i++ )
00446 {
00447 vcl_cout << "x = " << crossedges[i].x << '\n'
00448 << "y = " << crossedges[i].dx << '\n'
00449 << "v: chainnum=" << crossedges[i].v.chainnum
00450 << ", vertnum=" << crossedges[i].v.vertnum << '\n';
00451 }
00452 vcl_cout << "---------------------\n" << vcl_flush;
00453 }
00454
00455 #undef VGL_POLYGON_SCAN_ITERATOR_INSTANTIATE
00456 #define VGL_POLYGON_SCAN_ITERATOR_INSTANTIATE(T) \
00457 template class vgl_polygon_scan_iterator<T >
00458
00459 #endif // vgl_polygon_scan_iterator_txx_