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