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 #include "agg_math.h" 17 #include "agg_trans_double_path.h" 18 19 namespace agg 20 { 21 22 //------------------------------------------------------------------------ trans_double_path()23 trans_double_path::trans_double_path() : 24 m_base_length(0.0), 25 m_base_height(1.0), 26 m_kindex1(0.0), 27 m_kindex2(0.0), 28 m_status1(initial), 29 m_status2(initial), 30 m_preserve_x_scale(true) 31 { 32 } 33 34 35 //------------------------------------------------------------------------ reset()36 void trans_double_path::reset() 37 { 38 m_src_vertices1.remove_all(); 39 m_src_vertices2.remove_all(); 40 m_kindex1 = 0.0; 41 m_kindex2 = 0.0; 42 m_status1 = initial; 43 m_status2 = initial; 44 } 45 46 47 //------------------------------------------------------------------------ move_to1(double x,double y)48 void trans_double_path::move_to1(double x, double y) 49 { 50 if(m_status1 == initial) 51 { 52 m_src_vertices1.modify_last(vertex_dist(x, y)); 53 m_status1 = making_path; 54 } 55 else 56 { 57 line_to1(x, y); 58 } 59 } 60 61 62 //------------------------------------------------------------------------ line_to1(double x,double y)63 void trans_double_path::line_to1(double x, double y) 64 { 65 if(m_status1 == making_path) 66 { 67 m_src_vertices1.add(vertex_dist(x, y)); 68 } 69 } 70 71 72 //------------------------------------------------------------------------ move_to2(double x,double y)73 void trans_double_path::move_to2(double x, double y) 74 { 75 if(m_status2 == initial) 76 { 77 m_src_vertices2.modify_last(vertex_dist(x, y)); 78 m_status2 = making_path; 79 } 80 else 81 { 82 line_to2(x, y); 83 } 84 } 85 86 87 //------------------------------------------------------------------------ line_to2(double x,double y)88 void trans_double_path::line_to2(double x, double y) 89 { 90 if(m_status2 == making_path) 91 { 92 m_src_vertices2.add(vertex_dist(x, y)); 93 } 94 } 95 96 97 //------------------------------------------------------------------------ finalize_path(vertex_storage & vertices)98 double trans_double_path::finalize_path(vertex_storage& vertices) 99 { 100 unsigned i; 101 double dist; 102 double d; 103 104 vertices.close(false); 105 if(vertices.size() > 2) 106 { 107 if(vertices[vertices.size() - 2].dist * 10.0 < 108 vertices[vertices.size() - 3].dist) 109 { 110 d = vertices[vertices.size() - 3].dist + 111 vertices[vertices.size() - 2].dist; 112 113 vertices[vertices.size() - 2] = 114 vertices[vertices.size() - 1]; 115 116 vertices.remove_last(); 117 vertices[vertices.size() - 2].dist = d; 118 } 119 } 120 121 dist = 0; 122 for(i = 0; i < vertices.size(); i++) 123 { 124 vertex_dist& v = vertices[i]; 125 d = v.dist; 126 v.dist = dist; 127 dist += d; 128 } 129 130 return (vertices.size() - 1) / dist; 131 } 132 133 134 //------------------------------------------------------------------------ finalize_paths()135 void trans_double_path::finalize_paths() 136 { 137 if(m_status1 == making_path && m_src_vertices1.size() > 1 && 138 m_status2 == making_path && m_src_vertices2.size() > 1) 139 { 140 m_kindex1 = finalize_path(m_src_vertices1); 141 m_kindex2 = finalize_path(m_src_vertices2); 142 m_status1 = ready; 143 m_status2 = ready; 144 } 145 } 146 147 148 //------------------------------------------------------------------------ total_length1() const149 double trans_double_path::total_length1() const 150 { 151 if(m_base_length >= 1e-10) return m_base_length; 152 return (m_status1 == ready) ? 153 m_src_vertices1[m_src_vertices1.size() - 1].dist : 154 0.0; 155 } 156 157 158 //------------------------------------------------------------------------ total_length2() const159 double trans_double_path::total_length2() const 160 { 161 if(m_base_length >= 1e-10) return m_base_length; 162 return (m_status2 == ready) ? 163 m_src_vertices2[m_src_vertices2.size() - 1].dist : 164 0.0; 165 } 166 167 168 //------------------------------------------------------------------------ transform1(const vertex_storage & vertices,double kindex,double kx,double * x,double * y) const169 void trans_double_path::transform1(const vertex_storage& vertices, 170 double kindex, double kx, 171 double *x, double* y) const 172 { 173 double x1 = 0.0; 174 double y1 = 0.0; 175 double dx = 1.0; 176 double dy = 1.0; 177 double d = 0.0; 178 double dd = 1.0; 179 *x *= kx; 180 if(*x < 0.0) 181 { 182 // Extrapolation on the left 183 //-------------------------- 184 x1 = vertices[0].x; 185 y1 = vertices[0].y; 186 dx = vertices[1].x - x1; 187 dy = vertices[1].y - y1; 188 dd = vertices[1].dist - vertices[0].dist; 189 d = *x; 190 } 191 else 192 if(*x > vertices[vertices.size() - 1].dist) 193 { 194 // Extrapolation on the right 195 //-------------------------- 196 unsigned i = vertices.size() - 2; 197 unsigned j = vertices.size() - 1; 198 x1 = vertices[j].x; 199 y1 = vertices[j].y; 200 dx = x1 - vertices[i].x; 201 dy = y1 - vertices[i].y; 202 dd = vertices[j].dist - vertices[i].dist; 203 d = *x - vertices[j].dist; 204 } 205 else 206 { 207 // Interpolation 208 //-------------------------- 209 unsigned i = 0; 210 unsigned j = vertices.size() - 1; 211 if(m_preserve_x_scale) 212 { 213 unsigned k; 214 for(i = 0; (j - i) > 1; ) 215 { 216 if(*x < vertices[k = (i + j) >> 1].dist) 217 { 218 j = k; 219 } 220 else 221 { 222 i = k; 223 } 224 } 225 d = vertices[i].dist; 226 dd = vertices[j].dist - d; 227 d = *x - d; 228 } 229 else 230 { 231 i = unsigned(*x * kindex); 232 j = i + 1; 233 dd = vertices[j].dist - vertices[i].dist; 234 d = ((*x * kindex) - i) * dd; 235 } 236 x1 = vertices[i].x; 237 y1 = vertices[i].y; 238 dx = vertices[j].x - x1; 239 dy = vertices[j].y - y1; 240 } 241 *x = x1 + dx * d / dd; 242 *y = y1 + dy * d / dd; 243 } 244 245 246 //------------------------------------------------------------------------ transform(double * x,double * y) const247 void trans_double_path::transform(double *x, double *y) const 248 { 249 if(m_status1 == ready && m_status2 == ready) 250 { 251 if(m_base_length > 1e-10) 252 { 253 *x *= m_src_vertices1[m_src_vertices1.size() - 1].dist / 254 m_base_length; 255 } 256 257 double x1 = *x; 258 double y1 = *y; 259 double x2 = *x; 260 double y2 = *y; 261 double dd = m_src_vertices2[m_src_vertices2.size() - 1].dist / 262 m_src_vertices1[m_src_vertices1.size() - 1].dist; 263 264 transform1(m_src_vertices1, m_kindex1, 1.0, &x1, &y1); 265 transform1(m_src_vertices2, m_kindex2, dd, &x2, &y2); 266 267 *x = x1 + *y * (x2 - x1) / m_base_height; 268 *y = y1 + *y * (y2 - y1) / m_base_height; 269 } 270 } 271 272 } 273 274