1 // This is core/vgl/vgl_polygon_scan_iterator.h
2 #ifndef vgl_polygon_scan_iterator_h
3 #define vgl_polygon_scan_iterator_h
4 //:
5 // \file
6 // \author Adapted from FillPolygon by J.L. Mundy
7 //
8 // \verbatim
9 //  Modifications
10 //   Binary IO added and documentation tidied up NPC, 20/03/01
11 //   Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line
12 //   Nov.2003 - Peter Vanroose - made vgl_polygon_scan_iterator a templated class
13 //   Apr.2004 - Peter Vanroose - corrected an earlier with_boundary fix in next()
14 // \endverbatim
15 
16 #include "vgl_region_scan_iterator.h"
17 #include "vgl_polygon.h"
18 #include "vgl_box_2d.h"
19 
20 //: Fill a polygonal face with interior scan lines
21 //  This class provides an iterator-style interface to polygon scan
22 //  conversion.  There are convenient constructors from vgl_polygon, and_
23 //  lists of floats.  An auxiliary clipping window can be specified by the
24 //  constructor argument, vgl_box_2d<T> win.
25 //
26 // Concave Polygon Scan Conversion
27 // by Paul Heckbert
28 // from "Graphics Gems", Academic Press, 1990
29 //
30 // Scan convert nvert-sided concave non-simple polygon
31 // with vertices at  (point[i].x, point[i].y)
32 // for i in [0..nvert-1] within the window win by
33 // calling spanproc for each visible span of pixels.
34 // Polygon can be clockwise or counterclockwise.
35 // Algorithm does uniform point sampling at pixel centers.
36 // Inside-outside test done by Jordan's rule: a point is considered inside if
37 // an emanating ray intersects the polygon an odd number of times.
38 //
39 // Note: The span limits, startx and endx,  are closed intervals.
40 // That is, you can use the endpoints of the span as valid interior points.
41 // Also, the initial and final y scan lines returned by the iterator
42 // are interior to the polygon.  The constructor argument, win, is a clipping
43 // window that is intersected with the polygonal region to determine the actual
44 // scanned area.
45 //
46 // Example usage:
47 // \code
48 //  vgl_polygon_scan_iterator<float> psi(mypoints);
49 //  psi.set_include_boundary(true); // optional flag, default is true
50 //  for (psi.reset(); psi.next(); ) {
51 //    int y = psi.scany();
52 //    for (int x = psi.startx(); x <= psi.endx(); ++x)
53 //         ....
54 //  }
55 // \endcode
56 template <class T>
57 class vgl_polygon_scan_iterator : public vgl_region_scan_iterator
58 {
59   int boundp;       //!< boolean indicating if boundary should be included or not
60   int xl;           //!< left bound of current span
61   T fxl;            //!< left bound of current span (floating point value)
62   int xr;           //!< right bound of current span
63   T fxr;            //!< right bound of current span (floating point value)
64   int k;            //!< current index of vertices ordered by increasing y
65   int y0;           //!< bottommost scan line
66   int y1;           //!< topmost scan line
67   int y;            //!< current scan line
68   T fy;             //!< floating point value of current scan line (i.e. T(y))
69   int curcrossedge; //!< crossedge marking start of next scan segment
70   vgl_box_2d<T> win;//!< clipping window
71   bool have_window;
72 
73   vgl_polygon<T> poly_; //!< the polygon
74 
75  public:
76   // Stores coordinates of a 2d point
77   typedef typename vgl_polygon<T>::point_t Point2;
78 
79   // Constructors/Destructor---------------------------------------------------
80 
81   //: Construct with a polygon and bool indicating whether boundary included
82   vgl_polygon_scan_iterator(vgl_polygon<T> const& face, bool boundaryp = true);
83 
84   //: Construct with a polygon, bool indicating whether boundary included and window (area visible)
85   vgl_polygon_scan_iterator(vgl_polygon<T> const& face, bool boundaryp,
86                             vgl_box_2d<T> const& window);
87 
88   //: Destructor
89   ~vgl_polygon_scan_iterator() override;
90 
91   //Functions----------------------------------------------------------
92 
93   //: Resets iterator to first segment of first scan line
94   void reset() override;
95 
96   //: Moves iterator to next segment
97   bool next() override;
98 
99   //: Returns current scan line
scany()100   inline int scany() const override { return y-1; }
101 
102   //: Returns start of current span
startx()103   inline int startx() const override { return xl; }
104 
105   //: Returns end of current span
endx()106   inline int endx() const override { return xr; }
107 
108   //: Returns start of current span (floating point value)
fstartx()109   inline T fstartx() const { return fxl; }
110 
111   //: Returns end of current span (floating point value)
fendx()112   inline T fendx() const { return fxr; }
113 
114   //: Returns current scan line (floating point value)
fscany()115   inline T fscany() const { return fy; }
116 
117   // returns the vertices related to
118   void get_crossedge_vertices(int * &chainnum, int * &vertnum, int & numcrossedges);
119   //: Vertex index - uniquely identifies a vertex in the array chains
120   struct vertind {
121     int chainnum; //!< which chain the vertex is part of
122     int vertnum;  //!< which vertex in the chain
123   };
124 
125   //: Describes an edge crossing the current scan line
126   struct crossedge {
127     T x;       //!< x coord of edge's intersection with current scanline
128     T dx;      //!< change in x with respect to y
129     vertind v; //!< edge goes from vertex v.vertnum to v.vertnum + 1
130   };
131 
132 // Internals ---------------------------------------------------------------
133 
134  private:
135   // avoid copy constructor a operator=
136   vgl_polygon_scan_iterator(const vgl_polygon_scan_iterator& ) = delete;
137   vgl_polygon_scan_iterator& operator= (const vgl_polygon_scan_iterator& ) = delete;
138 
139   vertind * yverts;       //!< array of all vertices ordered by y coordinate
140   crossedge * crossedges; //!< array of edges crossing current scan line
141   int numcrossedges;      //!< number of edges currently crossing scan line
142   int numverts;           //!< total number of vertices comprising face
143 
144   // Returns x coord of vertex v
get_x(vertind v)145   inline T get_x(vertind v) const { return poly_[v.chainnum][v.vertnum].x(); }
146 
147   // Returns y coord of vertex v
get_y(vertind v)148   inline T get_y(vertind v) const { return poly_[v.chainnum][v.vertnum].y(); }
149 
150   // Returns vertex v
get_pt(vertind v)151   inline Point2 get_pt( vertind v ) const { return poly_[v.chainnum][v.vertnum]; }
152 
153   // assumes poly_, win, have_window, boundp are set
154   void init();
155 
156   // Deletes edge (v,get_next_vert(v)) from crossedges array
157   void delete_edge( vertind v );
158 
159   // Inserts edge (v,get_next_vert(v)) into crossedges array
160   void insert_edge( vertind v );
161 
162   // Returns next vertex on chain
163   void get_next_vert( vertind v, vertind & next );
164 
165   // Returns prev vertex on chain
166   void get_prev_vert( vertind v, vertind & prev );
167 
168   // For debugging purposes
169   void display_chains();
170   void display_crossedges();
171 };
172 
173 #define VGL_POLYGON_SCAN_ITERATOR_INSTANTIATE(T) extern "please include <vgl/vgl_polygon_scan_iterator.hxx> instead"
174 
175 #endif // vgl_polygon_scan_iterator_h
176