crs.c 11 KB

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