OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [mw/] [src/] [contrib/] [GPL/] [tpcal/] [transform.c] - Blame information for rev 673

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 673 markom
/*
2
 * transform.c
3
 * Calculate coefficients for tranformation equation
4
 * Copyright (C) 1999 Bradley D. LaRonde <brad@ltc.com>
5
 *
6
 * This program is free software; you may redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
#include "windows.h"
21
#include "mou_tp.h"
22
#include "transform.h"
23
 
24
int CalcTransformationCoefficientsSimple(CALIBRATION_PAIRS *pcp, TRANSFORMATION_COEFFICIENTS *ptc)
25
{
26
        /*
27
         * This is my simple way of calculating some of the coefficients -
28
         * enough to do a simple scale and translate.
29
         * It ignores any dependencies between axiis (rotation and/or skew).
30
         */
31
 
32
        int min_screen_x = pcp->ul.screen.x;
33
        int min_screen_y = pcp->ul.screen.y;
34
        int max_screen_x = pcp->lr.screen.x;
35
        int max_screen_y = pcp->lr.screen.y;
36
 
37
        int min_device_x = pcp->ul.device.x;
38
        int min_device_y = pcp->ul.device.y;
39
        int max_device_x = pcp->lr.device.x;
40
        int max_device_y = pcp->lr.device.y;
41
 
42
        ptc->s = (1 << 16);
43
        ptc->a = ptc->s * (min_screen_x - max_screen_x) / (min_device_x - max_device_x);
44
        ptc->b = 0;
45
        ptc->c = (ptc->a * -min_device_x) + (ptc->s * min_screen_x);
46
        ptc->d = 0;
47
        ptc->e = ptc->s * (min_screen_y - max_screen_y) / (min_device_y - max_device_y);
48
        ptc->f = (ptc->e * -min_device_y) + (ptc->s * min_screen_y);
49
 
50
        return 0;
51
}
52
 
53
int CalcTransformationCoefficientsBetter(CALIBRATION_PAIRS *pcp, TRANSFORMATION_COEFFICIENTS *ptc)
54
{
55
        /*
56
         * Janus (the man) <janus@place.org> came up with a much better way
57
         * to figure the coefficients.  His original algorithm was written in MOO.
58
         * Jay Carlson <> did the translation to C.
59
         * This way takes into account inter-axis dependency like rotation and skew.
60
         */
61
 
62
        double vector[3][2] =
63
        {
64
                {pcp->ul.screen.x, pcp->ul.screen.y},
65
                {pcp->ur.screen.x, pcp->ur.screen.y},
66
                {pcp->lr.screen.x, pcp->lr.screen.y}
67
        };
68
 
69
        double matrix[3][3] =
70
        {
71
                {pcp->ul.device.x, pcp->ul.device.y, 1.0},
72
                {pcp->ur.device.x, pcp->ur.device.y, 1.0},
73
                {pcp->lr.device.x, pcp->lr.device.y, 1.0}
74
        };
75
 
76
        int i, j, r, k;
77
        double p, q;
78
 
79
        for (i = 0; i < 3; i++) {
80
          p = matrix[i][i];
81
 
82
          for (j = 0; j < 3; j++) {
83
               matrix[i][j] = matrix[i][j] / p;
84
          }
85
 
86
          for (j = 0; j < 2; j++) {
87
               vector[i][j] = vector[i][j] / p;
88
          }
89
 
90
          for (r = 0; r < 3; r++) {
91
               if (r != i) {
92
                    q = matrix[r][i];
93
 
94
                    matrix[r][i] = 0.0;
95
 
96
                    for (k = i + 1; k < 3; k++) {
97
                         matrix[r][k] = matrix[r][k] - (q * matrix[i][k]);
98
                    }
99
 
100
                    for (k = 0; k < 2; k++) {
101
                         vector[r][k] = vector[r][k] - (q * vector[i][k]);
102
                    }
103
               }
104
          }
105
        }
106
 
107
        ptc->s = 1 << 16;
108
        ptc->a = vector[0][0] * ptc->s;
109
        ptc->b = vector[1][0] * ptc->s;
110
        ptc->c = vector[2][0] * ptc->s;
111
        ptc->d = vector[0][1] * ptc->s;
112
        ptc->e = vector[1][1] * ptc->s;
113
        ptc->f = vector[2][1] * ptc->s;
114
 
115
        return 0;
116
}
117
 
