gvl_calc.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. /*!
  2. \file lib/ogsf/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. /* initialize read/write buffers */
  518. dbuff[i].old = NULL;
  519. dbuff[i].new = NULL;
  520. dbuff[i].ndx_old = 0;
  521. dbuff[i].ndx_new = 0;
  522. dbuff[i].num_zero = 0;
  523. need_update[i] = 0;
  524. for (a = 1; a < MAX_ATTS; a++) {
  525. if (isosurf->att[a].changed) {
  526. read = 0;
  527. /* changed to map attribute */
  528. if (isosurf->att[a].att_src == MAP_ATT) {
  529. vf = gvl_file_get_volfile(isosurf->att[a].hfile);
  530. read = 1;
  531. }
  532. /* changed threshold value */
  533. if (a == ATT_TOPO) {
  534. isosurf->att[a].hfile = gvol->hfile;
  535. vf = gvl_file_get_volfile(gvol->hfile);
  536. read = 1;
  537. }
  538. /* initialize reading in selected mode */
  539. if (read) {
  540. gvl_file_set_mode(vf, 3);
  541. gvl_file_start_read(vf);
  542. }
  543. /* set update flag - isosurface will be calc */
  544. if (read || IS_IN_DATA(a)) {
  545. need_update[i] = 1;
  546. need_update_global = 1;
  547. }
  548. }
  549. }
  550. if (need_update[i]) {
  551. /* set data buffer */
  552. dbuff[i].old = isosurf->data;
  553. }
  554. }
  555. /* calculate if only some isosurface changed */
  556. if (need_update_global) {
  557. ResX = gvol->isosurf_x_mod;
  558. ResY = gvol->isosurf_y_mod;
  559. ResZ = gvol->isosurf_z_mod;
  560. Cols = gvol->cols / ResX;
  561. Rows = gvol->rows / ResY;
  562. Depths = gvol->depths / ResZ;
  563. /* calc isosurface - marching cubes - start */
  564. for (z = 0; z < Depths - 1; z++) {
  565. for (y = 0; y < Rows - 1; y++) {
  566. for (x = 0; x < Cols - 1; x++) {
  567. for (i = 0; i < gvol->n_isosurfs; i++) {
  568. /* recalculate only changed isosurfaces */
  569. if (need_update[i]) {
  570. iso_calc_cube(gvol->isosurf[i], x, y, z,
  571. &dbuff[i]);
  572. }
  573. }
  574. }
  575. }
  576. }
  577. }
  578. /* end */
  579. /* deinitialize */
  580. for (i = 0; i < gvol->n_isosurfs; i++) {
  581. isosurf = gvol->isosurf[i];
  582. /* set new isosurface data */
  583. if (need_update[i]) {
  584. if (dbuff[i].num_zero != 0)
  585. gvl_write_char(dbuff[i].ndx_new++, &(dbuff[i].new),
  586. dbuff[i].num_zero);
  587. if (dbuff[i].old == isosurf->data)
  588. dbuff[i].old = NULL;
  589. G_free(isosurf->data);
  590. gvl_align_data(dbuff[i].ndx_new, &(dbuff[i].new));
  591. isosurf->data = dbuff[i].new;
  592. isosurf->data_desc = 0;
  593. }
  594. for (a = 1; a < MAX_ATTS; a++) {
  595. if (isosurf->att[a].changed) {
  596. read = 0;
  597. /* changed map attribute */
  598. if (isosurf->att[a].att_src == MAP_ATT) {
  599. vf = gvl_file_get_volfile(isosurf->att[a].hfile);
  600. read = 1;
  601. }
  602. /* changed threshold value */
  603. if (a == ATT_TOPO) {
  604. isosurf->att[a].hfile = gvol->hfile;
  605. vf = gvl_file_get_volfile(gvol->hfile);
  606. read = 1;
  607. }
  608. /* deinitialize reading */
  609. if (read) {
  610. gvl_file_end_read(vf);
  611. /* set data description */
  612. SET_IN_DATA(a);
  613. }
  614. isosurf->att[a].changed = 0;
  615. }
  616. else if (isosurf->att[a].att_src == MAP_ATT) {
  617. /* set data description */
  618. SET_IN_DATA(a);
  619. }
  620. }
  621. }
  622. /* TODO: G_free() dbuff and need_update ??? */
  623. return (1);
  624. }
  625. /*!
  626. \brief ADD
  627. \param pos
  628. \param data
  629. \param c
  630. */
  631. void gvl_write_char(int pos, unsigned char **data, unsigned char c)
  632. {
  633. /* check to need allocation memory */
  634. if ((pos % BUFFER_SIZE) == 0) {
  635. *data = (char *)G_realloc(*data,
  636. sizeof(char) * ((pos / BUFFER_SIZE) +
  637. 1) * BUFFER_SIZE);
  638. if (!(*data)) {
  639. return;
  640. }
  641. G_debug(3,
  642. "gvl_write_char(): reallocate memory for pos : %d to : %lu B",
  643. pos, sizeof(char) * ((pos / BUFFER_SIZE) + 1) * BUFFER_SIZE);
  644. }
  645. (*data)[pos] = c;
  646. }
  647. /*!
  648. \brief Read char
  649. \param pos position index
  650. \param data data buffer
  651. \return char on success
  652. \return NULL on failure
  653. */
  654. unsigned char gvl_read_char(int pos, const unsigned char *data)
  655. {
  656. if (!data)
  657. return '\0';
  658. return data[pos];
  659. }
  660. /*!
  661. \brief Append data to buffer
  662. \param pos position index
  663. \param data data buffer
  664. */
  665. void gvl_align_data(int pos, unsigned char **data)
  666. {
  667. unsigned char *p = *data;
  668. /* realloc memory to fit in data length */
  669. p = (unsigned char *)G_realloc(p, sizeof(unsigned char) * pos); /* G_fatal_error */
  670. if (!p) {
  671. return;
  672. }
  673. G_debug(3, "gvl_align_data(): reallocate memory finally to : %d B", pos);
  674. if (pos == 0)
  675. p = NULL;
  676. *data = p;
  677. return;
  678. }
  679. /************************************************************************/
  680. /* SLICES */
  681. /************************************************************************/
  682. #define DISTANCE_2(x1, y1, x2, y2) sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
  683. #define SLICE_MODE_INTERP_NO 0
  684. #define SLICE_MODE_INTERP_YES 1
  685. /*!
  686. \brief Get volume value
  687. \param gvl pointer to geovol struct
  688. \param x,y,z
  689. \return value
  690. */
  691. float slice_get_value(geovol * gvl, int x, int y, int z)
  692. {
  693. static double d;
  694. static geovol_file *vf;
  695. static int type;
  696. static float value;
  697. if (x < 0 || y < 0 || z < 0 || (x > gvl->cols - 1) || (y > gvl->rows - 1)
  698. || (z > gvl->depths - 1))
  699. return 0.;
  700. /* get volume file from attribute handle */
  701. vf = gvl_file_get_volfile(gvl->hfile);
  702. type = gvl_file_get_data_type(vf);
  703. /* get value from volume file */
  704. if (type == VOL_DTYPE_FLOAT) {
  705. gvl_file_get_value(vf, x, y, z, &value);
  706. }
  707. else if (type == VOL_DTYPE_DOUBLE) {
  708. gvl_file_get_value(vf, x, y, z, &d);
  709. value = (float)d;
  710. }
  711. else {
  712. return 0.;
  713. }
  714. return value;
  715. }
  716. /*!
  717. \brief Calculate slices
  718. \param gvl pointer to geovol struct
  719. \param ndx_slc
  720. \param colors
  721. \return 1
  722. */
  723. int slice_calc(geovol * gvl, int ndx_slc, void *colors)
  724. {
  725. int cols, rows, c, r;
  726. int i, j, k, pos, color;
  727. int *p_x, *p_y, *p_z;
  728. float *p_ex, *p_ey, *p_ez;
  729. float value, v[8];
  730. float x, y, z, ei, ej, ek, stepx, stepy, stepz;
  731. float f_cols, f_rows, distxy, distz, modxy, modx, mody, modz;
  732. geovol_slice *slice;
  733. geovol_file *vf;
  734. slice = gvl->slice[ndx_slc];
  735. /* set mods, pointer to x, y, z step value */
  736. if (slice->dir == X) {
  737. modx = ResY;
  738. mody = ResZ;
  739. modz = ResX;
  740. p_x = &k;
  741. p_y = &i;
  742. p_z = &j;
  743. p_ex = &ek;
  744. p_ey = &ei;
  745. p_ez = &ej;
  746. }
  747. else if (slice->dir == Y) {
  748. modx = ResX;
  749. mody = ResZ;
  750. modz = ResY;
  751. p_x = &i;
  752. p_y = &k;
  753. p_z = &j;
  754. p_ex = &ei;
  755. p_ey = &ek;
  756. p_ez = &ej;
  757. }
  758. else {
  759. modx = ResX;
  760. mody = ResY;
  761. modz = ResZ;
  762. p_x = &i;
  763. p_y = &j;
  764. p_z = &k;
  765. p_ex = &ei;
  766. p_ey = &ej;
  767. p_ez = &ek;
  768. }
  769. /* distance between slice def. points */
  770. distxy = DISTANCE_2(slice->x2, slice->y2, slice->x1, slice->y1);
  771. distz = fabsf(slice->z2 - slice->z1);
  772. /* distance between slice def points is zero - nothing to do */
  773. if (distxy == 0. || distz == 0.) {
  774. return (1);
  775. }
  776. /* start reading volume file */
  777. vf = gvl_file_get_volfile(gvl->hfile);
  778. gvl_file_set_mode(vf, 3);
  779. gvl_file_start_read(vf);
  780. /* set xy resolution */
  781. modxy =
  782. DISTANCE_2((slice->x2 - slice->x1) / distxy * modx,
  783. (slice->y2 - slice->y1) / distxy * mody, 0., 0.);
  784. /* cols/rows of slice */
  785. f_cols = distxy / modxy;
  786. cols = f_cols > (int)f_cols ? (int)f_cols + 1 : (int)f_cols;
  787. f_rows = distz / modz;
  788. rows = f_rows > (int)f_rows ? (int)f_rows + 1 : (int)f_rows;
  789. /* set x,y intially to first slice point */
  790. x = slice->x1;
  791. y = slice->y1;
  792. /* set x,y step */
  793. stepx = (slice->x2 - slice->x1) / f_cols;
  794. stepy = (slice->y2 - slice->y1) / f_cols;
  795. stepz = (slice->z2 - slice->z1) / f_rows;
  796. /* set position in slice data */
  797. pos = 0;
  798. /* loop in slice cols */
  799. for (c = 0; c < cols + 1; c++) {
  800. /* convert x, y to integer - index in grid */
  801. i = (int)x;
  802. j = (int)y;
  803. /* distance between index and real position */
  804. ei = x - (float)i;
  805. ej = y - (float)j;
  806. /* set z to slice z1 point */
  807. z = slice->z1;
  808. /* loop in slice rows */
  809. for (r = 0; r < rows + 1; r++) {
  810. /* distance between index and real position */
  811. k = (int)z;
  812. ek = z - (float)k;
  813. /* get interpolated value */
  814. if (slice->mode == SLICE_MODE_INTERP_YES) {
  815. /* get grid values */
  816. v[0] = slice_get_value(gvl, *p_x, *p_y, *p_z);
  817. v[1] = slice_get_value(gvl, *p_x + 1, *p_y, *p_z);
  818. v[2] = slice_get_value(gvl, *p_x, *p_y + 1, *p_z);
  819. v[3] = slice_get_value(gvl, *p_x + 1, *p_y + 1, *p_z);
  820. v[4] = slice_get_value(gvl, *p_x, *p_y, *p_z + 1);
  821. v[5] = slice_get_value(gvl, *p_x + 1, *p_y, *p_z + 1);
  822. v[6] = slice_get_value(gvl, *p_x, *p_y + 1, *p_z + 1);
  823. v[7] = slice_get_value(gvl, *p_x + 1, *p_y + 1, *p_z + 1);
  824. /* get interpolated value */
  825. value = v[0] * (1. - *p_ex) * (1. - *p_ey) * (1. - *p_ez)
  826. + v[1] * (*p_ex) * (1. - *p_ey) * (1. - *p_ez)
  827. + v[2] * (1. - *p_ex) * (*p_ey) * (1. - *p_ez)
  828. + v[3] * (*p_ex) * (*p_ey) * (1. - *p_ez)
  829. + v[4] * (1. - *p_ex) * (1. - *p_ey) * (*p_ez)
  830. + v[5] * (*p_ex) * (1. - *p_ey) * (*p_ez)
  831. + v[6] * (1. - *p_ex) * (*p_ey) * (*p_ez)
  832. + v[7] * (*p_ex) * (*p_ey) * (*p_ez);
  833. /* no interp value */
  834. }
  835. else {
  836. value = slice_get_value(gvl, *p_x, *p_y, *p_z);
  837. }
  838. /* translate value to color */
  839. color = Gvl_get_color_for_value(colors, &value);
  840. /* write color to slice data */
  841. gvl_write_char(pos++, &(slice->data), color & RED_MASK);
  842. gvl_write_char(pos++, &(slice->data), (color & GRN_MASK) >> 8);
  843. gvl_write_char(pos++, &(slice->data), (color & BLU_MASK) >> 16);
  844. /* step in z */
  845. if (r + 1 > f_rows) {
  846. z += stepz * (f_rows - (float)r);
  847. }
  848. else {
  849. z += stepz;
  850. }
  851. }
  852. /* step in x,y */
  853. if (c + 1 > f_cols) {
  854. x += stepx * (f_cols - (float)c);
  855. y += stepy * (f_cols - (float)c);
  856. }
  857. else {
  858. x += stepx;
  859. y += stepy;
  860. }
  861. }
  862. /* end reading volume file */
  863. gvl_file_end_read(vf);
  864. gvl_align_data(pos, &(slice->data));
  865. return (1);
  866. }
  867. /*!
  868. \brief Calculate slices for given volume set
  869. \param gvol pointer to geovol struct
  870. \return 1
  871. */
  872. int gvl_slices_calc(geovol *gvol)
  873. {
  874. int i;
  875. void *colors;
  876. G_debug(5, "gvl_slices_calc(): id=%d", gvol->gvol_id);
  877. /* set current resolution */
  878. ResX = gvol->slice_x_mod;
  879. ResY = gvol->slice_y_mod;
  880. ResZ = gvol->slice_z_mod;
  881. /* set current num of cols, rows, depths */
  882. Cols = gvol->cols / ResX;
  883. Rows = gvol->rows / ResY;
  884. Depths = gvol->depths / ResZ;
  885. /* load colors for geovol file */
  886. Gvl_load_colors_data(&colors, gvl_file_get_name(gvol->hfile));
  887. /* calc changed slices */
  888. for (i = 0; i < gvol->n_slices; i++) {
  889. if (gvol->slice[i]->changed) {
  890. slice_calc(gvol, i, colors);
  891. /* set changed flag */
  892. gvol->slice[i]->changed = 0;
  893. }
  894. }
  895. /* free color */
  896. Gvl_unload_colors_data(colors);
  897. return (1);
  898. }