Blame mono/EllipseTruncate/Matrix.cs

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