ultimatepp/uppdev/plugin/agg24/agg_trans_perspective.cpp
cxl 4a1c627474 Adding uppdev....
git-svn-id: svn://ultimatepp.org/upp/trunk@328 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2008-08-15 08:36:24 +00:00

449 lines
13 KiB
C++

#include "agg24.h" //aris002
namespace agg
{
//------------------------------------------------------------------------
inline bool trans_perspective::square_to_quad(const double* q)
{
double dx = q[0] - q[2] + q[4] - q[6];
double dy = q[1] - q[3] + q[5] - q[7];
if(dx == 0.0 && dy == 0.0)
{
// Affine case (parallelogram)
//---------------
sx = q[2] - q[0];
shy = q[3] - q[1];
w0 = 0.0;
shx = q[4] - q[2];
sy = q[5] - q[3];
w1 = 0.0;
tx = q[0];
ty = q[1];
w2 = 1.0;
}
else
{
double dx1 = q[2] - q[4];
double dy1 = q[3] - q[5];
double dx2 = q[6] - q[4];
double dy2 = q[7] - q[5];
double den = dx1 * dy2 - dx2 * dy1;
if(den == 0.0)
{
// Singular case
//---------------
sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
return false;
}
// General case
//---------------
double u = (dx * dy2 - dy * dx2) / den;
double v = (dy * dx1 - dx * dy1) / den;
sx = q[2] - q[0] + u * q[2];
shy = q[3] - q[1] + u * q[3];
w0 = u;
shx = q[6] - q[0] + v * q[6];
sy = q[7] - q[1] + v * q[7];
w1 = v;
tx = q[0];
ty = q[1];
w2 = 1.0;
}
return true;
}
//------------------------------------------------------------------------
inline bool trans_perspective::invert()
{
double d0 = sy * w2 - w1 * ty;
double d1 = w0 * ty - shy * w2;
double d2 = shy * w1 - w0 * sy;
double d = sx * d0 + shx * d1 + tx * d2;
if(d == 0.0)
{
sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0;
return false;
}
d = 1.0 / d;
trans_perspective a = *this;
sx = d * d0;
shy = d * d1;
w0 = d * d2;
shx = d * (a.w1 *a.tx - a.shx*a.w2);
sy = d * (a.sx *a.w2 - a.w0 *a.tx);
w1 = d * (a.w0 *a.shx - a.sx *a.w1);
tx = d * (a.shx*a.ty - a.sy *a.tx);
ty = d * (a.shy*a.tx - a.sx *a.ty);
w2 = d * (a.sx *a.sy - a.shy*a.shx);
return true;
}
//------------------------------------------------------------------------
inline bool trans_perspective::quad_to_square(const double* q)
{
if(!square_to_quad(q)) return false;
invert();
return true;
}
//------------------------------------------------------------------------
inline bool trans_perspective::quad_to_quad(const double* qs,
const double* qd)
{
trans_perspective p;
if(! quad_to_square(qs)) return false;
if(!p.square_to_quad(qd)) return false;
multiply(p);
return true;
}
//------------------------------------------------------------------------
inline bool trans_perspective::rect_to_quad(double x1, double y1,
double x2, double y2,
const double* q)
{
double r[8];
r[0] = r[6] = x1;
r[2] = r[4] = x2;
r[1] = r[3] = y1;
r[5] = r[7] = y2;
return quad_to_quad(r, q);
}
//------------------------------------------------------------------------
inline bool trans_perspective::quad_to_rect(const double* q,
double x1, double y1,
double x2, double y2)
{
double r[8];
r[0] = r[6] = x1;
r[2] = r[4] = x2;
r[1] = r[3] = y1;
r[5] = r[7] = y2;
return quad_to_quad(q, r);
}
//------------------------------------------------------------------------
inline trans_perspective::trans_perspective(double x1, double y1,
double x2, double y2,
const double* quad)
{
rect_to_quad(x1, y1, x2, y2, quad);
}
//------------------------------------------------------------------------
inline trans_perspective::trans_perspective(const double* quad,
double x1, double y1,
double x2, double y2)
{
quad_to_rect(quad, x1, y1, x2, y2);
}
//------------------------------------------------------------------------
inline trans_perspective::trans_perspective(const double* src,
const double* dst)
{
quad_to_quad(src, dst);
}
//------------------------------------------------------------------------
inline const trans_perspective& trans_perspective::reset()
{
sx = 1; shy = 0; w0 = 0;
shx = 0; sy = 1; w1 = 0;
tx = 0; ty = 0; w2 = 1;
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective&
trans_perspective::multiply(const trans_perspective& a)
{
trans_perspective b = *this;
sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0;
w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1;
w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2;
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective&
trans_perspective::multiply(const trans_affine& a)
{
trans_perspective b = *this;
sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective&
trans_perspective::premultiply(const trans_perspective& b)
{
trans_perspective a = *this;
sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0;
shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1;
tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2;
shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0;
sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1;
ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2;
w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0;
w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1;
w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2;
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective&
trans_perspective::premultiply(const trans_affine& b)
{
trans_perspective a = *this;
sx = a.sx *b.sx + a.shx*b.shy;
shx = a.sx *b.shx + a.shx*b.sy;
tx = a.sx *b.tx + a.shx*b.ty + a.tx;
shy = a.shy*b.sx + a.sy *b.shy;
sy = a.shy*b.shx + a.sy *b.sy;
ty = a.shy*b.tx + a.sy *b.ty + a.ty;
w0 = a.w0 *b.sx + a.w1 *b.shy;
w1 = a.w0 *b.shx + a.w1 *b.sy;
w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2;
return *this;
}
//------------------------------------------------------------------------
const trans_perspective&
trans_perspective::multiply_inv(const trans_perspective& m)
{
trans_perspective t = m;
t.invert();
return multiply(t);
}
//------------------------------------------------------------------------
const trans_perspective&
trans_perspective::multiply_inv(const trans_affine& m)
{
trans_affine t = m;
t.invert();
return multiply(t);
}
//------------------------------------------------------------------------
const trans_perspective&
trans_perspective::premultiply_inv(const trans_perspective& m)
{
trans_perspective t = m;
t.invert();
return *this = t.multiply(*this);
}
//------------------------------------------------------------------------
const trans_perspective&
trans_perspective::premultiply_inv(const trans_affine& m)
{
trans_perspective t(m);
t.invert();
return *this = t.multiply(*this);
}
//------------------------------------------------------------------------
inline const trans_perspective&
trans_perspective::translate(double x, double y)
{
tx += x;
ty += y;
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective& trans_perspective::rotate(double a)
{
multiply(trans_affine_rotation(a));
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective& trans_perspective::scale(double s)
{
multiply(trans_affine_scaling(s));
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective& trans_perspective::scale(double x, double y)
{
multiply(trans_affine_scaling(x, y));
return *this;
}
//------------------------------------------------------------------------
inline void trans_perspective::transform(double* px, double* py) const
{
double x = *px;
double y = *py;
double m = 1.0 / (x*w0 + y*w1 + w2);
*px = m * (x*sx + y*shx + tx);
*py = m * (x*shy + y*sy + ty);
}
//------------------------------------------------------------------------
inline void trans_perspective::transform_affine(double* x, double* y) const
{
double tmp = *x;
*x = tmp * sx + *y * shx + tx;
*y = tmp * shy + *y * sy + ty;
}
//------------------------------------------------------------------------
inline void trans_perspective::transform_2x2(double* x, double* y) const
{
double tmp = *x;
*x = tmp * sx + *y * shx;
*y = tmp * shy + *y * sy;
}
//------------------------------------------------------------------------
inline void trans_perspective::inverse_transform(double* x, double* y) const
{
trans_perspective t(*this);
if(t.invert()) t.transform(x, y);
}
//------------------------------------------------------------------------
inline void trans_perspective::store_to(double* m) const
{
*m++ = sx; *m++ = shy; *m++ = w0;
*m++ = shx; *m++ = sy; *m++ = w1;
*m++ = tx; *m++ = ty; *m++ = w2;
}
//------------------------------------------------------------------------
inline const trans_perspective& trans_perspective::load_from(const double* m)
{
sx = *m++; shy = *m++; w0 = *m++;
shx = *m++; sy = *m++; w1 = *m++;
tx = *m++; ty = *m++; w2 = *m++;
return *this;
}
//------------------------------------------------------------------------
inline const trans_perspective&
trans_perspective::from_affine(const trans_affine& a)
{
sx = a.sx; shy = a.shy; w0 = 0;
shx = a.shx; sy = a.sy; w1 = 0;
tx = a.tx; ty = a.ty; w2 = 1;
return *this;
}
//------------------------------------------------------------------------
inline double trans_perspective::determinant() const
{
return sx * (sy * w2 - ty * w1) +
shx * (ty * w0 - shy * w2) +
tx * (shy * w1 - sy * w0);
}
//------------------------------------------------------------------------
inline double trans_perspective::determinant_reciprocal() const
{
return 1.0 / determinant();
}
//------------------------------------------------------------------------
inline bool trans_perspective::is_valid(double epsilon) const
{
return fabs(sx) > epsilon && fabs(sy) > epsilon && fabs(w2) > epsilon;
}
//------------------------------------------------------------------------
inline bool trans_perspective::is_identity(double epsilon) const
{
return is_equal_eps(sx, 1.0, epsilon) &&
is_equal_eps(shy, 0.0, epsilon) &&
is_equal_eps(w0, 0.0, epsilon) &&
is_equal_eps(shx, 0.0, epsilon) &&
is_equal_eps(sy, 1.0, epsilon) &&
is_equal_eps(w1, 0.0, epsilon) &&
is_equal_eps(tx, 0.0, epsilon) &&
is_equal_eps(ty, 0.0, epsilon) &&
is_equal_eps(w2, 1.0, epsilon);
}
//------------------------------------------------------------------------
inline bool trans_perspective::is_equal(const trans_perspective& m,
double epsilon) const
{
return is_equal_eps(sx, m.sx, epsilon) &&
is_equal_eps(shy, m.shy, epsilon) &&
is_equal_eps(w0, m.w0, epsilon) &&
is_equal_eps(shx, m.shx, epsilon) &&
is_equal_eps(sy, m.sy, epsilon) &&
is_equal_eps(w1, m.w1, epsilon) &&
is_equal_eps(tx, m.tx, epsilon) &&
is_equal_eps(ty, m.ty, epsilon) &&
is_equal_eps(w2, m.w2, epsilon);
}
//------------------------------------------------------------------------
inline double trans_perspective::scale() const
{
double x = 0.707106781 * sx + 0.707106781 * shx;
double y = 0.707106781 * shy + 0.707106781 * sy;
return sqrt(x*x + y*y);
}
//------------------------------------------------------------------------
inline double trans_perspective::rotation() const
{
double x1 = 0.0;
double y1 = 0.0;
double x2 = 1.0;
double y2 = 0.0;
transform(&x1, &y1);
transform(&x2, &y2);
return atan2(y2-y1, x2-x1);
}
//------------------------------------------------------------------------
void trans_perspective::translation(double* dx, double* dy) const
{
*dx = tx;
*dy = ty;
}
//------------------------------------------------------------------------
void trans_perspective::scaling(double* x, double* y) const
{
double x1 = 0.0;
double y1 = 0.0;
double x2 = 1.0;
double y2 = 1.0;
trans_perspective t(*this);
t *= trans_affine_rotation(-rotation());
t.transform(&x1, &y1);
t.transform(&x2, &y2);
*x = x2 - x1;
*y = y2 - y1;
}
//------------------------------------------------------------------------
void trans_perspective::scaling_abs(double* x, double* y) const
{
*x = sqrt(sx * sx + shx * shx);
*y = sqrt(shy * shy + sy * sy);
}
}