192 lines
6.3 KiB
C++
192 lines
6.3 KiB
C++
//----------------------------------------------------------------------------
|
|
// Anti-Grain Geometry - Version 2.4
|
|
// 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
|