118
int CalcTransformationCoefficientsEvenBetter(CALIBRATION_PAIRS *pcp, TRANSFORMATION_COEFFICIENTS *ptc)
119
{
120
        /*
121
         * Mike Klar <> added the an xy term to correct for trapezoidial distortion.
122
         */
123
 
124
        double vector[4][2] =
125
        {
126
                {pcp->ul.screen.x, pcp->ul.screen.y},
127
                {pcp->ur.screen.x, pcp->ur.screen.y},
128
                {pcp->lr.screen.x, pcp->lr.screen.y},
129
                {pcp->ll.screen.x, pcp->ll.screen.y}
130
        };
131
 
132
        double matrix[4][4] =
133
        {
134
                {pcp->ul.device.x, pcp->ul.device.x * pcp->ul.device.y, pcp->ul.device.y, 1.0},
135
                {pcp->ur.device.x, pcp->ur.device.x * pcp->ur.device.y, pcp->ur.device.y, 1.0},
136
                {pcp->lr.device.x, pcp->lr.device.x * pcp->lr.device.y, pcp->lr.device.y, 1.0},
137
                {pcp->ll.device.x, pcp->ll.device.x * pcp->ll.device.y, pcp->ll.device.y, 1.0}
138
        };
139
 
140
        int i, j, r, k;
141
        double p, q;
142
 
143
        for (i = 0; i < 4; i++) {
144
          p = matrix[i][i];
145
 
146
          for (j = 0; j < 4; j++) {
147
               matrix[i][j] = matrix[i][j] / p;
148
          }
149
 
150
          for (j = 0; j < 2; j++) {
151
               vector[i][j] = vector[i][j] / p;
152
          }
153
 
154
          for (r = 0; r < 4; r++) {
155
               if (r != i) {
156
                    q = matrix[r][i];
157
 
158
                    matrix[r][i] = 0.0;
159
 
160
                    for (k = i + 1; k < 4; k++) {
161
                         matrix[r][k] = matrix[r][k] - (q * matrix[i][k]);
162
                    }
163
 
164
                    for (k = 0; k < 2; k++) {
165
                         vector[r][k] = vector[r][k] - (q * vector[i][k]);
166
                    }
167
               }
168
          }
169
        }
170
 
171
        /* I just drop the xy coefficient since it is so small. */
172
        ptc->s = 1 << 16;
173
        ptc->a = vector[0][0] * ptc->s;
174
        ptc->b = vector[2][0] * ptc->s;
175
        ptc->c = vector[3][0] * ptc->s;
176
        ptc->d = vector[0][1] * ptc->s;
177
        ptc->e = vector[2][1] * ptc->s;
178
        ptc->f = vector[3][1] * ptc->s;
179
 
180
        return 0;
181
}
182
 
