1+ using System ;
2+
13namespace Synercoding . FileFormats . Pdf . Primitives . Matrices
24{
35 /// <summary>
4- /// Class that represents a <see cref="Matrix"/>
6+ /// Struct that represents a <see cref="Matrix"/>
57 /// </summary>
68 /// <remarks>
79 /// Matrix is structured as follows:
810 /// <code>
9- /// a b 0
10- /// c d 0
11- /// e f 1
11+ /// A B 0
12+ /// C D 0
13+ /// E F 1
1214 /// </code>
1315 /// </remarks>
14- public class Matrix
16+ public readonly struct Matrix
1517 {
16- private readonly double [ , ] _matrix = new double [ 3 , 3 ] ;
17-
18- private Matrix ( double [ , ] matrix )
18+ /// <summary>
19+ /// Copy constructor for the <see cref="Matrix"/>
20+ /// </summary>
21+ /// <param name="matrix">The matrix to copy</param>
22+ public Matrix ( Matrix matrix )
1923 {
20- _matrix = matrix ;
24+ A = matrix . A ;
25+ B = matrix . B ;
26+ C = matrix . C ;
27+ D = matrix . D ;
28+ E = matrix . E ;
29+ F = matrix . F ;
2130 }
2231
2332 /// <summary>
@@ -31,72 +40,158 @@ private Matrix(double[,] matrix)
3140 /// <param name="f">The <see cref="F"/> value</param>
3241 public Matrix ( double a , double b , double c , double d , double e , double f )
3342 {
34- _matrix [ 0 , 0 ] = a ;
35- _matrix [ 0 , 1 ] = b ;
36- _matrix [ 0 , 2 ] = 0 ;
37- _matrix [ 1 , 0 ] = c ;
38- _matrix [ 1 , 1 ] = d ;
39- _matrix [ 1 , 2 ] = 0 ;
40- _matrix [ 2 , 0 ] = e ;
41- _matrix [ 2 , 1 ] = f ;
42- _matrix [ 2 , 2 ] = 1 ;
43+ A = a ;
44+ B = b ;
45+ C = c ;
46+ D = d ;
47+ E = e ;
48+ F = f ;
4349 }
4450
4551 /// <summary>
4652 /// The A value
4753 /// </summary>
48- public double A => _matrix [ 0 , 0 ] ;
54+ public double A { get ; }
4955
5056 /// <summary>
5157 /// The B value
5258 /// </summary>
53- public double B => _matrix [ 0 , 1 ] ;
59+ public double B { get ; }
5460
5561 /// <summary>
5662 /// The C value
5763 /// </summary>
58- public double C => _matrix [ 1 , 0 ] ;
64+ public double C { get ; }
5965
6066 /// <summary>
6167 /// The D value
6268 /// </summary>
63- public double D => _matrix [ 1 , 1 ] ;
69+ public double D { get ; }
6470
6571 /// <summary>
6672 /// The E value
6773 /// </summary>
68- public double E => _matrix [ 2 , 0 ] ;
74+ public double E { get ; }
6975
7076 /// <summary>
7177 /// The F value
7278 /// </summary>
73- public double F => _matrix [ 2 , 1 ] ;
79+ public double F { get ; }
80+
81+ /// <summary>
82+ /// Apply a rotation operation on the matrix
83+ /// </summary>
84+ /// <param name="degrees">The amount of degrees to rotate</param>
85+ /// <returns>The new <see cref="Matrix"/></returns>
86+ public Matrix Rotate ( double degrees )
87+ => Multiply ( CreateRotationMatrix ( degrees ) ) ;
88+
89+ /// <summary>
90+ /// Apply a scale operation on the matrix
91+ /// </summary>
92+ /// <param name="x">The X amount to scale</param>
93+ /// <param name="y">The Y amount to scale</param>
94+ /// <returns>The new <see cref="Matrix"/></returns>
95+ public Matrix Scale ( double x , double y )
96+ => Multiply ( CreateScaleMatrix ( x , y ) ) ;
97+
98+ /// <summary>
99+ /// Apply a skew operation on the matrix
100+ /// </summary>
101+ /// <param name="a">The amount of degrees to skew (top left direction)</param>
102+ /// <param name="b">The amount of degrees to skew (bottom right direction)</param>
103+ /// <returns>The new <see cref="Matrix"/></returns>
104+ public Matrix Skew ( double a , double b )
105+ => Multiply ( CreateSkewMatrix ( a , b ) ) ;
106+
107+ /// <summary>
108+ /// Apply a translation operation on the matrix
109+ /// </summary>
110+ /// <param name="x">The X distance to translate</param>
111+ /// <param name="y">The Y distance to translate</param>
112+ /// <returns>The new <see cref="Matrix"/></returns>
113+ public Matrix Translate ( double x , double y )
114+ => Multiply ( CreateTranslationMatrix ( x , y ) ) ;
115+
116+ /// <summary>
117+ /// Multiply matrix <paramref name="m1"/> with <paramref name="m2"/>
118+ /// </summary>
119+ /// <param name="m1">The left side of the matrix multiplication</param>
120+ /// <param name="m2">The right side of the matrix multiplication</param>
121+ /// <returns>The new <see cref="Matrix"/></returns>
122+ public static Matrix operator * ( Matrix m1 , Matrix m2 )
123+ => m1 . Multiply ( m2 ) ;
74124
75125 /// <summary>
76126 /// Multiply this matrix with <paramref name="other"/>
77127 /// </summary>
78- /// <param name="other">The other matrix to multiply by </param>
128+ /// <param name="other">The matrix to multiply with </param>
79129 /// <returns>The new <see cref="Matrix"/></returns>
80- public Matrix Multiply ( Matrix other )
130+ public Matrix Multiply ( in Matrix other )
81131 {
82- var a = _matrix ;
83- var b = other . _matrix ;
84- var resultMatrix = new double [ 3 , 3 ] ;
85-
86- for ( int row = 0 ; row < 3 ; row ++ )
87- {
88- for ( int column = 0 ; column < 3 ; column ++ )
89- {
90- double temp = 0 ;
91- for ( int currentColumn = 0 ; currentColumn < 3 ; currentColumn ++ )
92- {
93- temp += a [ row , currentColumn ] * b [ currentColumn , column ] ;
94- }
95- resultMatrix [ row , column ] = temp ;
96- }
97- }
98-
99- return new Matrix ( resultMatrix ) ;
132+ double a , b , c , d , e , f ;
133+
134+ a = ( this . A * other . A ) + ( this . B * other . C ) ;
135+ b = ( this . A * other . B ) + ( this . B * other . D ) ;
136+ c = ( this . C * other . A ) + ( this . D * other . C ) ;
137+ d = ( this . C * other . B ) + ( this . D * other . D ) ;
138+ e = ( this . E * other . A ) + ( this . F * other . C ) + other . E ;
139+ f = ( this . E * other . B ) + ( this . F * other . D ) + other . F ;
140+
141+ return new Matrix ( a , b , c , d , e , f ) ;
142+ }
143+
144+ /// <summary>
145+ /// Create a matrix used for rotation
146+ /// </summary>
147+ /// <param name="degree">The amount of degrees to rotate by</param>
148+ /// <returns>A rotated matrix</returns>
149+ public static Matrix CreateRotationMatrix ( double degree )
150+ => new Matrix (
151+ Math . Cos ( _degreeToRad ( degree ) ) , Math . Sin ( _degreeToRad ( degree ) ) * - 1 ,
152+ Math . Sin ( _degreeToRad ( degree ) ) , Math . Cos ( _degreeToRad ( degree ) ) ,
153+ 0 , 0 ) ;
154+
155+ /// <summary>
156+ /// Create a matrix used for scaling
157+ /// </summary>
158+ /// <param name="x">The X scale</param>
159+ /// <param name="y">The Y scale</param>
160+ /// <returns>A scaled matrix</returns>
161+ public static Matrix CreateScaleMatrix ( double x , double y )
162+ => new Matrix (
163+ x , 0 ,
164+ 0 , y ,
165+ 0 , 0 ) ;
166+
167+ /// <summary>
168+ /// Create a matrix used for skewing
169+ /// </summary>
170+ /// <param name="a">The amount of degree to skew the top left direction</param>
171+ /// <param name="b">The amount of degree to skew the bottom right direction</param>
172+ /// <returns>A skewed matrix</returns>
173+ public static Matrix CreateSkewMatrix ( double a , double b )
174+ => new Matrix (
175+ 1 , Math . Tan ( _degreeToRad ( a ) ) ,
176+ Math . Tan ( _degreeToRad ( b ) ) , 1 ,
177+ 0 , 0 ) ;
178+
179+ /// <summary>
180+ /// Create a matrix used for translation
181+ /// </summary>
182+ /// <param name="x">The amount of X translation</param>
183+ /// <param name="y">The amount of Y translation</param>
184+ /// <returns>A matrix representing a translation</returns>
185+ public static Matrix CreateTranslationMatrix ( double x , double y )
186+ => new Matrix (
187+ 1 , 0 ,
188+ 0 , 1 ,
189+ x , y ) ;
190+
191+ private static double _degreeToRad ( double degree )
192+ {
193+ return degree * Math . PI / 180 ;
100194 }
101195 }
196+
102197}
0 commit comments