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 #ifndef AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED 16 #define AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED 17 18 #include "agg_trans_perspective.h" 19 #include "agg_dda_line.h" 20 21 namespace agg 22 { 23 24 25 26 //===========================================span_interpolator_persp_exact 27 template<unsigned SubpixelShift = 8> 28 class span_interpolator_persp_exact 29 { 30 public: 31 typedef trans_perspective trans_type; 32 typedef trans_perspective::iterator_x iterator_type; 33 enum subpixel_scale_e 34 { 35 subpixel_shift = SubpixelShift, 36 subpixel_scale = 1 << subpixel_shift 37 }; 38 39 //-------------------------------------------------------------------- span_interpolator_persp_exact()40 span_interpolator_persp_exact() {} 41 42 //-------------------------------------------------------------------- 43 // Arbitrary quadrangle transformations span_interpolator_persp_exact(const double * src,const double * dst)44 span_interpolator_persp_exact(const double* src, const double* dst) 45 { 46 quad_to_quad(src, dst); 47 } 48 49 //-------------------------------------------------------------------- 50 // Direct transformations span_interpolator_persp_exact(double x1,double y1,double x2,double y2,const double * quad)51 span_interpolator_persp_exact(double x1, double y1, 52 double x2, double y2, 53 const double* quad) 54 { 55 rect_to_quad(x1, y1, x2, y2, quad); 56 } 57 58 //-------------------------------------------------------------------- 59 // Reverse transformations span_interpolator_persp_exact(const double * quad,double x1,double y1,double x2,double y2)60 span_interpolator_persp_exact(const double* quad, 61 double x1, double y1, 62 double x2, double y2) 63 { 64 quad_to_rect(quad, x1, y1, x2, y2); 65 } 66 67 //-------------------------------------------------------------------- 68 // Set the transformations using two arbitrary quadrangles. quad_to_quad(const double * src,const double * dst)69 void quad_to_quad(const double* src, const double* dst) 70 { 71 m_trans_dir.quad_to_quad(src, dst); 72 m_trans_inv.quad_to_quad(dst, src); 73 } 74 75 //-------------------------------------------------------------------- 76 // Set the direct transformations, i.e., rectangle -> quadrangle rect_to_quad(double x1,double y1,double x2,double y2,const double * quad)77 void rect_to_quad(double x1, double y1, double x2, double y2, 78 const double* quad) 79 { 80 double src[8]; 81 src[0] = src[6] = x1; 82 src[2] = src[4] = x2; 83 src[1] = src[3] = y1; 84 src[5] = src[7] = y2; 85 quad_to_quad(src, quad); 86 } 87 88 89 //-------------------------------------------------------------------- 90 // Set the reverse transformations, i.e., quadrangle -> rectangle quad_to_rect(const double * quad,double x1,double y1,double x2,double y2)91 void quad_to_rect(const double* quad, 92 double x1, double y1, double x2, double y2) 93 { 94 double dst[8]; 95 dst[0] = dst[6] = x1; 96 dst[2] = dst[4] = x2; 97 dst[1] = dst[3] = y1; 98 dst[5] = dst[7] = y2; 99 quad_to_quad(quad, dst); 100 } 101 102 //-------------------------------------------------------------------- 103 // Check if the equations were solved successfully is_valid()104 bool is_valid() const { return m_trans_dir.is_valid(); } 105 106 //---------------------------------------------------------------- begin(double x,double y,unsigned len)107 void begin(double x, double y, unsigned len) 108 { 109 m_iterator = m_trans_dir.begin(x, y, 1.0); 110 double xt = m_iterator.x; 111 double yt = m_iterator.y; 112 113 double dx; 114 double dy; 115 const double delta = 1/double(subpixel_scale); 116 dx = xt + delta; 117 dy = yt; 118 m_trans_inv.transform(&dx, &dy); 119 dx -= x; 120 dy -= y; 121 int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; 122 dx = xt; 123 dy = yt + delta; 124 m_trans_inv.transform(&dx, &dy); 125 dx -= x; 126 dy -= y; 127 int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; 128 129 x += len; 130 xt = x; 131 yt = y; 132 m_trans_dir.transform(&xt, &yt); 133 134 dx = xt + delta; 135 dy = yt; 136 m_trans_inv.transform(&dx, &dy); 137 dx -= x; 138 dy -= y; 139 int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; 140 dx = xt; 141 dy = yt + delta; 142 m_trans_inv.transform(&dx, &dy); 143 dx -= x; 144 dy -= y; 145 int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; 146 147 m_scale_x = dda2_line_interpolator(sx1, sx2, len); 148 m_scale_y = dda2_line_interpolator(sy1, sy2, len); 149 } 150 151 152 //---------------------------------------------------------------- resynchronize(double xe,double ye,unsigned len)153 void resynchronize(double xe, double ye, unsigned len) 154 { 155 // Assume x1,y1 are equal to the ones at the previous end point 156 int sx1 = m_scale_x.y(); 157 int sy1 = m_scale_y.y(); 158 159 // Calculate transformed coordinates at x2,y2 160 double xt = xe; 161 double yt = ye; 162 m_trans_dir.transform(&xt, &yt); 163 164 const double delta = 1/double(subpixel_scale); 165 double dx; 166 double dy; 167 168 // Calculate scale by X at x2,y2 169 dx = xt + delta; 170 dy = yt; 171 m_trans_inv.transform(&dx, &dy); 172 dx -= xe; 173 dy -= ye; 174 int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; 175 176 // Calculate scale by Y at x2,y2 177 dx = xt; 178 dy = yt + delta; 179 m_trans_inv.transform(&dx, &dy); 180 dx -= xe; 181 dy -= ye; 182 int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; 183 184 // Initialize the interpolators 185 m_scale_x = dda2_line_interpolator(sx1, sx2, len); 186 m_scale_y = dda2_line_interpolator(sy1, sy2, len); 187 } 188 189 190 191 //---------------------------------------------------------------- 192 void operator++() 193 { 194 ++m_iterator; 195 ++m_scale_x; 196 ++m_scale_y; 197 } 198 199 //---------------------------------------------------------------- coordinates(int * x,int * y)200 void coordinates(int* x, int* y) const 201 { 202 *x = iround(m_iterator.x * subpixel_scale); 203 *y = iround(m_iterator.y * subpixel_scale); 204 } 205 206 //---------------------------------------------------------------- local_scale(int * x,int * y)207 void local_scale(int* x, int* y) 208 { 209 *x = m_scale_x.y(); 210 *y = m_scale_y.y(); 211 } 212 213 //---------------------------------------------------------------- transform(double * x,double * y)214 void transform(double* x, double* y) const 215 { 216 m_trans_dir.transform(x, y); 217 } 218 219 private: 220 trans_type m_trans_dir; 221 trans_type m_trans_inv; 222 iterator_type m_iterator; 223 dda2_line_interpolator m_scale_x; 224 dda2_line_interpolator m_scale_y; 225 }; 226 227 228 229 230 231 232 233 234 235 236 237 //============================================span_interpolator_persp_lerp 238 template<unsigned SubpixelShift = 8> 239 class span_interpolator_persp_lerp 240 { 241 public: 242 typedef trans_perspective trans_type; 243 enum subpixel_scale_e 244 { 245 subpixel_shift = SubpixelShift, 246 subpixel_scale = 1 << subpixel_shift 247 }; 248 249 //-------------------------------------------------------------------- span_interpolator_persp_lerp()250 span_interpolator_persp_lerp() {} 251 252 //-------------------------------------------------------------------- 253 // Arbitrary quadrangle transformations span_interpolator_persp_lerp(const double * src,const double * dst)254 span_interpolator_persp_lerp(const double* src, const double* dst) 255 { 256 quad_to_quad(src, dst); 257 } 258 259 //-------------------------------------------------------------------- 260 // Direct transformations span_interpolator_persp_lerp(double x1,double y1,double x2,double y2,const double * quad)261 span_interpolator_persp_lerp(double x1, double y1, 262 double x2, double y2, 263 const double* quad) 264 { 265 rect_to_quad(x1, y1, x2, y2, quad); 266 } 267 268 //-------------------------------------------------------------------- 269 // Reverse transformations span_interpolator_persp_lerp(const double * quad,double x1,double y1,double x2,double y2)270 span_interpolator_persp_lerp(const double* quad, 271 double x1, double y1, 272 double x2, double y2) 273 { 274 quad_to_rect(quad, x1, y1, x2, y2); 275 } 276 277 //-------------------------------------------------------------------- 278 // Set the transformations using two arbitrary quadrangles. quad_to_quad(const double * src,const double * dst)279 void quad_to_quad(const double* src, const double* dst) 280 { 281 m_trans_dir.quad_to_quad(src, dst); 282 m_trans_inv.quad_to_quad(dst, src); 283 } 284 285 //-------------------------------------------------------------------- 286 // Set the direct transformations, i.e., rectangle -> quadrangle rect_to_quad(double x1,double y1,double x2,double y2,const double * quad)287 void rect_to_quad(double x1, double y1, double x2, double y2, 288 const double* quad) 289 { 290 double src[8]; 291 src[0] = src[6] = x1; 292 src[2] = src[4] = x2; 293 src[1] = src[3] = y1; 294 src[5] = src[7] = y2; 295 quad_to_quad(src, quad); 296 } 297 298 299 //-------------------------------------------------------------------- 300 // Set the reverse transformations, i.e., quadrangle -> rectangle quad_to_rect(const double * quad,double x1,double y1,double x2,double y2)301 void quad_to_rect(const double* quad, 302 double x1, double y1, double x2, double y2) 303 { 304 double dst[8]; 305 dst[0] = dst[6] = x1; 306 dst[2] = dst[4] = x2; 307 dst[1] = dst[3] = y1; 308 dst[5] = dst[7] = y2; 309 quad_to_quad(quad, dst); 310 } 311 312 //-------------------------------------------------------------------- 313 // Check if the equations were solved successfully is_valid()314 bool is_valid() const { return m_trans_dir.is_valid(); } 315 316 //---------------------------------------------------------------- begin(double x,double y,unsigned len)317 void begin(double x, double y, unsigned len) 318 { 319 // Calculate transformed coordinates at x1,y1 320 double xt = x; 321 double yt = y; 322 m_trans_dir.transform(&xt, &yt); 323 int x1 = iround(xt * subpixel_scale); 324 int y1 = iround(yt * subpixel_scale); 325 326 double dx; 327 double dy; 328 const double delta = 1/double(subpixel_scale); 329 330 // Calculate scale by X at x1,y1 331 dx = xt + delta; 332 dy = yt; 333 m_trans_inv.transform(&dx, &dy); 334 dx -= x; 335 dy -= y; 336 int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; 337 338 // Calculate scale by Y at x1,y1 339 dx = xt; 340 dy = yt + delta; 341 m_trans_inv.transform(&dx, &dy); 342 dx -= x; 343 dy -= y; 344 int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; 345 346 // Calculate transformed coordinates at x2,y2 347 x += len; 348 xt = x; 349 yt = y; 350 m_trans_dir.transform(&xt, &yt); 351 int x2 = iround(xt * subpixel_scale); 352 int y2 = iround(yt * subpixel_scale); 353 354 // Calculate scale by X at x2,y2 355 dx = xt + delta; 356 dy = yt; 357 m_trans_inv.transform(&dx, &dy); 358 dx -= x; 359 dy -= y; 360 int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; 361 362 // Calculate scale by Y at x2,y2 363 dx = xt; 364 dy = yt + delta; 365 m_trans_inv.transform(&dx, &dy); 366 dx -= x; 367 dy -= y; 368 int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; 369 370 // Initialize the interpolators 371 m_coord_x = dda2_line_interpolator(x1, x2, len); 372 m_coord_y = dda2_line_interpolator(y1, y2, len); 373 m_scale_x = dda2_line_interpolator(sx1, sx2, len); 374 m_scale_y = dda2_line_interpolator(sy1, sy2, len); 375 } 376 377 378 //---------------------------------------------------------------- resynchronize(double xe,double ye,unsigned len)379 void resynchronize(double xe, double ye, unsigned len) 380 { 381 // Assume x1,y1 are equal to the ones at the previous end point 382 int x1 = m_coord_x.y(); 383 int y1 = m_coord_y.y(); 384 int sx1 = m_scale_x.y(); 385 int sy1 = m_scale_y.y(); 386 387 // Calculate transformed coordinates at x2,y2 388 double xt = xe; 389 double yt = ye; 390 m_trans_dir.transform(&xt, &yt); 391 int x2 = iround(xt * subpixel_scale); 392 int y2 = iround(yt * subpixel_scale); 393 394 const double delta = 1/double(subpixel_scale); 395 double dx; 396 double dy; 397 398 // Calculate scale by X at x2,y2 399 dx = xt + delta; 400 dy = yt; 401 m_trans_inv.transform(&dx, &dy); 402 dx -= xe; 403 dy -= ye; 404 int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; 405 406 // Calculate scale by Y at x2,y2 407 dx = xt; 408 dy = yt + delta; 409 m_trans_inv.transform(&dx, &dy); 410 dx -= xe; 411 dy -= ye; 412 int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; 413 414 // Initialize the interpolators 415 m_coord_x = dda2_line_interpolator(x1, x2, len); 416 m_coord_y = dda2_line_interpolator(y1, y2, len); 417 m_scale_x = dda2_line_interpolator(sx1, sx2, len); 418 m_scale_y = dda2_line_interpolator(sy1, sy2, len); 419 } 420 421 422 //---------------------------------------------------------------- 423 void operator++() 424 { 425 ++m_coord_x; 426 ++m_coord_y; 427 ++m_scale_x; 428 ++m_scale_y; 429 } 430 431 //---------------------------------------------------------------- coordinates(int * x,int * y)432 void coordinates(int* x, int* y) const 433 { 434 *x = m_coord_x.y(); 435 *y = m_coord_y.y(); 436 } 437 438 //---------------------------------------------------------------- local_scale(int * x,int * y)439 void local_scale(int* x, int* y) 440 { 441 *x = m_scale_x.y(); 442 *y = m_scale_y.y(); 443 } 444 445 //---------------------------------------------------------------- transform(double * x,double * y)446 void transform(double* x, double* y) const 447 { 448 m_trans_dir.transform(x, y); 449 } 450 451 private: 452 trans_type m_trans_dir; 453 trans_type m_trans_inv; 454 dda2_line_interpolator m_coord_x; 455 dda2_line_interpolator m_coord_y; 456 dda2_line_interpolator m_scale_x; 457 dda2_line_interpolator m_scale_y; 458 }; 459 460 } 461 462 #endif 463