1
+ using System ;
2
+
1
3
namespace Synercoding . FileFormats . Pdf . Primitives . Matrices
2
4
{
3
5
/// <summary>
4
- /// Class that represents a <see cref="Matrix"/>
6
+ /// Struct that represents a <see cref="Matrix"/>
5
7
/// </summary>
6
8
/// <remarks>
7
9
/// Matrix is structured as follows:
8
10
/// <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
12
14
/// </code>
13
15
/// </remarks>
14
- public class Matrix
16
+ public readonly struct Matrix
15
17
{
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 )
19
23
{
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 ;
21
30
}
22
31
23
32
/// <summary>
@@ -31,72 +40,158 @@ private Matrix(double[,] matrix)
31
40
/// <param name="f">The <see cref="F"/> value</param>
32
41
public Matrix ( double a , double b , double c , double d , double e , double f )
33
42
{
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 ;
43
49
}
44
50
45
51
/// <summary>
46
52
/// The A value
47
53
/// </summary>
48
- public double A => _matrix [ 0 , 0 ] ;
54
+ public double A { get ; }
49
55
50
56
/// <summary>
51
57
/// The B value
52
58
/// </summary>
53
- public double B => _matrix [ 0 , 1 ] ;
59
+ public double B { get ; }
54
60
55
61
/// <summary>
56
62
/// The C value
57
63
/// </summary>
58
- public double C => _matrix [ 1 , 0 ] ;
64
+ public double C { get ; }
59
65
60
66
/// <summary>
61
67
/// The D value
62
68
/// </summary>
63
- public double D => _matrix [ 1 , 1 ] ;
69
+ public double D { get ; }
64
70
65
71
/// <summary>
66
72
/// The E value
67
73
/// </summary>
68
- public double E => _matrix [ 2 , 0 ] ;
74
+ public double E { get ; }
69
75
70
76
/// <summary>
71
77
/// The F value
72
78
/// </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 ) ;
74
124
75
125
/// <summary>
76
126
/// Multiply this matrix with <paramref name="other"/>
77
127
/// </summary>
78
- /// <param name="other">The other matrix to multiply by </param>
128
+ /// <param name="other">The matrix to multiply with </param>
79
129
/// <returns>The new <see cref="Matrix"/></returns>
80
- public Matrix Multiply ( Matrix other )
130
+ public Matrix Multiply ( in Matrix other )
81
131
{
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 ;
100
194
}
101
195
}
196
+
102
197
}
0 commit comments