00001 // This is core/vgl/vgl_polygon_scan_iterator.h 00002 #ifndef vgl_polygon_scan_iterator_h 00003 #define vgl_polygon_scan_iterator_h 00004 //: 00005 // \file 00006 // \author Adapted from FillPolygon by J.L. Mundy 00007 // 00008 // \verbatim 00009 // Modifications 00010 // Binary IO added and documentation tidied up NPC, 20/03/01 00011 // Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line 00012 // Nov.2003 - Peter Vanroose - made vgl_polygon_scan_iterator a templated class 00013 // Apr.2004 - Peter Vanroose - corrected an earlier with_boundary fix in next() 00014 // \endverbatim 00015 00016 #include <vgl/vgl_region_scan_iterator.h> 00017 #include <vgl/vgl_polygon.h> 00018 #include <vgl/vgl_box_2d.h> 00019 00020 //: Fill a polygonal face with interior scan lines 00021 // This class provides an iterator-style interface to polygon scan 00022 // conversion. There are convenient constructors from vgl_polygon, and_ 00023 // lists of floats. An auxiliary clipping window can be specified by the 00024 // constructor argument, vgl_box_2d<T> win. 00025 // 00026 // Concave Polygon Scan Conversion 00027 // by Paul Heckbert 00028 // from "Graphics Gems", Academic Press, 1990 00029 // 00030 // Scan convert nvert-sided concave non-simple polygon 00031 // with vertices at (point[i].x, point[i].y) 00032 // for i in [0..nvert-1] within the window win by 00033 // calling spanproc for each visible span of pixels. 00034 // Polygon can be clockwise or counterclockwise. 00035 // Algorithm does uniform point sampling at pixel centers. 00036 // Inside-outside test done by Jordan's rule: a point is considered inside if 00037 // an emanating ray intersects the polygon an odd number of times. 00038 // 00039 // Note: The span limits, startx and endx, are closed intervals. 00040 // That is, you can use the endpoints of the span as valid interior points. 00041 // Also, the initial and final y scan lines returned by the iterator 00042 // are interior to the polygon. The constructor argument, win, is a clipping 00043 // window that is intersected with the polygonal region to determine the actual 00044 // scanned area. 00045 // 00046 // Example usage: 00047 // \code 00048 // vgl_polygon_scan_iterator<float> psi(mypoints); 00049 // psi.set_include_boundary(true); // optional flag, default is true 00050 // for (psi.reset(); psi.next(); ) { 00051 // int y = psi.scany(); 00052 // for (int x = psi.startx(); x <= psi.endx(); ++x) 00053 // .... 00054 // } 00055 // \endcode 00056 template <class T> 00057 class vgl_polygon_scan_iterator : public vgl_region_scan_iterator 00058 { 00059 int boundp; //!< boolean indicating if boundary should be included or not 00060 int xl; //!< left bound of current span 00061 T fxl; //!< left bound of current span (floating point value) 00062 int xr; //!< right bound of current span 00063 T fxr; //!< right bound of current span (floating point value) 00064 int k; //!< current index of vertices ordered by increasing y 00065 int y0; //!< bottommost scan line 00066 int y1; //!< topmost scan line 00067 int y; //!< current scan line 00068 T fy; //!< floating point value of current scan line (i.e. T(y)) 00069 int curcrossedge; //!< crossedge marking start of next scan segment 00070 vgl_box_2d<T> win;//!< clipping window 00071 bool have_window; 00072 00073 vgl_polygon<T> poly_; //!< the polygon 00074 00075 public: 00076 // Stores coordinates of a 2d point 00077 typedef typename vgl_polygon<T>::point_t Point2; 00078 00079 // Constructors/Destructor--------------------------------------------------- 00080 00081 //: Construct with a polygon and bool indicating whether boundary included 00082 vgl_polygon_scan_iterator(vgl_polygon<T> const& face, bool boundaryp = true); 00083 00084 //: Construct with a polygon, bool indicating whether boundary included and window (area visible) 00085 vgl_polygon_scan_iterator(vgl_polygon<T> const& face, bool boundaryp, 00086 vgl_box_2d<T> const& window); 00087 00088 //: Destructor 00089 ~vgl_polygon_scan_iterator(); 00090 00091 //Functions---------------------------------------------------------- 00092 00093 //: Resets iterator to first segment of first scan line 00094 void reset(); 00095 00096 //: Moves iterator to next segment 00097 bool next(); 00098 00099 //: Returns current scan line 00100 inline int scany() const { return y-1; } 00101 00102 //: Returns start of current span 00103 inline int startx() const { return xl; } 00104 00105 //: Returns end of current span 00106 inline int endx() const { return xr; } 00107 00108 //: Returns start of current span (floating point value) 00109 inline T fstartx() const { return fxl; } 00110 00111 //: Returns end of current span (floating point value) 00112 inline T fendx() const { return fxr; } 00113 00114 //: Returns current scan line (floating point value) 00115 inline T fscany() const { return fy; } 00116 00117 // returns the vertices related to 00118 void get_crossedge_vertices(int * &chainnum, int * &vertnum, int & numcrossedges); 00119 //: Vertex index - uniquely identifies a vertex in the array chains 00120 struct vertind { 00121 int chainnum; //!< which chain the vertex is part of 00122 int vertnum; //!< which vertex in the chain 00123 }; 00124 00125 //: Describes an edge crossing the current scan line 00126 struct crossedge { 00127 T x; //!< x coord of edge's intersection with current scanline 00128 T dx; //!< change in x with respect to y 00129 vertind v; //!< edge goes from vertex v.vertnum to v.vertnum + 1 00130 }; 00131 00132 // Internals --------------------------------------------------------------- 00133 00134 private: 00135 // avoid copy constructor a operator= 00136 vgl_polygon_scan_iterator(const vgl_polygon_scan_iterator& ); 00137 vgl_polygon_scan_iterator& operator= (const vgl_polygon_scan_iterator& ); 00138 00139 vertind * yverts; //!< array of all vertices ordered by y coordinate 00140 crossedge * crossedges; //!< array of edges crossing current scan line 00141 int numcrossedges; //!< number of edges currently crossing scan line 00142 int numverts; //!< total number of vertices comprising face 00143 00144 // Returns x coord of vertex v 00145 inline T get_x(vertind v) const { return poly_[v.chainnum][v.vertnum].x(); } 00146 00147 // Returns y coord of vertex v 00148 inline T get_y(vertind v) const { return poly_[v.chainnum][v.vertnum].y(); } 00149 00150 // Returns vertex v 00151 inline Point2 get_pt( vertind v ) const { return poly_[v.chainnum][v.vertnum]; } 00152 00153 // assumes poly_, win, have_window, boundp are set 00154 void init(); 00155 00156 // Deletes edge (v,get_next_vert(v)) from crossedges array 00157 void delete_edge( vertind v ); 00158 00159 // Inserts edge (v,get_next_vert(v)) into crossedges array 00160 void insert_edge( vertind v ); 00161 00162 // Returns next vertex on chain 00163 void get_next_vert( vertind v, vertind & next ); 00164 00165 // Returns prev vertex on chain 00166 void get_prev_vert( vertind v, vertind & prev ); 00167 00168 // For debugging purposes 00169 void display_chains(); 00170 void display_crossedges(); 00171 }; 00172 00173 #define VGL_POLYGON_SCAN_ITERATOR_INSTANTIATE(T) extern "please include <vgl/vgl_polygon_scan_iterator.txx> instead" 00174 00175 #endif // vgl_polygon_scan_iterator_h