map.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  1. #include <grass/config.h>
  2. #include <stdlib.h>
  3. #include <limits.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #ifdef HAVE_PTHREAD_H
  7. #include <pthread.h>
  8. #endif
  9. #include <grass/gis.h>
  10. #include <grass/raster.h>
  11. #include <grass/raster.h>
  12. #include <grass/btree.h>
  13. #include <grass/glocale.h>
  14. #include <grass/calc.h>
  15. #include "mapcalc.h"
  16. #include "globals.h"
  17. #include "globals2.h"
  18. /****************************************************************************/
  19. static void prepare_region_from_maps(expression **, int, int);
  20. int columns;
  21. struct Cell_head current_region2;
  22. void setup_region(void)
  23. {
  24. G_get_window(&current_region2);
  25. rows = Rast_window_rows();
  26. columns = Rast_window_cols();
  27. calc_init(columns);
  28. depths = 1;
  29. }
  30. /****************************************************************************/
  31. struct sub_cache
  32. {
  33. int row;
  34. char *valid;
  35. void **buf;
  36. };
  37. struct row_cache
  38. {
  39. int fd;
  40. int nrows;
  41. struct sub_cache *sub[3];
  42. };
  43. struct map
  44. {
  45. const char *name;
  46. const char *mapset;
  47. int have_cats;
  48. int have_colors;
  49. int use_rowio;
  50. int min_row, max_row;
  51. int fd;
  52. struct Categories cats;
  53. struct Colors colors;
  54. BTREE btree;
  55. struct row_cache cache;
  56. #ifdef HAVE_PTHREAD_H
  57. pthread_mutex_t mutex;
  58. #endif
  59. };
  60. /****************************************************************************/
  61. static struct map *maps;
  62. static int num_maps;
  63. static int max_maps;
  64. static int masking;
  65. static int min_row = INT_MAX;
  66. static int max_row = -INT_MAX;
  67. static int min_col = INT_MAX;
  68. static int max_col = -INT_MAX;
  69. static int max_rows_in_memory = 8;
  70. #ifdef HAVE_PTHREAD_H
  71. static pthread_mutex_t cats_mutex;
  72. static pthread_mutex_t mask_mutex;
  73. #endif
  74. /****************************************************************************/
  75. static void read_row(int fd, void *buf, int row, int res_type)
  76. {
  77. #ifdef HAVE_PTHREAD_H
  78. if (masking)
  79. pthread_mutex_lock(&mask_mutex);
  80. #endif
  81. Rast_get_row(fd, buf, row, res_type);
  82. #ifdef HAVE_PTHREAD_H
  83. if (masking)
  84. pthread_mutex_unlock(&mask_mutex);
  85. #endif
  86. }
  87. static void cache_sub_init(struct row_cache *cache, int data_type)
  88. {
  89. struct sub_cache *sub = G_malloc(sizeof(struct sub_cache));
  90. int i;
  91. sub->row = -cache->nrows;
  92. sub->valid = G_calloc(cache->nrows, 1);
  93. sub->buf = G_malloc(cache->nrows * sizeof(void *));
  94. for (i = 0; i < cache->nrows; i++)
  95. sub->buf[i] = Rast_allocate_buf(data_type);
  96. cache->sub[data_type] = sub;
  97. }
  98. static void cache_setup(struct row_cache *cache, int fd, int nrows)
  99. {
  100. cache->fd = fd;
  101. cache->nrows = nrows;
  102. cache->sub[CELL_TYPE] = NULL;
  103. cache->sub[FCELL_TYPE] = NULL;
  104. cache->sub[DCELL_TYPE] = NULL;
  105. }
  106. static void cache_release(struct row_cache *cache)
  107. {
  108. int t;
  109. for (t = 0; t < 3; t++) {
  110. struct sub_cache *sub = cache->sub[t];
  111. int i;
  112. if (!sub)
  113. continue;
  114. for (i = 0; i < cache->nrows; i++)
  115. G_free(sub->buf[i]);
  116. G_free(sub->buf);
  117. G_free(sub->valid);
  118. G_free(sub);
  119. }
  120. }
  121. static void *cache_get_raw(struct row_cache *cache, int row, int data_type)
  122. {
  123. struct sub_cache *sub;
  124. void **tmp;
  125. char *vtmp;
  126. int i, j;
  127. int newrow;
  128. if (!cache->sub[data_type])
  129. cache_sub_init(cache, data_type);
  130. sub = cache->sub[data_type];
  131. i = row - sub->row;
  132. if (i >= 0 && i < cache->nrows) {
  133. if (!sub->valid[i]) {
  134. read_row(cache->fd, sub->buf[i], row, data_type);
  135. sub->valid[i] = 1;
  136. }
  137. return sub->buf[i];
  138. }
  139. if (i <= -cache->nrows || i >= cache->nrows * 2 - 1) {
  140. memset(sub->valid, 0, cache->nrows);
  141. sub->row = row;
  142. read_row(cache->fd, sub->buf[0], row, data_type);
  143. sub->valid[0] = 1;
  144. return sub->buf[0];
  145. }
  146. tmp = G_alloca(cache->nrows * sizeof(void *));
  147. memcpy(tmp, sub->buf, cache->nrows * sizeof(void *));
  148. vtmp = G_alloca(cache->nrows);
  149. memcpy(vtmp, sub->valid, cache->nrows);
  150. i = (i < 0)
  151. ? 0
  152. : cache->nrows - 1;
  153. newrow = row - i;
  154. for (j = 0; j < cache->nrows; j++) {
  155. int r = newrow + j;
  156. int k = r - sub->row;
  157. int l = (k + cache->nrows) % cache->nrows;
  158. sub->buf[j] = tmp[l];
  159. sub->valid[j] = k >= 0 && k < cache->nrows && vtmp[l];
  160. }
  161. sub->row = newrow;
  162. G_freea(tmp);
  163. G_freea(vtmp);
  164. read_row(cache->fd, sub->buf[i], row, data_type);
  165. sub->valid[i] = 1;
  166. return sub->buf[i];
  167. }
  168. static void cache_get(struct row_cache *cache, void *buf, int row, int res_type)
  169. {
  170. void *p = cache_get_raw(cache, row, res_type);
  171. memcpy(buf, p, columns * Rast_cell_size(res_type));
  172. }
  173. /****************************************************************************/
  174. static int compare_ints(const void *a, const void *b)
  175. {
  176. return *(const int *)a - *(const int *)b;
  177. }
  178. static void init_colors(struct map *m)
  179. {
  180. if (Rast_read_colors((char *)m->name, (char *)m->mapset, &m->colors) < 0)
  181. G_fatal_error(_("Unable to read color file for raster map <%s@%s>"),
  182. m->name, m->mapset);
  183. m->have_colors = 1;
  184. }
  185. static void init_cats(struct map *m)
  186. {
  187. if (Rast_read_cats((char *)m->name, (char *)m->mapset, &m->cats) < 0)
  188. G_fatal_error(_("Unable to read category file of raster map <%s@%s>"),
  189. m->name, m->mapset);
  190. if (!btree_create(&m->btree, compare_ints, 1))
  191. G_fatal_error(_("Unable to create btree for raster map <%s@%s>"),
  192. m->name, m->mapset);
  193. m->have_cats = 1;
  194. }
  195. static void translate_from_colors(struct map *m, DCELL *rast, CELL *cell,
  196. int ncols, int mod)
  197. {
  198. unsigned char *red = G_alloca(columns);
  199. unsigned char *grn = G_alloca(columns);
  200. unsigned char *blu = G_alloca(columns);
  201. unsigned char *set = G_alloca(columns);
  202. int i;
  203. Rast_lookup_d_colors(rast, red, grn, blu, set, ncols, &m->colors);
  204. switch (mod) {
  205. case 'r':
  206. for (i = 0; i < ncols; i++)
  207. cell[i] = red[i];
  208. break;
  209. case 'g':
  210. for (i = 0; i < ncols; i++)
  211. cell[i] = grn[i];
  212. break;
  213. case 'b':
  214. for (i = 0; i < ncols; i++)
  215. cell[i] = blu[i];
  216. break;
  217. case '#': /* grey (backwards compatible) */
  218. /* old weightings: R=0.177, G=0.813, B=0.011 */
  219. for (i = 0; i < ncols; i++)
  220. cell[i] =
  221. (181 * red[i] + 833 * grn[i] + 11 * blu[i] + 512) / 1024;
  222. break;
  223. case 'y': /* grey (NTSC) */
  224. /* NTSC weightings: R=0.299, G=0.587, B=0.114 */
  225. for (i = 0; i < ncols; i++)
  226. cell[i] =
  227. (306 * red[i] + 601 * grn[i] + 117 * blu[i] + 512) / 1024;
  228. break;
  229. case 'i': /* grey (equal weight) */
  230. for (i = 0; i < ncols; i++)
  231. cell[i] = (red[i] + grn[i] + blu[i]) / 3;
  232. break;
  233. case 'M':
  234. case '@':
  235. default:
  236. G_fatal_error(_("Invalid map modifier: '%c'"), mod);
  237. break;
  238. }
  239. G_freea(red);
  240. G_freea(grn);
  241. G_freea(blu);
  242. G_freea(set);
  243. }
  244. /* convert cell values to double based on the values in the
  245. * category file.
  246. *
  247. * This requires performing sscanf() of the category label
  248. * and only do it it for new categories. Must maintain
  249. * some kind of maps of already scaned values.
  250. *
  251. * This maps is a hybrid tree, where the data in each node
  252. * of the tree is an array of, for example, 64 values, and
  253. * the key of the tree is the category represented by the
  254. * first index of the data
  255. *
  256. * To speed things up a little, use shifts instead of divide or multiply
  257. * to compute the key and the index
  258. *
  259. * This uses the BTREE library to manage the tree itself
  260. * btree structure must already be initialized
  261. * pcats structure must already contain category labels
  262. */
  263. #define SHIFT 6
  264. #define NCATS (1<<SHIFT)
  265. static void translate_from_cats(struct map *m, CELL * cell, DCELL * xcell,
  266. int ncols)
  267. {
  268. struct Categories *pcats;
  269. BTREE *btree;
  270. int i, idx;
  271. CELL cat, key;
  272. double vbuf[1 << SHIFT];
  273. double *values;
  274. void *ptr;
  275. char *label;
  276. #ifdef HAVE_PTHREAD_H
  277. pthread_mutex_lock(&cats_mutex);
  278. #endif
  279. btree = &m->btree;
  280. pcats = &m->cats;
  281. for (; ncols-- > 0; cell++, xcell++) {
  282. cat = *cell;
  283. if (IS_NULL_C(cell)) {
  284. SET_NULL_D(xcell);
  285. continue;
  286. }
  287. /* compute key as cat/NCATS * NCATS, adjusting down for negatives
  288. * and idx so that key+idx == cat
  289. */
  290. if (cat < 0)
  291. key = -(((-cat - 1) >> SHIFT) << SHIFT) - NCATS;
  292. else
  293. key = (cat >> SHIFT) << SHIFT;
  294. idx = cat - key;
  295. /* If key not already in the tree, sscanf() all cats for this key
  296. * and put them into the tree
  297. */
  298. if (!btree_find(btree, &key, &ptr)) {
  299. values = vbuf;
  300. for (i = 0; i < NCATS; i++) {
  301. CELL cat = i + key;
  302. if ((label = Rast_get_c_cat(&cat, pcats)) == NULL
  303. || sscanf(label, "%lf", values) != 1)
  304. SET_NULL_D(values);
  305. values++;
  306. }
  307. values = vbuf;
  308. btree_update(btree, &key, sizeof(key), vbuf, sizeof(vbuf));
  309. }
  310. else
  311. values = ptr;
  312. /* and finally lookup the translated value */
  313. if (IS_NULL_D(&values[idx]))
  314. SET_NULL_D(xcell);
  315. else
  316. *xcell = values[idx];
  317. }
  318. #ifdef HAVE_PTHREAD_H
  319. pthread_mutex_unlock(&cats_mutex);
  320. #endif
  321. }
  322. static void setup_map(struct map *m)
  323. {
  324. int nrows = m->max_row - m->min_row + 1;
  325. #ifdef HAVE_PTHREAD_H
  326. pthread_mutex_init(&m->mutex, NULL);
  327. #endif
  328. if (nrows > 1 && nrows <= max_rows_in_memory) {
  329. cache_setup(&m->cache, m->fd, nrows);
  330. m->use_rowio = 1;
  331. }
  332. else
  333. m->use_rowio = 0;
  334. }
  335. static void read_map(struct map *m, void *buf, int res_type, int row, int col)
  336. {
  337. CELL *ibuf = buf;
  338. FCELL *fbuf = buf;
  339. DCELL *dbuf = buf;
  340. if (row < 0 || row >= rows) {
  341. int i;
  342. switch (res_type) {
  343. case CELL_TYPE:
  344. for (i = 0; i < columns; i++)
  345. SET_NULL_C(&ibuf[i]);
  346. break;
  347. case FCELL_TYPE:
  348. for (i = 0; i < columns; i++)
  349. SET_NULL_F(&fbuf[i]);
  350. break;
  351. case DCELL_TYPE:
  352. for (i = 0; i < columns; i++)
  353. SET_NULL_D(&dbuf[i]);
  354. break;
  355. default:
  356. G_fatal_error(_("Unknown type: %d"), res_type);
  357. break;
  358. }
  359. return;
  360. }
  361. if (m->use_rowio)
  362. cache_get(&m->cache, buf, row, res_type);
  363. else
  364. read_row(m->fd, buf, row, res_type);
  365. if (col)
  366. column_shift(buf, res_type, col);
  367. }
  368. static void close_map(struct map *m)
  369. {
  370. if (m->fd < 0)
  371. return;
  372. Rast_close(m->fd);
  373. #ifdef HAVE_PTHREAD_H
  374. pthread_mutex_destroy(&m->mutex);
  375. #endif
  376. if (m->have_cats) {
  377. btree_free(&m->btree);
  378. Rast_free_cats(&m->cats);
  379. m->have_cats = 0;
  380. }
  381. if (m->have_colors) {
  382. Rast_free_colors(&m->colors);
  383. m->have_colors = 0;
  384. }
  385. if (m->use_rowio) {
  386. cache_release(&m->cache);
  387. m->use_rowio = 0;
  388. }
  389. }
  390. /****************************************************************************/
  391. int map_type(const char *name, int mod)
  392. {
  393. const char *mapset;
  394. char *tmpname;
  395. int result;
  396. switch (mod) {
  397. case 'M':
  398. tmpname = G_store((char *)name);
  399. mapset = G_find_raster2(tmpname, "");
  400. result = mapset ? Rast_map_type(tmpname, mapset) : -1;
  401. G_free(tmpname);
  402. return result;
  403. case '@':
  404. return DCELL_TYPE;
  405. case 'r':
  406. case 'g':
  407. case 'b':
  408. case '#':
  409. case 'y':
  410. case 'i':
  411. return CELL_TYPE;
  412. default:
  413. G_fatal_error(_("Invalid map modifier: '%c'"), mod);
  414. return -1;
  415. }
  416. }
  417. int open_map(const char *name, int mod, int row, int col)
  418. {
  419. int i;
  420. const char *mapset;
  421. int use_cats = 0;
  422. int use_colors = 0;
  423. struct map *m;
  424. if (row < min_row)
  425. min_row = row;
  426. if (row > max_row)
  427. max_row = row;
  428. if (col < min_col)
  429. min_col = col;
  430. if (col > max_col)
  431. max_col = col;
  432. mapset = G_find_raster2(name, "");
  433. if (!mapset)
  434. G_fatal_error(_("Raster map <%s> not found"), name);
  435. switch (mod) {
  436. case 'M':
  437. break;
  438. case '@':
  439. use_cats = 1;
  440. break;
  441. case 'r':
  442. case 'g':
  443. case 'b':
  444. case '#':
  445. case 'y':
  446. case 'i':
  447. use_colors = 1;
  448. break;
  449. default:
  450. G_fatal_error(_("Invalid map modifier: '%c'"), mod);
  451. break;
  452. }
  453. for (i = 0; i < num_maps; i++) {
  454. m = &maps[i];
  455. if (strcmp(m->name, name) != 0 || strcmp(m->mapset, mapset) != 0)
  456. continue;
  457. if (row < m->min_row)
  458. m->min_row = row;
  459. if (row > m->max_row)
  460. m->max_row = row;
  461. if (use_cats && !m->have_cats)
  462. init_cats(m);
  463. if (use_colors && !m->have_colors)
  464. init_colors(m);
  465. return i;
  466. }
  467. if (num_maps >= max_maps) {
  468. max_maps += 10;
  469. maps = G_realloc(maps, max_maps * sizeof(struct map));
  470. }
  471. m = &maps[num_maps];
  472. m->name = name;
  473. m->mapset = mapset;
  474. m->have_cats = 0;
  475. m->have_colors = 0;
  476. m->use_rowio = 0;
  477. m->min_row = row;
  478. m->max_row = row;
  479. m->fd = -1;
  480. if (use_cats)
  481. init_cats(m);
  482. if (use_colors)
  483. init_colors(m);
  484. m->fd = Rast_open_old(name, mapset);
  485. return num_maps++;
  486. }
  487. void setup_maps(void)
  488. {
  489. int i;
  490. #ifdef HAVE_PTHREAD_H
  491. pthread_mutex_init(&cats_mutex, NULL);
  492. pthread_mutex_init(&mask_mutex, NULL);
  493. masking = Rast_maskfd() >= 0;
  494. #endif
  495. for (i = 0; i < num_maps; i++)
  496. setup_map(&maps[i]);
  497. }
  498. void get_map_row(int idx, int mod, int depth, int row, int col, void *buf,
  499. int res_type)
  500. {
  501. CELL *ibuf;
  502. DCELL *fbuf;
  503. struct map *m = &maps[idx];
  504. #ifdef HAVE_PTHREAD_H
  505. pthread_mutex_lock(&m->mutex);
  506. #endif
  507. switch (mod) {
  508. case 'M':
  509. read_map(m, buf, res_type, row, col);
  510. break;
  511. case '@':
  512. ibuf = G_alloca(columns * sizeof(CELL));
  513. read_map(m, ibuf, CELL_TYPE, row, col);
  514. translate_from_cats(m, ibuf, buf, columns);
  515. G_freea(ibuf);
  516. break;
  517. case 'r':
  518. case 'g':
  519. case 'b':
  520. case '#':
  521. case 'y':
  522. case 'i':
  523. fbuf = G_alloca(columns * sizeof(DCELL));
  524. read_map(m, fbuf, DCELL_TYPE, row, col);
  525. translate_from_colors(m, fbuf, buf, columns, mod);
  526. G_freea(fbuf);
  527. break;
  528. default:
  529. G_fatal_error(_("Invalid map modifier: '%c'"), mod);
  530. break;
  531. }
  532. #ifdef HAVE_PTHREAD_H
  533. pthread_mutex_unlock(&m->mutex);
  534. #endif
  535. }
  536. void close_maps(void)
  537. {
  538. int i;
  539. for (i = 0; i < num_maps; i++)
  540. close_map(&maps[i]);
  541. num_maps = 0;
  542. #ifdef HAVE_PTHREAD_H
  543. pthread_mutex_destroy(&cats_mutex);
  544. pthread_mutex_destroy(&mask_mutex);
  545. #endif
  546. }
  547. void list_maps(FILE *fp, const char *sep)
  548. {
  549. int i;
  550. for (i = 0; i < num_maps; i++) {
  551. const struct map *m = &maps[i];
  552. fprintf(fp, "%s%s@%s", i ? sep : "", m->name, m->mapset);
  553. }
  554. }
  555. /****************************************************************************/
  556. int check_output_map(const char *name)
  557. {
  558. return !!G_find_raster2(name, G_mapset());
  559. }
  560. int open_output_map(const char *name, int res_type)
  561. {
  562. return Rast_open_new((char *)name, res_type);
  563. }
  564. void put_map_row(int fd, void *buf, int res_type)
  565. {
  566. Rast_put_row(fd, buf, res_type);
  567. }
  568. void close_output_map(int fd)
  569. {
  570. Rast_close(fd);
  571. }
  572. void unopen_output_map(int fd)
  573. {
  574. Rast_unopen(fd);
  575. }
  576. /****************************************************************************/
  577. void copy_cats(const char *dst, int idx)
  578. {
  579. const struct map *m = &maps[idx];
  580. struct Categories cats;
  581. if (Rast_read_cats((char *)m->name, (char *)m->mapset, &cats) < 0)
  582. return;
  583. Rast_write_cats((char *)dst, &cats);
  584. Rast_free_cats(&cats);
  585. }
  586. void copy_colors(const char *dst, int idx)
  587. {
  588. const struct map *m = &maps[idx];
  589. struct Colors colr;
  590. if (Rast_read_colors((char *)m->name, (char *)m->mapset, &colr) <= 0)
  591. return;
  592. Rast_write_colors((char *)dst, G_mapset(), &colr);
  593. Rast_free_colors(&colr);
  594. }
  595. void copy_history(const char *dst, int idx)
  596. {
  597. const struct map *m = &maps[idx];
  598. struct History hist;
  599. if (Rast_read_history((char *)m->name, (char *)m->mapset, &hist) < 0)
  600. return;
  601. Rast_write_history((char *)dst, &hist);
  602. }
  603. void create_history(const char *dst, expression * e)
  604. {
  605. int RECORD_LEN = 80;
  606. int WIDTH = RECORD_LEN - 12;
  607. struct History hist;
  608. char *expr = format_expression(e);
  609. char *p = expr;
  610. int len = strlen(expr);
  611. int i;
  612. Rast_short_history(dst, "raster", &hist);
  613. for (i = 0; ; i++) {
  614. char buf[RECORD_LEN];
  615. int n;
  616. if (!len)
  617. break;
  618. if (len > WIDTH) {
  619. for (n = WIDTH; n > 0 && p[n] != ' '; n--) ;
  620. if (n <= 0)
  621. n = WIDTH;
  622. else
  623. n++;
  624. }
  625. else
  626. n = len;
  627. memcpy(buf, p, n);
  628. buf[n] = '\0';
  629. Rast_append_history(&hist, buf);
  630. p += n;
  631. len -= n;
  632. }
  633. if (seeded) {
  634. char buf[RECORD_LEN];
  635. sprintf(buf, "random seed = %ld", seed_value);
  636. Rast_append_history(&hist, buf);
  637. }
  638. Rast_write_history(dst, &hist);
  639. G_free(expr);
  640. }
  641. /****************************************************************************/
  642. void prepare_region_from_maps_union(expression **map_list, int num_maps) {
  643. prepare_region_from_maps(map_list, 1, num_maps);
  644. }
  645. void prepare_region_from_maps_intersect(expression **map_list, int num_maps) {
  646. prepare_region_from_maps(map_list, 2, num_maps);
  647. }
  648. void prepare_region_from_maps(expression **map_list, int type, int num_maps) {
  649. /* \brief Setup the computational region from all raster maps
  650. *
  651. * This function computes the disjoint union or intersection extent
  652. * that is covered by all raster maps and sets the smallest
  653. * resolution that it can find.
  654. */
  655. int first = 0;
  656. struct Cell_head window, temp_window;
  657. int i;
  658. const char *mapset;
  659. for (i = 0; i < num_maps; i++) {
  660. expression *e = map_list[i];
  661. char rast_name[GNAME_MAX];
  662. strcpy(rast_name, e->data.map.name);
  663. mapset = G_find_raster2(rast_name, "");
  664. if (!mapset)
  665. G_fatal_error(_("Raster map <%s> not found"), rast_name);
  666. G_debug(1, "Setting region from raster map: %s@%s", rast_name, mapset);
  667. Rast_get_cellhd(rast_name, mapset, &temp_window);
  668. if (!first) {
  669. window = temp_window;
  670. first = 1;
  671. }
  672. else {
  673. if (type == 1) {
  674. /* Union: find the largest extent */
  675. window.north = (window.north > temp_window.north) ?
  676. window.north : temp_window.north;
  677. window.south = (window.south < temp_window.south) ?
  678. window.south : temp_window.south;
  679. window.east = (window.east > temp_window.east) ?
  680. window.east : temp_window.east;
  681. window.west = (window.west < temp_window.west) ?
  682. window.west : temp_window.west;
  683. }
  684. else {
  685. /* Intersect: Find the smallest extent */
  686. window.north = (window.north < temp_window.north) ?
  687. window.north : temp_window.north;
  688. window.south = (window.south > temp_window.south) ?
  689. window.south : temp_window.south;
  690. window.east = (window.east < temp_window.east) ?
  691. window.east : temp_window.east;
  692. window.west = (window.west > temp_window.west) ?
  693. window.west : temp_window.west;
  694. }
  695. /* Find the smallest resolution */
  696. window.ns_res = (window.ns_res < temp_window.ns_res) ?
  697. window.ns_res : temp_window.ns_res;
  698. window.ew_res = (window.ew_res < temp_window.ew_res) ?
  699. window.ew_res : temp_window.ew_res;
  700. }
  701. }
  702. /* Set the region only if a map was found in the expression */
  703. if (first == 1) {
  704. G_adjust_Cell_head3(&window, 0, 0, 0);
  705. G_debug(1, "Region was set to n %g s %g e %g w %g ns_res %g ew_res %g", window.north,
  706. window.south, window.east, window.west, window.ns_res, window.ew_res);
  707. G_put_window(&window);
  708. }
  709. }
  710. /****************************************************************************/