GRASS 8 Programmer's Manual 8.6.0dev(2026)-1d1e47ad9d
Loading...
Searching...
No Matches
georef.c
Go to the documentation of this file.
1/****************************************************************************
2 *
3 * MODULE: imagery library
4 * AUTHOR(S): Original author(s) name(s) unknown - written by CERL
5 * Written By: Brian J. Buckley
6 *
7 * At: The Center for Remote Sensing
8 * Michigan State University
9 *
10 * PURPOSE: Image processing library
11 * COPYRIGHT: (C) 1999, 2005 by the GRASS Development Team
12 *
13 * This program is free software under the GNU General Public
14 * License (>=v2). Read the file COPYING that comes with GRASS
15 * for details.
16 *
17 *****************************************************************************/
18
19/*
20 * Written: 12/19/91
21 *
22 * Last Update: 12/26/91 Brian J. Buckley
23 * Last Update: 1/24/92 Brian J. Buckley
24 * Added printout of trnfile. Triggered by BDEBUG.
25 * Last Update: 1/27/92 Brian J. Buckley
26 * Fixed bug so that only the active control points were used.
27 *
28 */
29
30#include <stdlib.h>
31#include <math.h>
32#include <grass/gis.h>
33#include <grass/imagery.h>
34#include <signal.h>
35
36/* STRUCTURE FOR USE INTERNALLY WITH THESE FUNCTIONS. THESE FUNCTIONS EXPECT
37 SQUARE MATRICES SO ONLY ONE VARIABLE IS GIVEN (N) FOR THE MATRIX SIZE */
38
39struct MATRIX {
40 int n; /* SIZE OF THIS MATRIX (N x N) */
41 double *v;
42};
43
44/* CALCULATE OFFSET INTO ARRAY BASED ON R/C */
45
46#define M(row, col) m->v[(((row) - 1) * (m->n)) + (col) - 1]
47
48#define MSUCCESS 1 /* SUCCESS */
49#define MNPTERR 0 /* NOT ENOUGH POINTS */
50#define MUNSOLVABLE -1 /* NOT SOLVABLE */
51#define MMEMERR -2 /* NOT ENOUGH MEMORY */
52#define MPARMERR -3 /* PARAMETER ERROR */
53#define MINTERR -4 /* INTERNAL ERROR */
54
55#define MAXORDER 3 /* HIGHEST SUPPORTED ORDER OF TRANSFORMATION */
56
57/***********************************************************************
58
59 FUNCTION PROTOTYPES FOR STATIC (INTERNAL) FUNCTIONS
60
61************************************************************************/
62
63static int calccoef(struct Control_Points *, double *, double *, int);
64static int calcls(struct Control_Points *, struct MATRIX *, double *, double *,
65 double *, double *);
66static int exactdet(struct Control_Points *, struct MATRIX *, double *,
67 double *, double *, double *);
68static int solvemat(struct MATRIX *, double *, double *, double *, double *);
69static double term(int, double, double);
70
71/***********************************************************************
72
73 TRANSFORM A SINGLE COORDINATE PAIR.
74
75************************************************************************/
76
77int I_georef(double e1, /* EASTING TO BE TRANSFORMED */
78 double n1, /* NORTHING TO BE TRANSFORMED */
79 double *e, /* EASTING, TRANSFORMED */
80 double *n, /* NORTHING, TRANSFORMED */
81 double E[], /* EASTING COEFFICIENTS */
82 double N[], /* NORTHING COEFFICIENTS */
83 int order /* ORDER OF TRANSFORMATION TO BE PERFORMED, MUST MATCH
84 THE ORDER USED TO CALCULATE THE COEFFICIENTS */
85)
86{
87 double e3, e2n, en2, n3, e2, en, n2;
88
89 switch (order) {
90 case 1:
91 *e = E[0] + E[1] * e1 + E[2] * n1;
92 *n = N[0] + N[1] * e1 + N[2] * n1;
93 break;
94
95 case 2:
96 e2 = e1 * e1;
97 n2 = n1 * n1;
98 en = e1 * n1;
99
100 *e = E[0] + E[1] * e1 + E[2] * n1 + E[3] * e2 + E[4] * en + E[5] * n2;
101 *n = N[0] + N[1] * e1 + N[2] * n1 + N[3] * e2 + N[4] * en + N[5] * n2;
102 break;
103
104 case 3:
105 e2 = e1 * e1;
106 en = e1 * n1;
107 n2 = n1 * n1;
108 e3 = e1 * e2;
109 e2n = e2 * n1;
110 en2 = e1 * n2;
111 n3 = n1 * n2;
112
113 *e = E[0] + E[1] * e1 + E[2] * n1 + E[3] * e2 + E[4] * en + E[5] * n2 +
114 E[6] * e3 + E[7] * e2n + E[8] * en2 + E[9] * n3;
115 *n = N[0] + N[1] * e1 + N[2] * n1 + N[3] * e2 + N[4] * en + N[5] * n2 +
116 N[6] * e3 + N[7] * e2n + N[8] * en2 + N[9] * n3;
117 break;
118
119 default:
120 return MPARMERR;
121 }
122
123 return MSUCCESS;
124}
125
126/***********************************************************************
127
128 COMPUTE THE FORWARD AND BACKWARD GEOREFFERENCING COEFFICIENTS
129 BASED ON A SET OF CONTROL POINTS
130
131************************************************************************/
132
134 double N12[], double E21[], double N21[],
135 int order)
136{
137 double *tempptr;
138 int status;
139
141 return MPARMERR;
142
143 /* CALCULATE THE FORWARD TRANSFORMATION COEFFICIENTS */
144
145 status = calccoef(cp, E12, N12, order);
146
147 if (status != MSUCCESS)
148 return status;
149
150 /* SWITCH THE 1 AND 2 EASTING AND NORTHING ARRAYS */
151
152 tempptr = cp->e1;
153 cp->e1 = cp->e2;
154 cp->e2 = tempptr;
155 tempptr = cp->n1;
156 cp->n1 = cp->n2;
157 cp->n2 = tempptr;
158
159 /* CALCULATE THE BACKWARD TRANSFORMATION COEFFICIENTS */
160
161 status = calccoef(cp, E21, N21, order);
162
163 /* SWITCH THE 1 AND 2 EASTING AND NORTHING ARRAYS BACK */
164
165 tempptr = cp->e1;
166 cp->e1 = cp->e2;
167 cp->e2 = tempptr;
168 tempptr = cp->n1;
169 cp->n1 = cp->n2;
170 cp->n2 = tempptr;
171
172 return status;
173}
174
175/***********************************************************************
176
177 COMPUTE THE GEOREFFERENCING COEFFICIENTS
178 BASED ON A SET OF CONTROL POINTS
179
180************************************************************************/
181
182static int calccoef(struct Control_Points *cp, double E[], double N[],
183 int order)
184{
185 struct MATRIX m;
186 double *a;
187 double *b;
188 int numactive; /* NUMBER OF ACTIVE CONTROL POINTS */
189 int status, i;
190
191 /* CALCULATE THE NUMBER OF VALID CONTROL POINTS */
192
193 for (i = numactive = 0; i < cp->count; i++) {
194 if (cp->status[i] > 0)
195 numactive++;
196 }
197
198 /* CALCULATE THE MINIMUM NUMBER OF CONTROL POINTS NEEDED TO DETERMINE
199 A TRANSFORMATION OF THIS ORDER */
200
201 m.n = ((order + 1) * (order + 2)) / 2;
202
203 if (numactive < m.n)
204 return MNPTERR;
205
206 /* INITIALIZE MATRIX */
207
208 m.v = G_calloc(m.n * m.n, sizeof(double));
209 a = G_calloc(m.n, sizeof(double));
210 b = G_calloc(m.n, sizeof(double));
211
212 if (numactive == m.n)
213 status = exactdet(cp, &m, a, b, E, N);
214 else
215 status = calcls(cp, &m, a, b, E, N);
216
217 G_free(m.v);
218 G_free(a);
219 G_free(b);
220
221 return status;
222}
223
224/***********************************************************************
225
226 CALCULATE THE TRANSFORMATION COEFFICIENTS WITH EXACTLY THE MINIMUM
227 NUMBER OF CONTROL POINTS REQUIRED FOR THIS TRANSFORMATION.
228
229************************************************************************/
230
231static int exactdet(struct Control_Points *cp, struct MATRIX *m, double a[],
232 double b[], double E[], /* EASTING COEFFICIENTS */
233 double N[] /* NORTHING COEFFICIENTS */
234)
235{
236 int pntnow, currow, j;
237
238 currow = 1;
239 for (pntnow = 0; pntnow < cp->count; pntnow++) {
240 if (cp->status[pntnow] > 0) {
241 /* POPULATE MATRIX M */
242
243 for (j = 1; j <= m->n; j++)
244 M(currow, j) = term(j, cp->e1[pntnow], cp->n1[pntnow]);
245
246 /* POPULATE MATRIX A AND B */
247
248 a[currow - 1] = cp->e2[pntnow];
249 b[currow - 1] = cp->n2[pntnow];
250
251 currow++;
252 }
253 }
254
255 if (currow - 1 != m->n)
256 return MINTERR;
257
258 return solvemat(m, a, b, E, N);
259}
260
261/***********************************************************************
262
263 CALCULATE THE TRANSFORMATION COEFFICIENTS WITH MORE THAN THE MINIMUM
264 NUMBER OF CONTROL POINTS REQUIRED FOR THIS TRANSFORMATION. THIS
265 ROUTINE USES THE LEAST SQUARES METHOD TO COMPUTE THE COEFFICIENTS.
266
267************************************************************************/
268
269static int calcls(struct Control_Points *cp, struct MATRIX *m, double a[],
270 double b[], double E[], /* EASTING COEFFICIENTS */
271 double N[] /* NORTHING COEFFICIENTS */
272)
273{
274 int i, j, n, numactive = 0;
275
276 /* INITIALIZE THE UPPER HALF OF THE MATRIX AND THE TWO COLUMN VECTORS */
277
278 for (i = 1; i <= m->n; i++) {
279 for (j = i; j <= m->n; j++)
280 M(i, j) = 0.0;
281 a[i - 1] = b[i - 1] = 0.0;
282 }
283
284 /* SUM THE UPPER HALF OF THE MATRIX AND THE COLUMN VECTORS ACCORDING TO
285 THE LEAST SQUARES METHOD OF SOLVING OVER DETERMINED SYSTEMS */
286
287 for (n = 0; n < cp->count; n++) {
288 if (cp->status[n] > 0) {
289 numactive++;
290 for (i = 1; i <= m->n; i++) {
291 for (j = i; j <= m->n; j++)
292 M(i, j) += term(i, cp->e1[n], cp->n1[n]) *
293 term(j, cp->e1[n], cp->n1[n]);
294
295 a[i - 1] += cp->e2[n] * term(i, cp->e1[n], cp->n1[n]);
296 b[i - 1] += cp->n2[n] * term(i, cp->e1[n], cp->n1[n]);
297 }
298 }
299 }
300
301 if (numactive <= m->n)
302 return MINTERR;
303
304 /* TRANSPOSE VALUES IN UPPER HALF OF M TO OTHER HALF */
305
306 for (i = 2; i <= m->n; i++)
307 for (j = 1; j < i; j++)
308 M(i, j) = M(j, i);
309
310 return solvemat(m, a, b, E, N);
311}
312
313/***********************************************************************
314
315 CALCULATE THE X/Y TERM BASED ON THE TERM NUMBER
316
317 ORDER\TERM 1 2 3 4 5 6 7 8 9 10
318 1 e0n0 e1n0 e0n1
319 2 e0n0 e1n0 e0n1 e2n0 e1n1 e0n2
320 3 e0n0 e1n0 e0n1 e2n0 e1n1 e0n2 e3n0 e2n1 e1n2 e0n3
321
322************************************************************************/
323
324static double term(int term, double e, double n)
325{
326 switch (term) {
327 case 1:
328 return 1.0;
329 case 2:
330 return e;
331 case 3:
332 return n;
333 case 4:
334 return e * e;
335 case 5:
336 return e * n;
337 case 6:
338 return n * n;
339 case 7:
340 return e * e * e;
341 case 8:
342 return e * e * n;
343 case 9:
344 return e * n * n;
345 case 10:
346 return n * n * n;
347 }
348
349 return 0.0;
350}
351
352/***********************************************************************
353
354 SOLVE FOR THE 'E' AND 'N' COEFFICIENTS BY USING A SOMEWHAT MODIFIED
355 GAUSSIAN ELIMINATION METHOD.
356
357 | M11 M12 ... M1n | | E0 | | a0 |
358 | M21 M22 ... M2n | | E1 | = | a1 |
359 | . . . . | | . | | . |
360 | Mn1 Mn2 ... Mnn | | En-1 | | an-1 |
361
362 and
363
364 | M11 M12 ... M1n | | N0 | | b0 |
365 | M21 M22 ... M2n | | N1 | = | b1 |
366 | . . . . | | . | | . |
367 | Mn1 Mn2 ... Mnn | | Nn-1 | | bn-1 |
368
369************************************************************************/
370
371static int solvemat(struct MATRIX *m, double a[], double b[], double E[],
372 double N[])
373{
374 int i, j, i2, j2, imark;
375 double factor, temp;
376 double pivot; /* ACTUAL VALUE OF THE LARGEST PIVOT CANDIDATE */
377
378 for (i = 1; i <= m->n; i++) {
379 j = i;
380
381 /* find row with largest magnitude value for pivot value */
382
383 pivot = M(i, j);
384 imark = i;
385 for (i2 = i + 1; i2 <= m->n; i2++) {
386 temp = fabs(M(i2, j));
387 if (temp > fabs(pivot)) {
388 pivot = M(i2, j);
389 imark = i2;
390 }
391 }
392
393 /* if the pivot is very small then the points are nearly co-linear */
394 /* co-linear points result in an undefined matrix, and nearly */
395 /* co-linear points results in a solution with rounding error */
396
397 if (pivot == 0.0)
398 return MUNSOLVABLE;
399
400 /* if row with highest pivot is not the current row, switch them */
401
402 if (imark != i) {
403 for (j2 = 1; j2 <= m->n; j2++) {
404 temp = M(imark, j2);
405 M(imark, j2) = M(i, j2);
406 M(i, j2) = temp;
407 }
408
409 temp = a[imark - 1];
410 a[imark - 1] = a[i - 1];
411 a[i - 1] = temp;
412
413 temp = b[imark - 1];
414 b[imark - 1] = b[i - 1];
415 b[i - 1] = temp;
416 }
417
418 /* compute zeros above and below the pivot, and compute
419 values for the rest of the row as well */
420
421 for (i2 = 1; i2 <= m->n; i2++) {
422 if (i2 != i) {
423 factor = M(i2, j) / pivot;
424 for (j2 = j; j2 <= m->n; j2++)
425 M(i2, j2) -= factor * M(i, j2);
426 a[i2 - 1] -= factor * a[i - 1];
427 b[i2 - 1] -= factor * b[i - 1];
428 }
429 }
430 }
431
432 /* SINCE ALL OTHER VALUES IN THE MATRIX ARE ZERO NOW, CALCULATE THE
433 COEFFICIENTS BY DIVIDING THE COLUMN VECTORS BY THE DIAGONAL VALUES. */
434
435 for (i = 1; i <= m->n; i++) {
436 E[i - 1] = a[i - 1] / M(i, i);
437 N[i - 1] = b[i - 1] / M(i, i);
438 }
439
440 return MSUCCESS;
441}
int order(int i_x, int i_y, int yNum)
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:147
#define G_calloc(m, n)
Definition defs/gis.h:140
#define N
int I_georef(double e1, double n1, double *e, double *n, double E[], double N[], int order)
Definition georef.c:77
#define MAXORDER
Definition georef.c:55
#define MNPTERR
Definition georef.c:49
int I_compute_georef_equations(struct Control_Points *cp, double E12[], double N12[], double E21[], double N21[], int order)
Definition georef.c:133
#define MINTERR
Definition georef.c:53
#define MSUCCESS
Definition georef.c:48
#define MPARMERR
Definition georef.c:52
#define MUNSOLVABLE
Definition georef.c:50
#define M(row, col)
Definition georef.c:46
double b
Definition r_raster.c:39