| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- //
- // System.Drawing.Drawing2D.Matrix.cs
- //
- // Author:
- // Stefan Maierhofer <[email protected]>
- //
- // (C) Ximian, Inc. http://www.ximian.com
- //
- using System;
- using System.Drawing;
- using System.Runtime.InteropServices;
- namespace System.Drawing.Drawing2D
- {
- public sealed class Matrix : MarshalByRefObject, IDisposable
- {
- // initialize to identity
- private float[] m = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
-
- // constructors
- public Matrix() { }
-
- /* TODO: depends on System.Drawing.Drawing2D.Rectangle
- public Matrix(Rectangle rect , Point[] plgpts)
- {
- // TODO
- }
- */
-
- /* TODO: depends on System.Drawing.Drawing2D.RectangleF
- public Matrix(RectangleF rect , PointF[] pa)
- {
- // TODO
- }
- */
- public Matrix(float m11, float m12,
- float m21, float m22,
- float dx, float dy)
- {
- m[0] = m11; m[1] = m12;
- m[2] = m21; m[3] = m22;
- m[4] = dx; m[5] = dy;
- }
-
- // properties
- public float[] Elements
- {
- get { return m; }
- }
-
- public bool IsIdentity
- {
- get
- {
- if ( (m[0] == 1.0f) && (m[1] == 0.0f) &&
- (m[2] == 0.0f) && (m[3] == 1.0f) &&
- (m[4] == 0.0f) && (m[5] == 0.0f) )
- return true;
- else
- return false;
- }
- }
-
- public bool IsInvertible
- {
- get
- {
- // matrix M is invertible if det(M) != 0
- float det = m[0] * m[3] - m[2] * m[1];
- if (det != 0.0f) return true;
- else return false;
- }
- }
-
- public float OffsetX
- {
- get { return m[4]; }
- }
-
- public float OffsetY
- {
- get { return m[5]; }
- }
-
- // methods
- public Matrix Clone()
- {
- return new Matrix(m[0], m[1], m[2], m[3], m[4], m[5]);
- }
-
- public void Dispose() { }
-
- public override bool Equals(object obj)
- {
- if (obj is Matrix)
- {
- float[] a = ((Matrix)obj).Elements;
- if ( m[0] == a[0] && m[1] == a[1] &&
- m[2] == a[2] && m[3] == a[3] &&
- m[4] == a[4] && m[5] == a[5] )
- return true;
- else
- return false;
- }
- else
- {
- return false;
- }
- }
-
- ~Matrix() {}
-
- [StructLayout(LayoutKind.Explicit)]
- internal struct BitConverter
- {
- [FieldOffset(0)] public float f;
- [FieldOffset(0)] public int i;
- }
-
- public override int GetHashCode()
- {
- BitConverter b;
- // compiler is not smart
- b.i = 0;
- int h = 0;
- for (int i = 0; i < 6; i++)
- {
- b.f = m[i];
- h ^= b.i >> i;
- }
- return h;
- }
-
- public void Invert()
- {
- float det = m[0] * m[3] - m[2] * m[1];
- if (det != 0.0f) // if invertible
- {
- float[] r =
- {
- m[3] / det,
- -m[1] / det,
- -m[2] / det,
- m[0] / det,
- (-m[3] * m[4] + m[1] * m[5]) / det,
- (m[2] * m[4] - m[0] * m[5]) / det
- };
- m = r;
- }
- }
-
- public void Multiply(Matrix matrix)
- {
- Multiply(matrix, MatrixOrder.Prepend);
- }
-
- public void Multiply(Matrix matrix, MatrixOrder order)
- {
- switch (order)
- {
- case MatrixOrder.Prepend:
- // this = matrix * this
- float[] p = matrix.Elements;
- float[] r0 =
- {
- p[0] * m[0] + p[1] * m[2],
- p[0] * m[1] + p[1] * m[3],
- p[2] * m[0] + p[3] * m[2],
- p[2] * m[1] + p[3] * m[3],
- p[4] * m[0] + p[5] * m[2] + m[4],
- p[4] * m[1] + p[5] * m[3] + m[5]
- };
- m = r0;
- break;
- case MatrixOrder.Append:
- // this = this * matrix
- float[] a = matrix.Elements;
- float[] r1 =
- {
- m[0] * a[0] + m[1] * a[2],
- m[0] * a[1] + m[1] * a[3],
- m[2] * a[0] + m[3] * a[2],
- m[2] * a[1] + m[3] * a[3],
- m[4] * a[0] + m[5] * a[2] + a[4],
- m[4] * a[1] + m[5] * a[3] + a[5]
- };
- m = r1;
- break;
- }
- }
-
- public void Reset()
- {
- m[0] = 1.0f; m[1] = 0.0f;
- m[2] = 0.0f; m[3] = 1.0f;
- m[4] = 0.0f; m[5] = 0.0f;
- }
-
- public void Rotate(float angle)
- {
- Rotate(angle, MatrixOrder.Prepend);
- }
-
- public void Rotate(float angle, MatrixOrder order)
- {
- angle *= (float)(Math.PI / 180.0); // degrees to randians
- float cos = (float)Math.Cos(angle);
- float sin = (float)Math.Sin(angle);
- switch (order)
- {
- case MatrixOrder.Prepend:
- // this = rotation * this
- float[] r0 =
- {
- cos * m[0] + sin * m[2],
- cos * m[1] + sin * m[3],
- -sin * m[0] + cos * m[2],
- -sin * m[1] + cos * m[3],
- m[4],
- m[5]
- };
- m = r0;
- break;
- case MatrixOrder.Append:
- // this = this * rotation
- float[] r1 =
- {
- m[0] * cos + m[1] * -sin,
- m[0] * sin + m[1] * cos,
- m[2] * cos + m[3] * -sin,
- m[2] * sin + m[3] * cos,
- m[4] * cos + m[5] * -sin,
- m[4] * sin + m[5] * cos
- };
- m = r1;
- break;
- }
- }
-
- public void RotateAt(float angle, PointF point)
- {
- RotateAt(angle, point, MatrixOrder.Prepend);
- }
-
- public void RotateAt(float angle, PointF point, MatrixOrder order)
- {
- angle *= (float)(Math.PI / 180.0); // degrees to randians
- float cos = (float)Math.Cos(angle);
- float sin = (float)Math.Sin(angle);
- float e4 = -point.X * cos + point.Y * sin + point.X;
- float e5 = -point.X * sin - point.Y * cos + point.Y;
- switch (order)
- {
- case MatrixOrder.Prepend:
- // this = rotation * this
- float[] r0 =
- {
- cos * m[0] + sin * m[2],
- cos * m[1] + sin * m[3],
- -sin * m[0] + cos * m[2],
- -sin * m[1] + cos * m[3],
- e4 * m[0] + e5 * m[2] + m[4],
- e4 * m[1] + e5 * m[3] + m[5]
- };
- m = r0;
- break;
- case MatrixOrder.Append:
- // this = this * rotation
- float[] r1 =
- {
- m[0] * cos + m[1] * -sin,
- m[0] * sin + m[1] * cos,
- m[2] * cos + m[3] * -sin,
- m[2] * sin + m[3] * cos,
- m[4] * cos + m[5] * -sin + e4,
- m[4] * sin + m[5] * cos + e5
- };
- m = r1;
- break;
- }
- }
-
- public void Scale(float scaleX, float scaleY)
- {
- Scale(scaleX, scaleY, MatrixOrder.Prepend);
- }
-
- public void Scale(float scaleX, float scaleY, MatrixOrder order)
- {
- switch (order)
- {
- case MatrixOrder.Prepend:
- // this = scale * this
- m[0] *= scaleX; m[1] *= scaleX;
- m[2] *= scaleY; m[3] *= scaleY;
- break;
- case MatrixOrder.Append:
- // this = this * scale
- m[0] *= scaleX; m[1] *= scaleY;
- m[2] *= scaleX; m[3] *= scaleY;
- m[4] *= scaleX; m[5] *= scaleY;
- break;
- }
- }
-
- public void Shear(float shearX, float shearY)
- {
- Shear(shearX, shearY, MatrixOrder.Prepend);
- }
-
- // LAMESPEC: quote from beta 2 sdk docs: "[To be supplied!]"
- //
- // assuming transformation matrix:
- //
- // (1 shearY 0)
- // (shearX 1 0)
- // (0 0 1)
- //
- public void Shear(float shearX, float shearY, MatrixOrder order)
- {
- switch (order)
- {
- case MatrixOrder.Prepend:
- // this = shear * this
- float[] r0 =
- {
- m[0] + shearY * m[2],
- m[1] + shearY * m[3],
- shearX * m[0] + m[2],
- shearX * m[1] + m[3],
- m[4],
- m[5]
- };
- m = r0;
- break;
- case MatrixOrder.Append:
- // this = this * shear
- float[] r1 =
- {
- m[0] + m[1] * shearX,
- m[0] * shearY + m[1],
- m[2] + m[3] * shearX,
- m[2] * shearY + m[3],
- m[4] + m[5] * shearX ,
- m[4] * shearY + m[5]
- };
- m = r1;
- break;
- }
- }
-
- public void TransformPoints(Point[] pts)
- {
- for (int i = 0; i < pts.Length; i++)
- {
- float x = (float)pts[i].X;
- float y = (float)pts[i].Y;
- pts[i].X = (int)(x * m[0] + y * m[2] + m[4]);
- pts[i].Y = (int)(x * m[1] + y * m[3] + m[5]);
- }
- }
-
- public void TransformPoints(PointF[] pts)
- {
- for (int i = 0; i < pts.Length; i++)
- {
- float x = pts[i].X;
- float y = pts[i].Y;
- pts[i].X = x * m[0] + y * m[2] + m[4];
- pts[i].Y = x * m[1] + y * m[3] + m[5];
- }
- }
-
- public void TransformVectors(Point[] pts)
- {
- for (int i = 0; i < pts.Length; i++)
- {
- float x = (float)pts[i].X;
- float y = (float)pts[i].Y;
- pts[i].X = (int)(x * m[0] + y * m[2]);
- pts[i].Y = (int)(x * m[1] + y * m[3]);
- }
- }
-
- public void TransformVectors(PointF[] pts)
- {
- for (int i = 0; i < pts.Length; i++)
- {
- float x = pts[i].X;
- float y = pts[i].Y;
- pts[i].X = x * m[0] + y * m[2];
- pts[i].Y = x * m[1] + y * m[3];
- }
- }
-
- public void Translate(float offsetX, float offsetY)
- {
- Translate(offsetX, offsetY, MatrixOrder.Prepend);
- }
-
- public void Translate(float offsetX, float offsetY, MatrixOrder order)
- {
- switch (order)
- {
- case MatrixOrder.Prepend:
- // this = translation * this
- m[4] = offsetX * m[0] + offsetY * m[2] + m[4];
- m[5] = offsetX * m[1] + offsetY * m[3] + m[5];
- break;
- case MatrixOrder.Append:
- // this = this * translation
- m[4] += offsetX;
- m[5] += offsetY;
- break;
- }
- }
-
- // LAMESPEC: quote from beta 2 sdk docs: "[To be supplied!]"
- // [MonoTODO]
- public void VectorTransformPoints(Point[] pts)
- {
- // TODO
- }
-
- // some simple test (TODO: remove)
- /*
- public static void Main()
- {
- PointF[] p = {new PointF(1.0f, 2.0f)};
- Console.WriteLine("(" + p[0].X + " " + p[0].Y + ")");
- Matrix m = new Matrix();
-
- m.Translate(1.0f, 1.0f);
- m.Scale(2.0f, 2.0f);
- m.Rotate(180.0f);
-
- m.TransformPoints(p);
- Console.WriteLine("(" + p[0].X + " " + p[0].Y + ")");
- m.Invert();
- m.TransformPoints(p);
- Console.WriteLine("(" + p[0].X + " " + p[0].Y + ")");
-
- Matrix a = new Matrix(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
- Matrix b = new Matrix(2.0f, 0.0f, 0.0f, 2.0f, 0.0f, 0.0f);
-
- Console.WriteLine("h(a) = " + a.GetHashCode());
- Console.WriteLine("h(b) = " + b.GetHashCode());
- }
- */
-
- }
- }
|