window_map.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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 always returns 0
  28. */
  29. int 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 0;
  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. return 0;
  98. }
  99. /**
  100. * \brief Northing to row.
  101. *
  102. * Converts a <b>north</b>ing relative to a <b>window</b> to a row.<br>
  103. * <b>Note:</b> The result is a double. Casting it to an integer will
  104. * give the row number.
  105. *
  106. * \param[in] north
  107. * \param[in] window
  108. * \return row id
  109. */
  110. double G_northing_to_row(double north, const struct Cell_head *window)
  111. {
  112. return (window->north - north) / window->ns_res;
  113. }
  114. /**
  115. * \brief Adjust east longitude.
  116. *
  117. * This routine returns an equivalent <b>east</b> that is
  118. * larger, but no more than 360 larger than the <b>west</b>
  119. * coordinate.<br>
  120. * <b>Note:</b> This routine should be used only with latitude-longitude
  121. * coordinates.
  122. *
  123. * \param[in,out] east
  124. * \param[in] west
  125. * \return east coordinate
  126. */
  127. double G_adjust_east_longitude(double east, double west)
  128. {
  129. while (east > west + 360.0)
  130. east -= 360.0;
  131. while (east <= west)
  132. east += 360.0;
  133. return east;
  134. }
  135. /**
  136. * \brief Returns east larger than west.
  137. *
  138. * If the region projection is <i>PROJECTION_LL</i>, then this routine
  139. * returns an equivalent <b>east</b> that is larger, but no more than
  140. * 360 degrees larger, than the coordinate for the western edge of the
  141. * region. Otherwise no adjustment is made and the original
  142. * <b>east</b> is returned.
  143. *
  144. * \param[in,out] east
  145. * \param[in] window
  146. * \return east coordinate
  147. */
  148. double G_adjust_easting(double east, const struct Cell_head *window)
  149. {
  150. if (window->proj == PROJECTION_LL) {
  151. east = G_adjust_east_longitude(east, window->west);
  152. if (east > window->east && east == window->west + 360)
  153. east = window->west;
  154. }
  155. return east;
  156. }
  157. /**
  158. * \brief Easting to column.
  159. *
  160. * Converts <b>east</b> relative to a <b>window</b> to a column.<br>
  161. * <b>Note:</b> The result is a <i>double</i>. Casting it to an
  162. * <i>int</i> will give the column number.
  163. *
  164. * \param[in] east
  165. * \param[in] window
  166. * \return column id
  167. */
  168. double G_easting_to_col(double east, const struct Cell_head *window)
  169. {
  170. east = G_adjust_easting(east, window);
  171. return (east - window->west) / window->ew_res;
  172. }
  173. /**
  174. * \brief Row to northing.
  175. *
  176. * Converts a <b>row</b> relative to a <b>window</b> to a
  177. * northing.<br>
  178. * <b>Note:</b> row is a double:
  179. * - row+0.0 will return the northing for the northern edge of the row.<br>
  180. * - row+0.5 will return the northing for the center of the row.<br>
  181. * - row+1.0 will return the northing for the southern edge of the row.<br>
  182. * <b>Note:</b> The result is a <i>double</i>. Casting it to an
  183. * <i>int</i> will give the column number.
  184. *
  185. * \param[in] row
  186. * \param[in] window
  187. * \return north coordinate
  188. */
  189. double G_row_to_northing(double row, const struct Cell_head *window)
  190. {
  191. return window->north - row * window->ns_res;
  192. }
  193. /**
  194. * \brief Column to easting.
  195. *
  196. * Converts a <b>col</b> relative to a <b>window</b> to an easting.<br>
  197. * <b>Note:</b> <b>col</b> is a <i>double</i>:<br>
  198. * - col+0.0 will return the easting for the western edge of the column.<br>
  199. * - col+0.5 will return the easting for the center of the column.<br>
  200. * - col+1.0 will return the easting for the eastern edge of the column.<br>
  201. *
  202. * \param[in] col
  203. * \param[in] window
  204. * \return east coordinate
  205. */
  206. double G_col_to_easting(double col, const struct Cell_head *window)
  207. {
  208. return window->west + col * window->ew_res;
  209. }
  210. /**
  211. * \brief Number of rows in active window.
  212. *
  213. * This routine returns the number of rows in the active module window.
  214. * Before raster files can be read or written, it is necessary to
  215. * known how many rows are in the active window. For example:<br>
  216. \code
  217. int nrows, cols;
  218. int row, col;
  219. nrows = G_window_rows( );
  220. ncols = G_window_cols( );
  221. for (row = 0; row < nrows; row++)
  222. {
  223. <i>read</i> row ...
  224. for (col = 0; col < ncols; col++)
  225. {
  226. process col ...
  227. }
  228. }
  229. \endcode
  230. *
  231. * \return number of rows
  232. */
  233. int G_window_rows(void)
  234. {
  235. G__init_window();
  236. return G__.window.rows;
  237. }
  238. /**
  239. * \brief Number of columns in active window.
  240. *
  241. * These
  242. * routines return the number of rows and columns (respectively) in the active
  243. * module region. Before raster maps can be read or written, it is necessary to
  244. * known how many rows and columns are in the active region. For example:<br>
  245. \code
  246. int nrows, cols;
  247. int row, col;
  248. nrows = G_window_rows( );
  249. ncols = G_window_cols( );
  250. for (row = 0; row < nrows; row++)
  251. {
  252. <i>read</i> row ...
  253. for (col = 0; col < ncols; col++)
  254. {
  255. process col ...
  256. }
  257. }
  258. \endcode
  259. *
  260. * \return number of columns
  261. */
  262. int G_window_cols(void)
  263. {
  264. G__init_window();
  265. return G__.window.cols;
  266. }
  267. /**
  268. * \brief Initialize window.
  269. *
  270. * \return always returns 0
  271. */
  272. int G__init_window(void)
  273. {
  274. if (!G__.window_set) {
  275. G__.window_set = 1;
  276. G_get_window(&G__.window);
  277. }
  278. return 0;
  279. }
  280. /**
  281. * \brief Loops rows until mismatch?.
  282. *
  283. * This routine works fine if the mask is not set. It may give incorrect
  284. * results with a mask, since the mask row may have a different repeat
  285. * value. The issue can be fixed by doing it for the mask as well and
  286. * using the smaller value.
  287. *
  288. * \param[in] fd file descriptor
  289. * \param[in] row starting row
  290. * \return number of rows completed
  291. */
  292. int G_row_repeat_nomask(int fd, int row)
  293. {
  294. struct fileinfo *fcb = &G__.fileinfo[fd];
  295. double f;
  296. int r1, r2;
  297. int count;
  298. count = 1;
  299. /* r1 is the row in the raster map itself.
  300. * r2 is the next row(s) in the raster map
  301. * see get_row.c for details on this calculation
  302. */
  303. f = row * fcb->C1 + fcb->C2;
  304. r1 = f;
  305. if (f < r1)
  306. r1--;
  307. while (++row < G__.window.rows) {
  308. f = row * fcb->C1 + fcb->C2;
  309. r2 = f;
  310. if (f < r2)
  311. r2--;
  312. if (r1 != r2)
  313. break;
  314. count++;
  315. }
  316. return count;
  317. }