window_map.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /**
  2. * \file window_map.c
  3. *
  4. * \brief GIS Library - Window mapping functions.
  5. *
  6. * (C) 2001-2008 by the GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public License
  9. * (>=v2). Read the file COPYING that comes with GRASS for details.
  10. *
  11. * \author GRASS GIS Development Team
  12. *
  13. * \date 1999-2008
  14. */
  15. #include <stdlib.h>
  16. #include <grass/gis.h>
  17. #include "G.h"
  18. #define alloc_index(n) (COLUMN_MAPPING *) G_malloc((n)*sizeof(COLUMN_MAPPING))
  19. /**
  20. * \brief Create window mapping.
  21. *
  22. * Creates mapping from cell header into window. The boundaries and
  23. * resolution of the two spaces do not have to be the same or aligned in
  24. * any way.
  25. *
  26. * \param[in] fd file descriptor
  27. * \return
  28. */
  29. void G__create_window_mapping(int fd)
  30. {
  31. struct fileinfo *fcb = &G__.fileinfo[fd];
  32. COLUMN_MAPPING *col;
  33. int i;
  34. int x;
  35. double C1, C2;
  36. double west;
  37. G__init_window();
  38. if (fcb->open_mode >= 0 && fcb->open_mode != OPEN_OLD) /* open for write? */
  39. return;
  40. if (fcb->open_mode == OPEN_OLD) /* already open ? */
  41. G_free(fcb->col_map);
  42. col = fcb->col_map = alloc_index(G__.window.cols);
  43. /*
  44. * for each column in the window, go to center of the cell,
  45. * compute nearest column in the data file
  46. * if column is not in data file, set column to 0
  47. *
  48. * for lat/lon move window so that west is bigger than
  49. * cellhd west.
  50. */
  51. west = G__.window.west;
  52. if (G__.window.proj == PROJECTION_LL) {
  53. while (west > fcb->cellhd.west + 360.0)
  54. west -= 360.0;
  55. while (west < fcb->cellhd.west)
  56. west += 360.0;
  57. }
  58. C1 = G__.window.ew_res / fcb->cellhd.ew_res;
  59. C2 = (west - fcb->cellhd.west +
  60. G__.window.ew_res / 2.0) / fcb->cellhd.ew_res;
  61. for (i = 0; i < G__.window.cols; i++) {
  62. x = C2;
  63. if (C2 < x) /* adjust for rounding of negatives */
  64. x--;
  65. if (x < 0 || x >= fcb->cellhd.cols) /* not in data file */
  66. x = -1;
  67. *col++ = x + 1;
  68. C2 += C1;
  69. }
  70. /* do wrap around for lat/lon */
  71. if (G__.window.proj == PROJECTION_LL) {
  72. col = fcb->col_map;
  73. C2 = (west - 360.0 - fcb->cellhd.west +
  74. G__.window.ew_res / 2.0) / fcb->cellhd.ew_res;
  75. for (i = 0; i < G__.window.cols; i++) {
  76. x = C2;
  77. if (C2 < x) /* adjust for rounding of negatives */
  78. x--;
  79. if (x < 0 || x >= fcb->cellhd.cols) /* not in data file */
  80. x = -1;
  81. if (*col == 0) /* only change those not already set */
  82. *col = x + 1;
  83. col++;
  84. C2 += C1;
  85. }
  86. }
  87. G_debug(3, "create window mapping (%d columns)", G__.window.cols);
  88. /* for (i = 0; i < G__.window.cols; i++)
  89. fprintf(stderr, "%s%ld", i % 15 ? " " : "\n", (long)fcb->col_map[i]);
  90. fprintf(stderr, "\n");
  91. */
  92. /* compute C1,C2 for row window mapping */
  93. fcb->C1 = G__.window.ns_res / fcb->cellhd.ns_res;
  94. fcb->C2 =
  95. (fcb->cellhd.north - G__.window.north +
  96. G__.window.ns_res / 2.0) / fcb->cellhd.ns_res;
  97. }
  98. /**
  99. * \brief Northing to row.
  100. *
  101. * Converts a <b>north</b>ing relative to a <b>window</b> to a row.<br>
  102. * <b>Note:</b> The result is a double. Casting it to an integer will
  103. * give the row number.
  104. *
  105. * \param[in] north
  106. * \param[in] window
  107. * \return row id
  108. */
  109. double G_northing_to_row(double north, const struct Cell_head *window)
  110. {
  111. return (window->north - north) / window->ns_res;
  112. }
  113. /**
  114. * \brief Adjust east longitude.
  115. *
  116. * This routine returns an equivalent <b>east</b> that is
  117. * larger, but no more than 360 larger than the <b>west</b>
  118. * coordinate.<br>
  119. * <b>Note:</b> This routine should be used only with latitude-longitude
  120. * coordinates.
  121. *
  122. * \param[in,out] east
  123. * \param[in] west
  124. * \return east coordinate
  125. */
  126. double G_adjust_east_longitude(double east, double west)
  127. {
  128. while (east > west + 360.0)
  129. east -= 360.0;
  130. while (east <= west)
  131. east += 360.0;
  132. return east;
  133. }
  134. /**
  135. * \brief Returns east larger than west.
  136. *
  137. * If the region projection is <i>PROJECTION_LL</i>, then this routine
  138. * returns an equivalent <b>east</b> that is larger, but no more than
  139. * 360 degrees larger, than the coordinate for the western edge of the
  140. * region. Otherwise no adjustment is made and the original
  141. * <b>east</b> is returned.
  142. *
  143. * \param[in,out] east
  144. * \param[in] window
  145. * \return east coordinate
  146. */
  147. double G_adjust_easting(double east, const struct Cell_head *window)
  148. {
  149. if (window->proj == PROJECTION_LL) {
  150. east = G_adjust_east_longitude(east, window->west);
  151. if (east > window->east && east == window->west + 360)
  152. east = window->west;
  153. }
  154. return east;
  155. }
  156. /**
  157. * \brief Easting to column.
  158. *
  159. * Converts <b>east</b> relative to a <b>window</b> to a column.<br>
  160. * <b>Note:</b> The result is a <i>double</i>. Casting it to an
  161. * <i>int</i> will give the column number.
  162. *
  163. * \param[in] east
  164. * \param[in] window
  165. * \return column id
  166. */
  167. double G_easting_to_col(double east, const struct Cell_head *window)
  168. {
  169. east = G_adjust_easting(east, window);
  170. return (east - window->west) / window->ew_res;
  171. }
  172. /**
  173. * \brief Row to northing.
  174. *
  175. * Converts a <b>row</b> relative to a <b>window</b> to a
  176. * northing.<br>
  177. * <b>Note:</b> row is a double:
  178. * - row+0.0 will return the northing for the northern edge of the row.<br>
  179. * - row+0.5 will return the northing for the center of the row.<br>
  180. * - row+1.0 will return the northing for the southern edge of the row.<br>
  181. * <b>Note:</b> The result is a <i>double</i>. Casting it to an
  182. * <i>int</i> will give the column number.
  183. *
  184. * \param[in] row
  185. * \param[in] window
  186. * \return north coordinate
  187. */
  188. double G_row_to_northing(double row, const struct Cell_head *window)
  189. {
  190. return window->north - row * window->ns_res;
  191. }
  192. /**
  193. * \brief Column to easting.
  194. *
  195. * Converts a <b>col</b> relative to a <b>window</b> to an easting.<br>
  196. * <b>Note:</b> <b>col</b> is a <i>double</i>:<br>
  197. * - col+0.0 will return the easting for the western edge of the column.<br>
  198. * - col+0.5 will return the easting for the center of the column.<br>
  199. * - col+1.0 will return the easting for the eastern edge of the column.<br>
  200. *
  201. * \param[in] col
  202. * \param[in] window
  203. * \return east coordinate
  204. */
  205. double G_col_to_easting(double col, const struct Cell_head *window)
  206. {
  207. return window->west + col * window->ew_res;
  208. }
  209. /**
  210. * \brief Number of rows in active window.
  211. *
  212. * This routine returns the number of rows in the active module window.
  213. * Before raster files can be read or written, it is necessary to
  214. * known how many rows are in the active window. For example:<br>
  215. \code
  216. int nrows, cols;
  217. int row, col;
  218. nrows = G_window_rows( );
  219. ncols = G_window_cols( );
  220. for (row = 0; row < nrows; row++)
  221. {
  222. <i>read</i> row ...
  223. for (col = 0; col < ncols; col++)
  224. {
  225. process col ...
  226. }
  227. }
  228. \endcode
  229. *
  230. * \return number of rows
  231. */
  232. int G_window_rows(void)
  233. {
  234. G__init_window();
  235. return G__.window.rows;
  236. }
  237. /**
  238. * \brief Number of columns in active window.
  239. *
  240. * These
  241. * routines return the number of rows and columns (respectively) in the active
  242. * module region. Before raster maps can be read or written, it is necessary to
  243. * known how many rows and columns are in the active region. For example:<br>
  244. \code
  245. int nrows, cols;
  246. int row, col;
  247. nrows = G_window_rows( );
  248. ncols = G_window_cols( );
  249. for (row = 0; row < nrows; row++)
  250. {
  251. <i>read</i> row ...
  252. for (col = 0; col < ncols; col++)
  253. {
  254. process col ...
  255. }
  256. }
  257. \endcode
  258. *
  259. * \return number of columns
  260. */
  261. int G_window_cols(void)
  262. {
  263. G__init_window();
  264. return G__.window.cols;
  265. }
  266. /**
  267. * \brief Initialize window.
  268. *
  269. * \return
  270. */
  271. void G__init_window(void)
  272. {
  273. if (!G__.window_set) {
  274. G__.window_set = 1;
  275. G_get_window(&G__.window);
  276. }
  277. }
  278. /**
  279. * \brief Loops rows until mismatch?.
  280. *
  281. * This routine works fine if the mask is not set. It may give incorrect
  282. * results with a mask, since the mask row may have a different repeat
  283. * value. The issue can be fixed by doing it for the mask as well and
  284. * using the smaller value.
  285. *
  286. * \param[in] fd file descriptor
  287. * \param[in] row starting row
  288. * \return number of rows completed
  289. */
  290. int G_row_repeat_nomask(int fd, int row)
  291. {
  292. struct fileinfo *fcb = &G__.fileinfo[fd];
  293. double f;
  294. int r1, r2;
  295. int count;
  296. count = 1;
  297. /* r1 is the row in the raster map itself.
  298. * r2 is the next row(s) in the raster map
  299. * see get_row.c for details on this calculation
  300. */
  301. f = row * fcb->C1 + fcb->C2;
  302. r1 = f;
  303. if (f < r1)
  304. r1--;
  305. while (++row < G__.window.rows) {
  306. f = row * fcb->C1 + fcb->C2;
  307. r2 = f;
  308. if (f < r2)
  309. r2--;
  310. if (r1 != r2)
  311. break;
  312. count++;
  313. }
  314. return count;
  315. }