-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcalibrate.cpp
363 lines (319 loc) · 13.7 KB
/
calibrate.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/*
*
* Copyright (c) 2001, Carlos E. Vidales. All rights reserved.
*
* This sample program was written and put in the public domain
* by Carlos E. Vidales. The program is provided "as is"
* without warranty of any kind, either expressed or implied.
* If you choose to use the program within your own products
* you do so at your own risk, and assume the responsibility
* for servicing, repairing or correcting the program should
* it prove defective in any manner.
* You may copy and distribute the program's source code in any
* medium, provided that you also include in each copy an
* appropriate copyright notice and disclaimer of warranty.
* You may also modify this program and distribute copies of
* it provided that you include prominent notices stating
* that you changed the file(s) and the date of any change,
* and that you do not charge any royalties or licenses for
* its use.
*
*
*
* File Name: calibrate.c
*
*
* This file contains functions that implement calculations
* necessary to obtain calibration factors for a touch screen
* that suffers from multiple distortion effects: namely,
* translation, scaling and rotation.
*
* The following set of equations represent a valid display
* point given a corresponding set of touch screen points:
*
*
* /- -\
* /- -\ /- -\ | |
* | | | | | Xs |
* | Xd | | A B C | | |
* | | = | | * | Ys |
* | Yd | | D E F | | |
* | | | | | 1 |
* \- -/ \- -/ | |
* \- -/
*
*
* where:
*
* (Xd,Yd) represents the desired display point
* coordinates,
*
* (Xs,Ys) represents the available touch screen
* coordinates, and the matrix
*
* /- -\
* |A,B,C|
* |D,E,F| represents the factors used to translate
* \- -/ the available touch screen point values
* into the corresponding display
* coordinates.
*
*
* Note that for practical considerations, the utilitities
* within this file do not use the matrix coefficients as
* defined above, but instead use the following
* equivalents, since floating point math is not used:
*
* A = An/Divider
* B = Bn/Divider
* C = Cn/Divider
* D = Dn/Divider
* E = En/Divider
* F = Fn/Divider
*
*
*
* The functions provided within this file are:
*
* setCalibrationMatrix() - calculates the set of factors
* in the above equation, given
* three sets of test points.
* getDisplayPoint() - returns the actual display
* coordinates, given a set of
* touch screen coordinates.
* translateRawScreenCoordinates() - helper function to transform
* raw screen points into values
* scaled to the desired display
* resolution.
*
*
*/
#define _CALIBRATE_C_
/****************************************************/
/* */
/* Included files */
/* */
/****************************************************/
#include "calibrate.h"
/****************************************************/
/* */
/* Local Definitions and macros */
/* */
/****************************************************/
/****************************************************/
/* */
/* Global variables */
/* */
/****************************************************/
/****************************************************/
/* */
/* Forward Declaration of local functions */
/* */
/****************************************************/
/**********************************************************************
*
* Function: setCalibrationMatrix()
*
* Description: Calling this function with valid input data
* in the display and screen input arguments
* causes the calibration factors between the
* screen and display points to be calculated,
* and the output argument - matrixPtr - to be
* populated.
*
* This function needs to be called only when new
* calibration factors are desired.
*
*
* Argument(s): displayPtr (input) - Pointer to an array of three
* sample, reference points.
* screenPtr (input) - Pointer to the array of touch
* screen points corresponding
* to the reference display points.
* matrixPtr (output) - Pointer to the calibration
* matrix computed for the set
* of points being provided.
*
*
* From the article text, recall that the matrix coefficients are
* resolved to be the following:
*
*
* Divider = (Xs0 - Xs2)*(Ys1 - Ys2) - (Xs1 - Xs2)*(Ys0 - Ys2)
*
*
*
* (Xd0 - Xd2)*(Ys1 - Ys2) - (Xd1 - Xd2)*(Ys0 - Ys2)
* A = ---------------------------------------------------
* Divider
*
*
* (Xs0 - Xs2)*(Xd1 - Xd2) - (Xd0 - Xd2)*(Xs1 - Xs2)
* B = ---------------------------------------------------
* Divider
*
*
* Ys0*(Xs2*Xd1 - Xs1*Xd2) +
* Ys1*(Xs0*Xd2 - Xs2*Xd0) +
* Ys2*(Xs1*Xd0 - Xs0*Xd1)
* C = ---------------------------------------------------
* Divider
*
*
* (Yd0 - Yd2)*(Ys1 - Ys2) - (Yd1 - Yd2)*(Ys0 - Ys2)
* D = ---------------------------------------------------
* Divider
*
*
* (Xs0 - Xs2)*(Yd1 - Yd2) - (Yd0 - Yd2)*(Xs1 - Xs2)
* E = ---------------------------------------------------
* Divider
*
*
* Ys0*(Xs2*Yd1 - Xs1*Yd2) +
* Ys1*(Xs0*Yd2 - Xs2*Yd0) +
* Ys2*(Xs1*Yd0 - Xs0*Yd1)
* F = ---------------------------------------------------
* Divider
*
*
* Return: OK - the calibration matrix was correctly
* calculated and its value is in the
* output argument.
* NOT_OK - an error was detected and the
* function failed to return a valid
* set of matrix values.
* The only time this sample code returns
* NOT_OK is when Divider == 0
*
*
*
* NOTE! NOTE! NOTE!
*
* setCalibrationMatrix() and getDisplayPoint() will do fine
* for you as they are, provided that your digitizer
* resolution does not exceed 10 bits (1024 values). Higher
* resolutions may cause the integer operations to overflow
* and return incorrect values. If you wish to use these
* functions with digitizer resolutions of 12 bits (4096
* values) you will either have to a) use 64-bit signed
* integer variables and math, or b) judiciously modify the
* operations to scale results by a factor of 2 or even 4.
*
*
*/
int setCalibrationMatrix( const CAL_POINT displayPtr[3],
const CAL_POINT screenPtr[3],
CAL_MATRIX * matrixPtr)
{
int retValue = OK ;
matrixPtr->Divider = ((screenPtr[0].x - screenPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) -
((screenPtr[1].x - screenPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ;
if( matrixPtr->Divider == 0 )
{
retValue = NOT_OK ;
}
else
{
matrixPtr->An = ((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) -
((displayPtr[1].x - displayPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ;
matrixPtr->Bn = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].x - displayPtr[2].x)) -
((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].x - screenPtr[2].x)) ;
matrixPtr->Cn = (screenPtr[2].x * displayPtr[1].x - screenPtr[1].x * displayPtr[2].x) * screenPtr[0].y +
(screenPtr[0].x * displayPtr[2].x - screenPtr[2].x * displayPtr[0].x) * screenPtr[1].y +
(screenPtr[1].x * displayPtr[0].x - screenPtr[0].x * displayPtr[1].x) * screenPtr[2].y ;
matrixPtr->Dn = ((displayPtr[0].y - displayPtr[2].y) * (screenPtr[1].y - screenPtr[2].y)) -
((displayPtr[1].y - displayPtr[2].y) * (screenPtr[0].y - screenPtr[2].y)) ;
matrixPtr->En = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].y - displayPtr[2].y)) -
((displayPtr[0].y - displayPtr[2].y) * (screenPtr[1].x - screenPtr[2].x)) ;
matrixPtr->Fn = (screenPtr[2].x * displayPtr[1].y - screenPtr[1].x * displayPtr[2].y) * screenPtr[0].y +
(screenPtr[0].x * displayPtr[2].y - screenPtr[2].x * displayPtr[0].y) * screenPtr[1].y +
(screenPtr[1].x * displayPtr[0].y - screenPtr[0].x * displayPtr[1].y) * screenPtr[2].y ;
}
return( retValue ) ;
} /* end of setCalibrationMatrix() */
/**********************************************************************
*
* Function: getDisplayPoint()
*
* Description: Given a valid set of calibration factors and a point
* value reported by the touch screen, this function
* calculates and returns the true (or closest to true)
* display point below the spot where the touch screen
* was touched.
*
*
*
* Argument(s): displayPtr (output) - Pointer to the calculated
* (true) display point.
* screenPtr (input) - Pointer to the reported touch
* screen point.
* matrixPtr (input) - Pointer to calibration factors
* matrix previously calculated
* from a call to
* setCalibrationMatrix()
*
*
* The function simply solves for Xd and Yd by implementing the
* computations required by the translation matrix.
*
* /- -\
* /- -\ /- -\ | |
* | | | | | Xs |
* | Xd | | A B C | | |
* | | = | | * | Ys |
* | Yd | | D E F | | |
* | | | | | 1 |
* \- -/ \- -/ | |
* \- -/
*
* It must be kept brief to avoid consuming CPU cycles.
*
*
* Return: OK - the display point was correctly calculated
* and its value is in the output argument.
* NOT_OK - an error was detected and the function
* failed to return a valid point.
*
*
*
* NOTE! NOTE! NOTE!
*
* setCalibrationMatrix() and getDisplayPoint() will do fine
* for you as they are, provided that your digitizer
* resolution does not exceed 10 bits (1024 values). Higher
* resolutions may cause the integer operations to overflow
* and return incorrect values. If you wish to use these
* functions with digitizer resolutions of 12 bits (4096
* values) you will either have to a) use 64-bit signed
* integer variables and math, or b) judiciously modify the
* operations to scale results by a factor of 2 or even 4.
*
*
*/
int getDisplayPoint( CAL_POINT * displayPtr,
const CAL_POINT * screenPtr,
const CAL_MATRIX * matrixPtr )
{
int retValue = OK ;
if( matrixPtr->Divider != 0 )
{
/* Operation order is important since we are doing integer */
/* math. Make sure you add all terms together before */
/* dividing, so that the remainder is not rounded off */
/* prematurely. */
displayPtr->x = ( (matrixPtr->An * screenPtr->x) +
(matrixPtr->Bn * screenPtr->y) +
matrixPtr->Cn
) / matrixPtr->Divider ;
displayPtr->y = ( (matrixPtr->Dn * screenPtr->x) +
(matrixPtr->En * screenPtr->y) +
matrixPtr->Fn
) / matrixPtr->Divider ;
}
else
{
retValue = NOT_OK ;
}
return( retValue ) ;
} /* end of getDisplayPoint() */