map3.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. #include <stdlib.h>
  2. #include <limits.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <grass/gis.h>
  6. #include <grass/raster.h>
  7. #include <grass/raster.h>
  8. #include <grass/raster3d.h>
  9. #include <grass/btree.h>
  10. #include <grass/glocale.h>
  11. #include "mapcalc.h"
  12. #include "globals.h"
  13. #include "globals3.h"
  14. /****************************************************************************/
  15. RASTER3D_Region current_region3;
  16. void setup_region(void)
  17. {
  18. Rast3d_init_defaults();
  19. Rast3d_get_window(&current_region3);
  20. rows = current_region3.rows;
  21. columns = current_region3.cols;
  22. depths = current_region3.depths;
  23. }
  24. /****************************************************************************/
  25. typedef struct map
  26. {
  27. const char *name;
  28. const char *mapset;
  29. int have_cats;
  30. int have_colors;
  31. int min_row, max_row;
  32. void *handle;
  33. int fd;
  34. struct Categories cats;
  35. struct Colors colors;
  36. BTREE btree;
  37. } map;
  38. /****************************************************************************/
  39. static map *maps;
  40. static int num_maps;
  41. static int max_maps;
  42. static void **omaps;
  43. static int num_omaps;
  44. static int max_omaps;
  45. static unsigned char *red, *grn, *blu;
  46. static unsigned char *set;
  47. static int min_row = INT_MAX;
  48. static int max_row = -INT_MAX;
  49. static int min_col = INT_MAX;
  50. static int max_col = -INT_MAX;
  51. /****************************************************************************/
  52. static void read_row(void *handle, char *buf, int type, int depth, int row)
  53. {
  54. int i;
  55. switch (type) {
  56. case CELL_TYPE:
  57. for (i = 0; i < columns; i++) {
  58. double x;
  59. Rast3d_get_value(handle, i, row, depth, (char *)&x, DCELL_TYPE);
  60. if (Rast3d_is_null_value_num(&x, DCELL_TYPE))
  61. SET_NULL_C(&((CELL *) buf)[i]);
  62. else
  63. ((CELL *) buf)[i] = (CELL) x;
  64. }
  65. break;
  66. case FCELL_TYPE:
  67. for (i = 0; i < columns; i++) {
  68. float x;
  69. Rast3d_get_value(handle, i, row, depth, (char *)&x, FCELL_TYPE);
  70. if (Rast3d_is_null_value_num(&x, FCELL_TYPE))
  71. SET_NULL_F(&((FCELL *) buf)[i]);
  72. else
  73. ((FCELL *) buf)[i] = x;
  74. }
  75. break;
  76. case DCELL_TYPE:
  77. for (i = 0; i < columns; i++) {
  78. double x;
  79. Rast3d_get_value(handle, i, row, depth, (char *)&x, DCELL_TYPE);
  80. if (Rast3d_is_null_value_num(&x, DCELL_TYPE))
  81. SET_NULL_D(&((DCELL *) buf)[i]);
  82. else
  83. ((DCELL *) buf)[i] = x;
  84. }
  85. break;
  86. }
  87. }
  88. static void write_row(void *handle, const char *buf, int type, int depth,
  89. int row)
  90. {
  91. int i;
  92. switch (type) {
  93. case CELL_TYPE:
  94. for (i = 0; i < columns; i++) {
  95. double x;
  96. if (IS_NULL_C(&((CELL *) buf)[i]))
  97. Rast3d_set_null_value(&x, 1, DCELL_TYPE);
  98. else
  99. x = ((CELL *) buf)[i];
  100. if (Rast3d_put_value(handle, i, row, depth, (char *)&x, DCELL_TYPE) <
  101. 0)
  102. G_fatal_error(_("Error writing data"));
  103. }
  104. break;
  105. case FCELL_TYPE:
  106. for (i = 0; i < columns; i++) {
  107. float x;
  108. if (IS_NULL_F(&((FCELL *) buf)[i]))
  109. Rast3d_set_null_value(&x, 1, FCELL_TYPE);
  110. else
  111. x = ((FCELL *) buf)[i];
  112. if (Rast3d_put_value(handle, i, row, depth, (char *)&x, FCELL_TYPE) <
  113. 0)
  114. G_fatal_error(_("Error writing data"));
  115. }
  116. break;
  117. case DCELL_TYPE:
  118. for (i = 0; i < columns; i++) {
  119. double x;
  120. if (IS_NULL_D(&((DCELL *) buf)[i]))
  121. Rast3d_set_null_value(&x, 1, DCELL_TYPE);
  122. else
  123. x = ((DCELL *) buf)[i];
  124. if (Rast3d_put_value(handle, i, row, depth, (char *)&x, DCELL_TYPE) <
  125. 0)
  126. G_fatal_error(_("Error writing data"));
  127. }
  128. break;
  129. }
  130. }
  131. /****************************************************************************/
  132. static int compare_ints(const void *a, const void *b)
  133. {
  134. return *(const int *)a - *(const int *)b;
  135. }
  136. static void init_colors(map * m)
  137. {
  138. if (!red)
  139. red = G_malloc(columns);
  140. if (!grn)
  141. grn = G_malloc(columns);
  142. if (!blu)
  143. blu = G_malloc(columns);
  144. if (!set)
  145. set = G_malloc(columns);
  146. if (Rast3d_read_colors((char *)m->name, (char *)m->mapset, &m->colors) < 0)
  147. G_fatal_error(_("Unable to read color file for raster map <%s@%s>"),
  148. m->name, m->mapset);
  149. m->have_colors = 1;
  150. }
  151. static void init_cats(map * m)
  152. {
  153. if (Rast3d_read_cats((char *)m->name, (char *)m->mapset, &m->cats) < 0)
  154. G_fatal_error(_("Unable to read category file of raster map <%s@%s>"),
  155. m->name, m->mapset);
  156. if (!btree_create(&m->btree, compare_ints, 1))
  157. G_fatal_error(_("Unable to create btree for raster map <%s@%s>"),
  158. m->name, m->mapset);
  159. m->have_cats = 1;
  160. }
  161. static void translate_from_colors(map * m, DCELL * rast, CELL * cell,
  162. int ncols, int mod)
  163. {
  164. int i;
  165. Rast_lookup_d_colors(rast, red, grn, blu, set, ncols, &m->colors);
  166. switch (mod) {
  167. case 'r':
  168. for (i = 0; i < ncols; i++)
  169. cell[i] = red[i];
  170. break;
  171. case 'g':
  172. for (i = 0; i < ncols; i++)
  173. cell[i] = grn[i];
  174. break;
  175. case 'b':
  176. for (i = 0; i < ncols; i++)
  177. cell[i] = blu[i];
  178. break;
  179. case '#': /* grey (backwards compatible) */
  180. /* old weightings: R=0.177, G=0.813, B=0.011 */
  181. for (i = 0; i < ncols; i++)
  182. cell[i] =
  183. (181 * red[i] + 833 * grn[i] + 11 * blu[i] + 512) / 1024;
  184. break;
  185. case 'y': /* grey (NTSC) */
  186. /* NTSC weightings: R=0.299, G=0.587, B=0.114 */
  187. for (i = 0; i < ncols; i++)
  188. cell[i] =
  189. (306 * red[i] + 601 * grn[i] + 117 * blu[i] + 512) / 1024;
  190. break;
  191. case 'i': /* grey (equal weight) */
  192. for (i = 0; i < ncols; i++)
  193. cell[i] = (red[i] + grn[i] + blu[i]) / 3;
  194. break;
  195. case 'M':
  196. case '@':
  197. default:
  198. G_fatal_error(_("Invalid map modifier: '%c'"), mod);
  199. break;
  200. }
  201. }
  202. /* convert cell values to double based on the values in the
  203. * category file.
  204. *
  205. * This requires performing sscanf() of the category label
  206. * and only do it it for new categories. Must maintain
  207. * some kind of maps of already scaned values.
  208. *
  209. * This maps is a hybrid tree, where the data in each node
  210. * of the tree is an array of, for example, 64 values, and
  211. * the key of the tree is the category represented by the
  212. * first index of the data
  213. *
  214. * To speed things up a little, use shifts instead of divide or multiply
  215. * to compute the key and the index
  216. *
  217. * This uses the BTREE library to manage the tree itself
  218. * btree structure must already be intialized
  219. * pcats structure must already contain category labels
  220. */
  221. #define SHIFT 6
  222. #define NCATS (1<<SHIFT)
  223. static void translate_from_cats(map * m, CELL * cell, DCELL * xcell,
  224. int ncols)
  225. {
  226. struct Categories *pcats;
  227. BTREE *btree;
  228. int i, idx;
  229. CELL cat, key;
  230. double vbuf[1 << SHIFT];
  231. double *values;
  232. void *ptr;
  233. char *label;
  234. btree = &m->btree;
  235. pcats = &m->cats;
  236. for (; ncols-- > 0; cell++, xcell++) {
  237. cat = *cell;
  238. if (IS_NULL_C(cell)) {
  239. SET_NULL_D(xcell);
  240. continue;
  241. }
  242. /* compute key as cat/NCATS * NCATS, adjusting down for negatives
  243. * and idx so that key+idx == cat
  244. */
  245. if (cat < 0)
  246. key = -(((-cat - 1) >> SHIFT) << SHIFT) - NCATS;
  247. else
  248. key = (cat >> SHIFT) << SHIFT;
  249. idx = cat - key;
  250. /* If key not already in the tree, sscanf() all cats for this key
  251. * and put them into the tree
  252. */
  253. if (!btree_find(btree, &key, &ptr)) {
  254. values = vbuf;
  255. int cat = i + key;
  256. for (i = 0; i < NCATS; i++) {
  257. if ((label = Rast_get_c_cat((CELL *) &cat, pcats)) == NULL
  258. || sscanf(label, "%lf", values) != 1)
  259. SET_NULL_D(values);
  260. values++;
  261. }
  262. values = vbuf;
  263. btree_update(btree, &key, sizeof(key), vbuf, sizeof(vbuf));
  264. }
  265. else
  266. values = ptr;
  267. /* and finally lookup the translated value */
  268. if (IS_NULL_D(&values[idx]))
  269. SET_NULL_D(xcell);
  270. else
  271. *xcell = values[idx];
  272. }
  273. }
  274. static void setup_map(map * m)
  275. {
  276. }
  277. static void read_map(map * m, void *buf, int res_type, int depth, int row,
  278. int col)
  279. {
  280. CELL *ibuf = buf;
  281. FCELL *fbuf = buf;
  282. DCELL *dbuf = buf;
  283. if (row < 0 || row >= rows || depth < 0 || depth >= depths) {
  284. int i;
  285. switch (res_type) {
  286. case CELL_TYPE:
  287. for (i = 0; i < columns; i++)
  288. SET_NULL_C(&ibuf[i]);
  289. break;
  290. case FCELL_TYPE:
  291. for (i = 0; i < columns; i++)
  292. SET_NULL_F(&fbuf[i]);
  293. break;
  294. case DCELL_TYPE:
  295. for (i = 0; i < columns; i++)
  296. SET_NULL_D(&dbuf[i]);
  297. break;
  298. default:
  299. G_fatal_error(_("Unknown type: %d"), res_type);
  300. break;
  301. }
  302. return;
  303. }
  304. read_row(m->handle, buf, res_type, depth, row);
  305. if (col)
  306. column_shift(buf, res_type, col);
  307. }
  308. static void close_map(map * m)
  309. {
  310. if (!m->handle)
  311. return;
  312. if (!Rast3d_close(m->handle))
  313. G_fatal_error(_("Unable to close raster map <%s@%s>"),
  314. m->name, m->mapset);
  315. if (m->have_cats) {
  316. btree_free(&m->btree);
  317. Rast_free_cats(&m->cats);
  318. m->have_cats = 0;
  319. }
  320. if (m->have_colors) {
  321. Rast_free_colors(&m->colors);
  322. m->have_colors = 0;
  323. }
  324. }
  325. /****************************************************************************/
  326. int map_type(const char *name, int mod)
  327. {
  328. const char *mapset;
  329. char *tmpname;
  330. int result;
  331. switch (mod) {
  332. case 'M':
  333. tmpname = G_store((char *)name);
  334. mapset = G_find_raster3d(tmpname, "");
  335. if (mapset) {
  336. void *handle;
  337. setup_region(); /* TODO: setup_region should be called by evaluate() ? */
  338. handle = Rast3d_open_cell_old(tmpname, mapset, &current_region3,
  339. RASTER3D_TILE_SAME_AS_FILE, RASTER3D_NO_CACHE);
  340. result = (Rast3d_file_type_map(handle) == FCELL_TYPE)
  341. ? FCELL_TYPE : DCELL_TYPE;
  342. Rast3d_close(handle);
  343. }
  344. else
  345. result = -1;
  346. G_free(tmpname);
  347. return result;
  348. case '@':
  349. return DCELL_TYPE;
  350. case 'r':
  351. case 'g':
  352. case 'b':
  353. case '#':
  354. case 'y':
  355. case 'i':
  356. return CELL_TYPE;
  357. default:
  358. G_fatal_error(_("Invalid map modifier: '%c'"), mod);
  359. return -1;
  360. }
  361. }
  362. int open_map(const char *name, int mod, int row, int col)
  363. {
  364. int i;
  365. const char *mapset;
  366. char *tmpname;
  367. int use_cats = 0;
  368. int use_colors = 0;
  369. map *m;
  370. if (row < min_row)
  371. min_row = row;
  372. if (row > max_row)
  373. max_row = row;
  374. if (col < min_col)
  375. min_col = col;
  376. if (col > max_col)
  377. max_col = col;
  378. tmpname = G_store((char *)name);
  379. mapset = G_find_raster3d(tmpname, "");
  380. G_free(tmpname);
  381. if (!mapset)
  382. G_fatal_error("open_map: map [%s] not found", name);
  383. switch (mod) {
  384. case 'M':
  385. break;
  386. case '@':
  387. use_cats = 1;
  388. break;
  389. case 'r':
  390. case 'g':
  391. case 'b':
  392. case '#':
  393. case 'y':
  394. case 'i':
  395. use_colors = 1;
  396. break;
  397. default:
  398. G_fatal_error(_("Invalid map modifier: '%c'"), mod);
  399. break;
  400. }
  401. for (i = 0; i < num_maps; i++) {
  402. m = &maps[i];
  403. if (strcmp(m->name, name) != 0 || strcmp(m->mapset, mapset) != 0)
  404. continue;
  405. if (row < m->min_row)
  406. m->min_row = row;
  407. if (row > m->max_row)
  408. m->max_row = row;
  409. if (use_cats && !m->have_cats)
  410. init_cats(m);
  411. if (use_colors && !m->have_colors)
  412. init_colors(m);
  413. return i;
  414. }
  415. if (num_maps >= max_maps) {
  416. max_maps += 10;
  417. maps = G_realloc(maps, max_maps * sizeof(map));
  418. }
  419. m = &maps[num_maps];
  420. m->name = name;
  421. m->mapset = mapset;
  422. m->have_cats = 0;
  423. m->have_colors = 0;
  424. m->min_row = row;
  425. m->max_row = row;
  426. if (use_cats)
  427. init_cats(m);
  428. if (use_colors)
  429. init_colors(m);
  430. m->handle = Rast3d_open_cell_old((char *)name, (char *)mapset,
  431. &current_region3, DCELL_TYPE,
  432. RASTER3D_USE_CACHE_DEFAULT);
  433. if (!m->handle)
  434. G_fatal_error(_("Unable to open raster map <%s>"), name);
  435. return num_maps++;
  436. }
  437. void setup_maps(void)
  438. {
  439. int i;
  440. for (i = 0; i < num_maps; i++)
  441. setup_map(&maps[i]);
  442. }
  443. void get_map_row(int idx, int mod, int depth, int row, int col, void *buf,
  444. int res_type)
  445. {
  446. static CELL *ibuf;
  447. static DCELL *fbuf;
  448. map *m = &maps[idx];
  449. switch (mod) {
  450. case 'M':
  451. read_map(m, buf, res_type, depth, row, col);
  452. break;
  453. case '@':
  454. if (!ibuf)
  455. ibuf = G_malloc(columns * sizeof(CELL));
  456. read_map(m, ibuf, CELL_TYPE, depth, row, col);
  457. translate_from_cats(m, ibuf, buf, columns);
  458. break;
  459. case 'r':
  460. case 'g':
  461. case 'b':
  462. case '#':
  463. case 'y':
  464. case 'i':
  465. if (!fbuf)
  466. fbuf = G_malloc(columns * sizeof(DCELL));
  467. read_map(m, fbuf, DCELL_TYPE, depth, row, col);
  468. translate_from_colors(m, fbuf, buf, columns, mod);
  469. break;
  470. default:
  471. G_fatal_error(_("Invalid map modifier: '%c'"), mod);
  472. break;
  473. }
  474. }
  475. void close_maps(void)
  476. {
  477. int i;
  478. for (i = 0; i < num_maps; i++)
  479. close_map(&maps[i]);
  480. num_maps = 0;
  481. }
  482. /****************************************************************************/
  483. int check_output_map(const char *name)
  484. {
  485. return !!G_find_raster3d(name, G_mapset());
  486. }
  487. int open_output_map(const char *name, int res_type)
  488. {
  489. void *handle;
  490. Rast3d_set_file_type(res_type == FCELL_TYPE ? FCELL_TYPE : DCELL_TYPE);
  491. handle = Rast3d_open_new_opt_tile_size((char *)name, RASTER3D_USE_CACHE_XYZ, &current_region3, res_type == FCELL_TYPE ? FCELL_TYPE : DCELL_TYPE, 32);
  492. if (!handle)
  493. G_fatal_error(_("Unable to create raster map <%s>"), name);
  494. if (num_omaps >= max_omaps) {
  495. max_omaps += 10;
  496. omaps = G_realloc(omaps, max_omaps * sizeof(void *));
  497. }
  498. omaps[num_omaps] = handle;
  499. return num_omaps++;
  500. }
  501. void put_map_row(int fd, void *buf, int res_type)
  502. {
  503. void *handle = omaps[fd];
  504. write_row(handle, buf, res_type, current_depth, current_row);
  505. }
  506. void close_output_map(int fd)
  507. {
  508. void *handle = omaps[fd];
  509. if (!Rast3d_close(handle))
  510. G_fatal_error(_("Unable to close output raster map"));
  511. }
  512. void unopen_output_map(int fd)
  513. {
  514. close_output_map(fd);
  515. }
  516. /****************************************************************************/
  517. void copy_cats(const char *dst, int idx)
  518. {
  519. const map *m = &maps[idx];
  520. struct Categories cats;
  521. if (Rast3d_read_cats((char *)m->name, (char *)m->mapset, &cats) < 0)
  522. return;
  523. Rast3d_write_cats((char *)dst, &cats);
  524. Rast_free_cats(&cats);
  525. }
  526. void copy_colors(const char *dst, int idx)
  527. {
  528. const map *m = &maps[idx];
  529. struct Colors colr;
  530. if (Rast3d_read_colors((char *)m->name, (char *)m->mapset, &colr) <= 0)
  531. return;
  532. Rast3d_write_colors((char *)dst, G_mapset(), &colr);
  533. Rast_free_colors(&colr);
  534. }
  535. void copy_history(const char *dst, int idx)
  536. {
  537. }
  538. void create_history(const char *dst, expression * e)
  539. {
  540. }
  541. /****************************************************************************/