1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.4 3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) 4 // 5 // Permission to copy, use, modify, sell and distribute this software 6 // is granted provided this copyright notice appears in all copies. 7 // This software is provided "as is" without express or implied 8 // warranty, and with no claim as to its suitability for any purpose. 9 // 10 //---------------------------------------------------------------------------- 11 // Contact: mcseem@antigrain.com 12 // mcseemagg@yahoo.com 13 // http://www.antigrain.com 14 //---------------------------------------------------------------------------- 15 // 16 // Contour generator 17 // 18 //---------------------------------------------------------------------------- 19 20 #include <math.h> 21 #include "agg_vcgen_contour.h" 22 23 namespace agg 24 { 25 26 //------------------------------------------------------------------------ vcgen_contour()27 vcgen_contour::vcgen_contour() : 28 m_stroker(), 29 m_width(1), 30 m_src_vertices(), 31 m_out_vertices(), 32 m_status(initial), 33 m_src_vertex(0), 34 m_closed(0), 35 m_orientation(0), 36 m_auto_detect(false) 37 { 38 } 39 40 //------------------------------------------------------------------------ remove_all()41 void vcgen_contour::remove_all() 42 { 43 m_src_vertices.remove_all(); 44 m_closed = 0; 45 m_orientation = 0; 46 m_status = initial; 47 } 48 49 //------------------------------------------------------------------------ add_vertex(double x,double y,unsigned cmd)50 void vcgen_contour::add_vertex(double x, double y, unsigned cmd) 51 { 52 m_status = initial; 53 if(is_move_to(cmd)) 54 { 55 m_src_vertices.modify_last(vertex_dist(x, y)); 56 } 57 else 58 { 59 if(is_vertex(cmd)) 60 { 61 m_src_vertices.add(vertex_dist(x, y)); 62 } 63 else 64 { 65 if(is_end_poly(cmd)) 66 { 67 m_closed = get_close_flag(cmd); 68 if(m_orientation == path_flags_none) 69 { 70 m_orientation = get_orientation(cmd); 71 } 72 } 73 } 74 } 75 } 76 77 //------------------------------------------------------------------------ rewind(unsigned)78 void vcgen_contour::rewind(unsigned) 79 { 80 if(m_status == initial) 81 { 82 m_src_vertices.close(true); 83 if(m_auto_detect) 84 { 85 if(!is_oriented(m_orientation)) 86 { 87 m_orientation = (calc_polygon_area(m_src_vertices) > 0.0) ? 88 path_flags_ccw : 89 path_flags_cw; 90 } 91 } 92 if(is_oriented(m_orientation)) 93 { 94 m_stroker.width(is_ccw(m_orientation) ? m_width : -m_width); 95 } 96 } 97 m_status = ready; 98 m_src_vertex = 0; 99 } 100 101 //------------------------------------------------------------------------ vertex(double * x,double * y)102 unsigned vcgen_contour::vertex(double* x, double* y) 103 { 104 unsigned cmd = path_cmd_line_to; 105 while(!is_stop(cmd)) 106 { 107 switch(m_status) 108 { 109 case initial: 110 rewind(0); 111 112 case ready: 113 if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) 114 { 115 cmd = path_cmd_stop; 116 break; 117 } 118 m_status = outline; 119 cmd = path_cmd_move_to; 120 m_src_vertex = 0; 121 m_out_vertex = 0; 122 123 case outline: 124 if(m_src_vertex >= m_src_vertices.size()) 125 { 126 m_status = end_poly; 127 break; 128 } 129 m_stroker.calc_join(m_out_vertices, 130 m_src_vertices.prev(m_src_vertex), 131 m_src_vertices.curr(m_src_vertex), 132 m_src_vertices.next(m_src_vertex), 133 m_src_vertices.prev(m_src_vertex).dist, 134 m_src_vertices.curr(m_src_vertex).dist); 135 ++m_src_vertex; 136 m_status = out_vertices; 137 m_out_vertex = 0; 138 139 case out_vertices: 140 if(m_out_vertex >= m_out_vertices.size()) 141 { 142 m_status = outline; 143 } 144 else 145 { 146 const point_d& c = m_out_vertices[m_out_vertex++]; 147 *x = c.x; 148 *y = c.y; 149 return cmd; 150 } 151 break; 152 153 case end_poly: 154 if(!m_closed) return path_cmd_stop; 155 m_status = stop; 156 return path_cmd_end_poly | path_flags_close | path_flags_ccw; 157 158 case stop: 159 return path_cmd_stop; 160 } 161 } 162 return cmd; 163 } 164 165 } 166