⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transform.c

📁 一个嵌入式操作系统(microwindows)的源代码
💻 C
字号:
/* * transform.c * Calculate coefficients for tranformation equation * Copyright (C) 1999 Bradley D. LaRonde <brad@ltc.com> * * This program is free software; you may redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "windows.h"#include "mou_tp.h"#include "transform.h"int CalcTransformationCoefficientsSimple(CALIBRATION_PAIRS *pcp, TRANSFORMATION_COEFFICIENTS *ptc){	/*	 * This is my simple way of calculating some of the coefficients -	 * enough to do a simple scale and translate.	 * It ignores any dependencies between axiis (rotation and/or skew).	 */	int min_screen_x = pcp->ul.screen.x;	int min_screen_y = pcp->ul.screen.y;	int max_screen_x = pcp->lr.screen.x;	int max_screen_y = pcp->lr.screen.y;	int min_device_x = pcp->ul.device.x;	int min_device_y = pcp->ul.device.y;	int max_device_x = pcp->lr.device.x;	int max_device_y = pcp->lr.device.y;	ptc->s = (1 << 16);	ptc->a = ptc->s * (min_screen_x - max_screen_x) / (min_device_x - max_device_x);	ptc->b = 0;	ptc->c = (ptc->a * -min_device_x) + (ptc->s * min_screen_x);	ptc->d = 0;	ptc->e = ptc->s * (min_screen_y - max_screen_y) / (min_device_y - max_device_y);	ptc->f = (ptc->e * -min_device_y) + (ptc->s * min_screen_y);	return 0;}int CalcTransformationCoefficientsBetter(CALIBRATION_PAIRS *pcp, TRANSFORMATION_COEFFICIENTS *ptc){	/*	 * Janus (the man) <janus@place.org> came up with a much better way	 * to figure the coefficients.  His original algorithm was written in MOO.	 * Jay Carlson <> did the translation to C.	 * This way takes into account inter-axis dependency like rotation and skew.	 */	double vector[3][2] =	{		{pcp->ul.screen.x, pcp->ul.screen.y},		{pcp->ur.screen.x, pcp->ur.screen.y},		{pcp->lr.screen.x, pcp->lr.screen.y}	};	double matrix[3][3] =	{		{pcp->ul.device.x, pcp->ul.device.y, 1.0},		{pcp->ur.device.x, pcp->ur.device.y, 1.0},		{pcp->lr.device.x, pcp->lr.device.y, 1.0}	};	int i, j, r, k;	double p, q;    	for (i = 0; i < 3; i++) {          p = matrix[i][i];                    for (j = 0; j < 3; j++) {               matrix[i][j] = matrix[i][j] / p;          }                    for (j = 0; j < 2; j++) {               vector[i][j] = vector[i][j] / p;          }          for (r = 0; r < 3; r++) {               if (r != i) {                    q = matrix[r][i];                                        matrix[r][i] = 0.0;                                        for (k = i + 1; k < 3; k++) {                         matrix[r][k] = matrix[r][k] - (q * matrix[i][k]);                    }                                        for (k = 0; k < 2; k++) {                         vector[r][k] = vector[r][k] - (q * vector[i][k]);                    }               }          }	}	ptc->s = 1 << 16;	ptc->a = vector[0][0] * ptc->s;	ptc->b = vector[1][0] * ptc->s;	ptc->c = vector[2][0] * ptc->s;	ptc->d = vector[0][1] * ptc->s;	ptc->e = vector[1][1] * ptc->s;	ptc->f = vector[2][1] * ptc->s;	return 0;}int CalcTransformationCoefficientsEvenBetter(CALIBRATION_PAIRS *pcp, TRANSFORMATION_COEFFICIENTS *ptc){	/*	 * Mike Klar <> added the an xy term to correct for trapezoidial distortion.	 */	double vector[4][2] =	{		{pcp->ul.screen.x, pcp->ul.screen.y},		{pcp->ur.screen.x, pcp->ur.screen.y},		{pcp->lr.screen.x, pcp->lr.screen.y},		{pcp->ll.screen.x, pcp->ll.screen.y}	};	double matrix[4][4] =	{		{pcp->ul.device.x, pcp->ul.device.x * pcp->ul.device.y, pcp->ul.device.y, 1.0},		{pcp->ur.device.x, pcp->ur.device.x * pcp->ur.device.y, pcp->ur.device.y, 1.0},		{pcp->lr.device.x, pcp->lr.device.x * pcp->lr.device.y, pcp->lr.device.y, 1.0},		{pcp->ll.device.x, pcp->ll.device.x * pcp->ll.device.y, pcp->ll.device.y, 1.0}	};	int i, j, r, k;	double p, q;    	for (i = 0; i < 4; i++) {          p = matrix[i][i];                    for (j = 0; j < 4; j++) {               matrix[i][j] = matrix[i][j] / p;          }                    for (j = 0; j < 2; j++) {               vector[i][j] = vector[i][j] / p;          }          for (r = 0; r < 4; r++) {               if (r != i) {                    q = matrix[r][i];                                        matrix[r][i] = 0.0;                                        for (k = i + 1; k < 4; k++) {                         matrix[r][k] = matrix[r][k] - (q * matrix[i][k]);                    }                                        for (k = 0; k < 2; k++) {                         vector[r][k] = vector[r][k] - (q * vector[i][k]);                    }               }          }	}	/* I just drop the xy coefficient since it is so small. */	ptc->s = 1 << 16;	ptc->a = vector[0][0] * ptc->s;	ptc->b = vector[2][0] * ptc->s;	ptc->c = vector[3][0] * ptc->s;	ptc->d = vector[0][1] * ptc->s;	ptc->e = vector[2][1] * ptc->s;	ptc->f = vector[3][1] * ptc->s;	return 0;}int CalcTransformationCoefficientsBest(CALIBRATION_PAIRS *pcp, TRANSFORMATION_COEFFICIENTS *ptc){	/*	 * Mike Klar <> came up with a best-fit solution that works best.	 */	const int first_point = 0;	const int last_point = 4;	int i;	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;	double t1, t2, t3, t4, t5, t6, q;	/* cast the struct to an array - hacky but ok */	CALIBRATION_PAIR *cp = (CALIBRATION_PAIR*)pcp;	/*	 * Do a best-fit calculation for as many points as we want, as	 * opposed to an exact fit, which can only be done against 3 points.	 *	 * The following calculates various sumnations of the sample data	 * coordinates.  For purposes of naming convention, x and y	 * refer to device coordinates, m and n refer to screen	 * coordinates, S means sumnation.  x2 and y2 are x squared and	 * y squared, S by itself is just a count of points (= sumnation	 * of 1).	 */	for (i = first_point; i < last_point + 1; i++) {		Sx += cp[i].device.x;		Sy += cp[i].device.y;		Sxy += cp[i].device.x * cp[i].device.y;		Sx2 += cp[i].device.x * cp[i].device.x;		Sy2 += cp[i].device.y * cp[i].device.y;		Sm += cp[i].screen.x;		Sn += cp[i].screen.y;		Smx += cp[i].screen.x * cp[i].device.x;		Smy += cp[i].screen.x * cp[i].device.y;		Snx += cp[i].screen.y * cp[i].device.x;		Sny += cp[i].screen.y * cp[i].device.y;		S += 1;	}#if 0	printf("%f, %f, %f, %f, "	       "%f, %f, %f, %f, "	       "%f, %f, %f, %f\n",	        Sx, Sy, Sxy, Sx2, Sy2, Sm, Sn, Smx, Smy, Snx, Sny, S);#endif	/*	 * Next we solve the simultaneous equations (these equations minimize	 * the sum of the square of the m and n error):	 *	 *    | Sx2 Sxy Sx |   | a d |   | Smx Snx |	 *    | Sxy Sy2 Sy | * | b e | = | Smy Sny |	 *    | Sx  Sy  S  |   | c f |   | Sm  Sn  |	 *	 * We could do the matrix solution in code, but that leads to several	 * divide by 0 conditions for cases where the data is truly solvable	 * (becuase those terms cancel out of the final solution), so we just	 * give the final solution instread.  t1 through t6 and q are just	 * convenience variables for terms that are used repeatedly - we could	 * calculate each of the coefficients directly at this point with a	 * nasty long equation, but that would be extremly inefficient.	 */	t1 = Sxy * Sy - Sx * Sy2;	t2 = Sxy * Sx - Sx2 * Sy;	t3 = Sx2 * Sy2 - Sxy * Sxy;	t4 = Sy2 * S - Sy * Sy;	t5 = Sx * Sy - Sxy * S;	t6 = Sx2 * S - Sx * Sx;	q = t1 * Sx + t2 * Sy + t3 * S;	/*	 * If q = 0, then the data is unsolvable.  This should only happen	 * when there are not enough unique data points (less than 3 points	 * will give infinite solutions), or at least one of the 	 * coefficients is infinite (which would indicate that the same	 * device point represents an infinite area of the screen, probably	 * as a result of the same device data point given for 2 different	 * screen points).  The first condition should never happen, since	 * we're always feeding in at least 3 unique screen points.  The	 * second condition would probably indicate bad user input or the	 * touchpanel device returning bad data.	 */	if (q == 0)		return -1;	ptc->s = 1 << 16;	ptc->a = ((t4 * Smx + t5 * Smy + t1 * Sm) / q + 0.5/65536) * ptc->s;	ptc->b = ((t5 * Smx + t6 * Smy + t2 * Sm) / q + 0.5/65536) * ptc->s;	ptc->c = ((t1 * Smx + t2 * Smy + t3 * Sm) / q + 0.5/65536) * ptc->s;	ptc->d = ((t4 * Snx + t5 * Sny + t1 * Sn) / q + 0.5/65536) * ptc->s;	ptc->e = ((t5 * Snx + t6 * Sny + t2 * Sn) / q + 0.5/65536) * ptc->s;	ptc->f = ((t1 * Snx + t2 * Sny + t3 * Sn) / q + 0.5/65536) * ptc->s;	/*	 * Finally, we check for overflow on the fp to integer conversion,	 * which would also probably indicate bad data.	 */	if ( (ptc->a == 0x80000000) || (ptc->b == 0x80000000) ||	     (ptc->c == 0x80000000) || (ptc->d == 0x80000000) ||	     (ptc->e == 0x80000000) || (ptc->f == 0x80000000) )		return -1;		return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -