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 // Bilinear 2D transformations 17 // 18 //---------------------------------------------------------------------------- 19 #ifndef AGG_TRANS_BILINEAR_INCLUDED 20 #define AGG_TRANS_BILINEAR_INCLUDED 21 22 #include "agg_basics.h" 23 #include "agg_simul_eq.h" 24 25 namespace agg 26 { 27 28 //==========================================================trans_bilinear 29 class trans_bilinear 30 { 31 public: 32 //-------------------------------------------------------------------- trans_bilinear()33 trans_bilinear() : m_valid(false) {} 34 35 //-------------------------------------------------------------------- 36 // Arbitrary quadrangle transformations trans_bilinear(const double * src,const double * dst)37 trans_bilinear(const double* src, const double* dst) 38 { 39 quad_to_quad(src, dst); 40 } 41 42 43 //-------------------------------------------------------------------- 44 // Direct transformations trans_bilinear(double x1,double y1,double x2,double y2,const double * quad)45 trans_bilinear(double x1, double y1, double x2, double y2, 46 const double* quad) 47 { 48 rect_to_quad(x1, y1, x2, y2, quad); 49 } 50 51 52 //-------------------------------------------------------------------- 53 // Reverse transformations trans_bilinear(const double * quad,double x1,double y1,double x2,double y2)54 trans_bilinear(const double* quad, 55 double x1, double y1, double x2, double y2) 56 { 57 quad_to_rect(quad, x1, y1, x2, y2); 58 } 59 60 61 //-------------------------------------------------------------------- 62 // Set the transformations using two arbitrary quadrangles. quad_to_quad(const double * src,const double * dst)63 void quad_to_quad(const double* src, const double* dst) 64 { 65 double left[4][4]; 66 double right[4][2]; 67 68 unsigned i; 69 for(i = 0; i < 4; i++) 70 { 71 unsigned ix = i * 2; 72 unsigned iy = ix + 1; 73 left[i][0] = 1.0; 74 left[i][1] = src[ix] * src[iy]; 75 left[i][2] = src[ix]; 76 left[i][3] = src[iy]; 77 78 right[i][0] = dst[ix]; 79 right[i][1] = dst[iy]; 80 } 81 m_valid = simul_eq<4, 2>::solve(left, right, m_mtx); 82 } 83 84 85 //-------------------------------------------------------------------- 86 // Set the direct transformations, i.e., rectangle -> quadrangle rect_to_quad(double x1,double y1,double x2,double y2,const double * quad)87 void rect_to_quad(double x1, double y1, double x2, double y2, 88 const double* quad) 89 { 90 double src[8]; 91 src[0] = src[6] = x1; 92 src[2] = src[4] = x2; 93 src[1] = src[3] = y1; 94 src[5] = src[7] = y2; 95 quad_to_quad(src, quad); 96 } 97 98 99 //-------------------------------------------------------------------- 100 // Set the reverse transformations, i.e., quadrangle -> rectangle quad_to_rect(const double * quad,double x1,double y1,double x2,double y2)101 void quad_to_rect(const double* quad, 102 double x1, double y1, double x2, double y2) 103 { 104 double dst[8]; 105 dst[0] = dst[6] = x1; 106 dst[2] = dst[4] = x2; 107 dst[1] = dst[3] = y1; 108 dst[5] = dst[7] = y2; 109 quad_to_quad(quad, dst); 110 } 111 112 //-------------------------------------------------------------------- 113 // Check if the equations were solved successfully is_valid()114 bool is_valid() const { return m_valid; } 115 116 //-------------------------------------------------------------------- 117 // Transform a point (x, y) transform(double * x,double * y)118 void transform(double* x, double* y) const 119 { 120 double tx = *x; 121 double ty = *y; 122 double xy = tx * ty; 123 *x = m_mtx[0][0] + m_mtx[1][0] * xy + m_mtx[2][0] * tx + m_mtx[3][0] * ty; 124 *y = m_mtx[0][1] + m_mtx[1][1] * xy + m_mtx[2][1] * tx + m_mtx[3][1] * ty; 125 } 126 127 128 //-------------------------------------------------------------------- 129 class iterator_x 130 { 131 double inc_x; 132 double inc_y; 133 134 public: 135 double x; 136 double y; 137 iterator_x()138 iterator_x() {} iterator_x(double tx,double ty,double step,const double m[4][2])139 iterator_x(double tx, double ty, double step, const double m[4][2]) : 140 inc_x(m[1][0] * step * ty + m[2][0] * step), 141 inc_y(m[1][1] * step * ty + m[2][1] * step), 142 x(m[0][0] + m[1][0] * tx * ty + m[2][0] * tx + m[3][0] * ty), 143 y(m[0][1] + m[1][1] * tx * ty + m[2][1] * tx + m[3][1] * ty) 144 { 145 } 146 147 void operator ++ () 148 { 149 x += inc_x; 150 y += inc_y; 151 } 152 }; 153 begin(double x,double y,double step)154 iterator_x begin(double x, double y, double step) const 155 { 156 return iterator_x(x, y, step, m_mtx); 157 } 158 159 private: 160 double m_mtx[4][2]; 161 bool m_valid; 162 }; 163 164 } 165 166 #endif 167