orthorot.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /***********************************************************************
  2. orthorot.c
  3. written by: Markus Metz
  4. loosely based on crs3d.c
  5. 2D/3D Transformation with orthogonal rotation
  6. ************************************************************************/
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include <math.h>
  11. #include <limits.h>
  12. #include <grass/gis.h>
  13. #include <grass/gmath.h>
  14. #include <grass/imagery.h>
  15. #include <grass/glocale.h>
  16. #include "crs.h"
  17. #define MSUCCESS 1 /* SUCCESS */
  18. #define MNPTERR 0 /* NOT ENOUGH POINTS */
  19. #define MUNSOLVABLE -1 /* NOT SOLVABLE */
  20. #define MMEMERR -2 /* NOT ENOUGH MEMORY */
  21. #define MPARMERR -3 /* PARAMETER ERROR */
  22. #define MINTERR -4 /* INTERNAL ERROR */
  23. /***********************************************************************
  24. FUNCTION PROTOTYPES FOR STATIC (INTERNAL) FUNCTIONS
  25. ************************************************************************/
  26. static int calccoef(struct Control_Points_3D *, double *, int);
  27. static int calcscale(struct Control_Points_3D *, double *);
  28. void transpose_matrix(int, int, double **, double **);
  29. void matmult(int, int, int, double **, double **, double **);
  30. void copy_matrix(int, int, double **, double **);
  31. void init_matrix(int, int, double **);
  32. void scale_matrix(int, int, double, double **, double **);
  33. void matrix_multiply(int, int, double **, double *, double *);
  34. void subtract_matrix(int, int, double **, double **, double **);
  35. double trace(int, int, double **);
  36. /***********************************************************************
  37. TRANSFORM A SINGLE COORDINATE PAIR.
  38. ************************************************************************/
  39. int CRS_georef_or(double e1, /* EASTING TO BE TRANSFORMED */
  40. double n1, /* NORTHING TO BE TRANSFORMED */
  41. double z1, /* HEIGHT TO BE TRANSFORMED */
  42. double *e, /* EASTING, TRANSFORMED */
  43. double *n, /* NORTHING, TRANSFORMED */
  44. double *z, /* HEIGHT, TRANSFORMED */
  45. double OR[] /* TRANSFORMATION COEFFICIENTS */
  46. )
  47. {
  48. *e = OR[9] + OR[12] * (OR[0] * e1 + OR[1] * n1 + OR[2] * z1);
  49. *n = OR[10] + OR[13] * (OR[3] * e1 + OR[4] * n1 + OR[5] * z1);
  50. *z = OR[11] + OR[14] * (OR[6] * e1 + OR[7] * n1 + OR[8] * z1);
  51. return MSUCCESS;
  52. }
  53. /***********************************************************************
  54. COMPUTE THE FORWARD AND BACKWARD GEOREFFERENCING COEFFICIENTS
  55. BASED ON A SET OF CONTROL POINTS
  56. ORTHOGONAL TRANSFORMATION (ORTHOGONAL ROTATION MATRIX)
  57. Rotation matrix
  58. OR[0] OR[1] OR[2]
  59. OR[3] OR[4] OR[5]
  60. OR[6] OR[7] OR[8]
  61. OR[9] x shift
  62. OR[10] y shift
  63. OR[11] z shift
  64. OR[12] x or global scale
  65. OR[13] y scale
  66. OR[14] z scale
  67. ************************************************************************/
  68. int CRS_compute_georef_equations_or(struct Control_Points_3D *cp,
  69. double OR12[], double OR21[])
  70. {
  71. double *tempptr, *OR;
  72. int status, i, numactive;
  73. struct Control_Points_3D cpc, /* center points */
  74. cpr; /* reduced to center */
  75. cpc.count = 1;
  76. cpc.e1 = (double *)G_calloc(cpc.count, sizeof(double));
  77. cpc.e2 = (double *)G_calloc(cpc.count, sizeof(double));
  78. cpc.n1 = (double *)G_calloc(cpc.count, sizeof(double));
  79. cpc.n2 = (double *)G_calloc(cpc.count, sizeof(double));
  80. cpc.z1 = (double *)G_calloc(cpc.count, sizeof(double));
  81. cpc.z2 = (double *)G_calloc(cpc.count, sizeof(double));
  82. cpc.status = (int *)G_calloc(cpc.count, sizeof(int));
  83. cpc.e1[0] = 0.0;
  84. cpc.e2[0] = 0.0;
  85. cpc.n1[0] = 0.0;
  86. cpc.n2[0] = 0.0;
  87. cpc.z1[0] = 0.0;
  88. cpc.z2[0] = 0.0;
  89. cpc.status[0] = 1;
  90. /* center points */
  91. for (i = numactive = 0; i < cp->count; i++) {
  92. if (cp->status[i] > 0) {
  93. numactive++;
  94. cpc.e1[0] += cp->e1[i];
  95. cpc.e2[0] += cp->e2[i];
  96. cpc.n1[0] += cp->n1[i];
  97. cpc.n2[0] += cp->n2[i];
  98. cpc.z1[0] += cp->z1[i];
  99. cpc.z2[0] += cp->z2[i];
  100. }
  101. }
  102. /* this version of 3D transformation needs 3 control points */
  103. if (numactive < 3)
  104. return MNPTERR;
  105. cpc.e1[0] /= numactive;
  106. cpc.e2[0] /= numactive;
  107. cpc.n1[0] /= numactive;
  108. cpc.n2[0] /= numactive;
  109. cpc.z1[0] /= numactive;
  110. cpc.z2[0] /= numactive;
  111. /* shift to center points */
  112. cpr.count = numactive;
  113. cpr.e1 = (double *)G_calloc(cpr.count, sizeof(double));
  114. cpr.e2 = (double *)G_calloc(cpr.count, sizeof(double));
  115. cpr.n1 = (double *)G_calloc(cpr.count, sizeof(double));
  116. cpr.n2 = (double *)G_calloc(cpr.count, sizeof(double));
  117. cpr.z1 = (double *)G_calloc(cpr.count, sizeof(double));
  118. cpr.z2 = (double *)G_calloc(cpr.count, sizeof(double));
  119. cpr.status = (int *)G_calloc(cpr.count, sizeof(int));
  120. for (i = numactive = 0; i < cp->count; i++) {
  121. if (cp->status[i] > 0) {
  122. cpr.e1[numactive] = cp->e1[i] - cpc.e1[0];
  123. cpr.e2[numactive] = cp->e2[i] - cpc.e2[0];
  124. cpr.n1[numactive] = cp->n1[i] - cpc.n1[0];
  125. cpr.n2[numactive] = cp->n2[i] - cpc.n2[0];
  126. cpr.z1[numactive] = cp->z1[i] - cpc.z1[0];
  127. cpr.z2[numactive] = cp->z2[i] - cpc.z2[0];
  128. cpr.status[numactive] = 1;
  129. numactive++;
  130. }
  131. }
  132. /* CALCULATE THE FORWARD TRANSFORMATION COEFFICIENTS */
  133. OR = OR12;
  134. status = calccoef(&cpr, OR, 3);
  135. calcscale(&cpr, OR);
  136. /* CALCULATE FORWARD SHIFTS */
  137. OR[9] = OR[10] = OR[11] = 0.0;
  138. for (i = numactive = 0; i < cp->count; i++) {
  139. if (cp->status[i] > 0) {
  140. OR[9] += cp->e2[i] - OR[12] *
  141. (OR[0] * cp->e1[i] +
  142. OR[1] * cp->n1[i] +
  143. OR[2] * cp->z1[i]);
  144. OR[10] += cp->n2[i] - OR[13] *
  145. (OR[3] * cp->e1[i] +
  146. OR[4] * cp->n1[i] +
  147. OR[5] * cp->z1[i]);
  148. OR[11] += cp->z2[i] - OR[14] *
  149. (OR[6] * cp->e1[i] +
  150. OR[7] * cp->n1[i] +
  151. OR[8] * cp->z1[i]);
  152. numactive++;
  153. }
  154. }
  155. OR[9] /= numactive;
  156. OR[10] /= numactive;
  157. OR[11] /= numactive;
  158. /* SWITCH THE 1 AND 2 EASTING, NORTHING, AND HEIGHT ARRAYS */
  159. tempptr = cpr.e1;
  160. cpr.e1 = cpr.e2;
  161. cpr.e2 = tempptr;
  162. tempptr = cpr.n1;
  163. cpr.n1 = cpr.n2;
  164. cpr.n2 = tempptr;
  165. tempptr = cpr.z1;
  166. cpr.z1 = cpr.z2;
  167. cpr.z2 = tempptr;
  168. /* CALCULATE THE BACKWARD TRANSFORMATION COEFFICIENTS */
  169. OR = OR21;
  170. status = calccoef(&cpr, OR, 3);
  171. if (status != MSUCCESS)
  172. return status;
  173. calcscale(&cpr, OR);
  174. /* SWITCH THE 1 AND 2 EASTING, NORTHING, AND HEIGHT ARRAYS BACK */
  175. tempptr = cpr.e1;
  176. cpr.e1 = cpr.e2;
  177. cpr.e2 = tempptr;
  178. tempptr = cpr.n1;
  179. cpr.n1 = cpr.n2;
  180. cpr.n2 = tempptr;
  181. tempptr = cpr.z1;
  182. cpr.z1 = cpr.z2;
  183. cpr.z2 = tempptr;
  184. /* CALCULATE BACKWARD SHIFTS */
  185. OR[9] = OR[10] = OR[11] = 0.0;
  186. for (i = numactive = 0; i < cp->count; i++) {
  187. if (cp->status[i] > 0) {
  188. OR[9] += cp->e1[i] - OR[12] *
  189. (OR[0] * cp->e2[i] +
  190. OR[1] * cp->n2[i] +
  191. OR[2] * cp->z2[i]);
  192. OR[10] += cp->n1[i] - OR[13] *
  193. (OR[3] * cp->e2[i] +
  194. OR[4] * cp->n2[i] +
  195. OR[5] * cp->z2[i]);
  196. OR[11] += cp->z1[i] - OR[14] *
  197. (OR[6] * cp->e2[i] +
  198. OR[7] * cp->n2[i] +
  199. OR[8] * cp->z2[i]);
  200. numactive++;
  201. }
  202. }
  203. OR[9] /= numactive;
  204. OR[10] /= numactive;
  205. OR[11] /= numactive;
  206. OR = OR12;
  207. G_debug(1, "********************************");
  208. G_debug(1, "Forward transformation:");
  209. G_debug(1, "Orthogonal rotation matrix:");
  210. G_debug(1, "%.4f %.4f %.4f", OR[0], OR[1], OR[2]);
  211. G_debug(1, "%.4f %.4f %.4f", OR[3], OR[4], OR[5]);
  212. G_debug(1, "%.4f %.4f %.4f", OR[6], OR[7], OR[8]);
  213. G_debug(1, "x, y, z shift: %.4f %.4f %.4f", OR[9], OR[10], OR[11]);
  214. G_debug(1, "x, y, z scale: %.4f %.4f %.4f", OR[12], OR[13], OR[14]);
  215. OR = OR21;
  216. G_debug(1, "********************************");
  217. G_debug(1, "Backward transformation:");
  218. G_debug(1, "Orthogonal rotation matrix:");
  219. G_debug(1, "%.4f %.4f %.4f", OR[0], OR[1], OR[2]);
  220. G_debug(1, "%.4f %.4f %.4f", OR[3], OR[4], OR[5]);
  221. G_debug(1, "%.4f %.4f %.4f", OR[6], OR[7], OR[8]);
  222. G_debug(1, "x, y, z shift: %.4f %.4f %.4f", OR[9], OR[10], OR[11]);
  223. G_debug(1, "x, y, z scale: %.4f %.4f %.4f", OR[12], OR[13], OR[14]);
  224. return status;
  225. }
  226. /***********************************************************************
  227. COMPUTE THE GEOREFFERENCING COEFFICIENTS
  228. BASED ON A SET OF CONTROL POINTS
  229. ************************************************************************/
  230. static int calccoef(struct Control_Points_3D *cp, double OR[], int ndims)
  231. {
  232. double **src_mat = NULL;
  233. double **src_mat_T = NULL;
  234. double **dest_mat = NULL;
  235. double **dest_mat_T = NULL;
  236. double **src_dest_mat = NULL;
  237. double *S_vec = NULL;
  238. double **R_mat = NULL;
  239. double **R_mat_T = NULL;
  240. double **mat_mn1 = NULL;
  241. double **mat_mn2 = NULL;
  242. double **mat_nm1 = NULL;
  243. double **mat_nm2 = NULL;
  244. double **mat_nn1 = NULL;
  245. double **E_mat = NULL;
  246. double **P_mat = NULL;
  247. double **Q_mat = NULL;
  248. double *D_vec = NULL;
  249. double *one_vec = NULL;
  250. double trace1 = 0.0;
  251. double trace2 = 0.0;
  252. int numactive; /* NUMBER OF ACTIVE CONTROL POINTS */
  253. int m, n, i, j;
  254. int status;
  255. /* CALCULATE THE NUMBER OF VALID CONTROL POINTS */
  256. for (i = numactive = 0; i < cp->count; i++) {
  257. if (cp->status[i] > 0)
  258. numactive++;
  259. }
  260. m = numactive;
  261. n = ndims;
  262. src_mat = G_alloc_matrix(m, n);
  263. dest_mat = G_alloc_matrix(m, n);
  264. for (i = numactive = 0; i < cp->count; i++) {
  265. if (cp->status[i] > 0) {
  266. src_mat[numactive][0] = cp->e1[i];
  267. src_mat[numactive][1] = cp->n1[i];
  268. src_mat[numactive][2] = cp->z1[i];
  269. dest_mat[numactive][0] = cp->e2[i];
  270. dest_mat[numactive][1] = cp->n2[i];
  271. dest_mat[numactive][2] = cp->z2[i];
  272. numactive++;
  273. }
  274. }
  275. D_vec = G_alloc_vector(ndims);
  276. src_mat_T = G_alloc_matrix(n, m);
  277. dest_mat_T = G_alloc_matrix(n, m);
  278. src_dest_mat = G_alloc_matrix(n, n);
  279. R_mat = G_alloc_matrix(n, n);
  280. R_mat_T = G_alloc_matrix(n, n);
  281. mat_mn1 = G_alloc_matrix(m, n);
  282. mat_mn2 = G_alloc_matrix(m, n);
  283. mat_nm1 = G_alloc_matrix(n, m);
  284. mat_nm2 = G_alloc_matrix(n, m);
  285. mat_nn1 = G_alloc_matrix(n, n);
  286. E_mat = G_alloc_matrix(m, m);
  287. P_mat = G_alloc_matrix(ndims, ndims);
  288. Q_mat = G_alloc_matrix(ndims, ndims);
  289. transpose_matrix(m, n, dest_mat, dest_mat_T);
  290. for (i = 0; i < m; i++) {
  291. for (j = 0; j < m; j++) {
  292. if (i != j) {
  293. E_mat[i][j] = -1.0 / (double)m;
  294. }
  295. else{
  296. E_mat[i][j] = 1.0 - 1.0 / (double)m;
  297. }
  298. }
  299. }
  300. matmult(n, m, m, dest_mat_T, E_mat, mat_nm1);
  301. matmult(n, m, n, mat_nm1, src_mat, src_dest_mat);
  302. copy_matrix(n, n, src_dest_mat, P_mat);
  303. copy_matrix(n, n, src_dest_mat, mat_nn1);
  304. status = G_math_svduv(D_vec, mat_nn1, P_mat, n, Q_mat, n);
  305. if (status == 0)
  306. status = MSUCCESS;
  307. transpose_matrix(n, n, P_mat, mat_nn1);
  308. /* rotation matrix */
  309. matmult(n, n, n, Q_mat, mat_nn1, R_mat_T);
  310. transpose_matrix(n, n, R_mat_T, R_mat);
  311. /* scale */
  312. matmult(n, n, n, src_dest_mat, R_mat_T, mat_nn1);
  313. trace1 = trace(n, n, mat_nn1);
  314. transpose_matrix(m, n, src_mat, src_mat_T);
  315. matmult(n, m, m, src_mat_T, E_mat, mat_nm1);
  316. matmult(n, m, n, mat_nm1, src_mat, mat_nn1);
  317. trace2 = trace(n, n, mat_nn1);
  318. OR[14] = trace1 / trace2;
  319. /* shifts */
  320. matmult(m, n, n, src_mat, R_mat_T, mat_mn1);
  321. scale_matrix(m, n, OR[14], mat_mn1, mat_mn2);
  322. subtract_matrix(m, n, dest_mat, mat_mn2, mat_mn1);
  323. scale_matrix(m, n, 1.0 / m, mat_mn1, mat_mn2);
  324. transpose_matrix(m, n, mat_mn2, mat_nm1);
  325. S_vec = G_alloc_vector(n);
  326. one_vec = G_alloc_vector(m);
  327. for (i = 0; i < m; i++){
  328. one_vec[i] = 1.0;
  329. }
  330. matrix_multiply(n, m, mat_nm1, one_vec, S_vec);
  331. /* matrix to vector */
  332. for (i = 0; i < ndims; i++) {
  333. for (j = 0; j < ndims; j++) {
  334. OR[i * ndims + j] = R_mat[i][j];
  335. }
  336. }
  337. G_free_matrix(src_mat);
  338. G_free_matrix(src_mat_T);
  339. G_free_matrix(dest_mat);
  340. G_free_matrix(dest_mat_T);
  341. G_free_matrix(src_dest_mat);
  342. G_free_vector(D_vec);
  343. G_free_matrix(E_mat);
  344. G_free_matrix(P_mat);
  345. G_free_matrix(Q_mat);
  346. G_free_matrix(R_mat);
  347. G_free_matrix(R_mat_T);
  348. G_free_matrix(mat_mn1);
  349. G_free_matrix(mat_mn2);
  350. G_free_matrix(mat_nm1);
  351. G_free_matrix(mat_nm2);
  352. G_free_matrix(mat_nn1);
  353. G_free_vector(S_vec);
  354. G_free_vector(one_vec);
  355. return status;
  356. }
  357. /***********************************************************************
  358. CALCULATE SCALE
  359. ************************************************************************/
  360. static int calcscale(struct Control_Points_3D *cp, double OR[])
  361. {
  362. double sumX, sumY, sumsqX, sumsqY, sumXY;
  363. int numactive; /* NUMBER OF ACTIVE CONTROL POINTS */
  364. int i;
  365. /* CALCULATE SCALE */
  366. sumX = sumY = sumsqX = sumsqY = sumXY = 0.0;
  367. for (i = numactive = 0; i < cp->count; i++) {
  368. if (cp->status[i] > 0) {
  369. double c1, c2;
  370. c1 = OR[0] * cp->e1[i] + OR[1] * cp->n1[i] + OR[2] * cp->z1[i];
  371. c2 = cp->e2[i];
  372. sumX += c1;
  373. sumY += c2;
  374. sumsqX += c1 * c1;
  375. sumsqY += c2 * c2;
  376. sumXY += c1 * c2;
  377. c1 = OR[3] * cp->e1[i] + OR[4] * cp->n1[i] + OR[5] * cp->z1[i];
  378. c2 = cp->n2[i];
  379. sumX += c1;
  380. sumY += c2;
  381. sumsqX += c1 * c1;
  382. sumsqY += c2 * c2;
  383. sumXY += c1 * c2;
  384. c1 = OR[6] * cp->e1[i] + OR[7] * cp->n1[i] + OR[8] * cp->z1[i];
  385. c2 = cp->z2[i];
  386. sumX += c1;
  387. sumY += c2;
  388. sumsqX += c1 * c1;
  389. sumsqY += c2 * c2;
  390. sumXY += c1 * c2;
  391. numactive++;
  392. }
  393. }
  394. OR[12] = (sumXY - sumX * sumY / numactive) /
  395. (sumsqX - sumX * sumX / numactive);
  396. if (fabs(OR[12] - OR[14]) > 10 * GRASS_EPSILON) {
  397. G_debug(1, "Scale mismatch: %.4f %.4f", OR[12], OR[14]);
  398. OR[12] = OR[14];
  399. }
  400. OR[13] = OR[14] = OR[12];
  401. return MSUCCESS;
  402. }
  403. void transpose_matrix(int m, int n, double **src_matrix, double **dest_matrix)
  404. {
  405. int i, j;
  406. for(i = 0; i < m; i++) {
  407. for(j = 0; j < n; j++) {
  408. dest_matrix[j][i] = src_matrix[i][j];
  409. }
  410. }
  411. }
  412. void matmult(int m, int n, int p, double **mat1, double **mat2, double **mat3)
  413. {
  414. int i, j, k;
  415. double sum;
  416. /* input mat1: m x n */
  417. /* input mat2: n x p */
  418. /* output mat3: m x p */
  419. for (i = 0; i < m; i++) {
  420. for (j = 0; j < p; j++) {
  421. sum = 0.0;
  422. for (k = 0; k < n; k++) {
  423. sum += mat1[i][k] * mat2[k][j];
  424. }
  425. mat3[i][j] = sum;
  426. }
  427. }
  428. }
  429. void copy_matrix(int n, int m, double **src_matrix, double **dest_matrix)
  430. {
  431. int i, j;
  432. for (i = 0; i < n; i++) {
  433. for (j = 0; j < m; j++) {
  434. dest_matrix[i][j] = src_matrix[i][j];
  435. }
  436. }
  437. }
  438. double trace(int n, int m, double **matrix)
  439. {
  440. int i;
  441. double t = 0.0;
  442. for (i = 0; i < n; i++) {
  443. t += matrix[i][i];
  444. }
  445. return t;
  446. }
  447. void init_matrix(int n, int m, double **matrix)
  448. {
  449. int i, j;
  450. for (i = 0; i < n; i++) {
  451. for (j = 0; j < m; j++) {
  452. matrix[i][j] = 0.0;
  453. }
  454. }
  455. }
  456. void scale_matrix(int n, int m, double scal, double **src_matrix,
  457. double **dest_matrix)
  458. {
  459. int i, j;
  460. for (i = 0; i < n; i++) {
  461. for (j = 0; j < m; j++) {
  462. dest_matrix[i][j] = scal * src_matrix[i][j];
  463. }
  464. }
  465. }
  466. void subtract_matrix(int n, int m, double **mat1, double **mat2,
  467. double **mat3)
  468. {
  469. int i, j;
  470. for (i = 0; i < n; i++) {
  471. for (j = 0; j < m; j++) {
  472. mat3[i][j] = mat1[i][j] - mat2[i][j];
  473. }
  474. }
  475. }
  476. void matrix_multiply(int n, int m, double **mat, double *iv,
  477. double *ov)
  478. {
  479. int i, j;
  480. for (i = 0; i < n; i++) {
  481. ov[i] = 0.0;
  482. for(j = 0; j < m; j++) {
  483. ov[i] += mat[i][j] * iv[j];
  484. }
  485. }
  486. }