1 /*!
2 \file lib/ogsf/gvl.c
3
4 \brief OGSF library - loading and manipulating volumes (lower level functions)
5
6 GRASS OpenGL gsurf OGSF Library
7
8 (C) 1999-2008 by the GRASS Development Team
9
10 This program is free software under the
11 GNU General Public License (>=v2).
12 Read the file COPYING that comes with GRASS
13 for details.
14
15 \author Bill Brown, UI-GMSL (May 1997)
16 \author Tomas Paudits (February 2004)
17 \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
18 */
19
20 #include <stdlib.h>
21
22 #include <grass/gis.h>
23 #include <grass/ogsf.h>
24
25 #include "gsget.h"
26
27 #define FIRST_VOL_ID 81721
28
29 static geovol *Vol_top = NULL;
30
31 /*!
32 \brief Get volume set structure
33
34 \param id volume set id
35
36 \return pointer to geovol struct
37 \return NULL on failure
38 */
gvl_get_vol(int id)39 geovol *gvl_get_vol(int id)
40 {
41 geovol *gvl;
42
43 G_debug(5, "gvl_get_vol():");
44
45 for (gvl = Vol_top; gvl; gvl = gvl->next) {
46 if (gvl->gvol_id == id) {
47 G_debug(5, " id=%d", id);
48 return (gvl);
49 }
50 }
51
52 return (NULL);
53 }
54
55 /*!
56 \brief Get previous volume
57
58 \param id current volume set id
59
60 \return pointer to geovol struct
61 \return NULL on failure
62 */
gvl_get_prev_vol(int id)63 geovol *gvl_get_prev_vol(int id)
64 {
65 geovol *pv;
66
67 G_debug(5, "gvl_get_prev_vol");
68
69 for (pv = Vol_top; pv; pv = pv->next) {
70 if (pv->gvol_id == id - 1) {
71 return (pv);
72 }
73 }
74
75 return (NULL);
76 }
77
78 /*!
79 \brief Get all volumes
80
81 \param[out] list of geovol structs
82
83 \return number of available volume sets
84 */
gvl_getall_vols(geovol ** gvols)85 int gvl_getall_vols(geovol ** gvols)
86 {
87 geovol *gvl;
88 int i;
89
90 G_debug(5, "gvl_getall_vols");
91
92 for (i = 0, gvl = Vol_top; gvl; gvl = gvl->next, i++) {
93 gvols[i] = gvl;
94 }
95
96 return (i);
97 }
98
99 /*!
100 \brief Get number of loaded volume sets
101
102 \return number of volumes
103 */
gvl_num_vols(void)104 int gvl_num_vols(void)
105 {
106 geovol *gvl;
107 int i;
108
109 for (i = 0, gvl = Vol_top; gvl; gvl = gvl->next, i++) ;
110
111 G_debug(5, "gvl_num_vols(): num=%d", i);
112
113 return (i);
114 }
115
116 /*!
117 \brief Get last volume set from the list
118
119 \return pointer to geovol struct
120 \return NULL on failure
121 */
gvl_get_last_vol(void)122 geovol *gvl_get_last_vol(void)
123 {
124 geovol *lvl;
125
126 G_debug(5, "gvl_get_last_vol");
127
128 if (!Vol_top) {
129 return (NULL);
130 }
131
132 for (lvl = Vol_top; lvl->next; lvl = lvl->next) ;
133
134 G_debug(5, " last vol id: %d", lvl->gvol_id);
135
136 return (lvl);
137 }
138
139 /*!
140 \brief Allocate new volume set and add it to the list
141
142 \return pointer to geovol struct
143 \return NULL on failure
144 */
gvl_get_new_vol(void)145 geovol *gvl_get_new_vol(void)
146 {
147 geovol *nvl, *lvl;
148
149 G_debug(5, "gvl_get_new_vol()");
150
151 nvl = (geovol *) G_malloc(sizeof(geovol)); /* G_fatal_error */
152 if (!nvl) {
153 return (NULL);
154 }
155
156 if ((lvl = gvl_get_last_vol())) {
157 lvl->next = nvl;
158 nvl->gvol_id = lvl->gvol_id + 1;
159 }
160 else {
161 Vol_top = nvl;
162 nvl->gvol_id = FIRST_VOL_ID;
163 }
164
165 nvl->next = NULL;
166
167 G_debug(5, " id=%d", nvl->gvol_id);
168
169 return (nvl);
170 }
171
172 /*!
173 \brief Initialize geovol structure
174
175 \param gvl pointer to geovol struct
176 \param ox,oy,oz
177 \param rows number of rows
178 \param cols number of cols
179 \param xres,yres,zres x/y/z resolution value
180
181 \return -1 on failure
182 \return 1 on success
183 */
gvl_init_vol(geovol * gvl,double ox,double oy,double oz,int rows,int cols,int depths,double xres,double yres,double zres)184 int gvl_init_vol(geovol * gvl, double ox, double oy, double oz,
185 int rows, int cols, int depths, double xres, double yres,
186 double zres)
187 {
188 G_debug(5, "gvl_init_vol() id=%d", gvl->gvol_id);
189
190 if (!gvl) {
191 return (-1);
192 }
193
194 gvl->ox = ox;
195 gvl->oy = oy;
196 gvl->oz = oz;
197 gvl->rows = rows;
198 gvl->cols = cols;
199 gvl->depths = depths;
200 gvl->xres = xres;
201 gvl->yres = yres;
202 gvl->zres = zres;
203
204 gvl->xmin = ox;
205 gvl->xmax = ox + (cols - 1) * xres;
206 gvl->xrange = gvl->xmax - gvl->xmin;
207 gvl->ymin = oy;
208 gvl->ymax = oy + (rows - 1) * yres;
209 gvl->yrange = gvl->ymax - gvl->ymin;
210 gvl->zmin = oz;
211 gvl->zmax = oz + (depths - 1) * zres;
212 gvl->zrange = gvl->zmax - gvl->zmin;
213
214 gvl->x_trans = gvl->y_trans = gvl->z_trans = 0.0;
215 gvl->draw_wire = 0;
216
217 gvl->n_isosurfs = 0;
218 G_zero(gvl->isosurf, sizeof(geovol_isosurf *) * MAX_ISOSURFS);
219 gvl->isosurf_x_mod = 1;
220 gvl->isosurf_y_mod = 1;
221 gvl->isosurf_z_mod = 1;
222 gvl->isosurf_draw_mode = DM_GOURAUD;
223
224 gvl->n_slices = 0;
225 G_zero(gvl->slice, sizeof(geovol_slice *) * MAX_SLICES);
226 gvl->slice_x_mod = 1;
227 gvl->slice_y_mod = 1;
228 gvl->slice_z_mod = 1;
229 gvl->slice_draw_mode = DM_GOURAUD;
230
231 gvl->hfile = -1;
232 gvl->clientdata = NULL;
233
234 return (1);
235 }
236
237 /*!
238 \brief Remove volume set from list
239
240 \param id volume set id
241 */
gvl_delete_vol(int id)242 void gvl_delete_vol(int id)
243 {
244 geovol *fvl;
245
246 G_debug(5, "gvl_delete_vol");
247
248 fvl = gvl_get_vol(id);
249
250 if (fvl) {
251 gvl_free_vol(fvl);
252 }
253
254 return;
255 }
256
257 /*!
258 \brief Free geovol struct
259
260 \param fvl pointer to geovol struct
261
262 \return -1 on failure
263 \return 1 on success
264 */
gvl_free_vol(geovol * fvl)265 int gvl_free_vol(geovol * fvl)
266 {
267 geovol *gvl;
268 int found = 0;
269
270 G_debug(5, "gvl_free_vol");
271
272 if (Vol_top) {
273 if (fvl == Vol_top) {
274 if (Vol_top->next) {
275 /* can't free top if last */
276 found = 1;
277 Vol_top = fvl->next;
278 }
279 else {
280 gvl_free_volmem(fvl);
281 G_free(fvl);
282 Vol_top = NULL;
283 }
284 }
285 else {
286 for (gvl = Vol_top; gvl && !found; gvl = gvl->next) {
287 /* can't free top */
288 if (gvl->next) {
289 if (gvl->next == fvl) {
290 found = 1;
291 gvl->next = fvl->next;
292 }
293 }
294 }
295 }
296
297 if (found) {
298 gvl_free_volmem(fvl);
299 G_free(fvl);
300 fvl = NULL;
301 }
302
303 return (1);
304 }
305
306 return (-1);
307 }
308
309 /*!
310 \brief Free geovol struct memory
311
312 \param fvl pointer to geovol struct
313 */
gvl_free_volmem(geovol * fvl)314 void gvl_free_volmem(geovol * fvl)
315 {
316 if (0 < fvl->hfile)
317 gvl_file_free_datah(fvl->hfile);
318
319 return;
320 }
321
322 /*!
323 \brief Debug volume fields
324
325 \param gvl pointer to geovol struct
326 */
print_vol_fields(geovol * gvl)327 void print_vol_fields(geovol * gvl)
328 {
329 G_debug(5, "ID: %d", gvl->gvol_id);
330 G_debug(5, "cols: %d rows: %d depths: %d", gvl->cols, gvl->rows,
331 gvl->depths);
332 G_debug(5, "ox: %lf oy: %lf oz: %lf", gvl->ox, gvl->oy, gvl->oz);
333 G_debug(5, "xres: %lf yres: %lf zres: %lf", gvl->xres, gvl->yres,
334 gvl->zres);
335 G_debug(5, "xmin: %f ymin: %f zmin: %f", gvl->xmin, gvl->ymin, gvl->zmin);
336 G_debug(5, "xmax: %f ymax: %f zmax: %f", gvl->xmax, gvl->ymax, gvl->zmax);
337 G_debug(5, "x_trans: %f y_trans: %f z_trans: %f", gvl->x_trans,
338 gvl->y_trans, gvl->z_trans);
339
340 return;
341 }
342
343 /*!
344 \brief Get volume x-extent value
345
346 \param gvl pointer to geovol struct
347 \param[out] min x-min value
348 \param[out] max y-max value
349
350 \return 1
351 */
gvl_get_xextents(geovol * gvl,float * min,float * max)352 int gvl_get_xextents(geovol * gvl, float *min, float *max)
353 {
354 *min = gvl->xmin + gvl->x_trans;
355 *max = gvl->xmax + gvl->x_trans;
356
357 return (1);
358 }
359
360 /*!
361 \brief Get volume y-extent value
362
363 \param gvl pointer to geovol struct
364 \param[out] min y-min value
365 \param[out] max y-max value
366
367 \return 1
368 */
gvl_get_yextents(geovol * gvl,float * min,float * max)369 int gvl_get_yextents(geovol * gvl, float *min, float *max)
370 {
371 *min = gvl->ymin + gvl->y_trans;
372 *max = gvl->ymax + gvl->y_trans;
373
374 return (1);
375 }
376
377 /*!
378 \brief Get volume z-extent value
379
380 \param gvl pointer to geovol struct
381 \param[out] min z-min value
382 \param[out] max z-max value
383
384 \return 1
385 */
gvl_get_zextents(geovol * gvl,float * min,float * max)386 int gvl_get_zextents(geovol * gvl, float *min, float *max)
387 {
388 *min = gvl->zmin + gvl->z_trans;
389 *max = gvl->zmax + gvl->z_trans;
390
391 return (1);
392 }
393
394 /*!
395 \brief Get volume x-range value
396
397 \param[out] min x-min value
398 \param[out] max x-max value
399
400 \return 1
401 */
gvl_get_xrange(float * min,float * max)402 int gvl_get_xrange(float *min, float *max)
403 {
404 geovol *gvl;
405 float tmin, tmax;
406
407 if (Vol_top) {
408 gvl_get_xextents(Vol_top, &tmin, &tmax);
409 *min = tmin;
410 *max = tmax;
411 }
412 else {
413 return (-1);
414 }
415
416 for (gvl = Vol_top->next; gvl; gvl = gvl->next) {
417 gvl_get_xextents(gvl, &tmin, &tmax);
418
419 if (tmin < *min) {
420 *min = tmin;
421 }
422
423 if (tmax > *max) {
424 *max = tmax;
425 }
426 }
427
428 return (1);
429 }
430
431 /*!
432 \brief Get volume y-range value
433
434 \param[out] min y-min value
435 \param[out] max y-max value
436
437 \return 1
438 */
gvl_get_yrange(float * min,float * max)439 int gvl_get_yrange(float *min, float *max)
440 {
441 geovol *gvl;
442 float tmin, tmax;
443
444 if (Vol_top) {
445 gvl_get_yextents(Vol_top, &tmin, &tmax);
446 *min = tmin;
447 *max = tmax;
448 }
449 else {
450 return (-1);
451 }
452
453 for (gvl = Vol_top->next; gvl; gvl = gvl->next) {
454 gvl_get_yextents(gvl, &tmin, &tmax);
455
456 if (tmin < *min) {
457 *min = tmin;
458 }
459
460 if (tmax > *max) {
461 *max = tmax;
462 }
463 }
464
465 return (1);
466 }
467
468 /*!
469 \brief Get volume z-range value
470
471 \param[out] min z-min value
472 \param[out] max z-max value
473
474 \return 1
475 */
gvl_get_zrange(float * min,float * max)476 int gvl_get_zrange(float *min, float *max)
477 {
478 geovol *gvl;
479 float tmin, tmax;
480
481 if (Vol_top) {
482 gvl_get_zextents(Vol_top, &tmin, &tmax);
483 *min = tmin;
484 *max = tmax;
485 }
486 else {
487 return (-1);
488 }
489
490 for (gvl = Vol_top->next; gvl; gvl = gvl->next) {
491 gvl_get_zextents(gvl, &tmin, &tmax);
492
493 if (tmin < *min) {
494 *min = tmin;
495 }
496
497 if (tmax > *max) {
498 *max = tmax;
499 }
500 }
501
502 return (1);
503 }
504
505 /************************************************************************/
506 /* ISOSURFACES */
507
508 /************************************************************************/
509
510 /*!
511 \brief Initialize geovol_isosurf struct
512
513 \param isosurf pointer to geovol_isosurf struct
514
515 \return -1 on failure
516 \return 1 on success
517 */
gvl_isosurf_init(geovol_isosurf * isosurf)518 int gvl_isosurf_init(geovol_isosurf * isosurf)
519 {
520 int i;
521
522 G_debug(5, "gvl_isosurf_init");
523
524 if (!isosurf)
525 return (-1);
526
527 for (i = 0; i < MAX_ATTS; i++) {
528 isosurf->att[i].att_src = NOTSET_ATT;
529 isosurf->att[i].constant = 0.;
530 isosurf->att[i].hfile = -1;
531 isosurf->att[i].user_func = NULL;
532 isosurf->att[i].att_data = NULL;
533 isosurf->att[i].changed = 0;
534 }
535
536 isosurf->data = NULL;
537 isosurf->data_desc = 0;
538 isosurf->inout_mode = 0;
539
540 return (1);
541 }
542
543 /*!
544 \brief Free geovol_isosurf struct
545
546 \param isosurf pointer to geovol_isosurf struct
547
548 \return -1 on failure
549 \return 1 on success
550 */
gvl_isosurf_freemem(geovol_isosurf * isosurf)551 int gvl_isosurf_freemem(geovol_isosurf * isosurf)
552 {
553 int i;
554
555 G_debug(5, "gvl_isosurf_freemem");
556
557 if (!isosurf)
558 return (-1);
559
560 for (i = 0; i < MAX_ATTS; i++) {
561 gvl_isosurf_set_att_src(isosurf, i, NOTSET_ATT);
562 }
563
564 G_free(isosurf->data);
565
566 return (1);
567 }
568
569 /*!
570 \brief Get isosurface of given volume set
571
572 \param id volume set id
573 \param isosurf_id isosurface id (0 - MAX_ISOSURFS)
574
575 \return pointer to geovol_isosurf struct
576 \return NULL on failure
577 */
gvl_isosurf_get_isosurf(int id,int isosurf_id)578 geovol_isosurf *gvl_isosurf_get_isosurf(int id, int isosurf_id)
579 {
580 geovol *gvl;
581
582 G_debug(5, "gvl_isosurf_get_isosurf(): id=%d isosurf=%d", id, isosurf_id);
583
584 gvl = gvl_get_vol(id);
585
586 if (gvl) {
587 if ((isosurf_id < 0) || (isosurf_id > (gvl->n_isosurfs - 1)))
588 return (NULL);
589
590 return gvl->isosurf[isosurf_id];
591 }
592
593 return (NULL);
594 }
595
596 /*!
597 \brief Get attribute source
598
599 \param isosurf pointer to geovol_isosurf struct
600 \param desc attribute id
601
602 \return -1 on failure
603 \return attribute value
604 */
gvl_isosurf_get_att_src(geovol_isosurf * isosurf,int desc)605 int gvl_isosurf_get_att_src(geovol_isosurf * isosurf, int desc)
606 {
607 G_debug(5, "isosurf_get_att_src");
608
609 if (!LEGAL_ATT(desc)) {
610 return (-1);
611 }
612
613 if (isosurf) {
614 return (isosurf->att[desc].att_src);
615 }
616
617 return (-1);
618 }
619
620 /*!
621 \brief Set attribute source
622
623 \param isosurf pointer to geovol_isosurf struct
624 \param desc attribute id
625 \param src attribute value
626
627 \return -1 on failure
628 \return 1 on success
629 */
gvl_isosurf_set_att_src(geovol_isosurf * isosurf,int desc,int src)630 int gvl_isosurf_set_att_src(geovol_isosurf * isosurf, int desc, int src)
631 {
632 G_debug(5, "gvl_isosurf_set_att_src");
633
634 /* check if old source was MAP_ATT, deattach volfile */
635 if (MAP_ATT == gvl_isosurf_get_att_src(isosurf, desc)) {
636 gvl_file_free_datah(isosurf->att[desc].hfile);
637
638 if (desc == ATT_COLOR) {
639 Gvl_unload_colors_data(isosurf->att[desc].att_data);
640 }
641 }
642
643 if (isosurf && LEGAL_SRC(src)) {
644 isosurf->att[desc].att_src = src;
645 gvl_isosurf_set_att_changed(isosurf, desc);
646
647 return (1);
648 }
649
650 return (-1);
651 }
652
653 /*!
654 \brief Set isosurface attribute constant
655
656 \param isosurf pointer to geovol_isosurf struct
657 \param desc attribute descriptor
658 \param constant attribute value
659
660 \return -1 on failure
661 \return 1 on success
662 */
gvl_isosurf_set_att_const(geovol_isosurf * isosurf,int desc,float constant)663 int gvl_isosurf_set_att_const(geovol_isosurf * isosurf, int desc,
664 float constant)
665 {
666 G_debug(5, "gvl_isosurf_set_att_const(): att=%d, const=%f",
667 desc, constant);
668
669 if (isosurf) {
670 isosurf->att[desc].constant = constant;
671
672 gvl_isosurf_set_att_src(isosurf, desc, CONST_ATT);
673
674 return (1);
675 }
676
677 return (-1);
678 }
679
680 /*!
681 \brief Set attribute map
682
683 \param isosurf pointer to geovol_isosurf struct
684 \param desc attribute id
685 \param filename filename
686
687 \return -1 on failure
688 \return 1 on success
689 */
gvl_isosurf_set_att_map(geovol_isosurf * isosurf,int desc,const char * filename)690 int gvl_isosurf_set_att_map(geovol_isosurf * isosurf, int desc,
691 const char *filename)
692 {
693 int hfile;
694
695 G_debug(5, "gvl_isosurf_set_att_map(): att=%d map=%s", desc, filename);
696
697 if (isosurf) {
698 if (0 > (hfile = gvl_file_newh(filename, VOL_FTYPE_RASTER3D)))
699 return (-1);
700
701 gvl_isosurf_set_att_src(isosurf, desc, MAP_ATT);
702
703 isosurf->att[desc].hfile = hfile;
704
705 if (ATT_COLOR == desc) {
706 Gvl_load_colors_data(&(isosurf->att[desc].att_data), filename);
707 }
708 return (1);
709 }
710
711 return (-1);
712 }
713
714 /*!
715 \brief Set attribute changed
716
717 \param isosurf pointer to geovol_isosurf struct
718 \param desc attribute id
719
720 \return -1 on failure
721 \return 1 on success
722 */
gvl_isosurf_set_att_changed(geovol_isosurf * isosurf,int desc)723 int gvl_isosurf_set_att_changed(geovol_isosurf * isosurf, int desc)
724 {
725 int i;
726
727 G_debug(5, "gvl_isosurf_set_att_changed");
728
729 if (isosurf && LEGAL_ATT(desc)) {
730 isosurf->att[desc].changed = 1;
731
732 if ((desc == ATT_TOPO) || (desc == ATT_MASK)) {
733 for (i = 1; i < MAX_ATTS; i++)
734 isosurf->att[i].changed = 1;
735 }
736
737 return (1);
738 }
739
740 return (-1);
741 }
742
743 /************************************************************************/
744 /* SLICES */
745
746 /************************************************************************/
747
748 /*!
749 \brief Initialize geovol_slice struct
750
751 \param slice pointer to geovol_slice struct
752
753 \return -1 on failure
754 \return 1 on success
755 */
gvl_slice_init(geovol_slice * slice)756 int gvl_slice_init(geovol_slice * slice)
757 {
758 G_debug(5, "gvl_slice_init");
759
760 if (!slice)
761 return (-1);
762
763 slice->data = NULL;
764 slice->changed = 0;
765 slice->mode = 1;
766 slice->transp = 0;
767
768 slice->z1 = 0;
769 slice->z2 = 99;
770
771 return (1);
772 }
773
774 /*!
775 \brief Free geovol_slice struct
776
777 \param slice pointer to geovol_slice struct
778
779 \return -1 on failure
780 \return 1 on success
781 */
gvl_slice_freemem(geovol_slice * slice)782 int gvl_slice_freemem(geovol_slice * slice)
783 {
784 G_debug(5, "gvl_slice_freemem");
785
786 if (!slice)
787 return (-1);
788
789 G_free(slice->data);
790
791 return (1);
792 }
793
794 /*!
795 \brief Get geovol_slice struct
796
797 \param id volume set id
798 \param slice_id slice id
799
800 \return pointer to geovol_slice struct
801 \return NULL on failure
802 */
gvl_slice_get_slice(int id,int slice_id)803 geovol_slice *gvl_slice_get_slice(int id, int slice_id)
804 {
805 geovol *gvl;
806
807 gvl = gvl_get_vol(id);
808
809 if (gvl) {
810 if ((slice_id < 0) || (slice_id > (gvl->n_slices - 1)))
811 return (NULL);
812
813 return gvl->slice[slice_id];
814 }
815
816 return (NULL);
817 }
818