13
18
*****************************************************************************/
15
#include <grass/config.h>
23
* Last Update: 12/26/91 Brian J. Buckley
24
* Last Update: 1/24/92 Brian J. Buckley
25
* Added printout of trnfile. Triggered by BDEBUG.
26
* Last Update: 1/27/92 Brian J. Buckley
27
* Fixed bug so that only the active control points were used.
34
#include <grass/gis.h>
16
35
#include <grass/imagery.h>
17
36
#include <signal.h>
19
static int floating_exception;
20
static void catch(int);
21
static double determinant(double, double,
22
double, double, double, double, double, double,
25
/* find coefficients A,B,C for e2 = A + B*e1 + C*n1
26
* also compute the reverse equations
28
* return 0 if no points
32
* method is least squares.
33
* the least squares problem reduces to solving the following
34
* system of equations for A,B,C
36
* s0*A + s1*B + s2*C = x0
37
* s1*A + s3*B + s4*C = x1
38
* s2*A + s4*B + s5*C = x2
42
* | x0 s1 s2 | | s0 x0 s2 | | s0 s1 x0 |
43
* | x1 s3 s4 | | s1 x1 s4 | | s1 s3 x1 |
44
* | x2 s4 s5 | | s2 x2 s5 | | s2 s4 x2 |
45
* A = ------------ B = ------------ C = ------------
46
* | s0 s1 s2 | | s0 s1 s2 | | s0 s1 s2 |
47
* | s1 s3 s4 | | s1 s3 s4 | | s1 s3 s4 |
48
* | s2 s4 s5 | | s2 s4 s5 | | s2 s4 s5 |
52
int I_compute_georef_equations(struct Control_Points *cp,
53
double E12[3], double N12[3], double E21[3],
56
RETSIGTYPE(*sigfpe) (int);
57
double s0, s1, s2, s3, s4, s5;
63
s0 = s1 = s2 = s3 = s4 = s5 = 0.0;
64
for (i = 0; i < cp->count; i++) {
65
if (cp->status[i] <= 0)
70
s3 += cp->e1[i] * cp->e1[i];
71
s4 += cp->e1[i] * cp->n1[i];
72
s5 += cp->n1[i] * cp->n1[i];
77
floating_exception = 0;
78
sigfpe = signal(SIGFPE, catch);
82
for (i = 0; i < cp->count; i++) {
83
if (cp->status[i] <= 0)
86
x1 += cp->e1[i] * cp->e2[i];
87
x2 += cp->n1[i] * cp->e2[i];
90
det = determinant(s0, s1, s2, s1, s3, s4, s2, s4, s5);
92
signal(SIGFPE, sigfpe);
95
E12[0] = determinant(x0, s1, s2, x1, s3, s4, x2, s4, s5) / det;
96
E12[1] = determinant(s0, x0, s2, s1, x1, s4, s2, x2, s5) / det;
97
E12[2] = determinant(s0, s1, x0, s1, s3, x1, s2, s4, x2) / det;
101
for (i = 0; i < cp->count; i++) {
102
if (cp->status[i] <= 0)
105
x1 += cp->e1[i] * cp->n2[i];
106
x2 += cp->n1[i] * cp->n2[i];
109
det = determinant(s0, s1, s2, s1, s3, s4, s2, s4, s5);
111
signal(SIGFPE, sigfpe);
114
N12[0] = determinant(x0, s1, s2, x1, s3, s4, x2, s4, s5) / det;
115
N12[1] = determinant(s0, x0, s2, s1, x1, s4, s2, x2, s5) / det;
116
N12[2] = determinant(s0, s1, x0, s1, s3, x1, s2, s4, x2) / det;
118
/* the inverse equations */
120
s0 = s1 = s2 = s3 = s4 = s5 = 0.0;
121
for (i = 0; i < cp->count; i++) {
122
if (cp->status[i] <= 0)
127
s3 += cp->e2[i] * cp->e2[i];
128
s4 += cp->e2[i] * cp->n2[i];
129
s5 += cp->n2[i] * cp->n2[i];
134
for (i = 0; i < cp->count; i++) {
135
if (cp->status[i] <= 0)
138
x1 += cp->e2[i] * cp->e1[i];
139
x2 += cp->n2[i] * cp->e1[i];
142
det = determinant(s0, s1, s2, s1, s3, s4, s2, s4, s5);
144
signal(SIGFPE, sigfpe);
147
E21[0] = determinant(x0, s1, s2, x1, s3, s4, x2, s4, s5) / det;
148
E21[1] = determinant(s0, x0, s2, s1, x1, s4, s2, x2, s5) / det;
149
E21[2] = determinant(s0, s1, x0, s1, s3, x1, s2, s4, x2) / det;
153
for (i = 0; i < cp->count; i++) {
154
if (cp->status[i] <= 0)
157
x1 += cp->e2[i] * cp->n1[i];
158
x2 += cp->n2[i] * cp->n1[i];
161
det = determinant(s0, s1, s2, s1, s3, s4, s2, s4, s5);
163
signal(SIGFPE, sigfpe);
166
N21[0] = determinant(x0, s1, s2, x1, s3, s4, x2, s4, s5) / det;
167
N21[1] = determinant(s0, x0, s2, s1, x1, s4, s2, x2, s5) / det;
168
N21[2] = determinant(s0, s1, x0, s1, s3, x1, s2, s4, x2) / det;
170
signal(SIGFPE, sigfpe);
171
return floating_exception ? -1 : 1;
174
static double determinant(double a, double b, double c, double d, double e,
175
double f, double g, double h, double i)
177
/* compute determinant of 3x3 matrix
182
return a * (e * i - f * h) - b * (d * i - f * g) + c * (d * h - e * g);
185
static void catch(int n)
187
floating_exception = 1;
191
int I_georef(double e1, double n1,
192
double *e2, double *n2, double E[3], double N[3])
194
*e2 = E[0] + E[1] * e1 + E[2] * n1;
195
*n2 = N[0] + N[1] * e1 + N[2] * n1;
38
/* STRUCTURE FOR USE INTERNALLY WITH THESE FUNCTIONS. THESE FUNCTIONS EXPECT
39
SQUARE MATRICES SO ONLY ONE VARIABLE IS GIVEN (N) FOR THE MATRIX SIZE */
43
int n; /* SIZE OF THIS MATRIX (N x N) */
47
/* CALCULATE OFFSET INTO ARRAY BASED ON R/C */
49
#define M(row,col) m->v[(((row)-1)*(m->n))+(col)-1]
51
#define MSUCCESS 1 /* SUCCESS */
52
#define MNPTERR 0 /* NOT ENOUGH POINTS */
53
#define MUNSOLVABLE -1 /* NOT SOLVABLE */
54
#define MMEMERR -2 /* NOT ENOUGH MEMORY */
55
#define MPARMERR -3 /* PARAMETER ERROR */
56
#define MINTERR -4 /* INTERNAL ERROR */
58
#define MAXORDER 3 /* HIGHEST SUPPORTED ORDER OF TRANSFORMATION */
60
/***********************************************************************
62
FUNCTION PROTOTYPES FOR STATIC (INTERNAL) FUNCTIONS
64
************************************************************************/
66
static int calccoef(struct Control_Points *, double *, double *, int);
67
static int calcls(struct Control_Points *, struct MATRIX *, double *,
68
double *, double *, double *);
69
static int exactdet(struct Control_Points *, struct MATRIX *, double *,
70
double *, double *, double *);
71
static int solvemat(struct MATRIX *, double *, double *, double *, double *);
72
static double term(int, double, double);
74
/***********************************************************************
76
TRANSFORM A SINGLE COORDINATE PAIR.
78
************************************************************************/
80
int I_georef(double e1, /* EASTING TO BE TRANSFORMED */
81
double n1, /* NORTHING TO BE TRANSFORMED */
82
double *e, /* EASTING, TRANSFORMED */
83
double *n, /* NORTHING, TRANSFORMED */
84
double E[], /* EASTING COEFFICIENTS */
85
double N[], /* NORTHING COEFFICIENTS */
86
int order /* ORDER OF TRANSFORMATION TO BE PERFORMED, MUST MATCH THE
87
ORDER USED TO CALCULATE THE COEFFICIENTS */
90
double e3, e2n, en2, n3, e2, en, n2;
94
*e = E[0] + E[1] * e1 + E[2] * n1;
95
*n = N[0] + N[1] * e1 + N[2] * n1;
103
*e = E[0] + E[1] * e1 + E[2] * n1 + E[3] * e2 + E[4] * en + E[5] * n2;
104
*n = N[0] + N[1] * e1 + N[2] * n1 + N[3] * e2 + N[4] * en + N[5] * n2;
117
E[1] * e1 + E[2] * n1 +
118
E[3] * e2 + E[4] * en + E[5] * n2 +
119
E[6] * e3 + E[7] * e2n + E[8] * en2 + E[9] * n3;
121
N[1] * e1 + N[2] * n1 +
122
N[3] * e2 + N[4] * en + N[5] * n2 +
123
N[6] * e3 + N[7] * e2n + N[8] * en2 + N[9] * n3;
133
/***********************************************************************
135
COMPUTE THE FORWARD AND BACKWARD GEOREFFERENCING COEFFICIENTS
136
BASED ON A SET OF CONTROL POINTS
138
************************************************************************/
140
int I_compute_georef_equations(struct Control_Points *cp, double E12[],
141
double N12[], double E21[], double N21[],
147
if (order < 1 || order > MAXORDER)
150
/* CALCULATE THE FORWARD TRANSFORMATION COEFFICIENTS */
152
status = calccoef(cp, E12, N12, order);
154
if (status != MSUCCESS)
157
/* SWITCH THE 1 AND 2 EASTING AND NORTHING ARRAYS */
166
/* CALCULATE THE BACKWARD TRANSFORMATION COEFFICIENTS */
168
status = calccoef(cp, E21, N21, order);
170
/* SWITCH THE 1 AND 2 EASTING AND NORTHING ARRAYS BACK */
182
/***********************************************************************
184
COMPUTE THE GEOREFFERENCING COEFFICIENTS
185
BASED ON A SET OF CONTROL POINTS
187
************************************************************************/
189
static int calccoef(struct Control_Points *cp, double E[], double N[],
195
int numactive; /* NUMBER OF ACTIVE CONTROL POINTS */
198
/* CALCULATE THE NUMBER OF VALID CONTROL POINTS */
200
for (i = numactive = 0; i < cp->count; i++) {
201
if (cp->status[i] > 0)
205
/* CALCULATE THE MINIMUM NUMBER OF CONTROL POINTS NEEDED TO DETERMINE
206
A TRANSFORMATION OF THIS ORDER */
208
m.n = ((order + 1) * (order + 2)) / 2;
213
/* INITIALIZE MATRIX */
215
m.v = G_calloc(m.n * m.n, sizeof(double));
216
a = G_calloc(m.n, sizeof(double));
217
b = G_calloc(m.n, sizeof(double));
219
if (numactive == m.n)
220
status = exactdet(cp, &m, a, b, E, N);
222
status = calcls(cp, &m, a, b, E, N);
231
/***********************************************************************
233
CALCULATE THE TRANSFORMATION COEFFICIENTS WITH EXACTLY THE MINIMUM
234
NUMBER OF CONTROL POINTS REQUIRED FOR THIS TRANSFORMATION.
236
************************************************************************/
238
static int exactdet(struct Control_Points *cp, struct MATRIX *m,
239
double a[], double b[],
240
double E[], /* EASTING COEFFICIENTS */
241
double N[] /* NORTHING COEFFICIENTS */
244
int pntnow, currow, j;
247
for (pntnow = 0; pntnow < cp->count; pntnow++) {
248
if (cp->status[pntnow] > 0) {
249
/* POPULATE MATRIX M */
251
for (j = 1; j <= m->n; j++)
252
M(currow, j) = term(j, cp->e1[pntnow], cp->n1[pntnow]);
254
/* POPULATE MATRIX A AND B */
256
a[currow - 1] = cp->e2[pntnow];
257
b[currow - 1] = cp->n2[pntnow];
263
if (currow - 1 != m->n)
266
return solvemat(m, a, b, E, N);
269
/***********************************************************************
271
CALCULATE THE TRANSFORMATION COEFFICIENTS WITH MORE THAN THE MINIMUM
272
NUMBER OF CONTROL POINTS REQUIRED FOR THIS TRANSFORMATION. THIS
273
ROUTINE USES THE LEAST SQUARES METHOD TO COMPUTE THE COEFFICIENTS.
275
************************************************************************/
277
static int calcls(struct Control_Points *cp, struct MATRIX *m,
278
double a[], double b[],
279
double E[], /* EASTING COEFFICIENTS */
280
double N[] /* NORTHING COEFFICIENTS */
283
int i, j, n, numactive = 0;
285
/* INITIALIZE THE UPPER HALF OF THE MATRIX AND THE TWO COLUMN VECTORS */
287
for (i = 1; i <= m->n; i++) {
288
for (j = i; j <= m->n; j++)
290
a[i - 1] = b[i - 1] = 0.0;
293
/* SUM THE UPPER HALF OF THE MATRIX AND THE COLUMN VECTORS ACCORDING TO
294
THE LEAST SQUARES METHOD OF SOLVING OVER DETERMINED SYSTEMS */
296
for (n = 0; n < cp->count; n++) {
297
if (cp->status[n] > 0) {
299
for (i = 1; i <= m->n; i++) {
300
for (j = i; j <= m->n; j++)
302
term(i, cp->e1[n], cp->n1[n]) * term(j, cp->e1[n],
305
a[i - 1] += cp->e2[n] * term(i, cp->e1[n], cp->n1[n]);
306
b[i - 1] += cp->n2[n] * term(i, cp->e1[n], cp->n1[n]);
311
if (numactive <= m->n)
314
/* TRANSPOSE VALUES IN UPPER HALF OF M TO OTHER HALF */
316
for (i = 2; i <= m->n; i++)
317
for (j = 1; j < i; j++)
320
return solvemat(m, a, b, E, N);
323
/***********************************************************************
325
CALCULATE THE X/Y TERM BASED ON THE TERM NUMBER
327
ORDER\TERM 1 2 3 4 5 6 7 8 9 10
329
2 e0n0 e1n0 e0n1 e2n0 e1n1 e0n2
330
3 e0n0 e1n0 e0n1 e2n0 e1n1 e0n2 e3n0 e2n1 e1n2 e0n3
332
************************************************************************/
334
static double term(int term, double e, double n)
362
/***********************************************************************
364
SOLVE FOR THE 'E' AND 'N' COEFFICIENTS BY USING A SOMEWHAT MODIFIED
365
GAUSSIAN ELIMINATION METHOD.
367
| M11 M12 ... M1n | | E0 | | a0 |
368
| M21 M22 ... M2n | | E1 | = | a1 |
369
| . . . . | | . | | . |
370
| Mn1 Mn2 ... Mnn | | En-1 | | an-1 |
374
| M11 M12 ... M1n | | N0 | | b0 |
375
| M21 M22 ... M2n | | N1 | = | b1 |
376
| . . . . | | . | | . |
377
| Mn1 Mn2 ... Mnn | | Nn-1 | | bn-1 |
379
************************************************************************/
381
static int solvemat(struct MATRIX *m, double a[], double b[], double E[],
384
int i, j, i2, j2, imark;
386
double pivot; /* ACTUAL VALUE OF THE LARGEST PIVOT CANDIDATE */
388
for (i = 1; i <= m->n; i++) {
391
/* find row with largest magnitude value for pivot value */
395
for (i2 = i + 1; i2 <= m->n; i2++) {
396
temp = fabs(M(i2, j));
397
if (temp > fabs(pivot)) {
403
/* if the pivot is very small then the points are nearly co-linear */
404
/* co-linear points result in an undefined matrix, and nearly */
405
/* co-linear points results in a solution with rounding error */
410
/* if row with highest pivot is not the current row, switch them */
413
for (j2 = 1; j2 <= m->n; j2++) {
415
M(imark, j2) = M(i, j2);
420
a[imark - 1] = a[i - 1];
424
b[imark - 1] = b[i - 1];
428
/* compute zeros above and below the pivot, and compute
429
values for the rest of the row as well */
431
for (i2 = 1; i2 <= m->n; i2++) {
433
factor = M(i2, j) / pivot;
434
for (j2 = j; j2 <= m->n; j2++)
435
M(i2, j2) -= factor * M(i, j2);
436
a[i2 - 1] -= factor * a[i - 1];
437
b[i2 - 1] -= factor * b[i - 1];
442
/* SINCE ALL OTHER VALUES IN THE MATRIX ARE ZERO NOW, CALCULATE THE
443
COEFFICIENTS BY DIVIDING THE COLUMN VECTORS BY THE DIAGONAL VALUES. */
445
for (i = 1; i <= m->n; i++) {
446
E[i - 1] = a[i - 1] / M(i, i);
447
N[i - 1] = b[i - 1] / M(i, i);