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 // Smooth polygon generator 17 // 18 //---------------------------------------------------------------------------- 19 20 #include "agg_vcgen_smooth_poly1.h" 21 22 namespace agg 23 { 24 25 //------------------------------------------------------------------------ vcgen_smooth_poly1()26 vcgen_smooth_poly1::vcgen_smooth_poly1() : 27 m_src_vertices(), 28 m_smooth_value(0.5), 29 m_closed(0), 30 m_status(initial), 31 m_src_vertex(0) 32 { 33 } 34 35 36 //------------------------------------------------------------------------ remove_all()37 void vcgen_smooth_poly1::remove_all() 38 { 39 m_src_vertices.remove_all(); 40 m_closed = 0; 41 m_status = initial; 42 } 43 44 45 //------------------------------------------------------------------------ add_vertex(double x,double y,unsigned cmd)46 void vcgen_smooth_poly1::add_vertex(double x, double y, unsigned cmd) 47 { 48 m_status = initial; 49 if(is_move_to(cmd)) 50 { 51 m_src_vertices.modify_last(vertex_dist(x, y)); 52 } 53 else 54 { 55 if(is_vertex(cmd)) 56 { 57 m_src_vertices.add(vertex_dist(x, y)); 58 } 59 else 60 { 61 m_closed = get_close_flag(cmd); 62 } 63 } 64 } 65 66 67 //------------------------------------------------------------------------ rewind(unsigned)68 void vcgen_smooth_poly1::rewind(unsigned) 69 { 70 if(m_status == initial) 71 { 72 m_src_vertices.close(m_closed != 0); 73 } 74 m_status = ready; 75 m_src_vertex = 0; 76 } 77 78 79 //------------------------------------------------------------------------ calculate(const vertex_dist & v0,const vertex_dist & v1,const vertex_dist & v2,const vertex_dist & v3)80 void vcgen_smooth_poly1::calculate(const vertex_dist& v0, 81 const vertex_dist& v1, 82 const vertex_dist& v2, 83 const vertex_dist& v3) 84 { 85 86 double k1 = v0.dist / (v0.dist + v1.dist); 87 double k2 = v1.dist / (v1.dist + v2.dist); 88 89 double xm1 = v0.x + (v2.x - v0.x) * k1; 90 double ym1 = v0.y + (v2.y - v0.y) * k1; 91 double xm2 = v1.x + (v3.x - v1.x) * k2; 92 double ym2 = v1.y + (v3.y - v1.y) * k2; 93 94 m_ctrl1_x = v1.x + m_smooth_value * (v2.x - xm1); 95 m_ctrl1_y = v1.y + m_smooth_value * (v2.y - ym1); 96 m_ctrl2_x = v2.x + m_smooth_value * (v1.x - xm2); 97 m_ctrl2_y = v2.y + m_smooth_value * (v1.y - ym2); 98 } 99 100 101 //------------------------------------------------------------------------ vertex(double * x,double * y)102 unsigned vcgen_smooth_poly1::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) 114 { 115 cmd = path_cmd_stop; 116 break; 117 } 118 119 if(m_src_vertices.size() == 2) 120 { 121 *x = m_src_vertices[m_src_vertex].x; 122 *y = m_src_vertices[m_src_vertex].y; 123 m_src_vertex++; 124 if(m_src_vertex == 1) return path_cmd_move_to; 125 if(m_src_vertex == 2) return path_cmd_line_to; 126 cmd = path_cmd_stop; 127 break; 128 } 129 130 cmd = path_cmd_move_to; 131 m_status = polygon; 132 m_src_vertex = 0; 133 134 case polygon: 135 if(m_closed) 136 { 137 if(m_src_vertex >= m_src_vertices.size()) 138 { 139 *x = m_src_vertices[0].x; 140 *y = m_src_vertices[0].y; 141 m_status = end_poly; 142 return path_cmd_curve4; 143 } 144 } 145 else 146 { 147 if(m_src_vertex >= m_src_vertices.size() - 1) 148 { 149 *x = m_src_vertices[m_src_vertices.size() - 1].x; 150 *y = m_src_vertices[m_src_vertices.size() - 1].y; 151 m_status = end_poly; 152 return path_cmd_curve3; 153 } 154 } 155 156 calculate(m_src_vertices.prev(m_src_vertex), 157 m_src_vertices.curr(m_src_vertex), 158 m_src_vertices.next(m_src_vertex), 159 m_src_vertices.next(m_src_vertex + 1)); 160 161 *x = m_src_vertices[m_src_vertex].x; 162 *y = m_src_vertices[m_src_vertex].y; 163 m_src_vertex++; 164 165 if(m_closed) 166 { 167 m_status = ctrl1; 168 return ((m_src_vertex == 1) ? 169 path_cmd_move_to : 170 path_cmd_curve4); 171 } 172 else 173 { 174 if(m_src_vertex == 1) 175 { 176 m_status = ctrl_b; 177 return path_cmd_move_to; 178 } 179 if(m_src_vertex >= m_src_vertices.size() - 1) 180 { 181 m_status = ctrl_e; 182 return path_cmd_curve3; 183 } 184 m_status = ctrl1; 185 return path_cmd_curve4; 186 } 187 break; 188 189 case ctrl_b: 190 *x = m_ctrl2_x; 191 *y = m_ctrl2_y; 192 m_status = polygon; 193 return path_cmd_curve3; 194 195 case ctrl_e: 196 *x = m_ctrl1_x; 197 *y = m_ctrl1_y; 198 m_status = polygon; 199 return path_cmd_curve3; 200 201 case ctrl1: 202 *x = m_ctrl1_x; 203 *y = m_ctrl1_y; 204 m_status = ctrl2; 205 return path_cmd_curve4; 206 207 case ctrl2: 208 *x = m_ctrl2_x; 209 *y = m_ctrl2_y; 210 m_status = polygon; 211 return path_cmd_curve4; 212 213 case end_poly: 214 m_status = stop; 215 return path_cmd_end_poly | m_closed; 216 217 case stop: 218 return path_cmd_stop; 219 } 220 } 221 return cmd; 222 } 223 224 } 225 226