GRASS GIS 8 Programmer's Manual 8.4.1(2025)-45ca3179ab
Loading...
Searching...
No Matches
gs.c
Go to the documentation of this file.
1/*!
2 \file lib/ogsf/gs.c
3
4 \brief OGSF library - loading and manipulating surfaces (lower level
5 functions)
6
7 GRASS OpenGL gsurf OGSF Library
8
9 (C) 1999-2008 by the GRASS Development Team
10
11 This program is free software under the
12 GNU General Public License (>=v2).
13 Read the file COPYING that comes with GRASS
14 for details.
15
16 \author Bill Brown USACERL, GMSL/University of Illinois (January 1993)
17 \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
18 */
19
20#include <stdlib.h>
21#include <stdio.h>
22
23#include <grass/ogsf.h>
24#include <grass/glocale.h>
25
26#include "gsget.h"
27#include "rowcol.h"
28
29#define FIRST_SURF_ID 110658
30
31static geosurf *Surf_top;
32static int Invertmask;
33
34/***********************************************************************/
35void gs_err(const char *msg)
36{
37 G_warning("%s", msg);
38
39 return;
40}
41
42/*!
43 \brief Initialize library
44
45 Still need to take care of library initialization,
46 probably want to define a Surf_top of constant value (i.e., 0)
47 */
48void gs_init(void)
49{
50 Surf_top = NULL;
51
52 return;
53}
54
55/*!
56 \brief Get geosurf struct
57
58 \param id surface id
59
60 \return pointer to geosurf struct
61 \return NULL if not found
62 */
63geosurf *gs_get_surf(int id)
64{
65 geosurf *gs;
66
67 G_debug(5, "gs_get_surf():");
68
69 for (gs = Surf_top; gs; gs = gs->next) {
70 if (gs->gsurf_id == id) {
71 G_debug(5, " id=%d", id);
72 return (gs);
73 }
74 }
75
76 return (NULL);
77}
78
79/*!
80 \brief Get previous geosurf struct
81
82 \param id current surface id
83
84 \return pointer to geosurf struct
85 \return NULL if not found
86 */
87geosurf *gs_get_prev_surface(int id)
88{
89 geosurf *ps;
90
91 G_debug(5, "gs_get_prev_surface");
92
93 for (ps = Surf_top; ps; ps = ps->next) {
94 if (ps->gsurf_id == id - 1) {
95 return (ps);
96 }
97 }
98
99 return (NULL);
100}
101
102/*!
103 \brief Get array of geosurf structs
104
105 \param gsurfs pointer to array
106
107 \return number of geosurfs
108 */
109int gs_getall_surfaces(geosurf **gsurfs)
110{
111 geosurf *gs;
112 int i;
113
114 for (i = 0, gs = Surf_top; gs; gs = gs->next, i++) {
115 gsurfs[i] = gs;
116 }
117
118 G_debug(5, "gs_num_surfaces(): num=%d", i);
119
120 return (i);
121}
122
123/*!
124 \brief Get number of surfaces
125
126 \return number of surfaces
127 */
129{
130 geosurf *gs;
131 int i;
132
133 for (i = 0, gs = Surf_top; gs; gs = gs->next, i++)
134 ;
135
136 G_debug(5, "gs_num_surfaces(): num=%d", i);
137
138 return (i);
139}
140
141/*!
142 \brief Check if attribute is set
143
144 \param surf pointer to gsurf or NULL to look at all geosurfs
145 \param att attribute id
146
147 \return 1 attribute is set up
148 \return 0 attribute is not set up
149 */
150int gs_att_is_set(geosurf *surf, IFLAG att)
151{
152 geosurf *gs;
153
154 if (surf) {
155 return (NOTSET_ATT != surf->att[att].att_src);
156 }
157
158 /* if surf == NULL, look at all surfs */
159 for (gs = Surf_top; gs; gs = gs->next) {
160 if (NOTSET_ATT != gs->att[att].att_src) {
161 return (1);
162 }
163 }
164
165 return (0);
166}
167
168/*!
169 \brief Get last allocated geosurf struct from list
170
171 \return pointer to geosurf struct
172 */
174{
175 geosurf *ls;
176
177 if (!Surf_top) {
178 return (NULL);
179 }
180
181 for (ls = Surf_top; ls->next; ls = ls->next)
182 ;
183
184 G_debug(5, "gs_get_last_surface(): last surface id=%d", ls->gsurf_id);
185
186 return (ls);
187}
188
189/*!
190 \brief Allocate new geosurf struct
191
192 \return pointer to geosurf struct
193 */
194geosurf *gs_get_new_surface(void)
195{
196 geosurf *ns, *ls;
197
198 ns = (geosurf *)G_malloc(sizeof(geosurf)); /* G_fatal_error */
199 if (!ns) {
200 return (NULL);
201 }
202
203 if ((ls = gs_get_last_surface())) {
204 ls->next = ns;
205 ns->gsurf_id = ls->gsurf_id + 1;
206 }
207 else {
208 Surf_top = ns;
209 ns->gsurf_id = FIRST_SURF_ID;
210 }
211
212 ns->next = NULL;
213
214 G_debug(5, "gs_get_new_surface(): id=%d", ns->gsurf_id);
215
216 return (ns);
217}
218
219/*!
220 \brief Initialize allocated geosurf struct
221
222 \todo Now xmin & ox are the same, right? - get rid of ox, oy in geosurf
223 struct?
224
225 \param gs pointer to geosurf struct
226 \param ox,oy x/y origin coordinates
227 \param rows number of rows
228 \param cols number of cols
229 \param xres,yres x/y resolution value
230
231 \return -1 on error
232 \return 0 on success
233 */
234int gs_init_surf(geosurf *gs, double ox, double oy, int rows, int cols,
235 double xres, double yres)
236{
237 geosurf *ps;
238 int i;
239
240 if (!gs) {
241 return (-1);
242 }
243
244 G_debug(5, "gs_init_surf() id=%d", gs->gsurf_id);
245
246 /* default attributes */
247 for (i = 0; i < MAX_ATTS; i++) {
248 gs->att[i].att_src = NOTSET_ATT;
249 gs->att[i].att_type = ATTY_INT;
250 gs->att[i].hdata = -1;
251 gs->att[i].user_func = NULL;
252 gs->att[i].constant = 0.;
253 gs->att[i].lookup = NULL;
254 gs->att[i].min_nz = gs->att[i].max_nz = gs->att[i].range_nz = 0;
255 gs->att[i].default_null = 0.;
256 }
257
258 /* default values */
259 gs->ox = ox;
260 gs->oy = oy;
261 gs->rows = rows;
262 gs->cols = cols;
263 gs->xres = xres;
264 gs->yres = yres;
265 gs->x_mod = 2;
266 gs->y_mod = 2;
267 gs->x_modw = rows / 30;
268 gs->y_modw = rows / 30;
269 gs->xmin = ox;
270 gs->xmax = ox + (cols - 1) * xres;
271 gs->xrange = gs->xmax - gs->xmin;
272 gs->ymin = oy;
273 gs->ymax = oy + (rows - 1) * yres;
274 gs->yrange = gs->ymax - gs->ymin;
275 gs->zmin = gs->zmin_nz = gs->zminmasked = 0;
276 gs->zmax = gs->zmax_nz = 0;
277 gs->zrange = gs->zrange_nz = 0;
278 gs->wire_color = 0x00888888;
279 gs->x_trans = gs->y_trans = gs->z_trans = 0.0;
280 gs->nz_topo = gs->nz_color = 0;
281 gs->norm_needupdate = 1;
282 gs->mask_needupdate = 1;
283 gs->curmask = NULL;
284 gs->norms = NULL;
285
286 gs->draw_mode = DM_GOURAUD;
287
288 /* default z_exag value */
289 if (gs->gsurf_id == FIRST_SURF_ID) {
290 gs->z_exag = 1.0;
291 }
292 else {
293 ps = gs_get_prev_surface(gs->gsurf_id);
294 gs->z_exag = ps->z_exag;
295 }
296
297 return (0);
298}
299
300/*!
301 \brief Init geosurf normbuff
302
303 \param gs pointer to geosurf struct
304
305 \return 0 on error
306 \return 1 on success
307 */
308int gs_init_normbuff(geosurf *gs)
309{
310 long size;
311
312 if (!gs) {
313 return (0);
314 }
315
316 if (gs->norms) {
317 G_free(gs->norms);
318 }
319
320 size = gs->rows * gs->cols * sizeof(unsigned long);
321
322 gs->norms = (unsigned long *)G_malloc(size); /* G_fatal_error */
323 if (!gs->norms) {
324 return (-1);
325 }
326
327 gs->norm_needupdate = 1;
328
329 return (1);
330}
331
332/*!
333 \brief Debugging, print 'from/to' model coordinates to stderr
334
335 \todo G_debug ?
336
337 \param ft pointer to coordinates
338 */
339void print_frto(float (*ft)[4])
340{
341 fprintf(stderr, "FROM: %f, %f, %f\n", ft[FROM][X], ft[FROM][Y],
342 ft[FROM][Z]);
343 fprintf(stderr, "TO: %f, %f, %f\n", ft[TO][X], ft[TO][Y], ft[TO][Z]);
344
345 return;
346}
347
348/*!
349 \brief Debugging, print 'to' real coordinates to stderr
350
351 \todo G_debug ?
352
353 \param ft pointer to coordinates
354 */
355void print_realto(float *rt)
356{
357 fprintf(stderr, "REAL TO: %f, %f, %f\n", rt[X], rt[Y], rt[Z]);
358
359 return;
360}
361
362/*!
363 \brief Debugging, 256 integer values from buffer
364
365 \todo G_debug ?
366
367 \param ft pointer to buffer
368 */
369void print_256lookup(int *buff)
370{
371 int i;
372
373 for (i = 0; i < 256; i++) {
374 if (!(i % 8)) {
375 fprintf(stderr, "\n");
376 }
377
378 fprintf(stderr, "%x ", buff[i]);
379 }
380
381 fprintf(stderr, "\n");
382
383 return;
384}
385
386/*!
387 \brief Debugging, print geosurf fields to stderr
388
389 \todo G_debug ?
390
391 \param s pointer to geosurf struct
392 */
393void print_surf_fields(geosurf *s)
394{
395 fprintf(stderr, "ID: %d\n", s->gsurf_id);
396 fprintf(stderr, "rows: %d cols: %d\n", s->rows, s->cols);
397 fprintf(stderr, "draw_mode: %x\n", s->draw_mode);
398 fprintf(stderr, "wire_color: %lx\n", s->wire_color);
399 fprintf(stderr, "ox: %lf oy: %lf\n", s->ox, s->oy);
400 fprintf(stderr, "xres: %lf yres: %lf\n", s->xres, s->yres);
401 fprintf(stderr, "z_exag: %f \n", s->z_exag);
402 fprintf(stderr, "x_trans: %f y_trans: %f z_trans: %f\n", s->x_trans,
403 s->y_trans, s->z_trans);
404 fprintf(stderr, "xmin: %f ymin: %f zmin: %f\n", s->xmin, s->ymin, s->zmin);
405 fprintf(stderr, "xmax: %f ymax: %f zmax: %f\n", s->xmax, s->ymax, s->zmax);
406 fprintf(stderr, "x_mod: %d y_mod: %d x_modw: %d y_modw: %d\n", s->x_mod,
407 s->y_mod, s->x_modw, s->y_modw);
408
409 return;
410}
411
412/*!
413 \brief Debugging, print geoview fields to stderr
414
415 \todo G_debug ?
416
417 \param gv pointer to geoview struct
418 */
419void print_view_fields(geoview *gv)
420{
421 fprintf(stderr, "coord_sys: %d\n", gv->coord_sys);
422 fprintf(stderr, "view_proj: %d\n", gv->view_proj);
423 fprintf(stderr, "infocus: %d\n", gv->infocus);
424 print_frto(gv->from_to);
425 fprintf(stderr, "twist: %d fov: %d\n", gv->twist, gv->fov);
426 fprintf(stderr, "incl: %d look: %d\n", gv->incl, gv->look);
427 fprintf(stderr, "real_to: %f %f %f\n", gv->real_to[X], gv->real_to[Y],
428 gv->real_to[Z]);
429 fprintf(stderr, "vert_exag: %f scale: %f \n", gv->vert_exag, gv->scale);
430
431 return;
432}
433
434/*!
435 \brief Set default attribute values
436
437 \param gs pointer to geosurf struct
438 \param defs array of default values (dim MAX_ATTRS)
439 \param null_defs array of null default values (dim MAX_ATTRS)
440 */
441void gs_set_defaults(geosurf *gs, float *defs, float *null_defs)
442{
443 int i;
444
445 G_debug(5, "gs_set_defaults(): id=%d", gs->gsurf_id);
446
447 for (i = 0; i < MAX_ATTS; i++) {
448 gs->att[i].constant = defs[i];
449 gs->att[i].default_null = null_defs[i];
450 gs->att[i].lookup = NULL;
451 gs->att[i].hdata = -1;
452 gs->att[i].att_src = NOTSET_ATT;
453 }
454
455 return;
456}
457
458/*!
459 \brief Remove geosurf struct from list
460
461 \param id surface id
462 */
463void gs_delete_surf(int id)
464{
465 geosurf *fs;
466
467 G_debug(5, "gs_delete_surf");
468
469 fs = gs_get_surf(id);
470
471 if (fs) {
472 gs_free_surf(fs);
473 }
474
475 return;
476}
477
478/*!
479 \brief Free geosurf struct
480
481 \param fs pointer to geosurf struct
482
483 \return 1 found
484 \return 0 not found
485 \return -1 on error
486 */
487int gs_free_surf(geosurf *fs)
488{
489 geosurf *gs;
490 int found = 0;
491
492 G_debug(5, "gs_free_surf");
493
494 if (Surf_top) {
495 if (fs == Surf_top) {
496 if (Surf_top->next) {
497 /* can't free top if last */
498 found = 1;
499 Surf_top = fs->next;
500 }
501 else {
503
504 if (fs->curmask) {
505 G_free(fs->curmask);
506 }
507
508 if (fs->norms) {
509 G_free(fs->norms);
510 }
511
512 G_free(fs);
513 Surf_top = NULL;
514 }
515 }
516 else {
517 for (gs = Surf_top; gs && !found; gs = gs->next) {
518 if (gs->next) {
519 if (gs->next == fs) {
520 found = 1;
521 gs->next = fs->next;
522 }
523 }
524 }
525 }
526
527 if (found) {
529
530 if (fs->curmask) {
531 G_free(fs->curmask);
532 }
533
534 if (fs->norms) {
535 G_free(fs->norms);
536 }
537
538 G_free(fs);
539 fs = NULL;
540 }
541
542 return (found);
543 }
544
545 return (-1);
546}
547
548/*!
549 \brief Free unshared buffers of geosurf struct
550
551 <i>fs</i> has already been taken out of the list
552
553 This function is fairly revealing about how shared datasets work
554
555 \param fs pointer to geosurf struct
556 */
557void gs_free_unshared_buffs(geosurf *fs)
558{
559 geosurf *gs;
560 int i, j, same;
561 int old_datah;
562
563 G_debug(5, "gs_free_unshared_buffs");
564
565 /* for each attribute
566 if !same, free buff
567 */
568 for (i = 0; i < MAX_ATTS; i++) {
569 same = 0;
570
571 if (0 < (old_datah = fs->att[i].hdata)) {
572 /* for ea att of all other surfs */
573 for (gs = Surf_top; gs; gs = gs->next) {
574 for (j = 0; j < MAX_ATTS; j++) {
575 if ((old_datah == gs->att[j].hdata) && (fs != gs)) {
576 same = 1;
577 }
578 }
579 }
580
581 if (!same) {
582 gsds_free_datah(old_datah);
583 }
584 }
585 }
586
587 return;
588}
589
590/*!
591 \brief Get number of reused values
592
593 \param dh value
594
595 \return number of reused values
596 */
598{
599 geosurf *gs;
600 int ref, j;
601
602 G_debug(5, "gs_num_datah_reused");
603
604 /* for each attribute
605 if same, ++reference
606 */
607 /* for ea att of all surfs */
608 ref = 0;
609
610 for (gs = Surf_top; gs; gs = gs->next) {
611 for (j = 0; j < MAX_ATTS; j++) {
612 if (dh == gs->att[j].hdata) {
613 ref++;
614 }
615 }
616 }
617
618 return (ref);
619}
620
621/*!
622 \brief Get attribute type
623
624 \param gs pointer to geosurf struct
625 \param desc attribute id
626
627 \return -1 on error
628 \return attribute type
629 */
630int gs_get_att_type(geosurf *gs, int desc)
631{
632 G_debug(5, "gs_get_att_type");
633
634 if (!LEGAL_ATT(desc)) {
635 return (-1);
636 }
637
638 if (gs) {
639 if (gs->att[desc].att_src != NOTSET_ATT) {
640 return (gs->att[desc].att_type);
641 }
642 }
643
644 return (-1);
645}
646
647/*!
648 \brief Get attribute source
649
650 \param gs pointer to geosurf struct
651 \param desc attribute id (descriptor)
652
653 \return -1 on error
654 \return attribute source id
655 */
656int gs_get_att_src(geosurf *gs, int desc)
657{
658 if (gs)
659 G_debug(5, "gs_get_att_src(): id=%d, desc=%d", gs->gsurf_id, desc);
660 if (!LEGAL_ATT(desc)) {
661 return (-1);
662 }
663
664 if (gs) {
665 return (gs->att[desc].att_src);
666 }
667
668 return (-1);
669}
670
671/*!
672 \brief Get attribute data buffer
673
674 \param gs pointer to geosurf struct
675 \param desc attribute id (descriptor)
676 \param to_write non-zero value for 'write'
677
678 \return NULL on error
679 \return pointer to typbuff
680 */
681typbuff *gs_get_att_typbuff(geosurf *gs, int desc, int to_write)
682{
683 typbuff *tb;
684 geosurf *gsref;
685
686 if (gs) {
687 G_debug(5, "gs_get_att_typbuff(): id=%d desc=%d to_write=%d",
688 gs->gsurf_id, desc, to_write);
689 if ((tb = gsds_get_typbuff(gs->att[desc].hdata, to_write))) {
690 tb->tfunc = NULL;
691
692 if (desc == ATT_TOPO) {
693 gsref = gsdiff_get_SDref();
694
695 if (gsref && gsref != gs) {
696 tb->tfunc = gsdiff_do_SD;
697 }
698 }
699
700 return (tb);
701 }
702 }
703
704 return (NULL);
705}
706
707/*!
708 \brief Allocate attribute buffer
709
710 \param gs pointer to geosurf struct
711 \param desc attribute id (descriptor)
712 \param type buffer type (based on raster map type)
713
714 \return -1 on error
715 \return amount of allocated memory
716 */
717size_t gs_malloc_att_buff(geosurf *gs, int desc, int type)
718{
719 int hdata, dims[2], ndims;
720
721 G_debug(5, "gs_malloc_att_buff");
722
723 if (gs) {
724 if (0 < (hdata = gs->att[desc].hdata)) {
725 dims[0] = gs->rows;
726 dims[1] = gs->cols;
727 ndims = 2;
728 gs_set_att_type(gs, desc, type);
729
730 return (gsds_alloc_typbuff(hdata, dims, ndims, type));
731 }
732 }
733
734 return 0;
735}
736
737/*!
738 \brief Allocate attribute lookup
739
740 \param gs pointer to geosurf struct
741 \param desc attribute id
742
743 \return -1 on error
744 \return pointer to typbuff (casted)
745 */
746int gs_malloc_lookup(geosurf *gs, int desc)
747{
748 int size;
749
750 G_debug(5, "gs_malloc_lookup");
751
752 if (gs) {
753 if (gs->att[desc].lookup) {
754 G_free(gs->att[desc].lookup);
755 gs->att[desc].lookup = NULL;
756 }
757
758 switch (gs->att[desc].att_type) {
759 case (ATTY_SHORT):
760 size = 32768 * sizeof(int);
761
762 /* positive integers only, because use as array index */
763 gs->att[desc].lookup = (int *)G_malloc(size); /* G_fatal_error */
764 if (!gs->att[desc].lookup) {
765 return (-1);
766 }
767
768 break;
769 case (ATTY_CHAR):
770 size = 256 * sizeof(int);
771
772 /* unsigned char */
773 gs->att[desc].lookup = (int *)G_malloc(size);
774 if (!gs->att[desc].lookup) {
775 return (-1);
776 }
777
778 break;
779 default:
780 G_warning("bad type: gs_malloc_lookup");
781 return (-1);
782 }
783
784 if (gs->att[desc].lookup) {
785 return (0);
786 }
787 }
788
789 return (-1);
790}
791
792/*!
793 \brief Set attribute type
794
795 \param gs pointer to geosurf struct
796 \param desc attribute id
797 \param type attribute type
798
799 \return -1 on error
800 \return 0 on success
801 */
802int gs_set_att_type(geosurf *gs, int desc, int type)
803{
804
805 G_debug(5, "gs_set_att_type(): desc=%d, type=%d", desc, type);
806
807 if (gs && LEGAL_TYPE(type)) {
808 gs->att[desc].att_type = type;
809
810 return (0);
811 }
812
813 return (-1);
814}
815
816/*!
817 \brief Set attribute source
818
819 \param gs pointer to geosurf struct
820 \param desc attribute id (descriptor)
821 \param src source id
822
823 \return -1 on error
824 \return 0 on success
825 */
826int gs_set_att_src(geosurf *gs, int desc, int src)
827{
828 if (gs)
829 G_debug(5, "gs_set_att_src(): id=%d desc=%d src=%d", gs->gsurf_id, desc,
830 src);
831
832 /* check if old source was MAP_ATT, free buff */
833 if (MAP_ATT == gs_get_att_src(gs, desc)) {
834 if (1 == gs_num_datah_reused(gs->att[desc].hdata)) {
835 /* only reference */
836 G_debug(5, "gs_set_att_src(): replacing existing map");
837 gsds_free_datah(gs->att[desc].hdata);
838 }
839
840 if (ATT_TOPO == desc) {
841 if (gs->norms) {
842 G_free(gs->norms);
843 }
844
845 gs->norms = NULL;
846 gs->norm_needupdate = 0;
847 }
848 }
849
850 if (gs && LEGAL_SRC(src)) {
851 gs->att[desc].att_src = src;
852
853 return (0);
854 }
855
856 return (-1);
857}
858
859/*!
860 \brief Set attribute constant value
861
862 \todo set typbuf constant
863
864 \param gs pointer to geosurf struct
865 \param desc attribute id
866 \param constant constant value
867
868 \return 0 on success
869 \return -1 on error
870 */
871int gs_set_att_const(geosurf *gs, int desc, float constant)
872{
873
874 if (gs) {
875 G_debug(5, "gs_set_att_const(): id=%d, desc=%d, const=%f", gs->gsurf_id,
876 desc, constant);
877 gs->att[desc].constant = constant;
878
879 if (ATT_MASK == desc) {
880 gs->mask_needupdate = 1;
881 }
882 else {
883 gs_set_att_src(gs, desc, CONST_ATT);
884 }
885
886 Gs_update_attrange(gs, desc);
887
888 return (0);
889 }
890
891 return (-1);
892}
893
894/*!
895 \brief Set geosurf mask mode
896
897 \param invert invert mask
898 */
899void gs_set_maskmode(int invert)
900{
901 Invertmask = invert;
902
903 return;
904}
905
906/*!
907 \brief Check if mask is defined
908
909 \param gs pointer to geosurf struct
910
911 \return 1 if defined
912 \return 0 not defined
913 */
914int gs_mask_defined(geosurf *gs)
915{
916 return (gs->att[ATT_MASK].att_src != NOTSET_ATT);
917}
918
919/*!
920 \brief
921
922 Should only be called when setting up the current mask (gs_bm.c)
923
924 \param tb pointer to typbuff
925 \param col number of cols
926 \param row number of rows
927 \param offset offset value
928
929 \return 1
930 \return 0
931 */
932int gs_masked(typbuff *tb, int col, int row, int offset)
933{
934 int ret;
935
936 ret = 1;
937
938 if (tb->bm) {
939 ret = BM_get(tb->bm, col, row);
940 }
941 else if (tb->cb) {
942 ret = tb->cb[offset];
943 }
944 else if (tb->sb) {
945 ret = tb->sb[offset];
946 }
947 else if (tb->ib) {
948 ret = tb->ib[offset];
949 }
950 else if (tb->fb) {
951 ret = tb->fb[offset];
952 }
953
954 return (Invertmask ? ret : !ret);
955}
956
957/*!
958 \brief
959
960 Call this one when you already know att_src is MAP_ATT
961
962 \param cobuff
963 \param coloratt color attribute
964 \param offset offset value
965
966 \return packed color for category at offset
967 */
968int gs_mapcolor(typbuff *cobuff, gsurf_att *coloratt, int offset)
969{
970 if (coloratt->lookup) {
971 /* for now, but may add larger color lookup capabilities later,
972 so would have to use GET_MAPATT */
973 return (coloratt->lookup[cobuff->cb[offset]]);
974 }
975
976 return (cobuff->ib[offset]);
977}
978
979/*
980 In the following functions, "extents" refers to translated extents for
981 a single surface, while "range" refers to accumulated extents of all
982 loaded surfaces
983 */
984
985/*!
986 \brief Get z-extent values
987
988 \todo pass flag to use zminmasked instead of zmin
989
990 \param gs pointer to geosurf struct
991 \param[out] min z-min value
992 \param[out] max z-max value
993 \param[out] mid z-middle value
994
995 \return 1
996 */
997int gs_get_zextents(geosurf *gs, float *min, float *max, float *mid)
998{
999 *min = gs->zmin + gs->z_trans;
1000 *max = gs->zmax + gs->z_trans;
1001 *mid = (*max + *min) / 2.;
1002
1003 return (1);
1004}
1005
1006/*!
1007 \brief Get x-extent values
1008
1009 \param gs pointer to geosurf struct
1010 \param[out] min x-min value
1011 \param[out] max x-max value
1012
1013 \return 1
1014 */
1015int gs_get_xextents(geosurf *gs, float *min, float *max)
1016{
1017 *min = gs->xmin + gs->x_trans;
1018 *max = gs->xmax + gs->x_trans;
1019
1020 return (1);
1021}
1022
1023/*!
1024 \brief Get y-extent values
1025
1026 \param gs pointer to geosurf struct
1027 \param[out] min y-min value
1028 \param[out] max y-max value
1029
1030 \return 1
1031 */
1032int gs_get_yextents(geosurf *gs, float *min, float *max)
1033{
1034 *min = gs->ymin + gs->y_trans;
1035 *max = gs->ymax + gs->y_trans;
1036
1037 return (1);
1038}
1039
1040/*!
1041 \brief Get z-range
1042
1043 \todo pass flag to use zminmasked instead of zmin
1044 could also have this return a weighted average for vertical "centroid"
1045
1046 \param[out] min z-min value
1047 \param[out] max z-max value
1048
1049 \return -1 on error (no surface)
1050 \return 1 on success
1051 */
1052int gs_get_zrange0(float *min, float *max)
1053{
1054 geosurf *gs;
1055
1056 if (Surf_top) {
1057 *min = Surf_top->zmin;
1058 *max = Surf_top->zmax;
1059 }
1060 else {
1061 return (-1);
1062 }
1063
1064 for (gs = Surf_top->next; gs; gs = gs->next) {
1065 if (gs->zmin < *min) {
1066 *min = gs->zmin;
1067 }
1068
1069 if (gs->zmax > *max) {
1070 *max = gs->zmax;
1071 }
1072 }
1073
1074 return (1);
1075}
1076
1077/*!
1078 \brief Get z-range
1079
1080 \param[out] min z-min value
1081 \param[out] max z-max value
1082
1083 \return -1 on error (no surface)
1084 \return 1 on success
1085 */
1086int gs_get_zrange(float *min, float *max)
1087{
1088 geosurf *gs;
1089 float tmin, tmax, tmid;
1090
1091 if (Surf_top) {
1092 gs_get_zextents(Surf_top, &tmin, &tmax, &tmid);
1093 *min = tmin;
1094 *max = tmax;
1095 }
1096 else {
1097 return (-1);
1098 }
1099
1100 for (gs = Surf_top->next; gs; gs = gs->next) {
1101 gs_get_zextents(gs, &tmin, &tmax, &tmid);
1102
1103 if (tmin < *min) {
1104 *min = tmin;
1105 }
1106
1107 if (tmax > *max) {
1108 *max = tmax;
1109 }
1110 }
1111
1112 return (1);
1113}
1114
1115/*!
1116 \brief Get x-range
1117
1118 \param[out] min x-min value
1119 \param[out] max x-max value
1120
1121 \return -1 on error (no surface)
1122 \return 1 on success
1123 */
1124int gs_get_xrange(float *min, float *max)
1125{
1126 geosurf *gs;
1127 float tmin, tmax;
1128
1129 if (Surf_top) {
1130 gs_get_xextents(Surf_top, &tmin, &tmax);
1131 *min = tmin;
1132 *max = tmax;
1133 }
1134 else {
1135 return (-1);
1136 }
1137
1138 for (gs = Surf_top->next; gs; gs = gs->next) {
1139 gs_get_xextents(gs, &tmin, &tmax);
1140
1141 if (tmin < *min) {
1142 *min = tmin;
1143 }
1144
1145 if (tmax > *max) {
1146 *max = tmax;
1147 }
1148 }
1149
1150 return (1);
1151}
1152
1153/*!
1154 \brief Get y-range
1155
1156 \param[out] min y-min value
1157 \param[out] max y-max value
1158
1159 \return -1 on error (no surface)
1160 \return 1 on success
1161 */
1162int gs_get_yrange(float *min, float *max)
1163{
1164 geosurf *gs;
1165 float tmin, tmax;
1166
1167 if (Surf_top) {
1168 gs_get_yextents(Surf_top, &tmin, &tmax);
1169 *min = tmin;
1170 *max = tmax;
1171 }
1172 else {
1173 return (-1);
1174 }
1175
1176 for (gs = Surf_top->next; gs; gs = gs->next) {
1177 gs_get_yextents(gs, &tmin, &tmax);
1178
1179 if (tmin < *min) {
1180 *min = tmin;
1181 }
1182
1183 if (tmax > *max) {
1184 *max = tmax;
1185 }
1186 }
1187
1188 return (1);
1189}
1190
1191/*!
1192 \brief Get average z-max value
1193
1194 Useful for setting position of cplane, lighting ball, etc.
1195
1196 \param[out] azmax average z-max value
1197
1198 \return -1 on error
1199 \return 1 on success
1200 */
1201int gs_get_data_avg_zmax(float *azmax)
1202{
1203 float zmax;
1204 int i;
1205 geosurf *gs;
1206
1207 zmax = *azmax = 0.0;
1208
1209 if (Surf_top) {
1210 for (i = 0, gs = Surf_top; gs; i++, gs = gs->next) {
1211 zmax += (gs->zmax + gs->z_trans);
1212 }
1213
1214 *azmax = zmax / i;
1215
1216 return (1);
1217 }
1218
1219 return (-1);
1220}
1221
1222/*!
1223 \brief Get data center point
1224
1225 \param[out] center (array X,Y,Z)
1226
1227 \return -1 on error
1228 \return 1 on success
1229 */
1230int gs_get_datacenter(float *cen)
1231{
1232 float zmin, zmax, ymin, ymax, xmin, xmax;
1233 geosurf *gs;
1234
1235 if (Surf_top) {
1236 zmin = Surf_top->zmin;
1237 zmax = Surf_top->zmax;
1238 ymin = Surf_top->ymin;
1239 ymax = Surf_top->ymax;
1240 xmin = Surf_top->xmin;
1241 xmax = Surf_top->xmax;
1242
1243 for (gs = Surf_top->next; gs; gs = gs->next) {
1244 if (gs->zmin < zmin) {
1245 zmin = gs->zmin;
1246 }
1247
1248 if (gs->zmax > zmax) {
1249 zmax = gs->zmax;
1250 }
1251
1252 if (gs->ymin < ymin) {
1253 ymin = gs->ymin;
1254 }
1255
1256 if (gs->ymax > ymax) {
1257 ymax = gs->ymax;
1258 }
1259
1260 if (gs->xmin < xmin) {
1261 xmin = gs->xmin;
1262 }
1263
1264 if (gs->xmax > xmax) {
1265 xmax = gs->xmax;
1266 }
1267 }
1268
1269 cen[X] = (xmin + xmax) / 2. - xmin;
1270 cen[Y] = (ymin + ymax) / 2. - ymin;
1271 cen[Z] = (zmin + zmax) / 2.;
1272
1273 return (1);
1274 }
1275
1276 cen[X] = cen[Y] = cen[Z] = 0.0;
1277
1278 return (-1);
1279}
1280
1281/*!
1282 \brief Set for geosurf need-to-update mark
1283
1284 \return -1 no surface available
1285 \return 1 on success
1286 */
1288{
1289 geosurf *gs;
1290
1291 if (Surf_top) {
1292 Surf_top->norm_needupdate = 1;
1293 }
1294 else {
1295 return (-1);
1296 }
1297
1298 for (gs = Surf_top->next; gs; gs = gs->next) {
1299 gs->norm_needupdate = 1;
1300 }
1301
1302 return (1);
1303}
1304
1305/*!
1306 \brief Check if point is masked
1307
1308 \param gs pointer to geosurf struct
1309 \param pt point coordinates (X,Y,Z)
1310
1311 \return 1 masked
1312 \return 0 not masked
1313 */
1314int gs_point_is_masked(geosurf *gs, float *pt)
1315{
1316 int vrow, vcol, drow, dcol;
1317 int retmask = 0, npts = 0;
1318 float p2[2];
1319
1320 if (!gs->curmask) {
1321 return (0);
1322 }
1323
1324 vrow = Y2VROW(gs, pt[Y]);
1325 vcol = X2VCOL(gs, pt[X]);
1326
1327 /* check right & bottom edges */
1328 if (pt[X] == VCOL2X(gs, VCOLS(gs))) {
1329 /* right edge */
1330 vcol -= 1;
1331 }
1332
1333 if (pt[Y] == VROW2Y(gs, VROWS(gs))) {
1334 /* bottom edge */
1335 vrow -= 1;
1336 }
1337
1338 drow = VROW2DROW(gs, vrow);
1339 dcol = VCOL2DCOL(gs, vcol);
1340
1341 if (BM_get(gs->curmask, dcol, drow)) {
1342 retmask |= MASK_TL;
1343 npts++;
1344 }
1345
1346 dcol = VCOL2DCOL(gs, vcol + 1);
1347
1348 if (BM_get(gs->curmask, dcol, drow)) {
1349 retmask |= MASK_TR;
1350 npts++;
1351 }
1352
1353 drow = VROW2DROW(gs, vrow + 1);
1354
1355 if (BM_get(gs->curmask, dcol, drow)) {
1356 retmask |= MASK_BR;
1357 npts++;
1358 }
1359
1360 dcol = VCOL2DCOL(gs, vcol);
1361
1362 if (BM_get(gs->curmask, dcol, drow)) {
1363 retmask |= MASK_BL;
1364 npts++;
1365 }
1366
1367 if (npts != 1) {
1368 /* zero or masked */
1369 return (retmask | npts);
1370 }
1371
1372 p2[X] = VCOL2X(gs, vcol);
1373 p2[Y] = VROW2Y(gs, vrow + 1);
1374
1375 switch (retmask) {
1376 case MASK_TL:
1377 if ((pt[X] - p2[X]) / VXRES(gs) > (pt[Y] - p2[Y]) / VYRES(gs)) {
1378 /* lower triangle */
1379 return (0);
1380 }
1381
1382 return (retmask | npts);
1383 case MASK_TR:
1384
1385 return (retmask | npts);
1386 case MASK_BR:
1387 if ((pt[X] - p2[X]) / VXRES(gs) <= (pt[Y] - p2[Y]) / VYRES(gs)) {
1388 /* upper triangle */
1389 return (0);
1390 }
1391
1392 return (retmask | npts);
1393 case MASK_BL:
1394
1395 return (retmask | npts);
1396 }
1397
1398 /* Assume that if we get here it is an error */
1399 return (0);
1400}
1401
1402/*!
1403 \brief Calculate distance on surface
1404
1405 \param gs pointer to geosurf struct
1406 \param p1 from point
1407 \param p2 to point
1408 \param[out] dist distance
1409 \param use_exag use exag for calculation
1410
1411 \return 0 on error (points not in region)
1412 \return 1 on success
1413 */
1414int gs_distance_onsurf(geosurf *gs, float *p1, float *p2, float *dist,
1415 int use_exag)
1416{
1417 Point3 *tmp;
1418 int np, i;
1419 float exag, length;
1420
1421 if (in_vregion(gs, p1) && in_vregion(gs, p2)) {
1422 if (NULL == (tmp = gsdrape_get_segments(gs, p1, p2, &np))) {
1423 return (0);
1424 }
1425
1426 length = 0.;
1427
1428 if (use_exag) {
1429 exag = GS_global_exag();
1430 tmp[0][Z] *= exag;
1431
1432 for (i = 0; i < (np - 1); i++) {
1433 tmp[i + 1][Z] *= exag;
1434 length += GS_distance(tmp[i], tmp[i + 1]);
1435 }
1436 }
1437 else {
1438 for (i = 0; i < (np - 1); i++) {
1439 length += GS_distance(tmp[i], tmp[i + 1]);
1440 }
1441 }
1442
1443 *dist = length;
1444
1445 return (1);
1446 }
1447
1448 return (0);
1449}
void G_free(void *buf)
Free allocated memory.
Definition alloc.c:150
int BM_get(struct BM *map, int x, int y)
Gets 'val' from the bitmap.
Definition bitmap.c:217
#define NULL
Definition ccmath.h:32
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition debug.c:66
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition gis/error.c:203
float GS_global_exag(void)
Get global z-exag value.
Definition gs2.c:1997
int Gs_update_attrange(geosurf *gs, int desc)
Update no_zero ranges for attribute (actually no_null now)
Definition gs3.c:1078
int gs_get_xextents(geosurf *gs, float *min, float *max)
Get x-extent values.
Definition gs.c:1015
int gs_masked(typbuff *tb, int col, int row, int offset)
Should only be called when setting up the current mask (gs_bm.c)
Definition gs.c:932
void print_view_fields(geoview *gv)
Debugging, print geoview fields to stderr.
Definition gs.c:419
int gs_get_datacenter(float *cen)
Get data center point.
Definition gs.c:1230
int gs_get_zextents(geosurf *gs, float *min, float *max, float *mid)
Get z-extent values.
Definition gs.c:997
int gs_get_zrange(float *min, float *max)
Get z-range.
Definition gs.c:1086
size_t gs_malloc_att_buff(geosurf *gs, int desc, int type)
Allocate attribute buffer.
Definition gs.c:717
int gs_set_att_src(geosurf *gs, int desc, int src)
Set attribute source.
Definition gs.c:826
int gs_get_yextents(geosurf *gs, float *min, float *max)
Get y-extent values.
Definition gs.c:1032
int gs_mapcolor(typbuff *cobuff, gsurf_att *coloratt, int offset)
Call this one when you already know att_src is MAP_ATT.
Definition gs.c:968
void gs_free_unshared_buffs(geosurf *fs)
Free unshared buffers of geosurf struct.
Definition gs.c:557
void gs_err(const char *msg)
Definition gs.c:35
int gs_get_xrange(float *min, float *max)
Get x-range.
Definition gs.c:1124
geosurf * gs_get_surf(int id)
Get geosurf struct.
Definition gs.c:63
geosurf * gs_get_last_surface(void)
Get last allocated geosurf struct from list.
Definition gs.c:173
int gs_set_att_const(geosurf *gs, int desc, float constant)
Set attribute constant value.
Definition gs.c:871
int gs_malloc_lookup(geosurf *gs, int desc)
Allocate attribute lookup.
Definition gs.c:746
int gs_get_yrange(float *min, float *max)
Get y-range.
Definition gs.c:1162
void gs_delete_surf(int id)
Remove geosurf struct from list.
Definition gs.c:463
int gs_set_att_type(geosurf *gs, int desc, int type)
Set attribute type.
Definition gs.c:802
void print_surf_fields(geosurf *s)
Debugging, print geosurf fields to stderr.
Definition gs.c:393
int gs_getall_surfaces(geosurf **gsurfs)
Get array of geosurf structs.
Definition gs.c:109
int gs_setall_norm_needupdate(void)
Set for geosurf need-to-update mark.
Definition gs.c:1287
void print_256lookup(int *buff)
Debugging, 256 integer values from buffer.
Definition gs.c:369
int gs_init_surf(geosurf *gs, double ox, double oy, int rows, int cols, double xres, double yres)
Initialize allocated geosurf struct.
Definition gs.c:234
#define FIRST_SURF_ID
Definition gs.c:29
void gs_init(void)
Initialize library.
Definition gs.c:48
void gs_set_maskmode(int invert)
Set geosurf mask mode.
Definition gs.c:899
geosurf * gs_get_new_surface(void)
Allocate new geosurf struct.
Definition gs.c:194
int gs_free_surf(geosurf *fs)
Free geosurf struct.
Definition gs.c:487
int gs_get_att_type(geosurf *gs, int desc)
Get attribute type.
Definition gs.c:630
int gs_distance_onsurf(geosurf *gs, float *p1, float *p2, float *dist, int use_exag)
Calculate distance on surface.
Definition gs.c:1414
geosurf * gs_get_prev_surface(int id)
Get previous geosurf struct.
Definition gs.c:87
int gs_num_surfaces(void)
Get number of surfaces.
Definition gs.c:128
int gs_init_normbuff(geosurf *gs)
Init geosurf normbuff.
Definition gs.c:308
typbuff * gs_get_att_typbuff(geosurf *gs, int desc, int to_write)
Get attribute data buffer.
Definition gs.c:681
int gs_num_datah_reused(int dh)
Get number of reused values.
Definition gs.c:597
void print_frto(float(*ft)[4])
Debugging, print 'from/to' model coordinates to stderr.
Definition gs.c:339
int gs_mask_defined(geosurf *gs)
Check if mask is defined.
Definition gs.c:914
int gs_get_zrange0(float *min, float *max)
Get z-range.
Definition gs.c:1052
int gs_point_is_masked(geosurf *gs, float *pt)
Check if point is masked.
Definition gs.c:1314
int gs_get_data_avg_zmax(float *azmax)
Get average z-max value.
Definition gs.c:1201
int gs_att_is_set(geosurf *surf, IFLAG att)
Check if attribute is set.
Definition gs.c:150
int gs_get_att_src(geosurf *gs, int desc)
Get attribute source.
Definition gs.c:656
void gs_set_defaults(geosurf *gs, float *defs, float *null_defs)
Set default attribute values.
Definition gs.c:441
void print_realto(float *rt)
Debugging, print 'to' real coordinates to stderr.
Definition gs.c:355
float GS_distance(float *from, float *to)
Calculate distance.
Definition gs_util.c:141
float gsdiff_do_SD(float val, int offset)
ADD.
Definition gsdiff.c:94
geosurf * gsdiff_get_SDref(void)
ADD.
Definition gsdiff.c:77
Point3 * gsdrape_get_segments(geosurf *gs, float *bgn, float *end, int *num)
ADD.
Definition gsdrape.c:349
int in_vregion(geosurf *gs, float *pt)
ADD.
Definition gsdrape.c:691
typbuff * gsds_get_typbuff(int id, IFLAG change_flag)
Get data buffer.
Definition gsds.c:281
int gsds_free_datah(int id)
Free allocated dataset.
Definition gsds.c:329
size_t gsds_alloc_typbuff(int id, int *dims, int ndims, int type)
Allocates correct buffer according to type, keeps track of total mem.
Definition gsds.c:480
#define min(a, b)
#define max(a, b)
struct ps_state ps
#define VYRES(gs)
Definition rowcol.h:10
#define Y2VROW(gs, py)
Definition rowcol.h:27
#define VXRES(gs)
Definition rowcol.h:9
#define VCOL2X(gs, vcol)
Definition rowcol.h:40
#define VCOLS(gs)
Definition rowcol.h:14
#define VROWS(gs)
Definition rowcol.h:13
#define VROW2Y(gs, vrow)
Definition rowcol.h:39
#define VROW2DROW(gs, vrow)
Definition rowcol.h:31
#define X2VCOL(gs, px)
Definition rowcol.h:28
#define VCOL2DCOL(gs, vcol)
Definition rowcol.h:32
#define X(j)
#define Y(j)