1457
// Old code, delete end of 2008
1460
/// Represents a 3-by-3 matrix that represents an affine 2D transformation.
1462
[DebuggerDisplay("({M11}, {M12}, {M21}, {M22}, {OffsetX}, {OffsetY})")]
1463
public struct XMatrix
1465
// TODO: In Windows 6.0 the type System.Windows.Media.Matrix is a much more
1466
// sophisticated implementation of a matrix -> enhance this implementation
1468
// is struct now and must be initializes with Matrix.Identity
1470
// /// Initializes a new instance of the Matrix class as the identity matrix.
1479
XMatrix.identity = new XMatrix(1, 0, 0, 1, 0, 0);
1483
///// Initializes a new instance of the Matrix class with the specified matrix.
1485
//public XMatrix(Matrix matrix)
1487
// float[] elements = matrix.Elements;
1488
// this.m11 = elements[0];
1489
// this.m12 = elements[1];
1490
// this.m21 = elements[2];
1491
// this.m22 = elements[3];
1492
// this.mdx = elements[4];
1493
// this.mdy = elements[5];
1498
/// Initializes a new instance of the Matrix class to the transform defined by the specified rectangle and
1499
/// array of points.
1501
public XMatrix(Rectangle rect, System.Drawing.Point[] plgpts)
1502
: this(new XRect(rect.X, rect.Y, rect.Width, rect.Height),
1503
new XPoint[3] { new XPoint(plgpts[0]), new XPoint(plgpts[1]), new XPoint(plgpts[2]) })
1509
/// Initializes a new instance of the Matrix class to the transform defined by the specified rectangle and
1510
/// array of points.
1512
public XMatrix(Rect rect, System.Windows.Point[] plgpts)
1513
: this(new XRect(rect.X, rect.Y, rect.Width, rect.Height),
1514
new XPoint[3] { new XPoint(plgpts[0]), new XPoint(plgpts[1]), new XPoint(plgpts[2]) })
1520
/// Initializes a new instance of the Matrix class to the transform defined by the specified rectangle and
1521
/// array of points.
1523
public XMatrix(RectangleF rect, PointF[] plgpts)
1524
: this(new XRect(rect.X, rect.Y, rect.Width, rect.Height),
1525
new XPoint[3] { new XPoint(plgpts[0]), new XPoint(plgpts[1]), new XPoint(plgpts[2]) })
1532
/// Initializes a new instance of the <see cref="XMatrix"/> class.
1534
public XMatrix(XRect rect, XPoint[] plgpts)
1538
// Lazy solution... left as an exercise :-)
1539
System.Drawing.Drawing2D.Matrix matrix = new System.Drawing.Drawing2D.Matrix(
1540
new RectangleF((float)rect.X, (float)rect.Y, (float)rect.Width, (float)rect.Height),
1541
new PointF[3]{new PointF((float)plgpts[0].X, (float)plgpts[0].Y),
1542
new PointF((float)plgpts[1].X, (float)plgpts[1].Y),
1543
new PointF((float)plgpts[2].X, (float)plgpts[2].Y)});
1544
float[] elements = matrix.Elements;
1545
this.m11 = elements[0];
1546
this.m12 = elements[1];
1547
this.m21 = elements[2];
1548
this.m22 = elements[3];
1549
this.mdx = elements[4];
1550
this.mdy = elements[5];
1552
// TODO work out the formulas for each value...
1559
throw new NotImplementedException("TODO");
1565
/// Initializes a new instance of the Matrix class with the specified points.
1567
public XMatrix(double m11, double m12, double m21, double m22, double offsetX, double offsetY)
1578
/// Returns the hash code for this instance.
1580
public override int GetHashCode()
1582
return base.GetHashCode();
1586
/// Indicates whether this instance and a specified object are equal.
1588
public override bool Equals(object obj)
1592
XMatrix matrix = (XMatrix)obj;
1593
return this.m11 == matrix.m11 && this.m12 == matrix.m12 && this.m21 == matrix.m21 &&
1594
this.m22 == matrix.m22 && this.mdx == matrix.mdx && this.mdy == matrix.mdy;
1600
/// Inverts this XMatrix object. Throws an exception if the matrix is not invertible.
1602
public void Invert()
1604
double det = this.m11 * this.m22 - this.m12 * this.m21;
1606
throw new InvalidOperationException("Matrix is singular and cannot be inverted.");
1608
double i11 = this.m22 / det;
1609
double i12 = -this.m12 / det;
1610
double i21 = -this.m21 / det;
1611
double i22 = this.m11 / det;
1612
double idx = (this.m21 * this.mdy - this.m22 * this.mdx) / det;
1613
double idy = (this.m12 * this.mdx - this.m11 * this.mdy) / det;
1624
/// Multiplies this matrix with the specified matrix.
1626
[Obsolete("Use MultiplyAppend or MultiplyPrepend explicitly, because in GDI+ and WPF the defaults are contrary.", true)]
1627
public void Multiply(XMatrix matrix)
1629
throw new InvalidOperationException("Temporarily out of order.");
1633
/// Multiplies this matrix with the specified matrix.
1635
public void MultiplyAppend(XMatrix matrix)
1637
Multiply(matrix, XMatrixOrder.Append);
1641
/// Multiplies this matrix with the specified matrix.
1643
public void MultiplyPrepend(XMatrix matrix)
1645
Multiply(matrix, XMatrixOrder.Prepend);
1649
/// Multiplies this matrix with the specified matrix.
1651
public void Multiply(XMatrix matrix, XMatrixOrder order)
1653
double t11 = this.m11;
1654
double t12 = this.m12;
1655
double t21 = this.m21;
1656
double t22 = this.m22;
1657
double tdx = this.mdx;
1658
double tdy = this.mdy;
1660
if (order == XMatrixOrder.Append)
1662
this.m11 = t11 * matrix.m11 + t12 * matrix.m21;
1663
this.m12 = t11 * matrix.m12 + t12 * matrix.m22;
1664
this.m21 = t21 * matrix.m11 + t22 * matrix.m21;
1665
this.m22 = t21 * matrix.m12 + t22 * matrix.m22;
1666
this.mdx = tdx * matrix.m11 + tdy * matrix.m21 + matrix.mdx;
1667
this.mdy = tdx * matrix.m12 + tdy * matrix.m22 + matrix.mdy;
1671
this.m11 = t11 * matrix.m11 + t21 * matrix.m12;
1672
this.m12 = t12 * matrix.m11 + t22 * matrix.m12;
1673
this.m21 = t11 * matrix.m21 + t21 * matrix.m22;
1674
this.m22 = t12 * matrix.m21 + t22 * matrix.m22;
1675
this.mdx = t11 * matrix.mdx + t21 * matrix.mdy + tdx;
1676
this.mdy = t12 * matrix.mdx + t22 * matrix.mdy + tdy;
1681
/// Translates the matrix with the specified offsets.
1683
[Obsolete("Use TranslateAppend or TranslatePrepend explicitly, because in GDI+ and WPF the defaults are contrary.", true)]
1684
public void Translate(double offsetX, double offsetY)
1686
throw new InvalidOperationException("Temporarily out of order.");
1690
/// Translates the matrix with the specified offsets.
1692
public void TranslateAppend(double offsetX, double offsetY)
1694
Translate(offsetX, offsetY, XMatrixOrder.Append);
1698
/// Translates the matrix with the specified offsets.
1700
public void TranslatePrepend(double offsetX, double offsetY)
1702
Translate(offsetX, offsetY, XMatrixOrder.Prepend);
1706
/// Translates the matrix with the specified offsets.
1708
public void Translate(double offsetX, double offsetY, XMatrixOrder order)
1710
if (order == XMatrixOrder.Append)
1712
this.mdx += offsetX;
1713
this.mdy += offsetY;
1717
this.mdx += offsetX * this.m11 + offsetY * this.m21;
1718
this.mdy += offsetX * this.m12 + offsetY * this.m22;
1723
/// Scales the matrix with the specified scalars.
1725
[Obsolete("Use ScaleAppend or ScalePrepend explicitly, because in GDI+ and WPF the defaults are contrary.", true)]
1726
public void Scale(double scaleX, double scaleY)
1728
throw new InvalidOperationException("Temporarily out of order.");
1732
/// Scales the matrix with the specified scalars.
1734
public void ScaleAppend(double scaleX, double scaleY)
1736
Scale(scaleX, scaleY, XMatrixOrder.Append);
1740
/// Scales the matrix with the specified scalars.
1742
public void ScalePrepend(double scaleX, double scaleY)
1744
Scale(scaleX, scaleY, XMatrixOrder.Prepend);
1748
/// Scales the matrix with the specified scalars.
1750
public void Scale(double scaleX, double scaleY, XMatrixOrder order)
1752
if (order == XMatrixOrder.Append)
1771
/// Scales the matrix with the specified scalar.
1773
[Obsolete("Use ScaleAppend or ScalePrepend explicitly, because in GDI+ and WPF the defaults are contrary.", true)]
1774
public void Scale(double scaleXY)
1776
throw new InvalidOperationException("Temporarily out of order.");
1780
/// Scales the matrix with the specified scalar.
1782
public void ScaleAppend(double scaleXY)
1784
Scale(scaleXY, scaleXY, XMatrixOrder.Append);
1788
/// Scales the matrix with the specified scalar.
1790
public void ScalePrepend(double scaleXY)
1792
Scale(scaleXY, scaleXY, XMatrixOrder.Prepend);
1796
/// Scales the matrix with the specified scalar.
1798
public void Scale(double scaleXY, XMatrixOrder order)
1800
Scale(scaleXY, scaleXY, order);
1804
/// Rotates the matrix with the specified angle.
1806
[Obsolete("Use RotateAppend or RotatePrepend explicitly, because in GDI+ and WPF the defaults are contrary.", true)]
1807
public void Rotate(double angle)
1809
throw new InvalidOperationException("Temporarily out of order.");
1813
/// Rotates the matrix with the specified angle.
1815
public void RotateAppend(double angle)
1817
Rotate(angle, XMatrixOrder.Append);
1821
/// Rotates the matrix with the specified angle.
1823
public void RotatePrepend(double angle)
1825
Rotate(angle, XMatrixOrder.Prepend);
1829
/// Rotates the matrix with the specified angle.
1831
public void Rotate(double angle, XMatrixOrder order)
1833
angle = angle * Calc.Deg2Rad;
1834
double cos = Math.Cos(angle);
1835
double sin = Math.Sin(angle);
1836
if (order == XMatrixOrder.Append)
1838
double t11 = this.m11;
1839
double t12 = this.m12;
1840
double t21 = this.m21;
1841
double t22 = this.m22;
1842
double tdx = this.mdx;
1843
double tdy = this.mdy;
1844
this.m11 = t11 * cos - t12 * sin;
1845
this.m12 = t11 * sin + t12 * cos;
1846
this.m21 = t21 * cos - t22 * sin;
1847
this.m22 = t21 * sin + t22 * cos;
1848
this.mdx = tdx * cos - tdy * sin;
1849
this.mdy = tdx * sin + tdy * cos;
1853
double t11 = this.m11;
1854
double t12 = this.m12;
1855
double t21 = this.m21;
1856
double t22 = this.m22;
1857
this.m11 = t11 * cos + t21 * sin;
1858
this.m12 = t12 * cos + t22 * sin;
1859
this.m21 = -t11 * sin + t21 * cos;
1860
this.m22 = -t12 * sin + t22 * cos;
1865
/// Rotates the matrix with the specified angle at the specified point.
1867
[Obsolete("Use RotateAtAppend or RotateAtPrepend explicitly, because in GDI+ and WPF the defaults are contrary.", true)]
1868
public void RotateAt(double angle, XPoint point)
1870
throw new InvalidOperationException("Temporarily out of order.");
1874
/// Rotates the matrix with the specified angle at the specified point.
1876
public void RotateAtAppend(double angle, XPoint point)
1878
RotateAt(angle, point, XMatrixOrder.Append);
1882
/// Rotates the matrix with the specified angle at the specified point.
1884
public void RotateAtPrepend(double angle, XPoint point)
1886
RotateAt(angle, point, XMatrixOrder.Prepend);
1890
/// Rotates the matrix with the specified angle at the specified point.
1892
public void RotateAt(double angle, XPoint point, XMatrixOrder order)
1895
if (order == XMatrixOrder.Prepend)
1897
this.Translate(point.X, point.Y, order);
1898
this.Rotate(angle, order);
1899
this.Translate(-point.X, -point.Y, order);
1903
throw new NotImplementedException("RotateAt with XMatrixOrder.Append");
1908
/// Shears the matrix with the specified scalars.
1910
[Obsolete("Use ShearAppend or ShearPrepend explicitly, because in GDI+ and WPF the defaults are contrary.", true)]
1911
public void Shear(double shearX, double shearY)
1913
throw new InvalidOperationException("Temporarily out of order.");
1917
/// Shears the matrix with the specified scalars.
1919
public void ShearAppend(double shearX, double shearY)
1921
Shear(shearX, shearY, XMatrixOrder.Append);
1925
/// Shears the matrix with the specified scalars.
1927
public void ShearPrepend(double shearX, double shearY)
1929
Shear(shearX, shearY, XMatrixOrder.Prepend);
1933
/// Shears the matrix with the specified scalars.
1935
public void Shear(double shearX, double shearY, XMatrixOrder order)
1937
double t11 = this.m11;
1938
double t12 = this.m12;
1939
double t21 = this.m21;
1940
double t22 = this.m22;
1941
double tdx = this.mdx;
1942
double tdy = this.mdy;
1943
if (order == XMatrixOrder.Append)
1945
this.m11 += shearX * t12;
1946
this.m12 += shearY * t11;
1947
this.m21 += shearX * t22;
1948
this.m22 += shearY * t21;
1949
this.mdx += shearX * tdy;
1950
this.mdy += shearY * tdx;
1954
this.m11 += shearY * t21;
1955
this.m12 += shearY * t22;
1956
this.m21 += shearX * t11;
1957
this.m22 += shearX * t12;
1963
/// Multiplies all points of the specified array with the this matrix.
1965
public void TransformPoints(System.Drawing.Point[] points)
1968
throw new ArgumentNullException("points");
1973
int count = points.Length;
1974
for (int idx = 0; idx < count; idx++)
1976
double x = points[idx].X;
1977
double y = points[idx].Y;
1978
points[idx].X = (int)(x * this.m11 + y * this.m21 + this.mdx);
1979
points[idx].Y = (int)(x * this.m12 + y * this.m22 + this.mdy);
1986
/// Multiplies all points of the specified array with the this matrix.
1988
public void TransformPoints(System.Windows.Point[] points)
1991
throw new ArgumentNullException("points");
1996
int count = points.Length;
1997
for (int idx = 0; idx < count; idx++)
1999
double x = points[idx].X;
2000
double y = points[idx].Y;
2001
points[idx].X = (int)(x * this.m11 + y * this.m21 + this.mdx);
2002
points[idx].Y = (int)(x * this.m12 + y * this.m22 + this.mdy);
2008
/// Multiplies all points of the specified array with the this matrix.
2010
public void TransformPoints(XPoint[] points)
2013
throw new ArgumentNullException("points");
2015
int count = points.Length;
2016
for (int idx = 0; idx < count; idx++)
2018
double x = points[idx].X;
2019
double y = points[idx].Y;
2020
points[idx].X = x * this.m11 + y * this.m21 + this.mdx;
2021
points[idx].Y = x * this.m12 + y * this.m22 + this.mdy;
2026
/// Multiplies all vectors of the specified array with the this matrix. The translation elements
2027
/// of this matrix (third row) are ignored.
2029
public void TransformVectors(XPoint[] points)
2032
throw new ArgumentNullException("points");
2034
int count = points.Length;
2035
for (int idx = 0; idx < count; idx++)
2037
double x = points[idx].X;
2038
double y = points[idx].Y;
2039
points[idx].X = x * this.m11 + y * this.m21;
2040
points[idx].Y = x * this.m12 + y * this.m22;
2044
public XVector Transform(XVector vector)
2046
return new XVector();
2051
/// Multiplies all vectors of the specified array with the this matrix. The translation elements
2052
/// of this matrix (third row) are ignored.
2054
public void TransformVectors(PointF[] points)
2057
throw new ArgumentNullException("points");
2059
int count = points.Length;
2060
for (int idx = 0; idx < count; idx++)
2062
double x = points[idx].X;
2063
double y = points[idx].Y;
2064
points[idx].X = (float)(x * this.m11 + y * this.m21 + this.mdx);
2065
points[idx].Y = (float)(x * this.m12 + y * this.m22 + this.mdy);
2071
/// Gets an array of double values that represents the elements of this matrix.
2073
public double[] Elements
2077
double[] elements = new double[6];
2078
elements[0] = this.m11;
2079
elements[1] = this.m12;
2080
elements[2] = this.m21;
2081
elements[3] = this.m22;
2082
elements[4] = this.mdx;
2083
elements[5] = this.mdy;
2089
/// Gets a value from the matrix.
2093
get { return this.m11; }
2094
set { this.m11 = value; }
2098
/// Gets a value from the matrix.
2102
get { return this.m12; }
2103
set { this.m12 = value; }
2107
/// Gets a value from the matrix.
2111
get { return this.m21; }
2112
set { this.m21 = value; }
2116
/// Gets a value from the matrix.
2120
get { return this.m22; }
2121
set { this.m22 = value; }
2125
/// Gets the x translation value.
2127
public double OffsetX
2129
get { return this.mdx; }
2130
set { this.mdx = value; }
2134
/// Gets the y translation value.
2136
public double OffsetY
2138
get { return this.mdy; }
2139
set { this.mdy = value; }
2144
/// Converts this matrix to a System.Drawing.Drawing2D.Matrix object.
2146
public System.Drawing.Drawing2D.Matrix ToGdiMatrix()
2148
return new System.Drawing.Drawing2D.Matrix((float)this.m11, (float)this.m12, (float)this.m21, (float)this.m22,
2149
(float)this.mdx, (float)this.mdy);
2155
/// Converts this matrix to a System.Drawing.Drawing2D.Matrix object.
2157
public System.Windows.Media.Matrix ToWpfMatrix()
2159
return new System.Windows.Media.Matrix(this.m11, this.m12, this.m21, this.m22, this.mdx, this.mdy);
2164
/// Indicates whether this matrix is the identity matrix.
2166
public bool IsIdentity
2168
get { return this.m11 == 1 && this.m12 == 0 && this.m21 == 0 && this.m22 == 1 && this.mdx == 0 && this.mdy == 0; }
2172
/// Indicates whether this matrix is invertible, i. e. its determinant is not zero.
2174
public bool IsInvertible
2176
get { return this.m11 * this.m22 - this.m12 * this.m21 != 0; }
2181
/// Explicitly converts a XMatrix to a Matrix.
2183
public static explicit operator System.Drawing.Drawing2D.Matrix(XMatrix matrix)
2185
return new System.Drawing.Drawing2D.Matrix(
2186
(float)matrix.m11, (float)matrix.m12,
2187
(float)matrix.m21, (float)matrix.m22,
2188
(float)matrix.mdx, (float)matrix.mdy);
2194
/// Explicitly converts a XMatrix to a Matrix.
2196
public static explicit operator System.Windows.Media.Matrix(XMatrix matrix)
2198
return new System.Windows.Media.Matrix(
2199
matrix.m11, matrix.m12,
2200
matrix.m21, matrix.m22,
2201
matrix.mdx, matrix.mdy);
2207
/// Implicitly converts a Matrix to an XMatrix.
2209
public static implicit operator XMatrix(System.Drawing.Drawing2D.Matrix matrix)
2211
float[] elements = matrix.Elements;
2212
return new XMatrix(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5]);
2218
/// Implicitly converts a Matrix to an XMatrix.
2220
public static implicit operator XMatrix(System.Windows.Media.Matrix matrix)
2222
return new XMatrix(matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.OffsetX, matrix.OffsetY);
2227
/// Gets an identity matrix.
2229
public static XMatrix Identity
2231
get { return XMatrix.identity; }
2235
/// Determines whether to matrices are equal.
2237
public static bool operator ==(XMatrix matrix1, XMatrix matrix2)
2240
matrix1.m11 == matrix2.m11 &&
2241
matrix1.m12 == matrix2.m12 &&
2242
matrix1.m21 == matrix2.m21 &&
2243
matrix1.m22 == matrix2.m22 &&
2244
matrix1.mdx == matrix2.mdx &&
2245
matrix1.mdy == matrix2.mdy;
2249
/// Determines whether to matrices are not equal.
2251
public static bool operator !=(XMatrix matrix1, XMatrix matrix2)
2253
return !(matrix1 == matrix2);
2256
//private static Matrix CreateIdentity()
2258
// Matrix matrix = new Matrix();
2259
// matrix.SetMatrix(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, MatrixTypes.TRANSFORM_IS_IDENTITY);
2264
double m11, m12, m21, m22, mdx, mdy;
2266
private static XMatrix identity;
2270
/// Some test code to check that there are no typing errors in the formulars.
2272
public static void Test()
2274
XMatrix xm1 = new XMatrix(23, -35, 837, 332, -3, 12);
2275
Matrix m1 = new Matrix(23, -35, 837, 332, -3, 12);
2276
DumpMatrix(xm1, m1);
2277
XMatrix xm2 = new XMatrix(12, 235, 245, 42, 33, -56);
2278
Matrix m2 = xm2.ToMatrix();
2279
DumpMatrix(xm2, m2);
2281
// xm1.Multiply(xm2, XMatrixOrder.Prepend);
2282
// m1.Multiply(m2, MatrixOrder.Append);
2283
xm1.Multiply(xm2, XMatrixOrder.Append);
2284
m1.Multiply(m2, MatrixOrder.Append);
2285
DumpMatrix(xm1, m1);
2287
xm1.Translate(-243, 342, XMatrixOrder.Append);
2288
m1.Translate(-243, 342, MatrixOrder.Append);
2289
DumpMatrix(xm1, m1);
2291
xm1.Scale(-5.66, 7.87);
2292
m1.Scale(-5.66f, 7.87f);
2293
// xm1.Scale(-5.66, 7.87, XMatrixOrder.Prepend);
2294
// m1.Scale(-5.66f, 7.87f, MatrixOrder.Prepend);
2295
DumpMatrix(xm1, m1);
2298
xm1.Rotate(135, XMatrixOrder.Append);
2299
m1.Rotate(135, MatrixOrder.Append);
2300
// xm1.Scale(-5.66, 7.87, XMatrixOrder.Prepend);
2301
// m1.Scale(-5.66f, 7.87f, MatrixOrder.Prepend);
2302
DumpMatrix(xm1, m1);
2304
xm1.RotateAt(177, new XPoint(-3456, 654), XMatrixOrder.Append);
2305
m1.RotateAt(177, new PointF(-3456, 654), MatrixOrder.Append);
2306
DumpMatrix(xm1, m1);
2308
xm1.Shear(0.76, -0.87, XMatrixOrder.Prepend);
2309
m1.Shear(0.76f, -0.87f, MatrixOrder.Prepend);
2310
DumpMatrix(xm1, m1);
2312
xm1 = new XMatrix(23, -35, 837, 332, -3, 12);
2313
m1 = new Matrix(23, -35, 837, 332, -3, 12);
2315
XPoint[] xpoints = new XPoint[3]{new XPoint(23, 10), new XPoint(-27, 120), new XPoint(-87, -55)};
2316
PointF[] points = new PointF[3]{new PointF(23, 10), new PointF(-27, 120), new PointF(-87, -55)};
2318
xm1.TransformPoints(xpoints);
2319
m1.TransformPoints(points);
2323
DumpMatrix(xm1, m1);
2327
static void DumpMatrix(XMatrix xm, Matrix m)
2329
double[] xmv = xm.Elements;
2330
float[] mv = m.Elements;
2331
string message = String.Format("{0:0.###} {1:0.###} {2:0.###} {3:0.###} {4:0.###} {5:0.###}",
2332
xmv[0], xmv[1], xmv[2], xmv[3], xmv[4], xmv[5]);
2333
Console.WriteLine(message);
2334
message = String.Format("{0:0.###} {1:0.###} {2:0.###} {3:0.###} {4:0.###} {5:0.###}",
2335
mv[0], mv[1], mv[2], mv[3], mv[4], mv[5]);
2336
Console.WriteLine(message);
2337
Console.WriteLine();
b'\\ No newline at end of file'