gvl_calc.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057
  1. /*!
  2. \file gvl_calc.c
  3. \brief OGSF library - loading and manipulating volumes (lower level functions)
  4. GRASS OpenGL gsurf OGSF Library
  5. (C) 1999-2008 by the GRASS Development Team
  6. This program is free software under the
  7. GNU General Public License (>=v2).
  8. Read the file COPYING that comes with GRASS
  9. for details.
  10. \author Tomas Paudits (February 2004)
  11. \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
  12. */
  13. #include <math.h>
  14. #include <grass/gis.h>
  15. #include <grass/ogsf.h>
  16. #include "rgbpack.h"
  17. #include "mc33_table.h"
  18. /*!
  19. \brief memory buffer for writing
  20. */
  21. #define BUFFER_SIZE 1000000
  22. /* USEFUL MACROS */
  23. /* interp. */
  24. #define LINTERP(d,a,b) (a + d * (b - a))
  25. #define TINTERP(d,v) ((v[0]*(1.-d[0])*(1.-d[1])*(1.-d[2])) +\
  26. (v[1]*d[0]*(1.-d[1])*(1.-d[2])) + \
  27. (v[2]*d[0]*d[1]*(1.-d[2])) + \
  28. (v[3]*(1.-d[0])*d[1]*(1.-d[2])) + \
  29. (v[4]*(1.-d[0])*(1.-d[1])*d[2]) + \
  30. (v[5]*d[0]*(1.-d[1])*d[2]) + \
  31. (v[6]*d[0]*d[1]*d[2]) + \
  32. (v[7]*(1.-d[0])*d[1]*d[2]))
  33. #define FOR_VAR i_for
  34. #define FOR_0_TO_N(n, cmd) { int FOR_VAR; for (FOR_VAR = 0; FOR_VAR < n; FOR_VAR++) {cmd;} }
  35. /*!
  36. \brief writing and reading isosurface data
  37. */
  38. #define WRITE(c) gvl_write_char(dbuff->ndx_new++, &(dbuff->new), c)
  39. #define READ() gvl_read_char(dbuff->ndx_old++, dbuff->old)
  40. #define SKIP(n) dbuff->ndx_old = dbuff->ndx_old + n
  41. /*!
  42. \brief check and set data descriptor
  43. */
  44. #define IS_IN_DATA(att) ((isosurf->data_desc >> att) & 1)
  45. #define SET_IN_DATA(att) isosurf->data_desc = (isosurf->data_desc | (1 << att))
  46. typedef struct
  47. {
  48. unsigned char *old;
  49. unsigned char *new;
  50. int ndx_old;
  51. int ndx_new;
  52. int num_zero;
  53. } data_buffer;
  54. int mc33_process_cube(int c_ndx, float *v);
  55. /* global variables */
  56. int Rows, Cols, Depths;
  57. double ResX, ResY, ResZ;
  58. /************************************************************************/
  59. /* ISOSURFACES */
  60. /*!
  61. \brief Write cube index
  62. \param ndx
  63. \param dbuff
  64. */
  65. void iso_w_cndx(int ndx, data_buffer * dbuff)
  66. {
  67. /* cube don't contains polys */
  68. if (ndx == -1) {
  69. if (dbuff->num_zero == 0) {
  70. WRITE(0);
  71. dbuff->num_zero++;
  72. }
  73. else if (dbuff->num_zero == 254) {
  74. WRITE(dbuff->num_zero + 1);
  75. dbuff->num_zero = 0;
  76. }
  77. else {
  78. dbuff->num_zero++;
  79. }
  80. }
  81. else { /* isosurface cube */
  82. if (dbuff->num_zero == 0) {
  83. WRITE((ndx / 256) + 1);
  84. WRITE(ndx % 256);
  85. }
  86. else {
  87. WRITE(dbuff->num_zero);
  88. dbuff->num_zero = 0;
  89. WRITE((ndx / 256) + 1);
  90. WRITE(ndx % 256);
  91. }
  92. }
  93. }
  94. /*!
  95. \brief Read cube index
  96. \param dbuff
  97. */
  98. int iso_r_cndx(data_buffer * dbuff)
  99. {
  100. int ndx, ndx2;
  101. if (dbuff->num_zero != 0) {
  102. dbuff->num_zero--;
  103. ndx = -1;
  104. }
  105. else {
  106. WRITE(ndx = READ());
  107. if (ndx == 0) {
  108. WRITE(dbuff->num_zero = READ());
  109. dbuff->num_zero--;
  110. ndx = -1;
  111. }
  112. else {
  113. WRITE(ndx2 = READ());
  114. ndx = (ndx - 1) * 256 + ndx2;
  115. }
  116. }
  117. return ndx;
  118. }
  119. /*!
  120. \brief Get value from data input
  121. \param isosurf
  122. \param desc
  123. \param x,y,z
  124. \param[out] value
  125. \return 0
  126. \return ?
  127. */
  128. int iso_get_cube_value(geovol_isosurf * isosurf, int desc, int x, int y,
  129. int z, float *v)
  130. {
  131. double d;
  132. geovol_file *vf;
  133. int type, ret = 1;
  134. /* get volume file from attribute handle */
  135. vf = gvl_file_get_volfile(isosurf->att[desc].hfile);
  136. type = gvl_file_get_data_type(vf);
  137. /* get value from volume file */
  138. if (type == VOL_DTYPE_FLOAT) {
  139. gvl_file_get_value(vf, (int)(x * ResX), (int)(y * ResY),
  140. (int)(z * ResZ), v);
  141. }
  142. else if (type == VOL_DTYPE_DOUBLE) {
  143. gvl_file_get_value(vf, (int)(x * ResX), (int)(y * ResY),
  144. (int)(z * ResZ), &d);
  145. *v = (float)d;
  146. }
  147. else {
  148. return 0;
  149. }
  150. /* null check */
  151. if (gvl_file_is_null_value(vf, v))
  152. ret = 0;
  153. /* adjust data */
  154. switch (desc) {
  155. case (ATT_TOPO):
  156. *v = (*v) - isosurf->att[desc].constant;
  157. break;
  158. case (ATT_MASK):
  159. if (isosurf->att[desc].constant)
  160. ret = !ret;
  161. break;
  162. }
  163. return ret;
  164. }
  165. /*!
  166. \brief Get volume file values range
  167. \param isosurf
  168. \param desc
  169. \param[out] min
  170. \param[out] max
  171. */
  172. void iso_get_range(geovol_isosurf * isosurf, int desc, double *min,
  173. double *max)
  174. {
  175. gvl_file_get_min_max(gvl_file_get_volfile(isosurf->att[desc].hfile), min,
  176. max);
  177. }
  178. /*!
  179. \brief Read values for cube
  180. \param isosurf
  181. \param desc
  182. \param x,y,z
  183. \param[out] v
  184. \return
  185. */
  186. int iso_get_cube_values(geovol_isosurf * isosurf, int desc, int x, int y,
  187. int z, float *v)
  188. {
  189. int p, ret = 1;
  190. for (p = 0; p < 8; ++p) {
  191. if (iso_get_cube_value
  192. (isosurf, desc, x + ((p ^ (p >> 1)) & 1), y + ((p >> 1) & 1),
  193. z + ((p >> 2) & 1), &v[p]) == 0) {
  194. ret = 0;
  195. }
  196. }
  197. return ret;
  198. }
  199. /*!
  200. \brief Calculate cube grads
  201. \param isosurf
  202. \param x,y,z
  203. \param grad
  204. */
  205. void iso_get_cube_grads(geovol_isosurf * isosurf, int x, int y, int z,
  206. float (*grad)[3])
  207. {
  208. float v[3];
  209. int i, j, k, p;
  210. for (p = 0; p < 8; ++p) {
  211. i = x + ((p ^ (p >> 1)) & 1);
  212. j = y + ((p >> 1) & 1);
  213. k = z + ((p >> 2) & 1);
  214. /* x */
  215. if (i == 0) {
  216. iso_get_cube_value(isosurf, ATT_TOPO, i, j, k, &v[1]);
  217. iso_get_cube_value(isosurf, ATT_TOPO, i + 1, j, k, &v[2]);
  218. grad[p][0] = v[2] - v[1];
  219. }
  220. else {
  221. if (i == (Cols - 1)) {
  222. iso_get_cube_value(isosurf, ATT_TOPO, i - 1, j, k, &v[0]);
  223. iso_get_cube_value(isosurf, ATT_TOPO, i, j, k, &v[1]);
  224. grad[p][0] = v[1] - v[0];
  225. }
  226. else {
  227. iso_get_cube_value(isosurf, ATT_TOPO, i - 1, j, k, &v[0]);
  228. iso_get_cube_value(isosurf, ATT_TOPO, i + 1, j, k, &v[2]);
  229. grad[p][0] = (v[2] - v[0]) / 2;
  230. }
  231. }
  232. /* y */
  233. if (j == 0) {
  234. iso_get_cube_value(isosurf, ATT_TOPO, i, j, k, &v[1]);
  235. iso_get_cube_value(isosurf, ATT_TOPO, i, j + 1, k, &v[2]);
  236. grad[p][1] = v[2] - v[1];
  237. }
  238. else {
  239. if (j == (Rows - 1)) {
  240. iso_get_cube_value(isosurf, ATT_TOPO, i, j - 1, k, &v[0]);
  241. iso_get_cube_value(isosurf, ATT_TOPO, i, j, k, &v[1]);
  242. grad[p][1] = v[1] - v[0];
  243. }
  244. else {
  245. iso_get_cube_value(isosurf, ATT_TOPO, i, j - 1, k, &v[0]);
  246. iso_get_cube_value(isosurf, ATT_TOPO, i, j + 1, k, &v[2]);
  247. grad[p][1] = (v[2] - v[0]) / 2;
  248. }
  249. }
  250. /* z */
  251. if (k == 0) {
  252. iso_get_cube_value(isosurf, ATT_TOPO, i, j, k, &v[1]);
  253. iso_get_cube_value(isosurf, ATT_TOPO, i, j, k + 1, &v[2]);
  254. grad[p][2] = v[2] - v[1];
  255. }
  256. else {
  257. if (k == (Depths - 1)) {
  258. iso_get_cube_value(isosurf, ATT_TOPO, i, j, k - 1, &v[0]);
  259. iso_get_cube_value(isosurf, ATT_TOPO, i, j, k, &v[1]);
  260. grad[p][2] = v[1] - v[0];
  261. }
  262. else {
  263. iso_get_cube_value(isosurf, ATT_TOPO, i, j, k - 1, &v[0]);
  264. iso_get_cube_value(isosurf, ATT_TOPO, i, j, k + 1, &v[2]);
  265. grad[p][2] = (v[2] - v[0]) / 2;
  266. }
  267. }
  268. }
  269. }
  270. /*!
  271. \brief Process cube
  272. \param isosurf
  273. \param x,y,z
  274. \param dbuff
  275. */
  276. void iso_calc_cube(geovol_isosurf * isosurf, int x, int y, int z,
  277. data_buffer * dbuff)
  278. {
  279. int i, c_ndx;
  280. int crnt, v1, v2, c;
  281. float val[MAX_ATTS][8], grad[8][3];
  282. float d, d3[3], d_sum[3], n[3], n_sum[3], tv;
  283. double min, max;
  284. if (isosurf->att[ATT_TOPO].changed) {
  285. /* read topo values, if there are NULL values then return */
  286. if (!iso_get_cube_values(isosurf, ATT_TOPO, x, y, z, val[ATT_TOPO])) {
  287. iso_w_cndx(-1, dbuff);
  288. return;
  289. }
  290. /* mask */
  291. if (isosurf->att[ATT_MASK].att_src == MAP_ATT) {
  292. if (!iso_get_cube_values
  293. (isosurf, ATT_MASK, x, y, z, val[ATT_MASK])) {
  294. iso_w_cndx(-1, dbuff);
  295. return;
  296. }
  297. }
  298. /* index to precalculated table */
  299. c_ndx = 0;
  300. for (i = 0; i < 8; i++) {
  301. if (val[ATT_TOPO][i] > 0)
  302. c_ndx |= 1 << i;
  303. }
  304. c_ndx = mc33_process_cube(c_ndx, val[ATT_TOPO]);
  305. iso_w_cndx(c_ndx, dbuff);
  306. if (c_ndx == -1)
  307. return;
  308. /* calc cube grads */
  309. iso_get_cube_grads(isosurf, x, y, z, grad);
  310. }
  311. else {
  312. /* read cube index */
  313. if ((c_ndx = iso_r_cndx(dbuff)) == -1)
  314. return;
  315. }
  316. /* get color values */
  317. if (isosurf->att[ATT_COLOR].changed &&
  318. isosurf->att[ATT_COLOR].att_src == MAP_ATT) {
  319. iso_get_cube_values(isosurf, ATT_COLOR, x, y, z, val[ATT_COLOR]);
  320. }
  321. /* get transparency values */
  322. if (isosurf->att[ATT_TRANSP].changed &&
  323. isosurf->att[ATT_TRANSP].att_src == MAP_ATT) {
  324. iso_get_cube_values(isosurf, ATT_TRANSP, x, y, z, val[ATT_TRANSP]);
  325. }
  326. /* get shine values */
  327. if (isosurf->att[ATT_SHINE].changed &&
  328. isosurf->att[ATT_SHINE].att_src == MAP_ATT) {
  329. iso_get_cube_values(isosurf, ATT_SHINE, x, y, z, val[ATT_SHINE]);
  330. }
  331. /* get emit values */
  332. if (isosurf->att[ATT_EMIT].changed &&
  333. isosurf->att[ATT_EMIT].att_src == MAP_ATT) {
  334. iso_get_cube_values(isosurf, ATT_EMIT, x, y, z, val[ATT_EMIT]);
  335. }
  336. FOR_0_TO_N(3, d_sum[FOR_VAR] = 0.;
  337. n_sum[FOR_VAR] = 0.);
  338. /* loop in edges */
  339. for (i = 0; i < cell_table[c_ndx].nedges; i++) {
  340. /* get edge number */
  341. crnt = cell_table[c_ndx].edges[i];
  342. /* set topo */
  343. if (isosurf->att[ATT_TOPO].changed) {
  344. /* interior vertex */
  345. if (crnt == 12) {
  346. FOR_0_TO_N(3,
  347. WRITE((d3[FOR_VAR] =
  348. d_sum[FOR_VAR] /
  349. ((float)(cell_table[c_ndx].nedges))) *
  350. 255));
  351. GS_v3norm(n_sum);
  352. FOR_0_TO_N(3,
  353. WRITE((n_sum[FOR_VAR] /
  354. ((float)(cell_table[c_ndx].nedges)) +
  355. 1.) * 127));
  356. /* edge vertex */
  357. }
  358. else {
  359. /* set egdes verts */
  360. v1 = edge_vert[crnt][0];
  361. v2 = edge_vert[crnt][1];
  362. /* calc intersection point - edge and isosurf */
  363. d = val[ATT_TOPO][v1] / (val[ATT_TOPO][v1] -
  364. val[ATT_TOPO][v2]);
  365. d_sum[edge_vert_pos[crnt][0]] += d;
  366. d_sum[edge_vert_pos[crnt][1]] += edge_vert_pos[crnt][2];
  367. d_sum[edge_vert_pos[crnt][3]] += edge_vert_pos[crnt][4];
  368. WRITE(d * 255);
  369. /* set normal for intersect. point */
  370. FOR_0_TO_N(3, n[FOR_VAR] =
  371. LINTERP(d, grad[v1][FOR_VAR], grad[v2][FOR_VAR]));
  372. GS_v3norm(n);
  373. FOR_0_TO_N(3, n_sum[FOR_VAR] += n[FOR_VAR]);
  374. FOR_0_TO_N(3, WRITE((n[FOR_VAR] + 1.) * 127));
  375. }
  376. }
  377. else {
  378. /* read x,y,z of intersection point in cube coords */
  379. if (crnt == 12) {
  380. WRITE(c = READ());
  381. d3[0] = ((float)c) / 255.0;
  382. WRITE(c = READ());
  383. d3[1] = ((float)c) / 255.0;
  384. WRITE(c = READ());
  385. d3[2] = ((float)c) / 255.0;
  386. }
  387. else {
  388. /* set egdes verts */
  389. v1 = edge_vert[crnt][0];
  390. v2 = edge_vert[crnt][1];
  391. WRITE(c = READ());
  392. d = ((float)c) / 255.0;
  393. }
  394. /* set normals */
  395. FOR_0_TO_N(3, WRITE(READ()));
  396. }
  397. /* set color */
  398. if (isosurf->att[ATT_COLOR].changed &&
  399. isosurf->att[ATT_COLOR].att_src == MAP_ATT) {
  400. if (crnt == 12) {
  401. tv = TINTERP(d3, val[ATT_COLOR]);
  402. }
  403. else {
  404. tv = LINTERP(d, val[ATT_COLOR][v1], val[ATT_COLOR][v2]);
  405. }
  406. c = Gvl_get_color_for_value(isosurf->att[ATT_COLOR].att_data,
  407. &tv);
  408. WRITE(c & RED_MASK);
  409. WRITE((c & GRN_MASK) >> 8);
  410. WRITE((c & BLU_MASK) >> 16);
  411. if (IS_IN_DATA(ATT_COLOR))
  412. SKIP(3);
  413. }
  414. else {
  415. if (isosurf->att[ATT_COLOR].att_src == MAP_ATT) {
  416. FOR_0_TO_N(3, WRITE(READ()));
  417. }
  418. else {
  419. if (IS_IN_DATA(ATT_COLOR))
  420. SKIP(3);
  421. }
  422. }
  423. /* set transparency */
  424. if (isosurf->att[ATT_TRANSP].changed &&
  425. isosurf->att[ATT_TRANSP].att_src == MAP_ATT) {
  426. if (crnt == 12) {
  427. tv = TINTERP(d3, val[ATT_TRANSP]);
  428. }
  429. else {
  430. tv = LINTERP(d, val[ATT_TRANSP][v1], val[ATT_TRANSP][v2]);
  431. }
  432. iso_get_range(isosurf, ATT_TRANSP, &min, &max);
  433. c = (min != max) ? 255 - (tv - min) / (max - min) * 255 : 0;
  434. WRITE(c);
  435. if (IS_IN_DATA(ATT_TRANSP))
  436. SKIP(1);
  437. }
  438. else {
  439. if (isosurf->att[ATT_TRANSP].att_src == MAP_ATT) {
  440. WRITE(READ());
  441. }
  442. else {
  443. if (IS_IN_DATA(ATT_TRANSP))
  444. SKIP(1);
  445. }
  446. }
  447. /* set shin */
  448. if (isosurf->att[ATT_SHINE].changed &&
  449. isosurf->att[ATT_SHINE].att_src == MAP_ATT) {
  450. if (crnt == 12) {
  451. tv = TINTERP(d3, val[ATT_SHINE]);
  452. }
  453. else {
  454. tv = LINTERP(d, val[ATT_SHINE][v1], val[ATT_SHINE][v2]);
  455. }
  456. iso_get_range(isosurf, ATT_SHINE, &min, &max);
  457. c = (min != max) ? (tv - min) / (max - min) * 255 : 0;
  458. WRITE(c);
  459. if (IS_IN_DATA(ATT_SHINE))
  460. SKIP(1);
  461. }
  462. else {
  463. if (isosurf->att[ATT_SHINE].att_src == MAP_ATT) {
  464. WRITE(READ());
  465. }
  466. else {
  467. if (IS_IN_DATA(ATT_SHINE))
  468. SKIP(1);
  469. }
  470. }
  471. /* set emit */
  472. if (isosurf->att[ATT_EMIT].changed &&
  473. isosurf->att[ATT_EMIT].att_src == MAP_ATT) {
  474. if (crnt == 12) {
  475. tv = TINTERP(d3, val[ATT_EMIT]);
  476. }
  477. else {
  478. tv = LINTERP(d, val[ATT_EMIT][v1], val[ATT_EMIT][v2]);
  479. }
  480. iso_get_range(isosurf, ATT_EMIT, &min, &max);
  481. c = (min != max) ? (tv - min) / (max - min) * 255 : 0;
  482. WRITE(c);
  483. if (IS_IN_DATA(ATT_SHINE))
  484. SKIP(1);
  485. }
  486. else {
  487. if (isosurf->att[ATT_EMIT].att_src == MAP_ATT) {
  488. WRITE(READ());
  489. }
  490. else {
  491. if (IS_IN_DATA(ATT_EMIT))
  492. SKIP(1);
  493. }
  494. }
  495. }
  496. }
  497. /*!
  498. \brief Fill data structure with computed isosurfaces polygons
  499. \param gvol pointer to geovol struct
  500. \return 1
  501. */
  502. int gvl_isosurf_calc(geovol * gvol)
  503. {
  504. int x, y, z;
  505. int i, a, read;
  506. geovol_file *vf;
  507. geovol_isosurf *isosurf;
  508. data_buffer *dbuff;
  509. int *need_update, need_update_global;
  510. dbuff = G_malloc(gvol->n_isosurfs * sizeof(data_buffer));
  511. need_update = G_malloc(gvol->n_isosurfs * sizeof(int));
  512. /* flag - changed any isosurface */
  513. need_update_global = 0;
  514. /* initialize */
  515. for (i = 0; i < gvol->n_isosurfs; i++) {
  516. isosurf = gvol->isosurf[i];
  517. need_update[i] = 0;
  518. for (a = 1; a < MAX_ATTS; a++) {
  519. if (isosurf->att[a].changed) {
  520. read = 0;
  521. /* changed to map attribute */
  522. if (isosurf->att[a].att_src == MAP_ATT) {
  523. vf = gvl_file_get_volfile(isosurf->att[a].hfile);
  524. read = 1;
  525. }
  526. /* changed threshold value */
  527. if (a == ATT_TOPO) {
  528. isosurf->att[a].hfile = gvol->hfile;
  529. vf = gvl_file_get_volfile(gvol->hfile);
  530. read = 1;
  531. }
  532. /* initialize reading in selected mode */
  533. if (read) {
  534. gvl_file_set_mode(vf, 3);
  535. gvl_file_start_read(vf);
  536. }
  537. /* set update flag - isosurface will be calc */
  538. if (read || IS_IN_DATA(a)) {
  539. need_update[i] = 1;
  540. need_update_global = 1;
  541. }
  542. }
  543. }
  544. if (need_update[i]) {
  545. /* initialize read/write buffers */
  546. dbuff[i].old = isosurf->data;
  547. dbuff[i].new = NULL;
  548. dbuff[i].ndx_old = 0;
  549. dbuff[i].ndx_new = 0;
  550. dbuff[i].num_zero = 0;
  551. }
  552. }
  553. /* calculate if only some isosurface changed */
  554. if (need_update_global) {
  555. ResX = gvol->isosurf_x_mod;
  556. ResY = gvol->isosurf_y_mod;
  557. ResZ = gvol->isosurf_z_mod;
  558. Cols = gvol->cols / ResX;
  559. Rows = gvol->rows / ResY;
  560. Depths = gvol->depths / ResZ;
  561. /* calc isosurface - marching cubes - start */
  562. for (z = 0; z < Depths - 1; z++) {
  563. for (y = 0; y < Rows - 1; y++) {
  564. for (x = 0; x < Cols - 1; x++) {
  565. for (i = 0; i < gvol->n_isosurfs; i++) {
  566. /* recalculate only changed isosurfaces */
  567. if (need_update[i]) {
  568. iso_calc_cube(gvol->isosurf[i], x, y, z,
  569. &dbuff[i]);
  570. }
  571. }
  572. }
  573. }
  574. }
  575. }
  576. /* end */
  577. /* deinitialize */
  578. for (i = 0; i < gvol->n_isosurfs; i++) {
  579. isosurf = gvol->isosurf[i];
  580. /* set new isosurface data */
  581. if (need_update[i]) {
  582. if (dbuff[i].num_zero != 0)
  583. gvl_write_char(dbuff[i].ndx_new++, &(dbuff[i].new),
  584. dbuff[i].num_zero);
  585. G_free(isosurf->data);
  586. gvl_align_data(dbuff[i].ndx_new, dbuff[i].new);
  587. isosurf->data = dbuff[i].new;
  588. isosurf->data_desc = 0;
  589. }
  590. for (a = 1; a < MAX_ATTS; a++) {
  591. if (isosurf->att[a].changed) {
  592. read = 0;
  593. /* changed map attribute */
  594. if (isosurf->att[a].att_src == MAP_ATT) {
  595. vf = gvl_file_get_volfile(isosurf->att[a].hfile);
  596. read = 1;
  597. }
  598. /* changed threshold value */
  599. if (a == ATT_TOPO) {
  600. isosurf->att[a].hfile = gvol->hfile;
  601. vf = gvl_file_get_volfile(gvol->hfile);
  602. read = 1;
  603. }
  604. /* deinitialize reading */
  605. if (read) {
  606. gvl_file_end_read(vf);
  607. /* set data description */
  608. SET_IN_DATA(a);
  609. }
  610. isosurf->att[a].changed = 0;
  611. }
  612. else if (isosurf->att[a].att_src == MAP_ATT) {
  613. /* set data description */
  614. SET_IN_DATA(a);
  615. }
  616. }
  617. }
  618. return (1);
  619. }
  620. /*!
  621. \brief ADD
  622. \param pos
  623. \param data
  624. \param c
  625. */
  626. void gvl_write_char(int pos, unsigned char **data, unsigned char c)
  627. {
  628. /* check to need allocation memory */
  629. if ((pos % BUFFER_SIZE) == 0) {
  630. *data = (char *)G_realloc(*data,
  631. sizeof(char) * ((pos / BUFFER_SIZE) +
  632. 1) * BUFFER_SIZE);
  633. if (!(*data)) {
  634. return;
  635. }
  636. G_debug(3,
  637. "gvl_write_char(): reallocate memory for pos : %d to : %d B",
  638. pos, sizeof(char) * ((pos / BUFFER_SIZE) + 1) * BUFFER_SIZE);
  639. }
  640. (*data)[pos] = c;
  641. }
  642. /*!
  643. \brief Read char
  644. \param pos position index
  645. \param data data buffer
  646. \return char on success
  647. \return NULL on failure
  648. */
  649. unsigned char gvl_read_char(int pos, const unsigned char *data)
  650. {
  651. if (!data)
  652. return '\0';
  653. return data[pos];
  654. }
  655. /*!
  656. \brief Append data to buffer
  657. \param pos position index
  658. \param data data buffer
  659. */
  660. void gvl_align_data(int pos, unsigned char *data)
  661. {
  662. /* realloc memory to fit in data length */
  663. data = (char *)G_realloc(data, sizeof(char) * pos); /* G_fatal_error */
  664. if (!data) {
  665. return;
  666. }
  667. G_debug(3, "gvl_align_data(): reallocate memory finally to : %d B", pos);
  668. return;
  669. }
  670. /************************************************************************/
  671. /* SLICES */
  672. /************************************************************************/
  673. #define DISTANCE_2(x1, y1, x2, y2) sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
  674. #define SLICE_MODE_INTERP_NO 0
  675. #define SLICE_MODE_INTERP_YES 1
  676. /*!
  677. \brief Get volume value
  678. \param gvl pointer to geovol struct
  679. \param x,y,z
  680. \return value
  681. */
  682. float slice_get_value(geovol * gvl, int x, int y, int z)
  683. {
  684. static double d;
  685. static geovol_file *vf;
  686. static int type;
  687. static float value;
  688. if (x < 0 || y < 0 || z < 0 || (x > gvl->cols - 1) || (y > gvl->rows - 1)
  689. || (z > gvl->depths - 1))
  690. return 0.;
  691. /* get volume file from attribute handle */
  692. vf = gvl_file_get_volfile(gvl->hfile);
  693. type = gvl_file_get_data_type(vf);
  694. /* get value from volume file */
  695. if (type == VOL_DTYPE_FLOAT) {
  696. gvl_file_get_value(vf, x, y, z, &value);
  697. }
  698. else if (type == VOL_DTYPE_DOUBLE) {
  699. gvl_file_get_value(vf, x, y, z, &d);
  700. value = (float)d;
  701. }
  702. else {
  703. return 0.;
  704. }
  705. return value;
  706. }
  707. /*!
  708. \brief Calculate slices
  709. \param gvl pointer to geovol struct
  710. \param ndx_slc
  711. \param colors
  712. \return 1
  713. */
  714. int slice_calc(geovol * gvl, int ndx_slc, void *colors)
  715. {
  716. int cols, rows, c, r;
  717. int i, j, k, pos, color;
  718. int *p_x, *p_y, *p_z;
  719. float *p_ex, *p_ey, *p_ez;
  720. float value, v[8];
  721. float x, y, z, ei, ej, ek, stepx, stepy, stepz;
  722. float f_cols, f_rows, distxy, distz, modxy, modx, mody, modz;
  723. geovol_slice *slice;
  724. geovol_file *vf;
  725. slice = gvl->slice[ndx_slc];
  726. /* set mods, pointer to x, y, z step value */
  727. if (slice->dir == X) {
  728. modx = ResY;
  729. mody = ResZ;
  730. modz = ResX;
  731. p_x = &k;
  732. p_y = &i;
  733. p_z = &j;
  734. p_ex = &ek;
  735. p_ey = &ei;
  736. p_ez = &ej;
  737. }
  738. else if (slice->dir == Y) {
  739. modx = ResX;
  740. mody = ResZ;
  741. modz = ResY;
  742. p_x = &i;
  743. p_y = &k;
  744. p_z = &j;
  745. p_ex = &ei;
  746. p_ey = &ek;
  747. p_ez = &ej;
  748. }
  749. else {
  750. modx = ResX;
  751. mody = ResY;
  752. modz = ResZ;
  753. p_x = &i;
  754. p_y = &j;
  755. p_z = &k;
  756. p_ex = &ei;
  757. p_ey = &ej;
  758. p_ez = &ek;
  759. }
  760. /* distance between slice def. points */
  761. distxy = DISTANCE_2(slice->x2, slice->y2, slice->x1, slice->y1);
  762. distz = fabsf(slice->z2 - slice->z1);
  763. /* distance between slice def points is zero - nothing to do */
  764. if (distxy == 0. || distz == 0.) {
  765. return (1);
  766. }
  767. /* start reading volume file */
  768. vf = gvl_file_get_volfile(gvl->hfile);
  769. gvl_file_set_mode(vf, 3);
  770. gvl_file_start_read(vf);
  771. /* set xy resolution */
  772. modxy =
  773. DISTANCE_2((slice->x2 - slice->x1) / distxy * modx,
  774. (slice->y2 - slice->y1) / distxy * mody, 0., 0.);
  775. /* cols/rows of slice */
  776. f_cols = distxy / modxy;
  777. cols = f_cols > (int)f_cols ? (int)f_cols + 1 : (int)f_cols;
  778. f_rows = distz / modz;
  779. rows = f_rows > (int)f_rows ? (int)f_rows + 1 : (int)f_rows;
  780. /* set x,y intially to first slice point */
  781. x = slice->x1;
  782. y = slice->y1;
  783. /* set x,y step */
  784. stepx = (slice->x2 - slice->x1) / f_cols;
  785. stepy = (slice->y2 - slice->y1) / f_cols;
  786. stepz = (slice->z2 - slice->z1) / f_rows;
  787. /* set position in slice data */
  788. pos = 0;
  789. /* loop in slice cols */
  790. for (c = 0; c < cols + 1; c++) {
  791. /* convert x, y to integer - index in grid */
  792. i = (int)x;
  793. j = (int)y;
  794. /* distance between index and real position */
  795. ei = x - (float)i;
  796. ej = y - (float)j;
  797. /* set z to slice z1 point */
  798. z = slice->z1;
  799. /* loop in slice rows */
  800. for (r = 0; r < rows + 1; r++) {
  801. /* distance between index and real position */
  802. k = (int)z;
  803. ek = z - (float)k;
  804. /* get interpolated value */
  805. if (slice->mode == SLICE_MODE_INTERP_YES) {
  806. /* get grid values */
  807. v[0] = slice_get_value(gvl, *p_x, *p_y, *p_z);
  808. v[1] = slice_get_value(gvl, *p_x + 1, *p_y, *p_z);
  809. v[2] = slice_get_value(gvl, *p_x, *p_y + 1, *p_z);
  810. v[3] = slice_get_value(gvl, *p_x + 1, *p_y + 1, *p_z);
  811. v[4] = slice_get_value(gvl, *p_x, *p_y, *p_z + 1);
  812. v[5] = slice_get_value(gvl, *p_x + 1, *p_y, *p_z + 1);
  813. v[6] = slice_get_value(gvl, *p_x, *p_y + 1, *p_z + 1);
  814. v[7] = slice_get_value(gvl, *p_x + 1, *p_y + 1, *p_z + 1);
  815. /* get interpolated value */
  816. value = v[0] * (1. - *p_ex) * (1. - *p_ey) * (1. - *p_ez)
  817. + v[1] * (*p_ex) * (1. - *p_ey) * (1. - *p_ez)
  818. + v[2] * (1. - *p_ex) * (*p_ey) * (1. - *p_ez)
  819. + v[3] * (*p_ex) * (*p_ey) * (1. - *p_ez)
  820. + v[4] * (1. - *p_ex) * (1. - *p_ey) * (*p_ez)
  821. + v[5] * (*p_ex) * (1. - *p_ey) * (*p_ez)
  822. + v[6] * (1. - *p_ex) * (*p_ey) * (*p_ez)
  823. + v[7] * (*p_ex) * (*p_ey) * (*p_ez);
  824. /* no interp value */
  825. }
  826. else {
  827. value = slice_get_value(gvl, *p_x, *p_y, *p_z);
  828. }
  829. /* translate value to color */
  830. color = Gvl_get_color_for_value(colors, &value);
  831. /* write color to slice data */
  832. gvl_write_char(pos++, &(slice->data), color & RED_MASK);
  833. gvl_write_char(pos++, &(slice->data), (color & GRN_MASK) >> 8);
  834. gvl_write_char(pos++, &(slice->data), (color & BLU_MASK) >> 16);
  835. /* step in z */
  836. if (r + 1 > f_rows) {
  837. z += stepz * (f_rows - (float)r);
  838. }
  839. else {
  840. z += stepz;
  841. }
  842. }
  843. /* step in x,y */
  844. if (c + 1 > f_cols) {
  845. x += stepx * (f_cols - (float)c);
  846. y += stepy * (f_cols - (float)c);
  847. }
  848. else {
  849. x += stepx;
  850. y += stepy;
  851. }
  852. }
  853. /* end reading volume file */
  854. gvl_file_end_read(vf);
  855. gvl_align_data(pos, slice->data);
  856. return (1);
  857. }
  858. /*!
  859. \brief Calculate slices for given volume set
  860. \param gvol pointer to geovol struct
  861. \return 1
  862. */
  863. int gvl_slices_calc(geovol *gvol)
  864. {
  865. int i;
  866. void *colors;
  867. G_debug(5, "gvl_slices_calc(): id=%d", gvol->gvol_id);
  868. /* set current resolution */
  869. ResX = gvol->slice_x_mod;
  870. ResY = gvol->slice_y_mod;
  871. ResZ = gvol->slice_z_mod;
  872. /* set current num of cols, rows, depths */
  873. Cols = gvol->cols / ResX;
  874. Rows = gvol->rows / ResY;
  875. Depths = gvol->depths / ResZ;
  876. /* load colors for geovol file */
  877. Gvl_load_colors_data(&colors, gvl_file_get_name(gvol->hfile));
  878. /* calc changed slices */
  879. for (i = 0; i < gvol->n_slices; i++) {
  880. if (gvol->slice[i]->changed) {
  881. slice_calc(gvol, i, colors);
  882. /* set changed flag */
  883. gvol->slice[i]->changed = 0;
  884. }
  885. }
  886. /* free color */
  887. Gvl_unload_colors_data(colors);
  888. return (1);
  889. }