home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
vis-ftp.cs.umass.edu
/
vis-ftp.cs.umass.edu.tar
/
vis-ftp.cs.umass.edu
/
pub
/
CMU
/
cmu_files
/
cal
/
coordtrans3.c
next >
Wrap
C/C++ Source or Header
|
1990-12-11
|
42KB
|
1,688 lines
/* coordtrans, coordmap1, coordequations, coordsave, coordrestore,
* coordfree
*
* SYNOPSIS
* coordtrans (x,y,dx,dy,n,order)
* double *x, *y, *dx, *dy;
* int n, order;
*
* coordmap1 (x,y,dx,dy)
* double x, y, *dx, *dy;
*
* coordequations (device,file)
* char *device, *file;
*
* coordsave (file)
* coordrestore (file)
* char *file;
*
* coordfree ()
*
* coordsetup (n)
* int n;
*
* coordstore (n)
* int n;
*
* coordsel (n)
* int n;
*
* DESCRIPTION
* Coordtrans takes as input two matrices of corresponding points whose
* coordinates are defined in the arrays x, y, dx, and dy, where point
* (x[i],y[i]) corresponds to (dx[i],dy[i]). The size of the arrays is given
* by n. A best fit transformation (x,y) => (dx,dy) is determined and
* maintained in internal data structures for use by coordmap1,
* coordequations, and coordsave. The parameter 'order' is the greatest
* power of any term in the computed transformation equation.
*
* Coordmap1 takes as input the coordinates (x,y) of a single point and,
* implicitly the transformation computed by coordtrans. Its returns the
* coordinates of the new point in the locations specified by dx and dy.
*
* Coordequations writes the transformation equations determined by the
* coordtrans routine into the specified file in Scribe format. The device
* parameter is put into a Scribe @device() command at the head of the file.
* If the device specified is "CRT", the Scribe output will produce a nicely
* formatted equation on a crt. **HACK NOTE** if the device is "none",
* coordequations will output a non-Scribe file, with no @device command and
* with exponents specified as a**b instead of a@+(b).
*
* Coordsave writes into the specified file all of the internal data
* structures computed by coordtrans that are required for coordmap1.
*
* Coordrestore reads from the specified file all the internal data
* structures previously written out by coordsave.
*
* Coordsetup, coordstore, and coordsel provide the capability for more than
* one transform, for example a transform and its inverse. Coordsetup
* allocates space for n transforms. Coordstore stores the current transform
* as the nth stored transform. Coordsel retrieves the nth stored transform
* and makes it the current transform. All other operations (coordtrans,
* coordmap1, coordequations, coordsave, and coordrestore) work on the current
* transform. The extra storage facilities provided by coordsetup, coordstore,
* and coordsel are is invisible to users who only need one transform.
*
* Coordfree releases all storage allocated by coordtrans and coordsetup.
*
* REFERENCE
* See chapters 5 and 7 of J. G. Hayes, ed., Numerical Approximation to
* Functions and Data, London, The Athlone Press, 1970, for a theoretical
* discusson of the algorithm used in coordtrans.
*
* HISTORY
* 15-Jul-85 Chuck Thorpe (cet) at Carnegie-Mellon University
* Added the special device "none" to coordequations to save running
* the output through Scribe.
*
* 22-Mar-84 Duane Williams (dtw) at Carnegie-Mellon University
* Corrected some flaws in the way coordequations output the equations.
*
* 10-Mar-83 Chuck Thorpe (cet) at Carnegie-Mellon University
* Added multiple in-memory transforms, and routines coordsetup (),
* coordstore (), and coordsel ().
*
* 16-Feb-83 Duane Williams (dtw) at Carnegie-Mellon University
* Added coordsave, coordrestore, and coordfree.
*
* 26-Jan-82 Duane Williams (dtw) at Carnegie-Mellon University
* Created.
*
*/
#include <stdio.h>
#include <math.h>
#include "matrix.h"
typedef enum {
FALSE, TRUE
} boolean;
#define hidden static
#define visible
#define UNDEFINED -1
#define TCOEFX(l) tcoefx[l][0]
#define TCOEFY(l) tcoefy[l][0]
#define XDEG(l) xdeg[l][0]
#define YDEG(l) ydeg[l][0]
#define BEFORE(l) before[l][0]
#define A(l) a[l][0]
#define BP(l) bp[l][0]
#define CCX(l) ccx[l][0]
#define CCY(l) ccy[l][0]
hidden dmat tcoefx_vector;
hidden dmat tcoefy_vector;
hidden double **tcoefx, **tcoefy;
hidden int Order;
hidden dmat bp_vector;
hidden dmat c_matrix;
hidden imat xdeg_vector;
hidden imat ydeg_vector;
hidden imat before_vector;
hidden imat num_matrix;
hidden double **bp, **c;
hidden int **xdeg, **ydeg;
hidden int **before, **num;
hidden boolean tcoefx_dirty = FALSE;
hidden boolean tcoefy_dirty = FALSE;
hidden boolean bp_dirty = FALSE;
hidden boolean c_dirty = FALSE;
hidden boolean xdeg_dirty = FALSE;
hidden boolean ydeg_dirty = FALSE;
hidden boolean before_dirty = FALSE;
hidden boolean num_dirty = FALSE;
hidden int selected = -1;
hidden int scount = -1;
hidden boolean *stcoefx_dirty;
hidden boolean *stcoefy_dirty;
hidden boolean *sbp_dirty;
hidden boolean *sc_dirty;
hidden boolean *sxdeg_dirty;
hidden boolean *sydeg_dirty;
hidden boolean *sbefore_dirty;
hidden boolean *snum_dirty;
hidden dmat *stcoefx_vector;
hidden dmat *stcoefy_vector;
hidden dmat *sc_matrix;
hidden dmat *sbp_vector;
hidden imat *snum_matrix;
hidden imat *sxdeg_vector;
hidden imat *sydeg_vector;
hidden imat *sbefore_vector;
extern char *malloc();
extern double pol();
/*****************************************************************
* coordtrans
*****************************************************************
*/
visible int
coordtrans (x,y,dx,dy,n,order)
double *x, *y, *dx, *dy;
int n, order;
{
register int i, j, k, l;
double sum, p;
dmat a_vector,
s_matrix,
t_matrix;
double **a, **s, **t;
int order1, pnum, pnum1, err;
/* save order in global */
Order = order;
order1 = order + 1;
pnum = order1 * (order1 + 1) / 2;
pnum1 = pnum - 1;
/*----------------------------------------------------------------
* Check that we have enough input (this is probably not right)
*----------------------------------------------------------------
*/
if (n < pnum) {
fprintf (stderr,
"Warning: there may not be enough data for a valid result!\n");
}
/*----------------------------------------------------------------
* Storage allocation.
*----------------------------------------------------------------
*/
/* storage allocated by coordalloc stays around and is shared with
coordmap1 */
if (coordalloc(pnum1, order) == 0) {
return 0;
}
/* the following storage is local to coordtrans and is freed prior to
exit */
a_vector = newdmat (0, pnum1, 0, 0, &err);
if (err) {
printf ("\tMemory exhausted.\n");
return 0;
}
a = a_vector.el;
s_matrix = newdmat (0, pnum1, 0, pnum1, &err);
if (err) {
printf ("\tMemory exhausted.\n");
return 0;
}
s = s_matrix.el;
t_matrix = newdmat (0, pnum1, 0, pnum1, &err);
if (err) {
printf ("\tMemory exhausted.\n");
return 0;
}
t = t_matrix.el;
/*----------------------------------------------------------------
* Initialization (probably unnecessary, but ...)
*----------------------------------------------------------------
*/
for (i = 0; i < pnum; i++) {
A (i) = BP (i) = 0.0;
XDEG (i) = YDEG (i) = BEFORE (i) = UNDEFINED;
for (j = 0; j < pnum; j++) {
s[i][j] = t[i][j] = c[i][j] = 0.0;
}
}
for (i = 0; i <= order; i++) {
for (j = 0; j <= order; j++) {
num[i][j] = 0;
}
}
/*----------------------------------------------------------------
* Prepare num, xdeg, ydeg, and before.
*
* Num is a square matrix of size 'order' which is meaningful only
* above the main diagonal. It is numbered as follows (for the
* case where order = 2):
*
* 0 2 5
* 1 4
* 3
*
* XDEG(i) is the row on which the number i is located in array
* num; similarly, YDEG(i) is the column for i.
*
* BEFORE(i) is the number that is "before" number i in the num
* array. The relation BEFORE is defined as follows:
*
* If i = 0, then BEFORE(i) is undefined;
* Else If XDEG(i) = 0, then BEFORE(i) is the number
* immediately to the left of i in array num;
* Else BEFORE(i) is the number immediately above i.
*----------------------------------------------------------------
*/
for (i = 0; i <= order; i++) {
for (j = 0; (k = i + j) <= order; j++) {
num[i][j] = l = (k * (k + 1) / 2) + j;
XDEG (l) = i;
YDEG (l) = j;
BEFORE (l) = (l == 0) ? UNDEFINED
: (i == 0) ? num[0][j - 1] : num[i - 1][j];
}
}
/*-----------------------------------------------------------------------
* a[l-1] = summation of ( pol(l-1,x,y) * pol(l-1,x,y) )
*-----------------------------------------------------------------------
*/
for (l = 1; l < pnum; l++) {/* main for loop */
for (sum = i = 0; i < n; i++) {
p = pol (l - 1, x[i], y[i]);
sum += p * p;
}
A (l - 1) = sum;
/*-----------------------------------------------------------------------
* s[j][l-1] = s[l-1][j] = summation of ( x * pol(j,x,y) * pol(l-1,x,y) )
*-----------------------------------------------------------------------
*/
for (j = 0; j < l; j++) {
for (sum = i = 0; i < n; i++) {
sum += x[i] * pol (j, x[i], y[i]) * pol (l - 1, x[i], y[i]);
}
s[j][l - 1] = s[l - 1][j] = sum;
/*-----------------------------------------------------------------------
* t[j][l-1] = t[l-1][j] = summation of ( y * pol(j,x,y) * pol(l-1,x,y) )
*-----------------------------------------------------------------------
*/
for (sum = i = 0; i < n; i++) {
sum += y[i] * pol (j, x[i], y[i]) * pol (l - 1, x[i], y[i]);
}
t[j][l - 1] = t[l - 1][j] = sum;
}
for (j = 0; j < l; j++) {
if (A (j) == 0) { /* prevent zero divide */
printf ("\tWarning: A[%d] = 0. ", j);
printf ("c[%d][%d] will be undefined.\n", l, j);
continue;
}
if (XDEG (l) == 0) {
c[l][j] = t[BEFORE (l)][j] / A (j);
}
else {
c[l][j] = s[BEFORE (l)][j] / A (j);
}
}
} /* end main for loop */
/*----------------------------------------------------------------
* a[pnum-1] = summation of ( pol(pnum-1,x,y) * pol(pnum-1,x,y) )
*----------------------------------------------------------------
*/
for (sum = i = 0; i < n; i++) {
p = pol (pnum1, x[i], y[i]);
sum += p * p;
}
A (pnum1) = sum;
/*----------------------------------------------------------------
* Determine coefficients
*----------------------------------------------------------------
*/
for (l = 0; l < pnum; l++) {
if (A (l) == 0) {
printf ("\tWarning: A[%d] = 0. ", j);
printf ("coefs[%d] will be undefined.\n", l);
continue;
}
for (sum = i = 0; i < n; i++) {
sum += dx[i] * pol (l, x[i], y[i]);
}
TCOEFX(l) = sum / A (l);
for (sum = i = 0; i < n; i++) {
sum += dy[i] * pol (l, x[i], y[i]);
}
TCOEFY(l) = sum / A (l);
}
/*----------------------------------------------------------------
* Free temporary storage.
*----------------------------------------------------------------
*/
freemat (a_vector);
freemat (s_matrix);
freemat (t_matrix);
return 1;
}
/*----------------------------------------------------------------
* Compute polynomial
*----------------------------------------------------------------
*/
hidden double
pol (l,x,y)
int l;
double x,y;
{
int i,j;
double val;
if (l == 0) {
return (1.0);
}
BP(0) = 1.0;
for (i=1; i <= l; i++) {
val = ((XDEG(i) != 0) ? x : y) * BP(BEFORE(i));
for (j=0; j < i; j++) {
val -= c[i][j] * BP(j);
}
BP(i) = val;
}
return ( BP(l) );
}
/*****************************************************************
* coordfree -- release all internal storage associated with
* coordtrans
*****************************************************************
*/
visible
coordfree ()
{
int i;
if (tcoefx_dirty) {
freemat(tcoefx_vector);
tcoefx_dirty = FALSE;
}
if (tcoefy_dirty) {
freemat(tcoefy_vector);
tcoefy_dirty = FALSE;
}
if (c_dirty) {
freemat(c_matrix);
c_dirty = FALSE;
}
if (bp_dirty) {
freemat(bp_vector);
bp_dirty = FALSE;
}
if (num_dirty) {
freemat(num_matrix);
num_dirty = FALSE;
}
if (xdeg_dirty) {
freemat(xdeg_vector);
xdeg_dirty = FALSE;
}
if (ydeg_dirty) {
freemat(ydeg_vector);
ydeg_dirty = FALSE;
}
if (before_dirty) {
freemat(before_vector);
before_dirty = FALSE;
}
for (i = 0; i < scount; i++) {
if (stcoefx_dirty[i]) {
freemat (stcoefx_vector[i]);
stcoefx_dirty[i] = FALSE;
}
if (stcoefy_dirty[i]) {
freemat (stcoefy_vector[i]);
stcoefy_dirty[i] = FALSE;
}
if (sc_dirty[i]) {
freemat (sc_matrix[i]);
sc_dirty[i] = FALSE;
}
if (sbp_dirty[i]) {
freemat (sbp_vector[i]);
sbp_dirty[i] = FALSE;
}
if (snum_dirty[i]) {
freemat (snum_matrix[i]);
snum_dirty[i] = FALSE;
}
if (sxdeg_dirty[i]) {
freemat (sxdeg_vector[i]);
sxdeg_dirty[i] = FALSE;
}
if (sydeg_dirty[i]) {
freemat (sydeg_vector[i]);
sydeg_dirty[i] = FALSE;
}
if (sbefore_dirty[i]) {
freemat (sbefore_vector[i]);
sbefore_dirty[i] = FALSE;
}
}
if (scount != -1) {
scount = -1;
free (stcoefx_vector);
free (stcoefy_vector);
free (sbp_vector);
free (c_matrix);
free (xdeg_vector);
free (ydeg_vector);
free (before_vector);
free (num_matrix);
free (stcoefx_dirty);
free (stcoefy_dirty);
free (sbp_dirty);
free (c_dirty);
free (xdeg_dirty);
free (ydeg_dirty);
free (before_dirty);
free (num_dirty);
}
}
/*-----------------------------------------------------------------
* coordalloc -- allocate storage common to coordtrans and coordmap1
*-----------------------------------------------------------------
*/
hidden int
coordalloc (pnum1, order)
int pnum1, order;
{
int err;
if (tcoefx_dirty) {
freemat (tcoefx_vector);
tcoefx_dirty = FALSE;
}
tcoefx_vector = newdmat (0, pnum1, 0, 0, &err);
if (err) {
printf("\tMemory exhausted.\n");
return 0;
}
tcoefx = tcoefx_vector.el;
tcoefx_dirty = TRUE;
if (tcoefy_dirty) {
freemat (tcoefy_vector);
tcoefy_dirty = FALSE;
}
tcoefy_vector = newdmat (0, pnum1, 0, 0, &err);
if (err) {
printf("\tMemory exhausted.\n");
return 0;
}
tcoefy = tcoefy_vector.el;
tcoefy_dirty = TRUE;
if (c_dirty) {
freemat (c_matrix);
c_dirty = FALSE;
}
c_matrix = newdmat (0, pnum1, 0, pnum1, &err);
if (err) {
printf ("\tMemory exhausted.\n");
return 0;
}
c = c_matrix.el;
c_dirty = TRUE;
if (bp_dirty) {
freemat (bp_vector);
bp_dirty = FALSE;
}
bp_vector = newdmat (0, pnum1, 0, 0, &err);
if (err) {
printf ("\tMemory exhausted.\n");
return 0;
}
bp = bp_vector.el;
bp_dirty = TRUE;
if (num_dirty) {
freemat (num_matrix);
num_dirty = FALSE;
}
num_matrix = newimat (0, order, 0, order, &err);
if (err) {
printf ("\tMemory exhausted.\n");
return 0;
}
num = num_matrix.el;
num_dirty = TRUE;
if (xdeg_dirty) {
freemat (xdeg_vector);
xdeg_dirty = FALSE;
}
xdeg_vector = newimat (0, pnum1, 0, 0, &err);
if (err) {
printf ("\tMemory exhausted.\n");
return 0;
}
xdeg = xdeg_vector.el;
xdeg_dirty = TRUE;
if (ydeg_dirty) {
freemat (ydeg_vector);
ydeg_dirty = FALSE;
}
ydeg_vector = newimat (0, pnum1, 0, 0, &err);
if (err) {
printf ("\tMemory exhausted.\n");
return 0;
}
ydeg = ydeg_vector.el;
ydeg_dirty = TRUE;
if (before_dirty) {
freemat (before_vector);
before_dirty = FALSE;
}
before_vector = newimat (0, pnum1, 0, 0, &err);
if (err) {
printf ("\tMemory exhausted.\n");
return 0;
}
before = before_vector.el;
before_dirty = TRUE;
return 1;
}
/*-----------------------------------------------------------------
* coordsave, coordrestore -- write and read data structures needed by
* coordmap1 to and from a file.
*
* The following data structures are saved and restored:
* dmat tcoefx_vector
* dmat tcoefy_vector
* dmat c_matrix
* dmat bp_vector
* imat num_matrix
* imat xdeg_vector
* imat ydeg_vector
* imat before_vector
*
* During the restoration the Order variable is recomputed.
*
* Both routines return 0 on error and 1 if successful.
*-----------------------------------------------------------------
*/
#define WRITE(ptr,bytes) fwrite((char *)(ptr), sizeof(char), bytes, fd)
#define READ(ptr,bytes) fread ((char *)(ptr), sizeof(char), bytes, fd)
#define HEADER "!<coord>\n"
#define HEADERLENGTH 9
#define ASCIIHEADER "Ascii_calibration_data_--_compliments_of_jdc"
#define ASCIIHEADLEN 44
visible
coordsave (file)
char *file;
{
FILE *fd; /* file descriptor for access to file */
char *header = HEADER;
fd = fopen (file, "w"); /* create for writing */
if (fd == NULL) {
printf("coordsave: can't create file '%s'\n",file);
return 0;
}
if (WRITE (header, HEADERLENGTH) != HEADERLENGTH) {
printf("coordsave: encountered an error writing the file header\n");
return 0;
}
if (writedmat (fd, tcoefx_vector) == 0 ||
writedmat (fd, tcoefy_vector) == 0 ||
writedmat (fd, c_matrix) == 0 ||
writedmat (fd, bp_vector) == 0 ||
writeimat (fd, num_matrix) == 0 ||
writeimat (fd, xdeg_vector) == 0 ||
writeimat (fd, ydeg_vector) == 0 ||
writeimat (fd, before_vector) == 0) {
printf("coordsave: encountered an error writing the file\n");
return 0;
}
if (fclose (fd) != EOF) {
return 0;
}
return 1;
}
visible
coordrestore (file)
char *file;
{
FILE *fd; /* file pointer for access to file */
char header [ HEADERLENGTH ];
selected = -1;
fd = fopen (file, "r"); /* open for reading */
if (fd == NULL) {
printf("coordrestore: can't open file '%s'\n",file);
return 0;
}
if (READ(header,HEADERLENGTH) != HEADERLENGTH) {
printf("coordrestore: error in reading the file header\n");
return 0;
}
if (strncmp (header, HEADER, HEADERLENGTH) != 0) {
printf("coordrestore: invalid file header ... restoration aborted\n");
return 0;
}
if (readdmat (fd, &tcoefx_vector) == 0 ||
readdmat (fd, &tcoefy_vector) == 0 ||
readdmat (fd, &c_matrix) == 0 ||
readdmat (fd, &bp_vector) == 0 ||
readimat (fd, &num_matrix) == 0 ||
readimat (fd, &xdeg_vector) == 0 ||
readimat (fd, &ydeg_vector) == 0 ||
readimat (fd, &before_vector) == 0) {
printf("coordrestore: encountered an error reading the file\n");
return 0;
}
if (fclose (fd) == EOF) {
return 0;
}
tcoefx = tcoefx_vector.el;
tcoefy = tcoefy_vector.el;
c = c_matrix.el;
bp = bp_vector.el;
num = num_matrix.el;
xdeg = xdeg_vector.el;
ydeg = ydeg_vector.el;
before = before_vector.el;
tcoefx_dirty = TRUE;
tcoefy_dirty = TRUE;
c_dirty = TRUE;
bp_dirty = TRUE;
num_dirty = TRUE;
xdeg_dirty = TRUE;
ydeg_dirty = TRUE;
before_dirty = TRUE;
Order = num_matrix.ub1;
return 1;
}
/*-----------------------------------------------------------------
* coordasciisave, coordasciirestore -- write and read data structures
* needed by coordmap1 to and from an ascii file.
*
* The following data structures are saved and restored:
* dmat tcoefx_vector
* dmat tcoefy_vector
* dmat c_matrix
* dmat bp_vector
* imat num_matrix
* imat xdeg_vector
* imat ydeg_vector
* imat before_vector
*
* During the restoration the Order variable is recomputed.
*
* Both routines return 0 on error and 1 if successful.
*-----------------------------------------------------------------
*/
visible
coordasciisave (file)
char *file;
{
FILE *fd; /* file descriptor for access to file */
char *header = ASCIIHEADER;
fd = fopen (file, "w"); /* create for writing */
if (fd == NULL) {
printf("coordsave: can't create file '%s'\n",file);
return 0;
}
if (fprintf(fd, "%s\n", header) != ASCIIHEADLEN + 1) {
printf("coordasciisave: error in writing the file header\n");
return 0;
}
if (fprintfdmat (fd, tcoefx_vector) == 0 ||
fprintfdmat (fd, tcoefy_vector) == 0 ||
fprintfdmat (fd, c_matrix) == 0 ||
fprintfdmat (fd, bp_vector) == 0 ||
fprintfimat (fd, num_matrix) == 0 ||
fprintfimat (fd, xdeg_vector) == 0 ||
fprintfimat (fd, ydeg_vector) == 0 ||
fprintfimat (fd, before_vector) == 0) {
printf("coordsave: encountered an error writing the file\n");
return 0;
}
if (fclose (fd) != EOF) {
return 0;
}
return 1;
}
visible
coordasciirestore (file)
char *file;
{
FILE *fd; /* file pointer for access to file */
char asciiheader [ ASCIIHEADLEN ];
int length;
selected = -1;
fd = fopen (file, "r"); /* open for reading */
if (fd == NULL) {
printf("coordasciirestore: can't open file '%s'\n",file);
return 0;
}
length = fscanf(fd, "%s\n", asciiheader);
/* if(length != ASCIIHEADLEN + 1) {
printf("coordasciirestore: error in reading the ascii file header\n");
return 0;
}
*/
if (strncmp (asciiheader, ASCIIHEADER, ASCIIHEADLEN) != 0) {
printf("coordasciirestore: invalid ascii file header\n");
return 0;
}
if (fscanfdmat (fd, &tcoefx_vector) == 0 ||
fscanfdmat (fd, &tcoefy_vector) == 0 ||
fscanfdmat (fd, &c_matrix) == 0 ||
fscanfdmat (fd, &bp_vector) == 0 ||
fscanfimat (fd, &num_matrix) == 0 ||
fscanfimat (fd, &xdeg_vector) == 0 ||
fscanfimat (fd, &ydeg_vector) == 0 ||
fscanfimat (fd, &before_vector) == 0) {
printf("coordasciirestore: encountered an error reading the file\n");
return 0;
}
if (fclose (fd) == EOF) {
return 0;
}
tcoefx = tcoefx_vector.el;
tcoefy = tcoefy_vector.el;
c = c_matrix.el;
bp = bp_vector.el;
num = num_matrix.el;
xdeg = xdeg_vector.el;
ydeg = ydeg_vector.el;
before = before_vector.el;
tcoefx_dirty = TRUE;
tcoefy_dirty = TRUE;
c_dirty = TRUE;
bp_dirty = TRUE;
num_dirty = TRUE;
xdeg_dirty = TRUE;
ydeg_dirty = TRUE;
before_dirty = TRUE;
Order = num_matrix.ub1;
return 1;
}
hidden writedmat (fd, mat)
FILE *fd;
dmat mat;
{
int size, rows;
int nbytes = 0;
char *data;
/* write out the matrix bounds - 4 ints */
nbytes += WRITE (&(mat.lb1), sizeof(int));
nbytes += WRITE (&(mat.ub1), sizeof(int));
nbytes += WRITE (&(mat.lb2), sizeof(int));
nbytes += WRITE (&(mat.ub2), sizeof(int));
/* compute the matrix size in bytes and the virtual address of the
actual data */
rows = mat.ub1 - mat.lb1 + 1;
size = rows * (mat.ub2 - mat.lb2 + 1) * sizeof(double);
data = mat.mat_sto + rows * sizeof(double **); /* (char *) */
/* write out the matrix data -- the matrix rows are documented to be
stored contiguously; so we can write them all at once! */
nbytes += WRITE (data, size);
/* check number of bytes written */
size = 4 * sizeof(int) + size;
if (nbytes != size) {
printf("writedmat: should have written %d bytes -- wrote %d\n",
size, nbytes);
return 0;
}
return 1;
}
hidden writeimat (fd, mat)
FILE *fd;
imat mat;
{
int size, rows;
int nbytes = 0;
char *data;
/* write out the matrix bounds - 4 ints */
nbytes += WRITE (&(mat.lb1), sizeof(int));
nbytes += WRITE (&(mat.ub1), sizeof(int));
nbytes += WRITE (&(mat.lb2), sizeof(int));
nbytes += WRITE (&(mat.ub2), sizeof(int));
/* compute the matrix size in bytes and the virtual address of the
actual data */
rows = mat.ub1 - mat.lb1 + 1;
size = rows * (mat.ub2 - mat.lb2 + 1) * sizeof(int);
data = mat.mat_sto + rows * sizeof(int **); /* (char *) */
/* write out the matrix data -- the matrix rows are documented to be
stored contiguously; so we can write them all at once! */
nbytes += WRITE (data, size);
/* check number of bytes written */
size = 4 * sizeof(int) + size;
if (nbytes != size) {
printf("writedmat: should have written %d bytes -- wrote %d\n",
size, nbytes);
return 0;
}
return 1;
}
hidden readdmat (fd, mat)
FILE *fd;
dmat *mat;
{
dmat mymat;
int lb1, ub1, lb2, ub2;
int nbytes = 0;
int err, size, rows;
char *data;
/* read the matrix bounds - 4 ints */
nbytes += READ (&lb1, sizeof(int));
nbytes += READ (&ub1, sizeof(int));
nbytes += READ (&lb2, sizeof(int));
nbytes += READ (&ub2, sizeof(int));
/* allocate the matrix */
mymat = newdmat (lb1, ub1, lb2, ub2, &err);
if (err) {
printf("readdmat: can't allocate storage for matrix\n");
return 0;
}
/* find out where to put data and how much there is */
rows = ub1 - lb1 + 1;
size = rows * (ub2 - lb2 + 1) * sizeof(double);
data = mymat.mat_sto + rows * sizeof(double **); /* (char *) */
/* read in the matrix data -- matrix rows are stored contiguously */
nbytes += READ (data, size);
/* check number of bytes read */
size = 4 * sizeof(int) + size;
if (nbytes != size) {
printf("readdmat: should have read %d bytes -- read %d\n",
size, nbytes);
return 0;
}
/* copy matrix fields to the outside world */
mat -> lb1 = lb1;
mat -> ub1 = ub1;
mat -> lb2 = lb2;
mat -> ub2 = ub2;
mat -> mat_sto = mymat.mat_sto;
mat -> el = mymat.el;
return 1;
}
hidden readimat (fd, mat)
FILE *fd;
imat *mat;
{
imat mymat;
int lb1, ub1, lb2, ub2;
int nbytes = 0;
int err, size, rows;
char *data;
/* read the matrix bounds - 4 ints */
nbytes += READ (&lb1, sizeof(int));
nbytes += READ (&ub1, sizeof(int));
nbytes += READ (&lb2, sizeof(int));
nbytes += READ (&ub2, sizeof(int));
/* allocate the matrix */
mymat = newimat (lb1, ub1, lb2, ub2, &err);
if (err) {
printf("readimat: can't allocate storage for matrix\n");
return 0;
}
/* find out where to put data and how much there is */
rows = ub1 - lb1 + 1;
size = rows * (ub2 - lb2 + 1) * sizeof(int);
data = mymat.mat_sto + rows * sizeof(int **); /* (char *) */
/* read in the matrix data -- matrix rows are stored contiguously */
nbytes += READ (data, size);
/* check number of bytes read */
size = 4 * sizeof(int) + size;
if (nbytes != size) {
printf("readimat: should have read %d bytes -- read %d\n",
size, nbytes);
return 0;
}
/* copy matrix fields to the outside world */
mat -> lb1 = lb1;
mat -> ub1 = ub1;
mat -> lb2 = lb2;
mat -> ub2 = ub2;
mat -> mat_sto = mymat.mat_sto;
mat -> el = mymat.el;
return 1;
}
hidden fprintfdmat (fd, mat)
FILE *fd;
dmat mat;
{
int size, rows;
int nbytes = 0;
double *data;
register int r, c;
/* write out the matrix bounds - 4 ints */
nbytes += fprintf (fd, "%d ", mat.lb1);
nbytes += fprintf (fd, "%d ", mat.ub1);
nbytes += fprintf (fd, "%d ", mat.lb2);
nbytes += fprintf (fd, "%d \n", mat.ub2);
/* write out the matrix data */
for (r = mat.lb1; r <= mat.ub1; r++) {
data = &mat.el[r][mat.lb2];
for (c = mat.lb2; c <= mat.ub2; c++) {
fprintf(fd, "%.12f ", *data++);
}
}
fprintf(fd, "\n");
return 1;
}
hidden fprintfimat (fd, mat)
FILE *fd;
imat mat;
{
int size, rows;
int nbytes = 0;
register int *data;
register int r, c;
/* write out the matrix bounds - 4 ints */
nbytes += fprintf (fd, "%d ", mat.lb1);
nbytes += fprintf (fd, "%d ", mat.ub1);
nbytes += fprintf (fd, "%d ", mat.lb2);
nbytes += fprintf (fd, "%d \n", mat.ub2);
/* write out the matrix data */
for (r = mat.lb1; r <= mat.ub1; r++) {
data = &mat.el[r][mat.lb2];
for (c = mat.lb2; c <= mat.ub2; c++) {
fprintf(fd, "%d ", *data++);
}
}
fprintf(fd, "\n");
return 1;
}
hidden fscanfdmat (fd, mat)
FILE *fd;
dmat *mat;
{
dmat mymat;
int lb1, ub1, lb2, ub2, r, c;
int nbytes = 0;
int err, size, rows;
double *data;
/* read the matrix bounds - 4 ints */
fscanf(fd, "%d ", &lb1);
fscanf(fd, "%d ", &ub1);
fscanf(fd, "%d ", &lb2);
fscanf(fd, "%d \n", &ub2);
/* allocate the matrix */
mymat = newdmat (lb1, ub1, lb2, ub2, &err);
if (err) {
printf("fscanfdmat: can't allocate storage for matrix\n");
return 0;
}
/* find out where to put data and how much there is */
for(r = lb1; r <= ub1; r++) {
data = &mymat.el[r][lb2];
for (c = lb2; c <= ub2; c++) {
fscanf(fd, "%F ", data++);
}
}
fscanf(fd, "\n");
/* copy matrix fields to the outside world */
mat -> lb1 = lb1;
mat -> ub1 = ub1;
mat -> lb2 = lb2;
mat -> ub2 = ub2;
mat -> mat_sto = mymat.mat_sto;
mat -> el = mymat.el;
return 1;
}
hidden fscanfimat (fd, mat)
FILE *fd;
imat *mat;
{
imat mymat;
int lb1, ub1, lb2, ub2, r, c;
int nbytes = 0;
int err, size, rows;
int *data;
/* read the matrix bounds - 4 ints */
fscanf(fd, "%d ", &lb1);
fscanf(fd, "%d ", &ub1);
fscanf(fd, "%d ", &lb2);
fscanf(fd, "%d \n", &ub2);
/* allocate the matrix */
mymat = newimat (lb1, ub1, lb2, ub2, &err);
if (err) {
printf("fscanfimat: can't allocate storage for matrix\n");
return 0;
}
/* find out where to put data and how much there is */
for(r = lb1; r <= ub1; r++) {
data = &mymat.el[r][lb2];
for (c = lb2; c <= ub2; c++) {
fscanf(fd, "%d ", data++);
}
}
fscanf(fd, "\n");
/* copy matrix fields to the outside world */
mat -> lb1 = lb1;
mat -> ub1 = ub1;
mat -> lb2 = lb2;
mat -> ub2 = ub2;
mat -> mat_sto = mymat.mat_sto;
mat -> el = mymat.el;
return 1;
}
/*****************************************************************
* coordmap1 -- transform one x,y point according to the transform
* computed by coordtrans.
*****************************************************************
*/
visible
coordmap1 (x,y,dx,dy)
double x, y, *dx, *dy;
{
int i, pnum;
double sum_x, sum_y, p;
if (tcoefx_dirty == FALSE) {
printf("coordmap1: transformation not yet defined\n");
return;
}
pnum = (Order+1) * (Order+2) / 2;
sum_x = sum_y = 0.;
for (i = 0; i < pnum; i++) {
p = pol(i,x,y);
sum_x += TCOEFX(i) * p;
sum_y += TCOEFY(i) * p;
}
*dx = sum_x;
*dy = sum_y;
return;
}
/*****************************************************************
* transformation cooefficients
* used by both coordequations and coordremap (not included)
*****************************************************************
*/
hidden dmat ccx_vector, ccy_vector;
hidden double **ccx;
hidden double **ccy;
hidden boolean ccx_dirty = FALSE;
hidden boolean ccy_dirty = FALSE;
/*****************************************************************
* coordequations -- determine and print fitting polynomial
*****************************************************************
*/
visible
coordequations (device,file)
char *device; /* scribe device (CRT for tty output) */
char *file;
{
char buf[128];
int fd;
int i, j, l, pnum, pnum1, err;
int previous_term;
double sum, sum_for_x, sum_for_y;
dmat pc_matrix;
double **pc;
pnum = (Order + 1) * (Order + 2) / 2;
pnum1 = pnum - 1;
/*----------------------------------------------------------------
* Allocate temporary storage
*----------------------------------------------------------------
*/
pc_matrix = newdmat (0, pnum1, 0, pnum1, &err);
if (err) {
printf ("\tMemory exhausted.\n");
return (1);
}
pc = pc_matrix.el;
if (ccx_dirty) {
freemat (ccx_vector);
ccx_dirty = FALSE;
}
ccx_vector = newdmat (0, pnum1, 0, 0, &err);
if (err) {
printf ("\tMemory exhausted.\n");
return (1);
}
ccx = ccx_vector.el;
ccx_dirty = TRUE;
if (ccy_dirty) {
freemat (ccy_vector);
ccy_dirty = FALSE;
}
ccy_vector = newdmat (0, pnum1, 0, 0, &err);
if (err) {
printf ("\tMemory exhausted.\n");
return (1);
}
ccy = ccy_vector.el;
ccy_dirty = TRUE;
pc[0][0] = 1.0;
for (i = 1; i < pnum; i++) {
pc[0][i] = 0;
}
for (l = 1; l < pnum; l++) {
if (XDEG (l) == 0) {
for (i = 0; i < pnum; i++) {
for (sum = j = 0; j < l; j++) {
sum += c[l][j] * pc[j][i];
}
if (YDEG (i) == 0) {
pc[l][i] = -sum;
}
else
if (YDEG (i) > 0) {
pc[l][i] = pc[BEFORE (l)][num[XDEG (i)][YDEG (i) - 1]] - sum;
}
} /* end for i */
}
else
if (XDEG (l) > 0) {
for (i = 0; i < pnum; i++) {
for (sum = j = 0; j < l; j++) {
sum += c[l][j] * pc[j][i];
}
if (XDEG (i) == 0) {
pc[l][i] = -sum;
}
else
if (XDEG (i) > 0) {
pc[l][i] = pc[BEFORE (l)][num[XDEG (i) - 1][YDEG (i)]] - sum;
}
} /* end for i */
}
} /* end for l */
for (i = 0; i < pnum; i++) {
for (sum_for_x = sum_for_y = j = 0; j < pnum; j++) {
sum_for_x += TCOEFX (j) * pc[j][i];
sum_for_y += TCOEFY (j) * pc[j][i];
}
CCX (i) = sum_for_x;
CCY (i) = sum_for_y;
}
/*----------------------------------------------------------------
* create new file for output
*----------------------------------------------------------------
*/
fd = creat (file, 0644);
if (fd == -1) {
printf ("Can't open file for output.\n");
freemat (pc_matrix);
return;
}
/*----------------------------------------------------------------
* write out the equations (what a mess!)
*----------------------------------------------------------------
*/
if (strcmp (device, "none") != 0) {
sprintf (buf, "@device(%s)\n\n", device);
write (fd, buf, strlen (buf));
}
sprintf (buf, "dx = ");
write (fd, buf, strlen (buf));
previous_term = 0;
if (CCX (0) != 0.0) {
sprintf (buf, "%lf", CCX (0));
write (fd, buf, strlen (buf));
previous_term = 1;
}
for (i = 1; i < pnum; i++) {
if (CCX (i) != 0.0) {
if (CCX (i) > 0.0) {
if (previous_term) {
sprintf (buf, " + ");
write (fd, buf, strlen (buf));
}
}
else {
sprintf (buf, " - ");
write (fd, buf, strlen (buf));
}
sprintf (buf, "%lf", (CCX (i) >= 0.0) ? CCX (i) : -CCX (i));
write (fd, buf, strlen (buf));
}
else {
continue;
}
if (XDEG (i) != 0) {
sprintf (buf, " x");
write (fd, buf, strlen (buf));
previous_term = 1;
if (XDEG (i) > 1) {
if (strcmp (device, "none") == 0) {
sprintf (buf, "**%d", XDEG(i));
}
else {
sprintf (buf, "@+(%d)", XDEG (i));
}
write (fd, buf, strlen (buf));
}
if (YDEG (i) != 0) {
sprintf (buf, " y");
write (fd, buf, strlen (buf));
if (YDEG (i) > 1) {
if (strcmp (device, "none") == 0) {
sprintf (buf, "**%d", YDEG(i));
}
else {
sprintf (buf, "@+(%d)", YDEG (i));
}
write (fd, buf, strlen (buf));
}
}
}
else {
if (YDEG (i) != 0) {
sprintf (buf, " y");
write (fd, buf, strlen (buf));
previous_term = 1;
if (YDEG (i) > 1) {
if (strcmp (device, "none") == 0) {
sprintf (buf, "**%d", YDEG(i));
}
else {
sprintf (buf, "@+(%d)", YDEG (i));
}
write (fd, buf, strlen (buf));
}
}
}
}
sprintf (buf, "\n\n");
write (fd, buf, strlen (buf));
sprintf (buf, "dy = ");
write (fd, buf, strlen (buf));
previous_term = 0;
if (CCY (0) != 0.0) {
sprintf (buf, "%lf", CCY (0));
write (fd, buf, strlen (buf));
previous_term = 1;
}
for (i = 1; i < pnum; i++) {
if (CCY (i) != 0.0) {
if (CCY (i) > 0.0) {
if (previous_term) {
sprintf (buf, " + ");
write (fd, buf, strlen (buf));
}
}
else {
sprintf (buf, " - ");
write (fd, buf, strlen (buf));
}
sprintf (buf, "%lf", (CCY (i) >= 0.0) ? CCY (i) : -CCY (i));
write (fd, buf, strlen (buf));
}
else {
continue;
}
if (XDEG (i) != 0) {
sprintf (buf, " x");
write (fd, buf, strlen (buf));
previous_term = 1;
if (XDEG (i) > 1) {
if (strcmp (device, "none") == 0) {
sprintf (buf, "**%d", XDEG(i));
}
else {
sprintf (buf, "@+(%d)", XDEG (i));
}
write (fd, buf, strlen (buf));
}
if (YDEG (i) != 0) {
sprintf (buf, " y");
write (fd, buf, strlen (buf));
if (YDEG (i) > 1) {
if (strcmp (device, "none") == 0) {
sprintf (buf, "**%d", YDEG(i));
}
else {
sprintf (buf, "@+(%d)", YDEG (i));
}
write (fd, buf, strlen (buf));
}
}
}
else
if (YDEG (i) != 0) {
sprintf (buf, " y");
write (fd, buf, strlen (buf));
previous_term = 1;
if (YDEG (i) > 1) {
if (strcmp (device, "none") == 0) {
sprintf (buf, "**%d", YDEG(i));
}
else {
sprintf (buf, "@+(%d)", YDEG (i));
}
write (fd, buf, strlen (buf));
}
}
}
sprintf (buf, "\n");
write (fd, buf, strlen (buf));
close (fd);
freemat (pc_matrix);
}
/******************************************************************************
* coordsetup -- allocate space for multiple transforms
******************************************************************************
*/
visible
coordsetup (n)
int n;
{
int i;
if (scount != -1) {
printf ("coordsetup: space has already been allocated\n");
return 0;
}
if (n < 0) {
printf ("coordsetup: can't allocate %d transforms\n", n);
return 0;
}
scount = n;
stcoefx_vector = (dmat *) malloc (n * sizeof (dmat));
stcoefy_vector = (dmat *) malloc (n * sizeof (dmat));
sc_matrix = (dmat *) malloc (n * sizeof (dmat));
sbp_vector = (dmat *) malloc (n * sizeof (dmat));
snum_matrix = (imat *) malloc (n * sizeof (imat));
sydeg_vector = (imat *) malloc (n * sizeof (imat));
sxdeg_vector = (imat *) malloc (n * sizeof (imat));
sbefore_vector = (imat *) malloc (n * sizeof (imat));
stcoefx_dirty = (boolean *) malloc (n * sizeof (boolean));
stcoefy_dirty = (boolean *) malloc (n * sizeof (boolean));
sc_dirty = (boolean *) malloc (n * sizeof (boolean));
sbp_dirty = (boolean *) malloc (n * sizeof (boolean));
snum_dirty = (boolean *) malloc (n * sizeof (boolean));
sydeg_dirty = (boolean *) malloc (n * sizeof (boolean));
sxdeg_dirty = (boolean *) malloc (n * sizeof (boolean));
sbefore_dirty = (boolean *) malloc (n * sizeof (boolean));
for (i = 0; i < n; i++)
stcoefx_dirty[i] = stcoefy_dirty[i] = sc_dirty[i] = sbp_dirty[i] =
sydeg_dirty[i] = sxdeg_dirty[i] = sbefore_dirty[i] = snum_dirty[i] = FALSE;
return 1;
}
/******************************************************************************
* coordstore -- store the current transform
******************************************************************************
*/
visible
coordstore (n)
int n;
{
if (scount == -1) {
printf ("coordstore: no space allocated\n");
return 0;
}
if ((n < 0) || (n > scount)) {
printf ("coordstore: don't have %d records allocated\n", n);
return 0;
}
if (stcoefx_dirty[n]) freemat (stcoefx_vector[n]);
stcoefx_vector[n] = tcoefx_vector;
tcoefx_dirty = FALSE;
stcoefx_dirty[n] = TRUE;
if (stcoefy_dirty[n]) freemat (stcoefy_vector[n]);
stcoefy_vector[n] = tcoefy_vector;
tcoefy_dirty = FALSE;
stcoefy_dirty[n] = TRUE;
if (sbp_dirty[n]) freemat (sbp_vector[n]);
sbp_vector[n] = bp_vector;
bp_dirty = FALSE;
sbp_dirty[n] = TRUE;
if (sc_dirty[n]) freemat (sc_matrix[n]);
sc_matrix[n] = c_matrix;
c_dirty = FALSE;
sc_dirty[n] = TRUE;
if (sxdeg_dirty[n]) freemat (sxdeg_vector[n]);
sxdeg_vector[n] = xdeg_vector;
xdeg_dirty = FALSE;
sxdeg_dirty[n] = TRUE;
if (sydeg_dirty[n]) freemat (sydeg_vector[n]);
sydeg_vector[n] = ydeg_vector;
ydeg_dirty = FALSE;
sydeg_dirty[n] = TRUE;
if (sbefore_dirty[n]) freemat (sbefore_vector[n]);
sbefore_vector[n] = before_vector;
before_dirty = FALSE;
sbefore_dirty[n] = TRUE;
if (snum_dirty[n]) freemat (snum_matrix[n]);
snum_matrix[n] = num_matrix;
num_dirty = FALSE;
snum_dirty[n] = TRUE;
return 1;
}
/******************************************************************************
* coordsel -- retrieve transform from storage
******************************************************************************
*/
visible
coordsel (n)
int n;
{
if (scount == -1) {
printf ("coordsel: no transforms stored\n");
return 0;
}
if ((n < 0) || (n > scount)) {
printf ("coordsel: don't have %d transforms\n", n);
return 0;
}
if (stcoefx_dirty[n] == FALSE) {
printf ("coordsel: transform %d not stored\n", n);
return 0;
}
if (n == scount) return 1;
tcoefx_vector = stcoefx_vector[n];
tcoefy_vector = stcoefy_vector[n];
c_matrix = sc_matrix[n];
bp_vector = sbp_vector[n];
num_matrix = snum_matrix[n];
xdeg_vector = sxdeg_vector[n];
ydeg_vector = sydeg_vector[n];
before_vector = sbefore_vector[n];
tcoefx = tcoefx_vector.el;
tcoefy = tcoefy_vector.el;
c = c_matrix.el;
bp = bp_vector.el;
num = num_matrix.el;
xdeg = xdeg_vector.el;
ydeg = ydeg_vector.el;
before = before_vector.el;
tcoefx_dirty = TRUE;
tcoefy_dirty = TRUE;
c_dirty = TRUE;
bp_dirty = TRUE;
num_dirty = TRUE;
xdeg_dirty = TRUE;
ydeg_dirty = TRUE;
before_dirty = TRUE;
Order = num_matrix.ub1;
return 1;
}