cnversions.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. #include <math.h>
  2. #include <grass/gis.h>
  3. #include <grass/display.h>
  4. /****** OLD CODE
  5. * #include "windround.h"
  6. **********/
  7. /* D_do_conversions(window, t, b, l, r)
  8. * struct Cell_head *window ;
  9. * int t, b, l, r ;
  10. *
  11. * Sets up conversion coefficients to translate between three
  12. * coordinate systems:
  13. *
  14. * 1. Screen coordinates (given by t, b, l, r values)
  15. * 2. UTM coordinates (given by values in window structure)
  16. * 3. Window array coors (given by values in window structure)
  17. *
  18. * Once D_do_conversions is called, lots of conversion coefficients
  19. * and conversion routines are available.
  20. *
  21. * Calls to convert row and column (x and y) values in one system to
  22. * another system are available. In addition calls which return the
  23. * conversion coefficients are alos provided.
  24. */
  25. struct vector
  26. {
  27. double x, y;
  28. };
  29. struct rect
  30. {
  31. double west;
  32. double east;
  33. double south;
  34. double north;
  35. struct vector size;
  36. };
  37. /* Bounding rectangles */
  38. static struct rect D; /* Display coordinates, pixels, (0,0) towards NW */
  39. static struct rect A; /* Map array coordinates, integers, (0,0) towards NW */
  40. static struct rect U; /* UTM coordinates, meters, (0,0) towards SW */
  41. /* Conversion factors */
  42. static struct vector D_to_A_conv; /* Display to Array */
  43. static struct vector A_to_U_conv; /* Array to UTM */
  44. static struct vector U_to_D_conv; /* UTM to Display */
  45. /* others */
  46. static int is_lat_lon;
  47. static void calc_size(struct rect *rect)
  48. {
  49. rect->size.x = rect->east - rect->west;
  50. rect->size.y = rect->south - rect->north;
  51. }
  52. static void calc_conv(struct vector *conv,
  53. const struct vector *src, const struct vector *dst)
  54. {
  55. conv->x = dst->x / src->x;
  56. conv->y = dst->y / src->y;
  57. }
  58. static void fit_aspect(struct rect *rect, const struct rect *ref)
  59. {
  60. struct vector conv;
  61. double scale, size, delta;
  62. calc_conv(&conv, &rect->size, &ref->size);
  63. if (fabs(conv.y) > fabs(conv.x)) {
  64. scale = fabs(conv.y) / fabs(conv.x);
  65. size = rect->size.x / scale;
  66. delta = rect->size.x - size;
  67. rect->west += delta/2;
  68. rect->east -= delta/2;
  69. rect->size.x = size;
  70. }
  71. else {
  72. scale = fabs(conv.x) / fabs(conv.y);
  73. size = rect->size.y / scale;
  74. delta = rect->size.y - size;
  75. rect->north += delta/2;
  76. rect->south -= delta/2;
  77. rect->size.y = size;
  78. }
  79. }
  80. void D_update_conversions(void)
  81. {
  82. calc_conv(&D_to_A_conv, &D.size, &A.size);
  83. calc_conv(&A_to_U_conv, &A.size, &U.size);
  84. calc_conv(&U_to_D_conv, &U.size, &D.size);
  85. }
  86. void D_fit_d_to_u(void)
  87. {
  88. fit_aspect(&D, &U);
  89. }
  90. void D_fit_u_to_d(void)
  91. {
  92. fit_aspect(&U, &D);
  93. }
  94. void D_show_conversions(void)
  95. {
  96. fprintf(stderr,
  97. " D_w %10.1f D_e %10.1f D_s %10.1f D_n %10.1f\n",
  98. D.west, D.east, D.south, D.north);
  99. fprintf(stderr,
  100. " A_w %10.1f A_e %10.1f A_s %10.1f A_n %10.1f\n",
  101. A.west, A.east, A.south, A.north);
  102. fprintf(stderr,
  103. " U_w %10.1f U_e %10.1f U_s %10.1f U_n %10.1f\n",
  104. U.west, U.east, U.south, U.north);
  105. fprintf(stderr,
  106. " D_x %10.1f D_y %10.1f\n" "\n", D.size.x, D.size.y);
  107. fprintf(stderr,
  108. " A_x %10.1f A_y %10.1f\n" "\n", A.size.x, A.size.y);
  109. fprintf(stderr,
  110. " U_x %10.1f U_y %10.1f\n" "\n", U.size.x, U.size.y);
  111. fprintf(stderr, " D_to_A_conv.x %10.1f D_to_A_conv.y %10.1f \n",
  112. D_to_A_conv.x, D_to_A_conv.y);
  113. fprintf(stderr, " A_to_U_conv.x %10.1f A_to_U_conv.y %10.1f \n",
  114. A_to_U_conv.x, A_to_U_conv.y);
  115. fprintf(stderr, " U_to_D_conv.x %10.1f U_to_D_conv.y %10.1f \n",
  116. U_to_D_conv.x, U_to_D_conv.y);
  117. }
  118. /*!
  119. * \brief initialize conversions
  120. *
  121. * The relationship between the earth <b>region</b> and the <b>top, bottom,
  122. * left</b>, and <b>right</b> screen coordinates is established, which then
  123. * allows conversions between all three coordinate systems to be performed.
  124. * Note this routine is called by <i>D_setup</i>.
  125. *
  126. * \param window region
  127. * \param t top
  128. * \param b bottom
  129. * \param l left
  130. * \param r right
  131. * \return none
  132. */
  133. void D_do_conversions(const struct Cell_head *window,
  134. double t, double b, double l, double r)
  135. {
  136. D_set_region(window);
  137. D_set_dst(t, b, l, r);
  138. D_fit_d_to_u();
  139. D_update_conversions();
  140. #ifdef DEBUG
  141. D_show_conversions();
  142. #endif /* DEBUG */
  143. }
  144. int D_is_lat_lon(void) { return (is_lat_lon); }
  145. double D_get_d_to_a_xconv(void) { return (D_to_A_conv.x); }
  146. double D_get_d_to_a_yconv(void) { return (D_to_A_conv.y); }
  147. double D_get_d_to_u_xconv(void) { return (1/U_to_D_conv.x); }
  148. double D_get_d_to_u_yconv(void) { return (1/U_to_D_conv.y); }
  149. double D_get_a_to_u_xconv(void) { return (A_to_U_conv.x); }
  150. double D_get_a_to_u_yconv(void) { return (A_to_U_conv.y); }
  151. double D_get_a_to_d_xconv(void) { return (1/D_to_A_conv.x); }
  152. double D_get_a_to_d_yconv(void) { return (1/D_to_A_conv.y); }
  153. double D_get_u_to_d_xconv(void) { return (U_to_D_conv.x); }
  154. double D_get_u_to_d_yconv(void) { return (U_to_D_conv.y); }
  155. double D_get_u_to_a_xconv(void) { return (1/A_to_U_conv.x); }
  156. double D_get_u_to_a_yconv(void) { return (1/A_to_U_conv.y); }
  157. double D_get_ns_resolution(void) { return D_get_a_to_u_yconv(); }
  158. double D_get_ew_resolution(void) { return D_get_a_to_u_xconv(); }
  159. double D_get_u_west(void) { return (U.west); }
  160. double D_get_u_east(void) { return (U.east); }
  161. double D_get_u_north(void) { return (U.north); }
  162. double D_get_u_south(void) { return (U.south); }
  163. double D_get_a_west(void) { return (A.west); }
  164. double D_get_a_east(void) { return (A.east); }
  165. double D_get_a_north(void) { return (A.north); }
  166. double D_get_a_south(void) { return (A.south); }
  167. double D_get_d_west(void) { return (D.west); }
  168. double D_get_d_east(void) { return (D.east); }
  169. double D_get_d_north(void) { return (D.north); }
  170. double D_get_d_south(void) { return (D.south); }
  171. void D_set_region(const struct Cell_head *window)
  172. {
  173. D_set_src(window->north, window->south, window->west, window->east);
  174. D_set_grid(0, window->rows, 0, window->cols);
  175. is_lat_lon = (window->proj == PROJECTION_LL);
  176. }
  177. void D_set_src(double t, double b, double l, double r)
  178. {
  179. U.north = t;
  180. U.south = b;
  181. U.west = l;
  182. U.east = r;
  183. calc_size(&U);
  184. }
  185. /*!
  186. * \brief returns frame bounds in source coordinate system
  187. *
  188. * D_get_src() returns the frame bounds in the source coordinate system
  189. * (used by D_* functions)
  190. *
  191. * \param t top
  192. * \param b bottom
  193. * \param l left
  194. * \param r right
  195. * \return void
  196. */
  197. void D_get_src(double *t, double *b, double *l, double *r)
  198. {
  199. *t = U.north;
  200. *b = U.south;
  201. *l = U.west;
  202. *r = U.east;
  203. }
  204. void D_set_grid(int t, int b, int l, int r)
  205. {
  206. A.north = t;
  207. A.south = b;
  208. A.west = l;
  209. A.east = r;
  210. calc_size(&A);
  211. }
  212. void D_get_grid(int *t, int *b, int *l, int *r)
  213. {
  214. *t = A.north;
  215. *b = A.south;
  216. *l = A.west;
  217. *r = A.east;
  218. }
  219. void D_set_dst(double t, double b, double l, double r)
  220. {
  221. D.north = t;
  222. D.south = b;
  223. D.west = l;
  224. D.east = r;
  225. calc_size(&D);
  226. }
  227. /*!
  228. * \brief returns frame bounds in destination coordinate system
  229. *
  230. * D_get_dst() returns the frame bounds in the destination coordinate system
  231. * (used by R_* commands).
  232. * The various D_setup() commands all set the destination coordinate
  233. * system to the current frame reported by R_get_window().
  234. *
  235. * \param t top
  236. * \param b bottom
  237. * \param l left
  238. * \param r right
  239. * \return none
  240. */
  241. void D_get_dst(double *t, double *b, double *l, double *r)
  242. {
  243. *t = D.north;
  244. *b = D.south;
  245. *l = D.west;
  246. *r = D.east;
  247. }
  248. void D_get_u(double x[2][2])
  249. {
  250. x[0][0] = U.west;
  251. x[0][1] = U.east;
  252. x[1][0] = U.north;
  253. x[1][1] = U.south;
  254. }
  255. void D_get_a(int x[2][2])
  256. {
  257. x[0][0] = (int)A.west;
  258. x[0][1] = (int)A.east;
  259. x[1][0] = (int)A.north;
  260. x[1][1] = (int)A.south;
  261. }
  262. void D_get_d(double x[2][2])
  263. {
  264. x[0][0] = D.west;
  265. x[0][1] = D.east;
  266. x[1][0] = D.north;
  267. x[1][1] = D.south;
  268. }
  269. /*!
  270. * \brief screen to array (y)
  271. *
  272. * Returns a <i>row</i> value in the array coordinate system when provided the
  273. * corresponding <b>y</b> value in the screen coordinate system.
  274. *
  275. * \param D_row y
  276. * \return double
  277. */
  278. double D_d_to_a_row(double D_row)
  279. {
  280. return A.north + (D_row - D.north) * D_to_A_conv.y;
  281. }
  282. /*!
  283. * \brief screen to array (x)
  284. *
  285. * Returns a <i>column</i> value in the array coordinate system when provided the
  286. * corresponding <b>x</b> value in the screen coordinate system.
  287. *
  288. * \param D_col x
  289. * \return double
  290. */
  291. double D_d_to_a_col(double D_col)
  292. {
  293. return A.west + (D_col - D.west) * D_to_A_conv.x;
  294. }
  295. /*!
  296. * \brief screen to earth (y)
  297. *
  298. * Returns a <i>north</i> value in the earth coordinate system when provided the
  299. * corresponding <b>y</b> value in the screen coordinate system.
  300. *
  301. * \param D_row y
  302. * \return double
  303. */
  304. double D_d_to_u_row(double D_row)
  305. {
  306. return U.north + (D_row - D.north) / U_to_D_conv.y;
  307. }
  308. /*!
  309. * \brief screen to earth (x)
  310. *
  311. * Returns an <i>east</i> value in the earth coordinate system when provided the
  312. * corresponding <b>x</b> value in the screen coordinate system.
  313. *
  314. * \param D_col x
  315. * \return double
  316. */
  317. double D_d_to_u_col(double D_col)
  318. {
  319. return U.west + (D_col - D.west) / U_to_D_conv.x;
  320. }
  321. /*!
  322. * \brief array to earth (row)
  323. *
  324. * Returns a <i>y</i> value in the earth coordinate system when provided the
  325. * corresponding <b>row</b> value in the array coordinate system.
  326. *
  327. * \param A_row row
  328. * \return double
  329. */
  330. double D_a_to_u_row(double A_row)
  331. {
  332. return U.north + (A_row - A.north) * A_to_U_conv.y;
  333. }
  334. /*!
  335. * \brief array to earth (column)
  336. *
  337. * Returns an <i>x</i> value in the earth coordinate system when
  338. * provided the corresponding <b>column</b> value in the array coordinate
  339. * system.
  340. *
  341. * \param A_col column
  342. * \return double
  343. */
  344. double D_a_to_u_col(double A_col)
  345. {
  346. return U.west + (A_col - A.west) * A_to_U_conv.x;
  347. }
  348. /*!
  349. * \brief array to screen (row)
  350. *
  351. * Returns a <i>y</i> value in the screen coordinate system when provided the
  352. * corresponding <b>row</b> value in the array coordinate system.
  353. *
  354. * \param A_row row
  355. * \return double
  356. */
  357. double D_a_to_d_row(double A_row)
  358. {
  359. return D.north + (A_row - A.north) / D_to_A_conv.y;
  360. }
  361. /*!
  362. * \brief array to screen (column)
  363. *
  364. * Returns an <i>x</i> value in the screen coordinate system when
  365. * provided the corresponding <b>column</b> value in the array coordinate
  366. * system.
  367. *
  368. * \param A_col column
  369. * \return double
  370. */
  371. double D_a_to_d_col(double A_col)
  372. {
  373. return D.west + (A_col - A.west) / D_to_A_conv.x;
  374. }
  375. /*!
  376. * \brief earth to screen (north)
  377. *
  378. * Returns a <i>y</i> value in the screen coordinate system when provided the
  379. * corresponding <b>north</b> value in the earth coordinate system.
  380. *
  381. * \param U_row north
  382. * \return double
  383. */
  384. double D_u_to_d_row(double U_row)
  385. {
  386. return D.north + (U_row - U.north) * U_to_D_conv.y;
  387. }
  388. /*!
  389. * \brief earth to screen (east)
  390. *
  391. * Returns an <i>x</i> value in the screen coordinate system when provided the
  392. * corresponding <b>east</b> value in the earth coordinate system.
  393. *
  394. * \param U_col east
  395. * \return double
  396. */
  397. double D_u_to_d_col(double U_col)
  398. {
  399. return D.west + (U_col - U.west) * U_to_D_conv.x;
  400. }
  401. /*!
  402. * \brief earth to array (north)
  403. *
  404. * Returns a <i>row</i> value in the array coordinate system when provided the
  405. * corresponding <b>north</b> value in the earth coordinate system.
  406. *
  407. * \param U_row north
  408. * \return double
  409. */
  410. double D_u_to_a_row(double U_row)
  411. {
  412. return A.north + (U_row - U.north) / A_to_U_conv.y;
  413. }
  414. /*!
  415. * \brief earth to array (east
  416. *
  417. * Returns a <i>column</i> value in the array coordinate system when provided the
  418. * corresponding <b>east</b> value in the earth coordinate system.
  419. *
  420. * \param U_col east
  421. * \return double
  422. */
  423. double D_u_to_a_col(double U_col)
  424. {
  425. return A.west + (U_col - U.west) / A_to_U_conv.x;
  426. }