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