1 /**
2 * libdmtx - Data Matrix Encoding/Decoding Library
3 * Copyright 2008, 2009 Mike Laughton. All rights reserved.
4 * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved.
5 *
6 * See LICENSE file in the main project directory for full
7 * terms of use and distribution.
8 *
9 * Contact:
10 * Vadim A. Misbakh-Soloviov <dmtx@mva.name>
11 * Mike Laughton <mike@dragonflylogic.com>
12 *
13 * \file dmtxmatrix3.c
14 * \brief 2D Matrix (3x3) math
15 */
16
17 /**
18 * \brief Copy matrix contents
19 * \param m0 Copy target
20 * \param m1 Copy source
21 * \return void
22 */
23 extern void
dmtxMatrix3Copy(DmtxMatrix3 m0,DmtxMatrix3 m1)24 dmtxMatrix3Copy(DmtxMatrix3 m0, DmtxMatrix3 m1)
25 {
26 memcpy(m0, m1, sizeof(DmtxMatrix3));
27 }
28
29 /**
30 * \brief Generate identity transformation matrix
31 * \param m Generated matrix
32 * \return void
33 *
34 * | 1 0 0 |
35 * m = | 0 1 0 |
36 * | 0 0 1 |
37 *
38 * Transform "m"
39 * (doesn't change anything)
40 * |\
41 * (0,1) x----o +--+ \ (0,1) x----o
42 * | | | \ | |
43 * | | | / | |
44 * +----* +--+ / +----*
45 * (0,0) (1,0) |/ (0,0) (1,0)
46 *
47 */
48 extern void
dmtxMatrix3Identity(DmtxMatrix3 m)49 dmtxMatrix3Identity(DmtxMatrix3 m)
50 {
51 static DmtxMatrix3 tmp = { {1, 0, 0},
52 {0, 1, 0},
53 {0, 0, 1} };
54 dmtxMatrix3Copy(m, tmp);
55 }
56
57 /**
58 * \brief Generate translate transformation matrix
59 * \param m Generated matrix
60 * \param tx
61 * \param ty
62 * \return void
63 *
64 * | 1 0 0 |
65 * m = | 0 1 0 |
66 * | tx ty 1 |
67 *
68 * Transform "m"
69 * _____ (tx,1+ty) x----o (1+tx,1+ty)
70 * \ | | |
71 * (0,1) x----o / | (0,1) +-|--+ |
72 * | | / /\| | +----* (1+tx,ty)
73 * | | \ / | |
74 * +----* ` +----+
75 * (0,0) (1,0) (0,0) (1,0)
76 *
77 */
dmtxMatrix3Translate(DmtxMatrix3 m,double tx,double ty)78 void dmtxMatrix3Translate(DmtxMatrix3 m, double tx, double ty)
79 {
80 dmtxMatrix3Identity(m);
81 m[2][0] = tx;
82 m[2][1] = ty;
83 }
84
85 /**
86 * \brief Generate rotate transformation
87 * \param m Generated matrix
88 * \param angle
89 * \return void
90 *
91 * | cos(a) sin(a) 0 |
92 * m = | -sin(a) cos(a) 0 |
93 * | 0 0 1 |
94 * o
95 * Transform "m" / `
96 * ___ / `
97 * (0,1) x----o |/ \ x * (cos(a),sin(a))
98 * | | '-- | ` /
99 * | | ___/ ` / a
100 * +----* `+ - - - - - -
101 * (0,0) (1,0) (0,0)
102 *
103 */
104 extern void
dmtxMatrix3Rotate(DmtxMatrix3 m,double angle)105 dmtxMatrix3Rotate(DmtxMatrix3 m, double angle)
106 {
107 double sinAngle, cosAngle;
108
109 sinAngle = sin(angle);
110 cosAngle = cos(angle);
111
112 dmtxMatrix3Identity(m);
113 m[0][0] = cosAngle;
114 m[0][1] = sinAngle;
115 m[1][0] = -sinAngle;
116 m[1][1] = cosAngle;
117 }
118
119 /**
120 * \brief Generate scale transformation matrix
121 * \param m Generated matrix
122 * \param sx
123 * \param sy
124 * \return void
125 *
126 * | sx 0 0 |
127 * m = | 0 sy 0 |
128 * | 0 0 1 |
129 *
130 * Transform "m"
131 * _____ (0,sy) x-------o (sx,sy)
132 * \ | | |
133 * (0,1) x----o / | (0,1) +----+ |
134 * | | / /\| | | |
135 * | | \ / | | |
136 * +----* ` +----+--*
137 * (0,0) (1,0) (0,0) (sx,0)
138 *
139 */
140 extern void
dmtxMatrix3Scale(DmtxMatrix3 m,double sx,double sy)141 dmtxMatrix3Scale(DmtxMatrix3 m, double sx, double sy)
142 {
143 dmtxMatrix3Identity(m);
144 m[0][0] = sx;
145 m[1][1] = sy;
146 }
147
148 /**
149 * \brief Generate shear transformation matrix
150 * \param m Generated matrix
151 * \param shx
152 * \param shy
153 * \return void
154 *
155 * | 0 shy 0 |
156 * m = | shx 0 0 |
157 * | 0 0 1 |
158 */
159 extern void
dmtxMatrix3Shear(DmtxMatrix3 m,double shx,double shy)160 dmtxMatrix3Shear(DmtxMatrix3 m, double shx, double shy)
161 {
162 dmtxMatrix3Identity(m);
163 m[1][0] = shx;
164 m[0][1] = shy;
165 }
166
167 /**
168 * \brief Generate top line skew transformation
169 * \param m
170 * \param b0
171 * \param b1
172 * \param sz
173 * \return void
174 *
175 * | b1/b0 0 (b1-b0)/(sz*b0) |
176 * m = | 0 sz/b0 0 |
177 * | 0 0 1 |
178 *
179 * (sz,b1) o
180 * /| Transform "m"
181 * / |
182 * / | +--+
183 * / | | |
184 * (0,b0) x | | |
185 * | | +-+ +-+
186 * (0,sz) +----+ \ / (0,sz) x----o
187 * | | \ / | |
188 * | | \/ | |
189 * +----+ +----+
190 * (0,0) (sz,0) (0,0) (sz,0)
191 *
192 */
193 extern void
dmtxMatrix3LineSkewTop(DmtxMatrix3 m,double b0,double b1,double sz)194 dmtxMatrix3LineSkewTop(DmtxMatrix3 m, double b0, double b1, double sz)
195 {
196 assert(b0 >= DmtxAlmostZero);
197
198 dmtxMatrix3Identity(m);
199 m[0][0] = b1/b0;
200 m[1][1] = sz/b0;
201 m[0][2] = (b1 - b0)/(sz*b0);
202 }
203
204 /**
205 * \brief Generate top line skew transformation (inverse)
206 * \param m
207 * \param b0
208 * \param b1
209 * \param sz
210 * \return void
211 */
212 extern void
dmtxMatrix3LineSkewTopInv(DmtxMatrix3 m,double b0,double b1,double sz)213 dmtxMatrix3LineSkewTopInv(DmtxMatrix3 m, double b0, double b1, double sz)
214 {
215 assert(b1 >= DmtxAlmostZero);
216
217 dmtxMatrix3Identity(m);
218 m[0][0] = b0/b1;
219 m[1][1] = b0/sz;
220 m[0][2] = (b0 - b1)/(sz*b1);
221 }
222
223 /**
224 * \brief Generate side line skew transformation
225 * \param m
226 * \param b0
227 * \param b1
228 * \param sz
229 * \return void
230 */
231 extern void
dmtxMatrix3LineSkewSide(DmtxMatrix3 m,double b0,double b1,double sz)232 dmtxMatrix3LineSkewSide(DmtxMatrix3 m, double b0, double b1, double sz)
233 {
234 assert(b0 >= DmtxAlmostZero);
235
236 dmtxMatrix3Identity(m);
237 m[0][0] = sz/b0;
238 m[1][1] = b1/b0;
239 m[1][2] = (b1 - b0)/(sz*b0);
240 }
241
242 /**
243 * \brief Generate side line skew transformation (inverse)
244 * \param m
245 * \param b0
246 * \param b1
247 * \param sz
248 * \return void
249 */
250 extern void
dmtxMatrix3LineSkewSideInv(DmtxMatrix3 m,double b0,double b1,double sz)251 dmtxMatrix3LineSkewSideInv(DmtxMatrix3 m, double b0, double b1, double sz)
252 {
253 assert(b1 >= DmtxAlmostZero);
254
255 dmtxMatrix3Identity(m);
256 m[0][0] = b0/sz;
257 m[1][1] = b0/b1;
258 m[1][2] = (b0 - b1)/(sz*b1);
259 }
260
261 /**
262 * \brief Multiply two matrices to create a third
263 * \param mOut
264 * \param m0
265 * \param m1
266 * \return void
267 */
268 extern void
dmtxMatrix3Multiply(DmtxMatrix3 mOut,DmtxMatrix3 m0,DmtxMatrix3 m1)269 dmtxMatrix3Multiply(DmtxMatrix3 mOut, DmtxMatrix3 m0, DmtxMatrix3 m1)
270 {
271 int i, j, k;
272 double val;
273
274 for(i = 0; i < 3; i++) {
275 for(j = 0; j < 3; j++) {
276 val = 0.0;
277 for(k = 0; k < 3; k++) {
278 val += m0[i][k] * m1[k][j];
279 }
280 mOut[i][j] = val;
281 }
282 }
283 }
284
285 /**
286 * \brief Multiply two matrices in place
287 * \param m0
288 * \param m1
289 * \return void
290 */
291 extern void
dmtxMatrix3MultiplyBy(DmtxMatrix3 m0,DmtxMatrix3 m1)292 dmtxMatrix3MultiplyBy(DmtxMatrix3 m0, DmtxMatrix3 m1)
293 {
294 DmtxMatrix3 mTmp;
295
296 dmtxMatrix3Copy(mTmp, m0);
297 dmtxMatrix3Multiply(m0, mTmp, m1);
298 }
299
300 /**
301 * \brief Multiply vector and matrix
302 * \param vOut Vector (output)
303 * \param vIn Vector (input)
304 * \param m Matrix to be multiplied
305 * \return DmtxPass | DmtxFail
306 */
307 extern int
dmtxMatrix3VMultiply(DmtxVector2 * vOut,DmtxVector2 * vIn,DmtxMatrix3 m)308 dmtxMatrix3VMultiply(DmtxVector2 *vOut, DmtxVector2 *vIn, DmtxMatrix3 m)
309 {
310 double w;
311
312 w = vIn->X*m[0][2] + vIn->Y*m[1][2] + m[2][2];
313 if(fabs(w) <= DmtxAlmostZero) {
314 vOut->X = FLT_MAX;
315 vOut->Y = FLT_MAX;
316 return DmtxFail;
317 }
318
319 vOut->X = (vIn->X*m[0][0] + vIn->Y*m[1][0] + m[2][0])/w;
320 vOut->Y = (vIn->X*m[0][1] + vIn->Y*m[1][1] + m[2][1])/w;
321
322 return DmtxPass;
323 }
324
325 /**
326 * \brief Multiply vector and matrix in place
327 * \param v Vector (input and output)
328 * \param m Matrix to be multiplied
329 * \return DmtxPass | DmtxFail
330 */
331 extern int
dmtxMatrix3VMultiplyBy(DmtxVector2 * v,DmtxMatrix3 m)332 dmtxMatrix3VMultiplyBy(DmtxVector2 *v, DmtxMatrix3 m)
333 {
334 int success;
335 DmtxVector2 vOut;
336
337 success = dmtxMatrix3VMultiply(&vOut, v, m);
338 *v = vOut;
339
340 return success;
341 }
342
343 /**
344 * \brief Print matrix contents to STDOUT
345 * \param m
346 * \return void
347 */
348 extern void
dmtxMatrix3Print(DmtxMatrix3 m)349 dmtxMatrix3Print(DmtxMatrix3 m)
350 {
351 fprintf(stdout, "%8.8f\t%8.8f\t%8.8f\n", m[0][0], m[0][1], m[0][2]);
352 fprintf(stdout, "%8.8f\t%8.8f\t%8.8f\n", m[1][0], m[1][1], m[1][2]);
353 fprintf(stdout, "%8.8f\t%8.8f\t%8.8f\n", m[2][0], m[2][1], m[2][2]);
354 fprintf(stdout, "\n");
355 }
356