core/vgl/vgl_polygon_scan_iterator.h
Go to the documentation of this file.
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