diff options
Diffstat (limited to 'agg/inc/agg_trans_perspective.h')
-rwxr-xr-x | agg/inc/agg_trans_perspective.h | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/agg/inc/agg_trans_perspective.h b/agg/inc/agg_trans_perspective.h new file mode 100755 index 000000000000..a127c9095ad2 --- /dev/null +++ b/agg/inc/agg_trans_perspective.h @@ -0,0 +1,192 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Perspective 2D transformations +// +//---------------------------------------------------------------------------- +#ifndef AGG_TRANS_PERSPECTIVE_INCLUDED +#define AGG_TRANS_PERSPECTIVE_INCLUDED + +#include "agg_basics.h" +#include "agg_simul_eq.h" + +namespace agg +{ + //=======================================================trans_perspective + class trans_perspective + { + public: + //-------------------------------------------------------------------- + trans_perspective() : m_valid(false) {} + + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + trans_perspective(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + + //-------------------------------------------------------------------- + // Direct transformations + trans_perspective(double x1, double y1, double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + + //-------------------------------------------------------------------- + // Reverse transformations + trans_perspective(const double* quad, + double x1, double y1, double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + + double left[8][8]; + double right[8][1]; + + unsigned i; + for (i = 0; i < 4; i++) + { + unsigned ix = i * 2; + unsigned iy = ix + 1; + + left[ix][0] = 1.0; + left[ix][1] = src[ix]; + left[ix][2] = src[iy]; + left[ix][3] = 0.0; + left[ix][4] = 0.0; + left[ix][5] = 0.0; + left[ix][6] = -src[ix] * dst[ix]; + left[ix][7] = -src[iy] * dst[ix]; + right[ix][0] = dst[ix]; + + left[iy][0] = 0.0; + left[iy][1] = 0.0; + left[iy][2] = 0.0; + left[iy][3] = 1.0; + left[iy][4] = src[ix]; + left[iy][5] = src[iy]; + left[iy][6] = -src[ix] * dst[iy]; + left[iy][7] = -src[iy] * dst[iy]; + right[iy][0] = dst[iy]; + } + m_valid = simul_eq<8, 1>::solve(left, right, m_mtx); + } + + + //-------------------------------------------------------------------- + // Set the direct transformations, i.e., rectangle -> quadrangle + void rect_to_quad(double x1, double y1, double x2, double y2, + const double* quad) + { + double src[8]; + src[0] = src[6] = x1; + src[2] = src[4] = x2; + src[1] = src[3] = y1; + src[5] = src[7] = y2; + quad_to_quad(src, quad); + } + + + //-------------------------------------------------------------------- + // Set the reverse transformations, i.e., quadrangle -> rectangle + void quad_to_rect(const double* quad, + double x1, double y1, double x2, double y2) + { + double dst[8]; + dst[0] = dst[6] = x1; + dst[2] = dst[4] = x2; + dst[1] = dst[3] = y1; + dst[5] = dst[7] = y2; + quad_to_quad(quad, dst); + } + + //-------------------------------------------------------------------- + // Check if the equations were solved successfully + bool is_valid() const { return m_valid; } + + //-------------------------------------------------------------------- + // Transform a point (x, y) + void transform(double* x, double* y) const + { + double tx = *x; + double ty = *y; + double d = 1.0 / (m_mtx[6][0] * tx + m_mtx[7][0] * ty + 1.0); + *x = (m_mtx[0][0] + m_mtx[1][0] * tx + m_mtx[2][0] * ty) * d; + *y = (m_mtx[3][0] + m_mtx[4][0] * tx + m_mtx[5][0] * ty) * d; + } + + //-------------------------------------------------------------------- + class iterator_x + { + double den; + double den_step; + double nom_x; + double nom_x_step; + double nom_y; + double nom_y_step; + + public: + double x; + double y; + + iterator_x() {} + iterator_x(double tx, double ty, double step, const double m[8][1]) : + den(m[6][0] * tx + m[7][0] * ty + 1.0), + den_step(m[6][0] * step), + nom_x(m[0][0] + m[1][0] * tx + m[2][0] * ty), + nom_x_step(m[1][0] * step), + nom_y(m[3][0] + m[4][0] * tx + m[5][0] * ty), + nom_y_step(m[4][0] * step), + x(nom_x / den), + y(nom_y / den) + { + } + + void operator ++ () + { + den += den_step; + nom_x += nom_x_step; + nom_y += nom_y_step; + double d = 1.0 / den; + x = nom_x * d; + y = nom_y * d; + } + }; + + //-------------------------------------------------------------------- + iterator_x begin(double x, double y, double step) const + { + return iterator_x(x, y, step, m_mtx); + } + + private: + double m_mtx[8][1]; + bool m_valid; + }; + +} + +#endif |