|
|
4ef489 |
using System;
|
|
|
4ef489 |
|
|
|
4ef489 |
namespace EllipseTruncate {
|
|
|
4ef489 |
public struct Matrix {
|
|
|
4ef489 |
public double m00, m01, m02,
|
|
|
4ef489 |
m10, m11, m12,
|
|
|
4ef489 |
m20, m21, m22;
|
|
|
4ef489 |
|
|
|
4ef489 |
public Matrix(Point p0, Point p1, Point p2 = new Point()) {
|
|
|
4ef489 |
m00 = p0.x; m01 = p0.y; m02 = 0.0;
|
|
|
4ef489 |
m10 = p1.x; m11 = p1.y; m12 = 0.0;
|
|
|
4ef489 |
m20 = p2.x; m21 = p2.y; m22 = 1.0;
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
public Matrix(Cairo.Matrix m) {
|
|
|
4ef489 |
m00 = m.Xx; m01 = m.Yx; m02 = 0.0;
|
|
|
4ef489 |
m10 = m.Xy; m11 = m.Yy; m12 = 0.0;
|
|
|
4ef489 |
m20 = m.X0; m21 = m.Y0; m22 = 1.0;
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
public Point row0()
|
|
|
4ef489 |
{ return new Point(m00, m01); }
|
|
|
4ef489 |
public Point row1()
|
|
|
4ef489 |
{ return new Point(m10, m11); }
|
|
|
4ef489 |
public Point row2()
|
|
|
4ef489 |
{ return new Point(m20, m21); }
|
|
|
4ef489 |
|
|
|
4ef489 |
public Point row(int index) {
|
|
|
4ef489 |
switch(index) {
|
|
|
4ef489 |
case 0: return row0();
|
|
|
4ef489 |
case 1: return row1();
|
|
|
4ef489 |
case 2: return row2();
|
|
|
4ef489 |
}
|
|
|
4ef489 |
return new Point();
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
public static Matrix zero()
|
|
|
4ef489 |
{ return new Matrix(); }
|
|
|
4ef489 |
|
|
|
4ef489 |
public static Matrix identity() {
|
|
|
4ef489 |
Matrix m = new Matrix();
|
|
|
4ef489 |
m.m00 = m.m11 = m.m22 = 1.0;
|
|
|
4ef489 |
return m;
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
public static Matrix rotation(double angle) {
|
|
|
4ef489 |
double s = Math.Sin(angle);
|
|
|
4ef489 |
double c = Math.Cos(angle);
|
|
|
4ef489 |
Matrix m = identity();
|
|
|
4ef489 |
m.m00 = c; m.m01 = s;
|
|
|
4ef489 |
m.m10 =-s; m.m11 = c;
|
|
|
4ef489 |
return m;
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
public static Matrix translation(double x, double y) {
|
|
|
4ef489 |
Matrix m = identity();
|
|
|
4ef489 |
m.m20 = x; m.m21 = y;
|
|
|
4ef489 |
return m;
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
public static Matrix scaling(double x, double y) {
|
|
|
4ef489 |
Matrix m = identity();
|
|
|
4ef489 |
m.m00 = x; m.m11 = y;
|
|
|
4ef489 |
return m;
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
public static Matrix translation(Point t)
|
|
|
4ef489 |
{ return translation(t.x, t.y); }
|
|
|
4ef489 |
public static Matrix scaling(Point s)
|
|
|
4ef489 |
{ return scaling(s.x, s.y); }
|
|
|
4ef489 |
public static Matrix scaling(double s)
|
|
|
4ef489 |
{ return scaling(s, s); }
|
|
|
4ef489 |
|
|
|
4ef489 |
public Matrix rotate(double angle)
|
|
|
4ef489 |
{ return this*rotation(angle); }
|
|
|
4ef489 |
public Matrix translate(double x, double y)
|
|
|
4ef489 |
{ return this*translation(x, y); }
|
|
|
4ef489 |
public Matrix translate(Point t)
|
|
|
4ef489 |
{ return this*translation(t); }
|
|
|
4ef489 |
public Matrix scale(double x, double y)
|
|
|
4ef489 |
{ return this*scaling(x, y); }
|
|
|
4ef489 |
public Matrix scale(Point s)
|
|
|
4ef489 |
{ return this*scaling(s); }
|
|
|
a79478 |
public Matrix scale(double s)
|
|
|
a79478 |
{ return this*scaling(s, s); }
|
|
|
4ef489 |
|
|
|
4ef489 |
public Point transform(Point p) {
|
|
|
4ef489 |
return new Point( m00*p.x + m10*p.y + m20,
|
|
|
4ef489 |
m01*p.x + m11*p.y + m21 );
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
public Point turn(Point p) {
|
|
|
4ef489 |
return new Point( m00*p.x + m10*p.y,
|
|
|
4ef489 |
m01*p.x + m11*p.y );
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
public static Point operator* (Matrix m, Point p)
|
|
|
4ef489 |
{ return m.transform(p); }
|
|
|
4ef489 |
|
|
|
4ef489 |
public static Matrix operator* (Matrix a, Matrix b) {
|
|
|
4ef489 |
Matrix m = new Matrix();
|
|
|
4ef489 |
|
|
|
4ef489 |
m.m00 = a.m00*b.m00 + a.m10*b.m01 + a.m20*b.m02;
|
|
|
4ef489 |
m.m01 = a.m01*b.m00 + a.m11*b.m01 + a.m21*b.m02;
|
|
|
4ef489 |
m.m02 = a.m02*b.m00 + a.m12*b.m01 + a.m22*b.m02;
|
|
|
4ef489 |
|
|
|
4ef489 |
m.m10 = a.m00*b.m10 + a.m10*b.m11 + a.m20*b.m12;
|
|
|
4ef489 |
m.m11 = a.m01*b.m10 + a.m11*b.m11 + a.m21*b.m12;
|
|
|
4ef489 |
m.m12 = a.m02*b.m10 + a.m12*b.m11 + a.m22*b.m12;
|
|
|
4ef489 |
|
|
|
4ef489 |
m.m20 = a.m00*b.m20 + a.m10*b.m21 + a.m20*b.m22;
|
|
|
4ef489 |
m.m21 = a.m01*b.m20 + a.m11*b.m21 + a.m21*b.m22;
|
|
|
4ef489 |
m.m22 = a.m02*b.m20 + a.m12*b.m21 + a.m22*b.m22;
|
|
|
4ef489 |
|
|
|
4ef489 |
return m;
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
public bool isEqual(Matrix other) {
|
|
|
4ef489 |
return Math.Abs(m00 - other.m00) <= Geometry.precision
|
|
|
4ef489 |
&& Math.Abs(m01 - other.m01) <= Geometry.precision
|
|
|
4ef489 |
&& Math.Abs(m02 - other.m02) <= Geometry.precision
|
|
|
4ef489 |
&& Math.Abs(m10 - other.m10) <= Geometry.precision
|
|
|
4ef489 |
&& Math.Abs(m11 - other.m11) <= Geometry.precision
|
|
|
4ef489 |
&& Math.Abs(m12 - other.m12) <= Geometry.precision
|
|
|
4ef489 |
&& Math.Abs(m20 - other.m20) <= Geometry.precision
|
|
|
4ef489 |
&& Math.Abs(m21 - other.m21) <= Geometry.precision
|
|
|
4ef489 |
&& Math.Abs(m22 - other.m22) <= Geometry.precision;
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
static double det2x2(double m00, double m01, double m10, double m11)
|
|
|
4ef489 |
{ return m00*m11 - m10*m01; }
|
|
|
4ef489 |
|
|
|
4ef489 |
public double det() {
|
|
|
4ef489 |
return m00*m11*m22 - m00*m12*m21
|
|
|
4ef489 |
+ m01*m12*m20 - m01*m10*m22
|
|
|
4ef489 |
+ m02*m10*m21 - m02*m11*m20;
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
public Matrix invert() {
|
|
|
4ef489 |
double d = det();
|
|
|
4ef489 |
Matrix m = new Matrix();
|
|
|
4ef489 |
if (Math.Abs(d) > Geometry.precision) {
|
|
|
4ef489 |
d = 1.0/d;
|
|
|
4ef489 |
double e = -d;
|
|
|
4ef489 |
m.m00 = det2x2(m11, m12, m21, m22)*d;
|
|
|
4ef489 |
m.m10 = det2x2(m10, m12, m20, m22)*e;
|
|
|
4ef489 |
m.m20 = det2x2(m10, m11, m20, m21)*d;
|
|
|
4ef489 |
|
|
|
4ef489 |
m.m01 = det2x2(m01, m02, m21, m22)*e;
|
|
|
4ef489 |
m.m11 = det2x2(m00, m02, m20, m22)*d;
|
|
|
4ef489 |
m.m21 = det2x2(m00, m01, m20, m21)*e;
|
|
|
4ef489 |
|
|
|
4ef489 |
m.m02 = det2x2(m01, m02, m11, m12)*d;
|
|
|
4ef489 |
m.m12 = det2x2(m00, m02, m10, m12)*e;
|
|
|
4ef489 |
m.m22 = det2x2(m00, m01, m10, m11)*d;
|
|
|
4ef489 |
}
|
|
|
4ef489 |
return m;
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|
|
|
4ef489 |
public Cairo.Matrix toCairo()
|
|
|
4ef489 |
{ return new Cairo.Matrix(m00, m01, m10, m11, m20, m21); }
|
|
|
4ef489 |
}
|
|
|
4ef489 |
}
|
|
|
4ef489 |
|