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 // Perspective 2D transformations 17 // 18 //---------------------------------------------------------------------------- 19 #ifndef AGG_TRANS_PERSPECTIVE_INCLUDED 20 #define AGG_TRANS_PERSPECTIVE_INCLUDED 21 22 #include "agg_basics.h" 23 #include "agg_simul_eq.h" 24 25 namespace agg 26 { 27 //=======================================================trans_perspective 28 class trans_perspective 29 { 30 public: 31 //-------------------------------------------------------------------- 32 trans_perspective() : m_valid(false) {} 33 34 35 //-------------------------------------------------------------------- 36 // Arbitrary quadrangle transformations 37 trans_perspective(const double* src, const double* dst) 38 { 39 quad_to_quad(src, dst); 40 } 41 42 43 //-------------------------------------------------------------------- 44 // Direct transformations 45 trans_perspective(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 54 trans_perspective(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. 63 void quad_to_quad(const double* src, const double* dst) 64 { 65 66 double left[8][8]; 67 double right[8][1]; 68 69 unsigned i; 70 for (i = 0; i < 4; i++) 71 { 72 unsigned ix = i * 2; 73 unsigned iy = ix + 1; 74 75 left[ix][0] = 1.0; 76 left[ix][1] = src[ix]; 77 left[ix][2] = src[iy]; 78 left[ix][3] = 0.0; 79 left[ix][4] = 0.0; 80 left[ix][5] = 0.0; 81 left[ix][6] = -src[ix] * dst[ix]; 82 left[ix][7] = -src[iy] * dst[ix]; 83 right[ix][0] = dst[ix]; 84 85 left[iy][0] = 0.0; 86 left[iy][1] = 0.0; 87 left[iy][2] = 0.0; 88 left[iy][3] = 1.0; 89 left[iy][4] = src[ix]; 90 left[iy][5] = src[iy]; 91 left[iy][6] = -src[ix] * dst[iy]; 92 left[iy][7] = -src[iy] * dst[iy]; 93 right[iy][0] = dst[iy]; 94 } 95 m_valid = simul_eq<8, 1>::solve(left, right, m_mtx); 96 } 97 98 99 //-------------------------------------------------------------------- 100 // Set the direct transformations, i.e., rectangle -> quadrangle 101 void rect_to_quad(double x1, double y1, double x2, double y2, 102 const double* quad) 103 { 104 double src[8]; 105 src[0] = src[6] = x1; 106 src[2] = src[4] = x2; 107 src[1] = src[3] = y1; 108 src[5] = src[7] = y2; 109 quad_to_quad(src, quad); 110 } 111 112 113 //-------------------------------------------------------------------- 114 // Set the reverse transformations, i.e., quadrangle -> rectangle 115 void quad_to_rect(const double* quad, 116 double x1, double y1, double x2, double y2) 117 { 118 double dst[8]; 119 dst[0] = dst[6] = x1; 120 dst[2] = dst[4] = x2; 121 dst[1] = dst[3] = y1; 122 dst[5] = dst[7] = y2; 123 quad_to_quad(quad, dst); 124 } 125 126 //-------------------------------------------------------------------- 127 // Check if the equations were solved successfully 128 bool is_valid() const { return m_valid; } 129 130 //-------------------------------------------------------------------- 131 // Transform a point (x, y) 132 void transform(double* x, double* y) const 133 { 134 double tx = *x; 135 double ty = *y; 136 double d = 1.0 / (m_mtx[6][0] * tx + m_mtx[7][0] * ty + 1.0); 137 *x = (m_mtx[0][0] + m_mtx[1][0] * tx + m_mtx[2][0] * ty) * d; 138 *y = (m_mtx[3][0] + m_mtx[4][0] * tx + m_mtx[5][0] * ty) * d; 139 } 140 141 //-------------------------------------------------------------------- 142 class iterator_x 143 { 144 double den; 145 double den_step; 146 double nom_x; 147 double nom_x_step; 148 double nom_y; 149 double nom_y_step; 150 151 public: 152 double x; 153 double y; 154 155 iterator_x() {} 156 iterator_x(double tx, double ty, double step, const double m[8][1]) : 157 den(m[6][0] * tx + m[7][0] * ty + 1.0), 158 den_step(m[6][0] * step), 159 nom_x(m[0][0] + m[1][0] * tx + m[2][0] * ty), 160 nom_x_step(m[1][0] * step), 161 nom_y(m[3][0] + m[4][0] * tx + m[5][0] * ty), 162 nom_y_step(m[4][0] * step), 163 x(nom_x / den), 164 y(nom_y / den) 165 { 166 } 167 168 void operator ++ () 169 { 170 den += den_step; 171 nom_x += nom_x_step; 172 nom_y += nom_y_step; 173 double d = 1.0 / den; 174 x = nom_x * d; 175 y = nom_y * d; 176 } 177 }; 178 179 //-------------------------------------------------------------------- 180 iterator_x begin(double x, double y, double step) const 181 { 182 return iterator_x(x, y, step, m_mtx); 183 } 184 185 private: 186 double m_mtx[8][1]; 187 bool m_valid; 188 }; 189 190 } 191 192 #endif 193