183
int CalcTransformationCoefficientsBest(CALIBRATION_PAIRS *pcp, TRANSFORMATION_COEFFICIENTS *ptc)
184
{
185
        /*
186
         * Mike Klar <> came up with a best-fit solution that works best.
187
         */
188
 
189
        const int first_point = 0;
190
        const int last_point = 4;
191
        int i;
192
 
193
        double Sx=0, Sy=0, Sxy=0, Sx2=0, Sy2=0, Sm=0, Sn=0, Smx=0, Smy=0, Snx=0, Sny=0, S=0;
194
        double t1, t2, t3, t4, t5, t6, q;
195
 
196
        /* cast the struct to an array - hacky but ok */
197
        CALIBRATION_PAIR *cp = (CALIBRATION_PAIR*)pcp;
198
 
199
        /*
200
         * Do a best-fit calculation for as many points as we want, as
201
         * opposed to an exact fit, which can only be done against 3 points.
202
         *
203
         * The following calculates various sumnations of the sample data
204
         * coordinates.  For purposes of naming convention, x and y
205
         * refer to device coordinates, m and n refer to screen
206
         * coordinates, S means sumnation.  x2 and y2 are x squared and
207
         * y squared, S by itself is just a count of points (= sumnation
208
         * of 1).
209
         */
210
 
211
        for (i = first_point; i < last_point + 1; i++) {
212
                Sx += cp[i].device.x;
213
                Sy += cp[i].device.y;
214
                Sxy += cp[i].device.x * cp[i].device.y;
215
                Sx2 += cp[i].device.x * cp[i].device.x;
216
                Sy2 += cp[i].device.y * cp[i].device.y;
217
                Sm += cp[i].screen.x;
218
                Sn += cp[i].screen.y;
219
                Smx += cp[i].screen.x * cp[i].device.x;
220
                Smy += cp[i].screen.x * cp[i].device.y;
221
                Snx += cp[i].screen.y * cp[i].device.x;
222
                Sny += cp[i].screen.y * cp[i].device.y;
223
                S += 1;
224
        }
225
 
226
#if 0
227
        printf("%f, %f, %f, %f, "
228
               "%f, %f, %f, %f, "
229
               "%f, %f, %f, %f\n",
230
                Sx, Sy, Sxy, Sx2, Sy2, Sm, Sn, Smx, Smy, Snx, Sny, S);
231
#endif
232
 
233
        /*
234
         * Next we solve the simultaneous equations (these equations minimize
235
         * the sum of the square of the m and n error):
236
         *
237
         *    | Sx2 Sxy Sx |   | a d |   | Smx Snx |
238
         *    | Sxy Sy2 Sy | * | b e | = | Smy Sny |
239
         *    | Sx  Sy  S  |   | c f |   | Sm  Sn  |
240
         *
241
         * We could do the matrix solution in code, but that leads to several
242
         * divide by 0 conditions for cases where the data is truly solvable
243
         * (becuase those terms cancel out of the final solution), so we just
244
         * give the final solution instread.  t1 through t6 and q are just
245
         * convenience variables for terms that are used repeatedly - we could
246
         * calculate each of the coefficients directly at this point with a
247
         * nasty long equation, but that would be extremly inefficient.
248
         */
249
 
250
        t1 = Sxy * Sy - Sx * Sy2;
251
        t2 = Sxy * Sx - Sx2 * Sy;
252
        t3 = Sx2 * Sy2 - Sxy * Sxy;
253
        t4 = Sy2 * S - Sy * Sy;
254
        t5 = Sx * Sy - Sxy * S;
255
        t6 = Sx2 * S - Sx * Sx;
256
 
257
        q = t1 * Sx + t2 * Sy + t3 * S;
258
 
259
        /*
260
         * If q = 0, then the data is unsolvable.  This should only happen
261
         * when there are not enough unique data points (less than 3 points
262
         * will give infinite solutions), or at least one of the
263
         * coefficients is infinite (which would indicate that the same
264
         * device point represents an infinite area of the screen, probably
265
         * as a result of the same device data point given for 2 different
266
         * screen points).  The first condition should never happen, since
267
         * we're always feeding in at least 3 unique screen points.  The
268
         * second condition would probably indicate bad user input or the
269
         * touchpanel device returning bad data.
270
         */
271
 
272
        if (q == 0)
273
                return -1;
274
 
275
        ptc->s = 1 << 16;
276
        ptc->a = ((t4 * Smx + t5 * Smy + t1 * Sm) / q + 0.5/65536) * ptc->s;
277
        ptc->b = ((t5 * Smx + t6 * Smy + t2 * Sm) / q + 0.5/65536) * ptc->s;
278
        ptc->c = ((t1 * Smx + t2 * Smy + t3 * Sm) / q + 0.5/65536) * ptc->s;
279
        ptc->d = ((t4 * Snx + t5 * Sny + t1 * Sn) / q + 0.5/65536) * ptc->s;
280
        ptc->e = ((t5 * Snx + t6 * Sny + t2 * Sn) / q + 0.5/65536) * ptc->s;
281
        ptc->f = ((t1 * Snx + t2 * Sny + t3 * Sn) / q + 0.5/65536) * ptc->s;
282
 
283
        /*
284
         * Finally, we check for overflow on the fp to integer conversion,
285
         * which would also probably indicate bad data.
286
         */
287
 
288
        if ( (ptc->a == 0x80000000) || (ptc->b == 0x80000000) ||
289
             (ptc->c == 0x80000000) || (ptc->d == 0x80000000) ||
290
             (ptc->e == 0x80000000) || (ptc->f == 0x80000000) )
291
                return -1;
292
 
293
        return 0;
294
}
295
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.