mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 20:39:01 +00:00
234 lines
4.8 KiB
C#
234 lines
4.8 KiB
C#
using System;
|
|
|
|
namespace Orvid.Graphics.FontSupport
|
|
{
|
|
public class AffineTransform
|
|
{
|
|
static double AffineEpsilon = 1e-14;
|
|
public double sx, shy, shx, sy, tx, ty;
|
|
|
|
public AffineTransform(AffineTransform copyFrom)
|
|
{
|
|
sx = copyFrom.sx;
|
|
shy = copyFrom.shy;
|
|
shx = copyFrom.shx;
|
|
sy = copyFrom.sy;
|
|
tx = copyFrom.tx;
|
|
ty = copyFrom.ty;
|
|
}
|
|
|
|
public AffineTransform(double v0, double v1, double v2,
|
|
double v3, double v4, double v5)
|
|
{
|
|
sx = v0;
|
|
shy = v1;
|
|
shx = v2;
|
|
sy = v3;
|
|
tx = v4;
|
|
ty = v5;
|
|
}
|
|
|
|
public AffineTransform(double[] m)
|
|
{
|
|
sx = m[0];
|
|
shy = m[1];
|
|
shx = m[2];
|
|
sy = m[3];
|
|
tx = m[4];
|
|
ty = m[5];
|
|
}
|
|
|
|
public static AffineTransform NewIdentity()
|
|
{
|
|
AffineTransform newAffine = new AffineTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
|
|
|
|
return newAffine;
|
|
}
|
|
|
|
public static AffineTransform NewRotation(double angleRadians)
|
|
{
|
|
return new AffineTransform(Math.Cos(angleRadians), Math.Sin(angleRadians), -Math.Sin(angleRadians), Math.Cos(angleRadians), 0.0, 0.0);
|
|
}
|
|
|
|
public static AffineTransform NewScaling(double scale)
|
|
{
|
|
return new AffineTransform(scale, 0.0, 0.0, scale, 0.0, 0.0);
|
|
}
|
|
|
|
public static AffineTransform NewScaling(double x, double y)
|
|
{
|
|
return new AffineTransform(x, 0.0, 0.0, y, 0.0, 0.0);
|
|
}
|
|
|
|
public static AffineTransform NewTranslation(double x, double y)
|
|
{
|
|
return new AffineTransform(1.0, 0.0, 0.0, 1.0, x, y);
|
|
}
|
|
|
|
public static AffineTransform NewSkewing(double x, double y)
|
|
{
|
|
return new AffineTransform(1.0, Math.Tan(y), Math.Tan(x), 1.0, 0.0, 0.0);
|
|
}
|
|
|
|
public void Identity()
|
|
{
|
|
sx = sy = 1.0;
|
|
shy = shx = tx = ty = 0.0;
|
|
}
|
|
|
|
public void Translate(double x, double y)
|
|
{
|
|
tx += x;
|
|
ty += y;
|
|
}
|
|
|
|
public void Rotate(double angleRadians)
|
|
{
|
|
double ca = Math.Cos(angleRadians);
|
|
double sa = Math.Sin(angleRadians);
|
|
double t0 = sx * ca - shy * sa;
|
|
double t2 = shx * ca - sy * sa;
|
|
double t4 = tx * ca - ty * sa;
|
|
shy = sx * sa + shy * ca;
|
|
sy = shx * sa + sy * ca;
|
|
ty = tx * sa + ty * ca;
|
|
sx = t0;
|
|
shx = t2;
|
|
tx = t4;
|
|
}
|
|
|
|
public void Scale(double x, double y)
|
|
{
|
|
double mm0 = x;
|
|
double mm3 = y;
|
|
sx *= mm0;
|
|
shx *= mm0;
|
|
tx *= mm0;
|
|
shy *= mm3;
|
|
sy *= mm3;
|
|
ty *= mm3;
|
|
}
|
|
|
|
public void Scale(double scaleAmount)
|
|
{
|
|
sx *= scaleAmount;
|
|
shx *= scaleAmount;
|
|
tx *= scaleAmount;
|
|
shy *= scaleAmount;
|
|
sy *= scaleAmount;
|
|
ty *= scaleAmount;
|
|
}
|
|
|
|
void Multiply(AffineTransform m)
|
|
{
|
|
double t0 = sx * m.sx + shy * m.shx;
|
|
double t2 = shx * m.sx + sy * m.shx;
|
|
double t4 = tx * m.sx + ty * m.shx + m.tx;
|
|
shy = sx * m.shy + shy * m.sy;
|
|
sy = shx * m.shy + sy * m.sy;
|
|
ty = tx * m.shy + ty * m.sy + m.ty;
|
|
sx = t0;
|
|
shx = t2;
|
|
tx = t4;
|
|
}
|
|
|
|
public void Invert()
|
|
{
|
|
double d = DeterminantReciprocal;
|
|
|
|
double t0 = sy * d;
|
|
sy = sx * d;
|
|
shy = -shy * d;
|
|
shx = -shx * d;
|
|
|
|
double t4 = -tx * t0 - ty * shx;
|
|
ty = -tx * shy - ty * sy;
|
|
|
|
sx = t0;
|
|
tx = t4;
|
|
}
|
|
|
|
public static AffineTransform operator *(AffineTransform a, AffineTransform b)
|
|
{
|
|
AffineTransform temp = new AffineTransform(a);
|
|
temp.Multiply(b);
|
|
return temp;
|
|
}
|
|
|
|
public void Transform(ref double x, ref double y)
|
|
{
|
|
double tmp = x;
|
|
x = tmp * sx + y * shx + tx;
|
|
y = tmp * shy + y * sy + ty;
|
|
}
|
|
|
|
public void Transform(ref Vec2d pointToTransform)
|
|
{
|
|
Transform(ref pointToTransform.X, ref pointToTransform.Y);
|
|
}
|
|
|
|
public void InverseTransform(ref double x, ref double y)
|
|
{
|
|
double d = DeterminantReciprocal;
|
|
double a = (x - tx) * d;
|
|
double b = (y - ty) * d;
|
|
x = a * sy - b * shx;
|
|
y = b * sx - a * shy;
|
|
}
|
|
|
|
private double DeterminantReciprocal
|
|
{
|
|
get { return 1.0 / (sx * sy - shy * shx); }
|
|
}
|
|
|
|
|
|
public double GetScale()
|
|
{
|
|
double x = 0.707106781 * sx + 0.707106781 * shx;
|
|
double y = 0.707106781 * shy + 0.707106781 * sy;
|
|
return Math.Sqrt(x * x + y * y);
|
|
}
|
|
|
|
public bool IsValid(double epsilon)
|
|
{
|
|
return Math.Abs(sx) > epsilon && Math.Abs(sy) > epsilon;
|
|
}
|
|
|
|
public double Rotation()
|
|
{
|
|
double x1 = 0.0;
|
|
double y1 = 0.0;
|
|
double x2 = 1.0;
|
|
double y2 = 0.0;
|
|
Transform(ref x1, ref y1);
|
|
Transform(ref x2, ref y2);
|
|
return Math.Atan2(y2 - y1, x2 - x1);
|
|
}
|
|
|
|
public void Translation(out double dx, out double dy)
|
|
{
|
|
dx = tx;
|
|
dy = ty;
|
|
}
|
|
|
|
public void Scaling(out double x, out double y)
|
|
{
|
|
double x1 = 0.0;
|
|
double y1 = 0.0;
|
|
double x2 = 1.0;
|
|
double y2 = 1.0;
|
|
AffineTransform t = new AffineTransform(this);
|
|
t *= NewRotation(-Rotation());
|
|
t.Transform(ref x1, ref y1);
|
|
t.Transform(ref x2, ref y2);
|
|
x = x2 - x1;
|
|
y = y2 - y1;
|
|
}
|
|
|
|
public void ScalingAbs(out double x, out double y)
|
|
{
|
|
x = Math.Sqrt(sx * sx + shx * shx);
|
|
y = Math.Sqrt(shy * shy + sy * sy);
|
|
}
|
|
}
|
|
}
|