georef.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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. * Written: 12/19/91
  20. *
  21. * Last Update: 12/26/91 Brian J. Buckley
  22. * Last Update: 1/24/92 Brian J. Buckley
  23. * Added printout of trnfile. Triggered by BDEBUG.
  24. * Last Update: 1/27/92 Brian J. Buckley
  25. * Fixed bug so that only the active control points were used.
  26. *
  27. */
  28. #include <stdlib.h>
  29. #include <math.h>
  30. #include <grass/gis.h>
  31. #include <grass/imagery.h>
  32. #include <signal.h>
  33. /* STRUCTURE FOR USE INTERNALLY WITH THESE FUNCTIONS. THESE FUNCTIONS EXPECT
  34. SQUARE MATRICES SO ONLY ONE VARIABLE IS GIVEN (N) FOR THE MATRIX SIZE */
  35. struct MATRIX
  36. {
  37. int n; /* SIZE OF THIS MATRIX (N x N) */
  38. double *v;
  39. };
  40. /* CALCULATE OFFSET INTO ARRAY BASED ON R/C */
  41. #define M(row,col) m->v[(((row)-1)*(m->n))+(col)-1]
  42. #define MSUCCESS 1 /* SUCCESS */
  43. #define MNPTERR 0 /* NOT ENOUGH POINTS */
  44. #define MUNSOLVABLE -1 /* NOT SOLVABLE */
  45. #define MMEMERR -2 /* NOT ENOUGH MEMORY */
  46. #define MPARMERR -3 /* PARAMETER ERROR */
  47. #define MINTERR -4 /* INTERNAL ERROR */
  48. #define MAXORDER 3 /* HIGHEST SUPPORTED ORDER OF TRANSFORMATION */
  49. /***********************************************************************
  50. FUNCTION PROTOTYPES FOR STATIC (INTERNAL) FUNCTIONS
  51. ************************************************************************/
  52. static int calccoef(struct Control_Points *, double *, double *, int);
  53. static int calcls(struct Control_Points *, struct MATRIX *, double *,
  54. double *, double *, double *);
  55. static int exactdet(struct Control_Points *, struct MATRIX *, double *,
  56. double *, double *, double *);
  57. static int solvemat(struct MATRIX *, double *, double *, double *, double *);
  58. static double term(int, double, double);
  59. /***********************************************************************
  60. TRANSFORM A SINGLE COORDINATE PAIR.
  61. ************************************************************************/
  62. int I_georef(double e1, /* EASTING TO BE TRANSFORMED */
  63. double n1, /* NORTHING TO BE TRANSFORMED */
  64. double *e, /* EASTING, TRANSFORMED */
  65. double *n, /* NORTHING, TRANSFORMED */
  66. double E[], /* EASTING COEFFICIENTS */
  67. double N[], /* NORTHING COEFFICIENTS */
  68. int order /* ORDER OF TRANSFORMATION TO BE PERFORMED, MUST MATCH THE
  69. ORDER USED TO CALCULATE THE COEFFICIENTS */
  70. )
  71. {
  72. double e3, e2n, en2, n3, e2, en, n2;
  73. switch (order) {
  74. case 1:
  75. *e = E[0] + E[1] * e1 + E[2] * n1;
  76. *n = N[0] + N[1] * e1 + N[2] * n1;
  77. break;
  78. case 2:
  79. e2 = e1 * e1;
  80. n2 = n1 * n1;
  81. en = e1 * n1;
  82. *e = E[0] + E[1] * e1 + E[2] * n1 + E[3] * e2 + E[4] * en + E[5] * n2;
  83. *n = N[0] + N[1] * e1 + N[2] * n1 + N[3] * e2 + N[4] * en + N[5] * n2;
  84. break;
  85. case 3:
  86. e2 = e1 * e1;
  87. en = e1 * n1;
  88. n2 = n1 * n1;
  89. e3 = e1 * e2;
  90. e2n = e2 * n1;
  91. en2 = e1 * n2;
  92. n3 = n1 * n2;
  93. *e = E[0] +
  94. E[1] * e1 + E[2] * n1 +
  95. E[3] * e2 + E[4] * en + E[5] * n2 +
  96. E[6] * e3 + E[7] * e2n + E[8] * en2 + E[9] * n3;
  97. *n = N[0] +
  98. N[1] * e1 + N[2] * n1 +
  99. N[3] * e2 + N[4] * en + N[5] * n2 +
  100. N[6] * e3 + N[7] * e2n + N[8] * en2 + N[9] * n3;
  101. break;
  102. default:
  103. return MPARMERR;
  104. }
  105. return MSUCCESS;
  106. }
  107. /***********************************************************************
  108. COMPUTE THE FORWARD AND BACKWARD GEOREFFERENCING COEFFICIENTS
  109. BASED ON A SET OF CONTROL POINTS
  110. ************************************************************************/
  111. int I_compute_georef_equations(struct Control_Points *cp, double E12[],
  112. double N12[], double E21[], double N21[],
  113. int order)
  114. {
  115. double *tempptr;
  116. int status;
  117. if (order < 1 || order > MAXORDER)
  118. return MPARMERR;
  119. /* CALCULATE THE FORWARD TRANSFORMATION COEFFICIENTS */
  120. status = calccoef(cp, E12, N12, order);
  121. if (status != MSUCCESS)
  122. return status;
  123. /* SWITCH THE 1 AND 2 EASTING AND NORTHING ARRAYS */
  124. tempptr = cp->e1;
  125. cp->e1 = cp->e2;
  126. cp->e2 = tempptr;
  127. tempptr = cp->n1;
  128. cp->n1 = cp->n2;
  129. cp->n2 = tempptr;
  130. /* CALCULATE THE BACKWARD TRANSFORMATION COEFFICIENTS */
  131. status = calccoef(cp, E21, N21, order);
  132. /* SWITCH THE 1 AND 2 EASTING AND NORTHING ARRAYS BACK */
  133. tempptr = cp->e1;
  134. cp->e1 = cp->e2;
  135. cp->e2 = tempptr;
  136. tempptr = cp->n1;
  137. cp->n1 = cp->n2;
  138. cp->n2 = tempptr;
  139. return status;
  140. }
  141. /***********************************************************************
  142. COMPUTE THE GEOREFFERENCING COEFFICIENTS
  143. BASED ON A SET OF CONTROL POINTS
  144. ************************************************************************/
  145. static int calccoef(struct Control_Points *cp, double E[], double N[],
  146. int order)
  147. {
  148. struct MATRIX m;
  149. double *a;
  150. double *b;
  151. int numactive; /* NUMBER OF ACTIVE CONTROL POINTS */
  152. int status, i;
  153. /* CALCULATE THE NUMBER OF VALID CONTROL POINTS */
  154. for (i = numactive = 0; i < cp->count; i++) {
  155. if (cp->status[i] > 0)
  156. numactive++;
  157. }
  158. /* CALCULATE THE MINIMUM NUMBER OF CONTROL POINTS NEEDED TO DETERMINE
  159. A TRANSFORMATION OF THIS ORDER */
  160. m.n = ((order + 1) * (order + 2)) / 2;
  161. if (numactive < m.n)
  162. return MNPTERR;
  163. /* INITIALIZE MATRIX */
  164. m.v = G_calloc(m.n * m.n, sizeof(double));
  165. a = G_calloc(m.n, sizeof(double));
  166. b = G_calloc(m.n, sizeof(double));
  167. if (numactive == m.n)
  168. status = exactdet(cp, &m, a, b, E, N);
  169. else
  170. status = calcls(cp, &m, a, b, E, N);
  171. G_free(m.v);
  172. G_free(a);
  173. G_free(b);
  174. return status;
  175. }
  176. /***********************************************************************
  177. CALCULATE THE TRANSFORMATION COEFFICIENTS WITH EXACTLY THE MINIMUM
  178. NUMBER OF CONTROL POINTS REQUIRED FOR THIS TRANSFORMATION.
  179. ************************************************************************/
  180. static int exactdet(struct Control_Points *cp, struct MATRIX *m,
  181. double a[], double b[],
  182. double E[], /* EASTING COEFFICIENTS */
  183. double N[] /* NORTHING COEFFICIENTS */
  184. )
  185. {
  186. int pntnow, currow, j;
  187. currow = 1;
  188. for (pntnow = 0; pntnow < cp->count; pntnow++) {
  189. if (cp->status[pntnow] > 0) {
  190. /* POPULATE MATRIX M */
  191. for (j = 1; j <= m->n; j++)
  192. M(currow, j) = term(j, cp->e1[pntnow], cp->n1[pntnow]);
  193. /* POPULATE MATRIX A AND B */
  194. a[currow - 1] = cp->e2[pntnow];
  195. b[currow - 1] = cp->n2[pntnow];
  196. currow++;
  197. }
  198. }
  199. if (currow - 1 != m->n)
  200. return MINTERR;
  201. return solvemat(m, a, b, E, N);
  202. }
  203. /***********************************************************************
  204. CALCULATE THE TRANSFORMATION COEFFICIENTS WITH MORE THAN THE MINIMUM
  205. NUMBER OF CONTROL POINTS REQUIRED FOR THIS TRANSFORMATION. THIS
  206. ROUTINE USES THE LEAST SQUARES METHOD TO COMPUTE THE COEFFICIENTS.
  207. ************************************************************************/
  208. static int calcls(struct Control_Points *cp, struct MATRIX *m,
  209. double a[], double b[],
  210. double E[], /* EASTING COEFFICIENTS */
  211. double N[] /* NORTHING COEFFICIENTS */
  212. )
  213. {
  214. int i, j, n, numactive = 0;
  215. /* INITIALIZE THE UPPER HALF OF THE MATRIX AND THE TWO COLUMN VECTORS */
  216. for (i = 1; i <= m->n; i++) {
  217. for (j = i; j <= m->n; j++)
  218. M(i, j) = 0.0;
  219. a[i - 1] = b[i - 1] = 0.0;
  220. }
  221. /* SUM THE UPPER HALF OF THE MATRIX AND THE COLUMN VECTORS ACCORDING TO
  222. THE LEAST SQUARES METHOD OF SOLVING OVER DETERMINED SYSTEMS */
  223. for (n = 0; n < cp->count; n++) {
  224. if (cp->status[n] > 0) {
  225. numactive++;
  226. for (i = 1; i <= m->n; i++) {
  227. for (j = i; j <= m->n; j++)
  228. M(i, j) +=
  229. term(i, cp->e1[n], cp->n1[n]) * term(j, cp->e1[n],
  230. cp->n1[n]);
  231. a[i - 1] += cp->e2[n] * term(i, cp->e1[n], cp->n1[n]);
  232. b[i - 1] += cp->n2[n] * term(i, cp->e1[n], cp->n1[n]);
  233. }
  234. }
  235. }
  236. if (numactive <= m->n)
  237. return MINTERR;
  238. /* TRANSPOSE VALUES IN UPPER HALF OF M TO OTHER HALF */
  239. for (i = 2; i <= m->n; i++)
  240. for (j = 1; j < i; j++)
  241. M(i, j) = M(j, i);
  242. return solvemat(m, a, b, E, N);
  243. }
  244. /***********************************************************************
  245. CALCULATE THE X/Y TERM BASED ON THE TERM NUMBER
  246. ORDER\TERM 1 2 3 4 5 6 7 8 9 10
  247. 1 e0n0 e1n0 e0n1
  248. 2 e0n0 e1n0 e0n1 e2n0 e1n1 e0n2
  249. 3 e0n0 e1n0 e0n1 e2n0 e1n1 e0n2 e3n0 e2n1 e1n2 e0n3
  250. ************************************************************************/
  251. static double term(int term, double e, double n)
  252. {
  253. switch (term) {
  254. case 1:
  255. return 1.0;
  256. case 2:
  257. return e;
  258. case 3:
  259. return n;
  260. case 4:
  261. return e * e;
  262. case 5:
  263. return e * n;
  264. case 6:
  265. return n * n;
  266. case 7:
  267. return e * e * e;
  268. case 8:
  269. return e * e * n;
  270. case 9:
  271. return e * n * n;
  272. case 10:
  273. return n * n * n;
  274. }
  275. return 0.0;
  276. }
  277. /***********************************************************************
  278. SOLVE FOR THE 'E' AND 'N' COEFFICIENTS BY USING A SOMEWHAT MODIFIED
  279. GAUSSIAN ELIMINATION METHOD.
  280. | M11 M12 ... M1n | | E0 | | a0 |
  281. | M21 M22 ... M2n | | E1 | = | a1 |
  282. | . . . . | | . | | . |
  283. | Mn1 Mn2 ... Mnn | | En-1 | | an-1 |
  284. and
  285. | M11 M12 ... M1n | | N0 | | b0 |
  286. | M21 M22 ... M2n | | N1 | = | b1 |
  287. | . . . . | | . | | . |
  288. | Mn1 Mn2 ... Mnn | | Nn-1 | | bn-1 |
  289. ************************************************************************/
  290. static int solvemat(struct MATRIX *m, double a[], double b[], double E[],
  291. double N[])
  292. {
  293. int i, j, i2, j2, imark;
  294. double factor, temp;
  295. double pivot; /* ACTUAL VALUE OF THE LARGEST PIVOT CANDIDATE */
  296. for (i = 1; i <= m->n; i++) {
  297. j = i;
  298. /* find row with largest magnitude value for pivot value */
  299. pivot = M(i, j);
  300. imark = i;
  301. for (i2 = i + 1; i2 <= m->n; i2++) {
  302. temp = fabs(M(i2, j));
  303. if (temp > fabs(pivot)) {
  304. pivot = M(i2, j);
  305. imark = i2;
  306. }
  307. }
  308. /* if the pivot is very small then the points are nearly co-linear */
  309. /* co-linear points result in an undefined matrix, and nearly */
  310. /* co-linear points results in a solution with rounding error */
  311. if (pivot == 0.0)
  312. return MUNSOLVABLE;
  313. /* if row with highest pivot is not the current row, switch them */
  314. if (imark != i) {
  315. for (j2 = 1; j2 <= m->n; j2++) {
  316. temp = M(imark, j2);
  317. M(imark, j2) = M(i, j2);
  318. M(i, j2) = temp;
  319. }
  320. temp = a[imark - 1];
  321. a[imark - 1] = a[i - 1];
  322. a[i - 1] = temp;
  323. temp = b[imark - 1];
  324. b[imark - 1] = b[i - 1];
  325. b[i - 1] = temp;
  326. }
  327. /* compute zeros above and below the pivot, and compute
  328. values for the rest of the row as well */
  329. for (i2 = 1; i2 <= m->n; i2++) {
  330. if (i2 != i) {
  331. factor = M(i2, j) / pivot;
  332. for (j2 = j; j2 <= m->n; j2++)
  333. M(i2, j2) -= factor * M(i, j2);
  334. a[i2 - 1] -= factor * a[i - 1];
  335. b[i2 - 1] -= factor * b[i - 1];
  336. }
  337. }
  338. }
  339. /* SINCE ALL OTHER VALUES IN THE MATRIX ARE ZERO NOW, CALCULATE THE
  340. COEFFICIENTS BY DIVIDING THE COLUMN VECTORS BY THE DIAGONAL VALUES. */
  341. for (i = 1; i <= m->n; i++) {
  342. E[i - 1] = a[i - 1] / M(i, i);
  343. N[i - 1] = b[i - 1] / M(i, i);
  344. }
  345. return MSUCCESS;
  346. }