|
|
248685 |
/* === S Y N F I G ========================================================= */
|
|
|
248685 |
/*! \file synfig/rendering/primitive/affinetransformation.cpp
|
|
|
248685 |
** \brief AffineTransformation
|
|
|
248685 |
**
|
|
|
248685 |
** $Id$
|
|
|
248685 |
**
|
|
|
248685 |
** \legal
|
|
|
da4398 |
** ......... ... 2015-2018 Ivan Mahonin
|
|
|
248685 |
**
|
|
|
248685 |
** This package is free software; you can redistribute it and/or
|
|
|
248685 |
** modify it under the terms of the GNU General Public License as
|
|
|
248685 |
** published by the Free Software Foundation; either version 2 of
|
|
|
248685 |
** the License, or (at your option) any later version.
|
|
|
248685 |
**
|
|
|
248685 |
** This package is distributed in the hope that it will be useful,
|
|
|
248685 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
248685 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
248685 |
** General Public License for more details.
|
|
|
248685 |
** \endlegal
|
|
|
248685 |
*/
|
|
|
248685 |
/* ========================================================================= */
|
|
|
248685 |
|
|
|
248685 |
/* === H E A D E R S ======================================================= */
|
|
|
248685 |
|
|
|
248685 |
#ifdef USING_PCH
|
|
|
248685 |
# include "pch.h"
|
|
|
248685 |
#else
|
|
|
248685 |
#ifdef HAVE_CONFIG_H
|
|
|
248685 |
# include <config.h></config.h>
|
|
|
248685 |
#endif
|
|
|
248685 |
|
|
|
da4398 |
#include "transformationaffine.h"
|
|
|
248685 |
|
|
|
248685 |
#endif
|
|
|
248685 |
|
|
|
248685 |
using namespace synfig;
|
|
|
248685 |
using namespace rendering;
|
|
|
248685 |
|
|
|
248685 |
/* === M A C R O S ========================================================= */
|
|
|
248685 |
|
|
|
248685 |
/* === G L O B A L S ======================================================= */
|
|
|
248685 |
|
|
|
248685 |
/* === P R O C E D U R E S ================================================= */
|
|
|
248685 |
|
|
|
248685 |
/* === M E T H O D S ======================================================= */
|
|
|
248685 |
|
|
|
81df8d |
Transformation*
|
|
|
81df8d |
TransformationAffine::clone_vfunc() const
|
|
|
81df8d |
{ return new TransformationAffine(matrix); }
|
|
|
81df8d |
|
|
|
81df8d |
Transformation*
|
|
|
da4398 |
TransformationAffine::create_inverted_vfunc() const
|
|
|
da4398 |
{ return new TransformationAffine(Matrix(matrix).invert()); }
|
|
|
da4398 |
|
|
|
da4398 |
Point
|
|
|
f44ff0 |
TransformationAffine::transform_vfunc(const Point &x) const
|
|
|
f44ff0 |
{ return matrix.get_transformed(x); }
|
|
|
f44ff0 |
|
|
|
f44ff0 |
Matrix2
|
|
|
f44ff0 |
TransformationAffine::derivative_vfunc(const Point&) const
|
|
|
f44ff0 |
{ return Matrix2(matrix.m00, matrix.m01, matrix.m10, matrix.m11); }
|
|
|
f44ff0 |
|
|
|
f44ff0 |
Vector
|
|
|
f44ff0 |
TransformationAffine::calc_optimal_resolution(const Matrix2 &matrix) {
|
|
|
f44ff0 |
const Real max_overscale_sqr = 1.0*4.0;
|
|
|
f44ff0 |
const Real max_overscale_sqrsqr = max_overscale_sqr*max_overscale_sqr;
|
|
|
f44ff0 |
const Real real_precision_sqr = real_precision<real>() * real_precision<real>();</real></real>
|
|
|
f44ff0 |
|
|
|
f44ff0 |
const Real a = matrix.m00 * matrix.m00;
|
|
|
f44ff0 |
const Real b = matrix.m01 * matrix.m01;
|
|
|
f44ff0 |
const Real c = matrix.m10 * matrix.m10;
|
|
|
f44ff0 |
const Real d = matrix.m11 * matrix.m11;
|
|
|
f44ff0 |
Real e = fabs(matrix.det());
|
|
|
f44ff0 |
if (e < real_precision_sqr)
|
|
|
f44ff0 |
return Vector();
|
|
|
f44ff0 |
e = 1.0/e;
|
|
|
f44ff0 |
|
|
|
f44ff0 |
const Real sum = a*d + b*c;
|
|
|
f44ff0 |
Vector scale;
|
|
|
f44ff0 |
if (2*a*b + real_precision_sqr >= sum) {
|
|
|
f44ff0 |
scale[0] = sqrt(2*b)*e;
|
|
|
f44ff0 |
scale[1] = sqrt(2*a)*e;
|
|
|
f44ff0 |
} else
|
|
|
f44ff0 |
if (2*c*d + real_precision_sqr >= sum) {
|
|
|
f44ff0 |
scale[0] = sqrt(2*d)*e;
|
|
|
f44ff0 |
scale[1] = sqrt(2*c)*e;
|
|
|
f44ff0 |
} else {
|
|
|
f44ff0 |
const Real dif = a*d - b*c;
|
|
|
f44ff0 |
scale[0] = sqrt(dif/(a - c))*e;
|
|
|
f44ff0 |
scale[1] = sqrt(dif/(d - b))*e;
|
|
|
f44ff0 |
}
|
|
|
f44ff0 |
|
|
|
f44ff0 |
const Real sx2 = scale[0]*scale[0];
|
|
|
f44ff0 |
const Real sy2 = scale[1]*scale[1];
|
|
|
f44ff0 |
const Real sqrsqr = (a*sx2 + b*sy2)*(c*sx2 + d*sy2);
|
|
|
f44ff0 |
if (sqrsqr > max_overscale_sqrsqr)
|
|
|
f44ff0 |
scale *= sqrt(sqrt(max_overscale_sqrsqr / sqrsqr));
|
|
|
f44ff0 |
|
|
|
f44ff0 |
return scale[0] <= real_precision<real>() || scale[1] <= real_precision<real>()</real></real>
|
|
|
f44ff0 |
? Vector() : scale;
|
|
|
f44ff0 |
}
|
|
|
da4398 |
|
|
|
da4398 |
Transformation::Bounds
|
|
|
f44ff0 |
TransformationAffine::transform_bounds_affine(const Matrix &matrix, const Bounds &bounds)
|
|
|
248685 |
{
|
|
|
da4398 |
if (!bounds.is_valid())
|
|
|
da4398 |
return Bounds();
|
|
|
f44ff0 |
|
|
|
f44ff0 |
const Real kx = 1/bounds.resolution[0];
|
|
|
f44ff0 |
const Real ky = 1/bounds.resolution[1];
|
|
|
f44ff0 |
|
|
|
f44ff0 |
return Bounds(
|
|
|
f44ff0 |
Rect( matrix.get_transformed( Vector(bounds.rect.minx, bounds.rect.miny) ) )
|
|
|
f44ff0 |
.expand( matrix.get_transformed( Vector(bounds.rect.minx, bounds.rect.maxy) ) )
|
|
|
f44ff0 |
.expand( matrix.get_transformed( Vector(bounds.rect.maxx, bounds.rect.miny) ) )
|
|
|
f44ff0 |
.expand( matrix.get_transformed( Vector(bounds.rect.maxx, bounds.rect.maxy) ) ),
|
|
|
f44ff0 |
calc_optimal_resolution(Matrix2(
|
|
|
f44ff0 |
matrix.m00*kx, matrix.m01*kx,
|
|
|
f44ff0 |
matrix.m10*ky, matrix.m11*ky )) );
|
|
|
248685 |
}
|
|
|
248685 |
|
|
|
f44ff0 |
Transformation::Bounds
|
|
|
f44ff0 |
TransformationAffine::transform_bounds_vfunc(const Bounds &bounds) const
|
|
|
f44ff0 |
{ return transform_bounds_affine(matrix, bounds); }
|
|
|
f44ff0 |
|
|
|
81df8d |
bool
|
|
|
81df8d |
TransformationAffine::can_merge_outer_vfunc(const Transformation &other) const
|
|
|
81df8d |
{ return (bool)dynamic_cast<const transformationaffine*="">(&other); }</const>
|
|
|
81df8d |
|
|
|
81df8d |
bool
|
|
|
81df8d |
TransformationAffine::can_merge_inner_vfunc(const Transformation &other) const
|
|
|
81df8d |
{ return can_merge_outer_vfunc(other); }
|
|
|
81df8d |
|
|
|
81df8d |
void
|
|
|
81df8d |
TransformationAffine::merge_outer_vfunc(const Transformation &other)
|
|
|
81df8d |
{ matrix = dynamic_cast<const transformationaffine*="">(&other)->matrix * matrix; }</const>
|
|
|
81df8d |
|
|
|
81df8d |
void
|
|
|
81df8d |
TransformationAffine::merge_inner_vfunc(const Transformation &other)
|
|
|
81df8d |
{ matrix *= dynamic_cast<const transformationaffine*="">(&other)->matrix; }</const>
|
|
|
81df8d |
|
|
|
81df8d |
|
|
|
248685 |
/* === E N T R Y P O I N T ================================================= */
|