GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
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 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 USACERL, GMSL/University of Illinois (January 1993)
16  \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
17  */
18 
19 #include <stdlib.h>
20 #include <stdio.h>
21 
22 #include <grass/ogsf.h>
23 #include <grass/glocale.h>
24 
25 #include "gsget.h"
26 #include "rowcol.h"
27 
28 #define FIRST_SURF_ID 110658
29 
30 static geosurf *Surf_top;
31 static int Invertmask;
32 
33 /***********************************************************************/
34 void gs_err(const char *msg)
35 {
36  G_warning("%s", msg);
37 
38  return;
39 }
40 
41 /*!
42  \brief Initialize library
43 
44  Still need to take care of library initialization,
45  probably want to define a Surf_top of constant value (i.e., 0)
46  */
47 void gs_init(void)
48 {
49  Surf_top = NULL;
50 
51  return;
52 }
53 
54 /*!
55  \brief Get geosurf struct
56 
57  \param id surface id
58 
59  \return pointer to geosurf struct
60  \return NULL if not found
61  */
63 {
64  geosurf *gs;
65 
66  G_debug(5, "gs_get_surf():");
67 
68  for (gs = Surf_top; gs; gs = gs->next) {
69  if (gs->gsurf_id == id) {
70  G_debug(5, " id=%d", id);
71  return (gs);
72  }
73  }
74 
75  return (NULL);
76 }
77 
78 /*!
79  \brief Get previous geosurf struct
80 
81  \param id current surface id
82 
83  \return pointer to geosurf struct
84  \return NULL if not found
85  */
87 {
88  geosurf *ps;
89 
90  G_debug(5, "gs_get_prev_surface");
91 
92  for (ps = Surf_top; ps; ps = ps->next) {
93  if (ps->gsurf_id == id - 1) {
94  return (ps);
95  }
96  }
97 
98  return (NULL);
99 }
100 
101 /*!
102  \brief Get array of geosurf structs
103 
104  \param gsurfs pointer to array
105 
106  \return number of geosurfs
107  */
109 {
110  geosurf *gs;
111  int i;
112 
113  for (i = 0, gs = Surf_top; gs; gs = gs->next, i++) {
114  gsurfs[i] = gs;
115  }
116 
117  G_debug(5, "gs_num_surfaces(): num=%d", i);
118 
119  return (i);
120 }
121 
122 /*!
123  \brief Get number of surfaces
124 
125  \return number of surfaces
126  */
128 {
129  geosurf *gs;
130  int i;
131 
132  for (i = 0, gs = Surf_top; gs; gs = gs->next, i++) ;
133 
134  G_debug(5, "gs_num_surfaces(): num=%d", i);
135 
136  return (i);
137 }
138 
139 
140 /*!
141  \brief Check if attribute is set
142 
143  \param surf pointer to gsurf or NULL to look at all geosurfs
144  \param att attribute id
145 
146  \return 1 attribute is set up
147  \return 0 attribute is not set up
148  */
149 int gs_att_is_set(geosurf * surf, IFLAG att)
150 {
151  geosurf *gs;
152 
153  if (surf) {
154  return (NOTSET_ATT != surf->att[att].att_src);
155  }
156 
157  /* if surf == NULL, look at all surfs */
158  for (gs = Surf_top; gs; gs = gs->next) {
159  if (NOTSET_ATT != gs->att[att].att_src) {
160  return (1);
161  }
162  }
163 
164  return (0);
165 }
166 
167 /*!
168  \brief Get last allocated geosurf struct from list
169 
170  \return pointer to geosurf struct
171  */
173 {
174  geosurf *ls;
175 
176  if (!Surf_top) {
177  return (NULL);
178  }
179 
180  for (ls = Surf_top; ls->next; ls = ls->next) ;
181 
182  G_debug(5, "gs_get_last_surface(): last surface id=%d", ls->gsurf_id);
183 
184  return (ls);
185 }
186 
187 
188 /*!
189  \brief Allocate new geosurf struct
190 
191  \return pointer to geosurf struct
192  */
194 {
195  geosurf *ns, *ls;
196 
197  ns = (geosurf *) G_malloc(sizeof(geosurf)); /* G_fatal_error */
198  if (!ns) {
199  return (NULL);
200  }
201 
202  if ((ls = gs_get_last_surface())) {
203  ls->next = ns;
204  ns->gsurf_id = ls->gsurf_id + 1;
205  }
206  else {
207  Surf_top = ns;
208  ns->gsurf_id = FIRST_SURF_ID;
209  }
210 
211  ns->next = NULL;
212 
213  G_debug(5, "gs_get_new_surface(): id=%d", ns->gsurf_id);
214 
215  return (ns);
216 }
217 
218 /*!
219  \brief Initialize allocated geosurf struct
220 
221  \todo Now xmin & ox are the same, right? - get rid of ox, oy in geosurf struct?
222 
223  \param gs pointer to geosurf struct
224  \param ox,oy x/y origin coordinates
225  \param rows number of rows
226  \param cols number of cols
227  \param xres,yres x/y resolution value
228 
229  \return -1 on error
230  \return 0 on success
231  */
232 int gs_init_surf(geosurf * gs, double ox, double oy, int rows, int cols,
233  double xres, double yres)
234 {
235  geosurf *ps;
236  int i;
237 
238  if (!gs) {
239  return (-1);
240  }
241 
242  G_debug(5, "gs_init_surf() id=%d", gs->gsurf_id);
243 
244  /* default attributes */
245  for (i = 0; i < MAX_ATTS; i++) {
246  gs->att[i].att_src = NOTSET_ATT;
247  gs->att[i].att_type = ATTY_INT;
248  gs->att[i].hdata = -1;
249  gs->att[i].user_func = NULL;
250  gs->att[i].constant = 0.;
251  gs->att[i].lookup = NULL;
252  gs->att[i].min_nz = gs->att[i].max_nz = gs->att[i].range_nz = 0;
253  gs->att[i].default_null = 0.;
254  }
255 
256  /* default values */
257  gs->ox = ox;
258  gs->oy = oy;
259  gs->rows = rows;
260  gs->cols = cols;
261  gs->xres = xres;
262  gs->yres = yres;
263  gs->x_mod = 2;
264  gs->y_mod = 2;
265  gs->x_modw = rows / 30;
266  gs->y_modw = rows / 30;
267  gs->xmin = ox;
268  gs->xmax = ox + (cols - 1) * xres;
269  gs->xrange = gs->xmax - gs->xmin;
270  gs->ymin = oy;
271  gs->ymax = oy + (rows - 1) * yres;
272  gs->yrange = gs->ymax - gs->ymin;
273  gs->zmin = gs->zmin_nz = gs->zminmasked = 0;
274  gs->zmax = gs->zmax_nz = 0;
275  gs->zrange = gs->zrange_nz = 0;
276  gs->wire_color = 0x00888888;
277  gs->x_trans = gs->y_trans = gs->z_trans = 0.0;
278  gs->nz_topo = gs->nz_color = 0;
279  gs->norm_needupdate = 1;
280  gs->mask_needupdate = 1;
281  gs->curmask = NULL;
282  gs->norms = NULL;
283 
284  gs->draw_mode = DM_GOURAUD;
285 
286  /* default z_exag value */
287  if (gs->gsurf_id == FIRST_SURF_ID) {
288  gs->z_exag = 1.0;
289  }
290  else {
291  ps = gs_get_prev_surface(gs->gsurf_id);
292  gs->z_exag = ps->z_exag;
293  }
294 
295  return (0);
296 }
297 
298 /*!
299  \brief Init geosurf normbuff
300 
301  \param gs pointer to geosurf struct
302 
303  \return 0 on error
304  \return 1 on success
305  */
307 {
308  long size;
309 
310  if (!gs) {
311  return (0);
312  }
313 
314  if (gs->norms) {
315  G_free(gs->norms);
316  }
317 
318  size = gs->rows * gs->cols * sizeof(unsigned long);
319 
320  gs->norms = (unsigned long *)G_malloc(size); /* G_fatal_error */
321  if (!gs->norms) {
322  return (-1);
323  }
324 
325  gs->norm_needupdate = 1;
326 
327  return (1);
328 }
329 
330 /*!
331  \brief Debugging, print 'from/to' model coordinates to stderr
332 
333  \todo G_debug ?
334 
335  \param ft pointer to coordinates
336  */
337 void print_frto(float (*ft)[4])
338 {
339  fprintf(stderr, "FROM: %f, %f, %f\n", ft[FROM][X], ft[FROM][Y],
340  ft[FROM][Z]);
341  fprintf(stderr, "TO: %f, %f, %f\n", ft[TO][X], ft[TO][Y], ft[TO][Z]);
342 
343  return;
344 }
345 
346 /*!
347  \brief Debugging, print 'to' real coordinates to stderr
348 
349  \todo G_debug ?
350 
351  \param ft pointer to coordinates
352  */
353 void print_realto(float *rt)
354 {
355  fprintf(stderr, "REAL TO: %f, %f, %f\n", rt[X], rt[Y], rt[Z]);
356 
357  return;
358 }
359 
360 /*!
361  \brief Debugging, 256 integer values from buffer
362 
363  \todo G_debug ?
364 
365  \param ft pointer to buffer
366  */
367 void print_256lookup(int *buff)
368 {
369  int i;
370 
371  for (i = 0; i < 256; i++) {
372  if (!(i % 8)) {
373  fprintf(stderr, "\n");
374  }
375 
376  fprintf(stderr, "%x ", buff[i]);
377  }
378 
379  fprintf(stderr, "\n");
380 
381  return;
382 }
383 
384 /*!
385  \brief Debugging, print geosurf fields to stderr
386 
387  \todo G_debug ?
388 
389  \param s pointer to geosurf struct
390  */
392 {
393  fprintf(stderr, "ID: %d\n", s->gsurf_id);
394  fprintf(stderr, "rows: %d cols: %d\n", s->rows, s->cols);
395  fprintf(stderr, "draw_mode: %x\n", s->draw_mode);
396  fprintf(stderr, "wire_color: %lx\n", s->wire_color);
397  fprintf(stderr, "ox: %lf oy: %lf\n", s->ox, s->oy);
398  fprintf(stderr, "xres: %lf yres: %lf\n", s->xres, s->yres);
399  fprintf(stderr, "z_exag: %f \n", s->z_exag);
400  fprintf(stderr, "x_trans: %f y_trans: %f z_trans: %f\n",
401  s->x_trans, s->y_trans, s->z_trans);
402  fprintf(stderr, "xmin: %f ymin: %f zmin: %f\n",
403  s->xmin, s->ymin, s->zmin);
404  fprintf(stderr, "xmax: %f ymax: %f zmax: %f\n",
405  s->xmax, s->ymax, s->zmax);
406  fprintf(stderr, "x_mod: %d y_mod: %d x_modw: %d y_modw: %d\n",
407  s->x_mod, 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  */
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",
428  gv->real_to[X], gv->real_to[Y], 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  */
441 void 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  */
463 void 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  */
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 datsets work
554 
555  \param fs pointer to geosurf struct
556  */
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  */
630 int 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  */
656 int 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  */
681 typbuff *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  */
717 size_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  */
746 int 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 
790  return (-1);
791 }
792 
793 /*!
794  \brief Set attribute type
795 
796  \param gs pointer to geosurf struct
797  \param desc attribute id
798  \param type attribute type
799 
800  \return -1 on error
801  \return 0 on success
802  */
803 int gs_set_att_type(geosurf * gs, int desc, int type)
804 {
805 
806  G_debug(5, "gs_set_att_type(): desc=%d, type=%d", desc, type);
807 
808  if (gs && LEGAL_TYPE(type)) {
809  gs->att[desc].att_type = type;
810 
811  return (0);
812  }
813 
814  return (-1);
815 }
816 
817 /*!
818  \brief Set attribute source
819 
820  \param gs pointer to geosurf struct
821  \param desc attribute id (descriptor)
822  \param src source id
823 
824  \return -1 on error
825  \return 0 on success
826  */
827 int gs_set_att_src(geosurf * gs, int desc, int src)
828 {
829  if (gs)
830  G_debug(5, "gs_set_att_src(): id=%d desc=%d src=%d",
831  gs->gsurf_id, desc, src);
832 
833  /* check if old source was MAP_ATT, free buff */
834  if (MAP_ATT == gs_get_att_src(gs, desc)) {
835  if (1 == gs_num_datah_reused(gs->att[desc].hdata)) {
836  /* only reference */
837  G_debug(5, "gs_set_att_src(): replacing existing map");
838  gsds_free_datah(gs->att[desc].hdata);
839  }
840 
841  if (ATT_TOPO == desc) {
842  if (gs->norms) {
843  G_free(gs->norms);
844  }
845 
846  gs->norms = NULL;
847  gs->norm_needupdate = 0;
848  }
849  }
850 
851  if (gs && LEGAL_SRC(src)) {
852  gs->att[desc].att_src = src;
853 
854  return (0);
855  }
856 
857  return (-1);
858 }
859 
860 /*!
861  \brief Set attribute constant value
862 
863  \todo set typbuf constant
864 
865  \param gs pointer to geosurf struct
866  \param desc attribute id
867  \param constant constant value
868 
869  \return 0 on success
870  \return -1 on error
871  */
872 int gs_set_att_const(geosurf * gs, int desc, float constant)
873 {
874 
875  if (gs) {
876  G_debug(5, "gs_set_att_const(): id=%d, desc=%d, const=%f",
877  gs->gsurf_id, desc, constant);
878  gs->att[desc].constant = constant;
879 
880  if (ATT_MASK == desc) {
881  gs->mask_needupdate = 1;
882  }
883  else {
884  gs_set_att_src(gs, desc, CONST_ATT);
885  }
886 
887  Gs_update_attrange(gs, desc);
888 
889  return (0);
890  }
891 
892  return (-1);
893 }
894 
895 /*!
896  \brief Set geosurf mask mode
897 
898  \param invert invert mask
899  */
900 void gs_set_maskmode(int invert)
901 {
902  Invertmask = invert;
903 
904  return;
905 }
906 
907 /*!
908  \brief Check if mask is defined
909 
910  \param gs pointer to geosurf struct
911 
912  \return 1 if defined
913  \return 0 not defined
914  */
916 {
917  return (gs->att[ATT_MASK].att_src != NOTSET_ATT);
918 }
919 
920 /*!
921  \brief
922 
923  Should only be called when setting up the current mask (gs_bm.c)
924 
925  \param tb pointer to typbuff
926  \param col number of cols
927  \param row number of rows
928  \param offset offset value
929 
930  \return 1
931  \return 0
932  */
933 int gs_masked(typbuff * tb, int col, int row, int offset)
934 {
935  int ret;
936 
937  ret = 1;
938 
939  if (tb->bm) {
940  ret = BM_get(tb->bm, col, row);
941  }
942  else if (tb->cb) {
943  ret = tb->cb[offset];
944  }
945  else if (tb->sb) {
946  ret = tb->sb[offset];
947  }
948  else if (tb->ib) {
949  ret = tb->ib[offset];
950  }
951  else if (tb->fb) {
952  ret = tb->fb[offset];
953  }
954 
955  return (Invertmask ? ret : !ret);
956 }
957 
958 /*!
959  \brief
960 
961  Call this one when you already know att_src is MAP_ATT
962 
963  \param cobuff
964  \param coloratt color attribute
965  \param offset offset value
966 
967  \return packed color for category at offset
968  */
969 int gs_mapcolor(typbuff * cobuff, gsurf_att * coloratt, int offset)
970 {
971  if (coloratt->lookup) {
972  /* for now, but may add larger color lookup capabilities later,
973  so would have to use GET_MAPATT */
974  return (coloratt->lookup[cobuff->cb[offset]]);
975  }
976 
977  return (cobuff->ib[offset]);
978 }
979 
980 /*
981  In the following functions, "extents" refers to translated extents for
982  a single surface, while "range" refers to accumulated extents of all
983  loaded surfaces
984  */
985 
986 /*!
987  \brief Get z-extent values
988 
989  \todo pass flag to use zminmasked instead of zmin
990 
991  \param gs pointer to geosurf struct
992  \param[out] min z-min value
993  \param[out] max z-max value
994  \param[out] mid z-middle value
995 
996  \return 1
997  */
998 int gs_get_zextents(geosurf * gs, float *min, float *max, float *mid)
999 {
1000  *min = gs->zmin + gs->z_trans;
1001  *max = gs->zmax + gs->z_trans;
1002  *mid = (*max + *min) / 2.;
1003 
1004  return (1);
1005 }
1006 
1007 /*!
1008  \brief Get x-extent values
1009 
1010  \param gs pointer to geosurf struct
1011  \param[out] min x-min value
1012  \param[out] max x-max value
1013 
1014  \return 1
1015  */
1016 int gs_get_xextents(geosurf * gs, float *min, float *max)
1017 {
1018  *min = gs->xmin + gs->x_trans;
1019  *max = gs->xmax + gs->x_trans;
1020 
1021  return (1);
1022 }
1023 
1024 /*!
1025  \brief Get y-extent values
1026 
1027  \param gs pointer to geosurf struct
1028  \param[out] min y-min value
1029  \param[out] max y-max value
1030 
1031  \return 1
1032  */
1033 int gs_get_yextents(geosurf * gs, float *min, float *max)
1034 {
1035  *min = gs->ymin + gs->y_trans;
1036  *max = gs->ymax + gs->y_trans;
1037 
1038  return (1);
1039 }
1040 
1041 
1042 /*!
1043  \brief Get z-range
1044 
1045  \todo pass flag to use zminmasked instead of zmin
1046  could also have this return a weighted average for vertical "centroid"
1047 
1048  \param[out] min z-min value
1049  \param[out] max z-max value
1050 
1051  \return -1 on error (no surface)
1052  \return 1 on success
1053  */
1054 int gs_get_zrange0(float *min, float *max)
1055 {
1056  geosurf *gs;
1057 
1058  if (Surf_top) {
1059  *min = Surf_top->zmin;
1060  *max = Surf_top->zmax;
1061  }
1062  else {
1063  return (-1);
1064  }
1065 
1066  for (gs = Surf_top->next; gs; gs = gs->next) {
1067  if (gs->zmin < *min) {
1068  *min = gs->zmin;
1069  }
1070 
1071  if (gs->zmax > *max) {
1072  *max = gs->zmax;
1073  }
1074  }
1075 
1076  return (1);
1077 }
1078 
1079 /*!
1080  \brief Get z-range
1081 
1082  \param[out] min z-min value
1083  \param[out] max z-max value
1084 
1085  \return -1 on error (no surface)
1086  \return 1 on success
1087  */
1088 int gs_get_zrange(float *min, float *max)
1089 {
1090  geosurf *gs;
1091  float tmin, tmax, tmid;
1092 
1093  if (Surf_top) {
1094  gs_get_zextents(Surf_top, &tmin, &tmax, &tmid);
1095  *min = tmin;
1096  *max = tmax;
1097  }
1098  else {
1099  return (-1);
1100  }
1101 
1102  for (gs = Surf_top->next; gs; gs = gs->next) {
1103  gs_get_zextents(gs, &tmin, &tmax, &tmid);
1104 
1105  if (tmin < *min) {
1106  *min = tmin;
1107  }
1108 
1109  if (tmax > *max) {
1110  *max = tmax;
1111  }
1112  }
1113 
1114  return (1);
1115 }
1116 
1117 /*!
1118  \brief Get x-range
1119 
1120  \param[out] min x-min value
1121  \param[out] max x-max value
1122 
1123  \return -1 on error (no surface)
1124  \return 1 on success
1125  */
1126 int gs_get_xrange(float *min, float *max)
1127 {
1128  geosurf *gs;
1129  float tmin, tmax;
1130 
1131  if (Surf_top) {
1132  gs_get_xextents(Surf_top, &tmin, &tmax);
1133  *min = tmin;
1134  *max = tmax;
1135  }
1136  else {
1137  return (-1);
1138  }
1139 
1140  for (gs = Surf_top->next; gs; gs = gs->next) {
1141  gs_get_xextents(gs, &tmin, &tmax);
1142 
1143  if (tmin < *min) {
1144  *min = tmin;
1145  }
1146 
1147  if (tmax > *max) {
1148  *max = tmax;
1149  }
1150  }
1151 
1152  return (1);
1153 }
1154 
1155 /*!
1156  \brief Get y-range
1157 
1158  \param[out] min y-min value
1159  \param[out] max y-max value
1160 
1161  \return -1 on error (no surface)
1162  \return 1 on success
1163  */
1164 int gs_get_yrange(float *min, float *max)
1165 {
1166  geosurf *gs;
1167  float tmin, tmax;
1168 
1169  if (Surf_top) {
1170  gs_get_yextents(Surf_top, &tmin, &tmax);
1171  *min = tmin;
1172  *max = tmax;
1173  }
1174  else {
1175  return (-1);
1176  }
1177 
1178  for (gs = Surf_top->next; gs; gs = gs->next) {
1179  gs_get_yextents(gs, &tmin, &tmax);
1180 
1181  if (tmin < *min) {
1182  *min = tmin;
1183  }
1184 
1185  if (tmax > *max) {
1186  *max = tmax;
1187  }
1188  }
1189 
1190  return (1);
1191 }
1192 
1193 /*!
1194  \brief Get average z-max value
1195 
1196  Useful for setting position of cplane, lighting ball, etc.
1197 
1198  \param[out] azmax average z-max value
1199 
1200  \return -1 on error
1201  \return 1 on success
1202  */
1203 int gs_get_data_avg_zmax(float *azmax)
1204 {
1205  float zmax;
1206  int i;
1207  geosurf *gs;
1208 
1209  zmax = *azmax = 0.0;
1210 
1211  if (Surf_top) {
1212  for (i = 0, gs = Surf_top; gs; i++, gs = gs->next) {
1213  zmax += (gs->zmax + gs->z_trans);
1214  }
1215 
1216  *azmax = zmax / i;
1217 
1218  return (1);
1219  }
1220 
1221  return (-1);
1222 }
1223 
1224 /*!
1225  \brief Get data center point
1226 
1227  \param[out] center (array X,Y,Z)
1228 
1229  \return -1 on error
1230  \return 1 on success
1231  */
1232 int gs_get_datacenter(float *cen)
1233 {
1234  float zmin, zmax, ymin, ymax, xmin, xmax;
1235  geosurf *gs;
1236 
1237  if (Surf_top) {
1238  zmin = Surf_top->zmin;
1239  zmax = Surf_top->zmax;
1240  ymin = Surf_top->ymin;
1241  ymax = Surf_top->ymax;
1242  xmin = Surf_top->xmin;
1243  xmax = Surf_top->xmax;
1244 
1245  for (gs = Surf_top->next; gs; gs = gs->next) {
1246  if (gs->zmin < zmin) {
1247  zmin = gs->zmin;
1248  }
1249 
1250  if (gs->zmax > zmax) {
1251  zmax = gs->zmax;
1252  }
1253 
1254  if (gs->ymin < ymin) {
1255  ymin = gs->ymin;
1256  }
1257 
1258  if (gs->ymax > ymax) {
1259  ymax = gs->ymax;
1260  }
1261 
1262  if (gs->xmin < xmin) {
1263  xmin = gs->xmin;
1264  }
1265 
1266  if (gs->xmax > xmax) {
1267  xmax = gs->xmax;
1268  }
1269  }
1270 
1271  cen[X] = (xmin + xmax) / 2. - xmin;
1272  cen[Y] = (ymin + ymax) / 2. - ymin;
1273  cen[Z] = (zmin + zmax) / 2.;
1274 
1275  return (1);
1276  }
1277 
1278  cen[X] = cen[Y] = cen[Z] = 0.0;
1279 
1280  return (-1);
1281 }
1282 
1283 
1284 /*!
1285  \brief Set for geosurf need-to-update mark
1286 
1287  \return -1 no surface available
1288  \return 1 on success
1289  */
1291 {
1292  geosurf *gs;
1293 
1294  if (Surf_top) {
1295  Surf_top->norm_needupdate = 1;
1296  }
1297  else {
1298  return (-1);
1299  }
1300 
1301  for (gs = Surf_top->next; gs; gs = gs->next) {
1302  gs->norm_needupdate = 1;
1303  }
1304 
1305  return (1);
1306 }
1307 
1308 /*!
1309  \brief Check if point is masked
1310 
1311  \param gs pointer to geosurf struct
1312  \param pt point coordinates (X,Y,Z)
1313 
1314  \return 1 masked
1315  \return 0 not masked
1316  */
1317 int gs_point_is_masked(geosurf * gs, float *pt)
1318 {
1319  int vrow, vcol, drow, dcol;
1320  int retmask = 0, npts = 0;
1321  float p2[2];
1322 
1323  if (!gs->curmask) {
1324  return (0);
1325  }
1326 
1327  vrow = Y2VROW(gs, pt[Y]);
1328  vcol = X2VCOL(gs, pt[X]);
1329 
1330  /* check right & bottom edges */
1331  if (pt[X] == VCOL2X(gs, VCOLS(gs))) {
1332  /* right edge */
1333  vcol -= 1;
1334  }
1335 
1336  if (pt[Y] == VROW2Y(gs, VROWS(gs))) {
1337  /* bottom edge */
1338  vrow -= 1;
1339  }
1340 
1341  drow = VROW2DROW(gs, vrow);
1342  dcol = VCOL2DCOL(gs, vcol);
1343 
1344  if (BM_get(gs->curmask, dcol, drow)) {
1345  retmask |= MASK_TL;
1346  npts++;
1347  }
1348 
1349  dcol = VCOL2DCOL(gs, vcol + 1);
1350 
1351  if (BM_get(gs->curmask, dcol, drow)) {
1352  retmask |= MASK_TR;
1353  npts++;
1354  }
1355 
1356  drow = VROW2DROW(gs, vrow + 1);
1357 
1358  if (BM_get(gs->curmask, dcol, drow)) {
1359  retmask |= MASK_BR;
1360  npts++;
1361  }
1362 
1363  dcol = VCOL2DCOL(gs, vcol);
1364 
1365  if (BM_get(gs->curmask, dcol, drow)) {
1366  retmask |= MASK_BL;
1367  npts++;
1368  }
1369 
1370  if (npts != 1) {
1371  /* zero or masked */
1372  return (retmask | npts);
1373  }
1374 
1375  p2[X] = VCOL2X(gs, vcol);
1376  p2[Y] = VROW2Y(gs, vrow + 1);
1377 
1378  switch (retmask) {
1379  case MASK_TL:
1380  if ((pt[X] - p2[X]) / VXRES(gs) > (pt[Y] - p2[Y]) / VYRES(gs)) {
1381  /* lower triangle */
1382  return (0);
1383  }
1384 
1385  return (retmask | npts);
1386  case MASK_TR:
1387 
1388  return (retmask | npts);
1389  case MASK_BR:
1390  if ((pt[X] - p2[X]) / VXRES(gs) <= (pt[Y] - p2[Y]) / VYRES(gs)) {
1391  /* upper triangle */
1392  return (0);
1393  }
1394 
1395  return (retmask | npts);
1396  case MASK_BL:
1397 
1398  return (retmask | npts);
1399  }
1400 
1401  /* Assume that if we get here it is an error */
1402  return (0);
1403 }
1404 
1405 /*!
1406  \brief Calculate distance on surface
1407 
1408  \param gs pointer to geosurf struct
1409  \param p1 from point
1410  \param p2 to point
1411  \param[out] dist distnace
1412  \param use_exag use exag for calculation
1413 
1414  \return 0 on error (points not in region)
1415  \return 1 on success
1416  */
1417 int gs_distance_onsurf(geosurf * gs, float *p1, float *p2, float *dist,
1418  int use_exag)
1419 {
1420  Point3 *tmp;
1421  int np, i;
1422  float exag, length;
1423 
1424  if (in_vregion(gs, p1) && in_vregion(gs, p2)) {
1425  if (NULL == (tmp = gsdrape_get_segments(gs, p1, p2, &np))) {
1426  return (0);
1427  }
1428 
1429  length = 0.;
1430 
1431  if (use_exag) {
1432  exag = GS_global_exag();
1433  tmp[0][Z] *= exag;
1434 
1435  for (i = 0; i < (np - 1); i++) {
1436  tmp[i + 1][Z] *= exag;
1437  length += GS_distance(tmp[i], tmp[i + 1]);
1438  }
1439  }
1440  else {
1441  for (i = 0; i < (np - 1); i++) {
1442  length += GS_distance(tmp[i], tmp[i + 1]);
1443  }
1444  }
1445 
1446  *dist = length;
1447 
1448  return (1);
1449  }
1450 
1451  return (0);
1452 }
#define VXRES(gs)
Definition: rowcol.h:9
float scale
Definition: ogsf.h:487
#define G_malloc(n)
Definition: defs/gis.h:112
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:232
float xrange
Definition: ogsf.h:269
float min_nz
Definition: ogsf.h:253
float zmin
Definition: ogsf.h:268
int gs_num_datah_reused(int dh)
Get number of reused values.
Definition: gs.c:597
#define ATTY_CHAR
Definition: ogsf.h:168
void gs_delete_surf(int id)
Remove geosurf struct from list.
Definition: gs.c:463
long wire_color
Definition: ogsf.h:263
float ymin
Definition: ogsf.h:268
#define VCOL2X(gs, vcol)
Definition: rowcol.h:40
#define MASK_TR
Definition: ogsf.h:187
typbuff * gsds_get_typbuff(int, IFLAG)
Get data buffer.
Definition: gsds.c:281
float max_nz
Definition: ogsf.h:253
short * sb
Definition: ogsf.h:208
float zrange_nz
Definition: ogsf.h:270
int gs_get_datacenter(float *cen)
Get data center point.
Definition: gs.c:1232
void gs_set_maskmode(int invert)
Set geosurf mask mode.
Definition: gs.c:900
int gs_get_data_avg_zmax(float *azmax)
Get average z-max value.
Definition: gs.c:1203
int Gs_update_attrange(geosurf *, int)
Update no_zero ranges for attribute (actually no_null now)
Definition: gs3.c:1087
int incl
Definition: ogsf.h:485
double ox
Definition: ogsf.h:264
struct ps_state ps
unsigned long * norms
Definition: ogsf.h:274
int gs_point_is_masked(geosurf *gs, float *pt)
Check if point is masked.
Definition: gs.c:1317
#define NOTSET_ATT
Definition: ogsf.h:82
#define min(x, y)
Definition: draw2.c:31
#define VROWS(gs)
Definition: rowcol.h:13
int rows
Definition: ogsf.h:260
float zmax_nz
Definition: ogsf.h:270
float xmax
Definition: ogsf.h:268
#define VCOLS(gs)
Definition: rowcol.h:14
#define ATT_TOPO
Definition: ogsf.h:73
#define LEGAL_ATT(a)
Definition: ogsf.h:79
float range_nz
Definition: ogsf.h:253
int * ib
Definition: ogsf.h:207
int gs_mask_defined(geosurf *gs)
Check if mask is defined.
Definition: gs.c:915
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
size_t gs_malloc_att_buff(geosurf *gs, int desc, int type)
Allocate attribute buffer.
Definition: gs.c:717
int gs_get_yextents(geosurf *gs, float *min, float *max)
Get y-extent values.
Definition: gs.c:1033
float Point3[3]
Definition: ogsf.h:201
geosurf * gs_get_prev_surface(int id)
Get previous geosurf struct.
Definition: gs.c:86
int gs_get_yrange(float *min, float *max)
Get y-range.
Definition: gs.c:1164
int gs_att_is_set(geosurf *surf, IFLAG att)
Check if attribute is set.
Definition: gs.c:149
#define NULL
Definition: ccmath.h:32
void print_frto(float(*ft)[4])
Debugging, print &#39;from/to&#39; model coordinates to stderr.
Definition: gs.c:337
#define max(x, y)
Definition: draw2.c:32
void gs_set_defaults(geosurf *gs, float *defs, float *null_defs)
Set default attribute values.
Definition: gs.c:441
void gs_init(void)
Initialize library.
Definition: gs.c:47
IFLAG att_src
Definition: ogsf.h:247
int gs_set_att_type(geosurf *gs, int desc, int type)
Set attribute type.
Definition: gs.c:803
float z_exag
Definition: ogsf.h:266
#define VYRES(gs)
Definition: rowcol.h:10
float zrange
Definition: ogsf.h:269
void print_view_fields(geoview *gv)
Debugging, print geoview fields to stderr.
Definition: gs.c:419
#define ATTY_SHORT
Definition: ogsf.h:167
#define VROW2Y(gs, vrow)
Definition: rowcol.h:39
#define FIRST_SURF_ID
Definition: gs.c:28
float GS_distance(float *, float *)
Calculate distance.
Definition: gs_util.c:141
void print_surf_fields(geosurf *s)
Debugging, print geosurf fields to stderr.
Definition: gs.c:391
int cols
Definition: ogsf.h:260
int * lookup
Definition: ogsf.h:252
float yrange
Definition: ogsf.h:269
IFLAG draw_mode
Definition: ogsf.h:262
double yres
Definition: ogsf.h:265
typbuff * gs_get_att_typbuff(geosurf *gs, int desc, int to_write)
Get attribute data buffer.
Definition: gs.c:681
int x_mod
Definition: ogsf.h:271
float gsdiff_do_SD(float, int)
ADD.
Definition: gsdiff.c:94
float default_null
Definition: ogsf.h:254
int norm_needupdate
Definition: ogsf.h:273
int in_vregion(geosurf *, float *)
ADD.
Definition: gsdrape.c:696
void gs_err(const char *msg)
Definition: gs.c:34
float x_trans
Definition: ogsf.h:267
#define ATTY_INT
Definition: ogsf.h:166
#define Y2VROW(gs, py)
Definition: rowcol.h:27
#define X2VCOL(gs, px)
Definition: rowcol.h:28
float zminmasked
Definition: ogsf.h:268
int fov
Definition: ogsf.h:485
int gs_num_surfaces(void)
Get number of surfaces.
Definition: gs.c:127
Definition: ogsf.h:478
float zmin_nz
Definition: ogsf.h:270
#define MAP_ATT
Definition: ogsf.h:83
int nz_topo
Definition: ogsf.h:272
int y_mod
Definition: ogsf.h:271
#define DM_GOURAUD
Definition: ogsf.h:54
int hdata
Definition: ogsf.h:249
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:933
IFLAG att_type
Definition: ogsf.h:248
void print_realto(float *rt)
Debugging, print &#39;to&#39; real coordinates to stderr.
Definition: gs.c:353
int gs_set_att_const(geosurf *gs, int desc, float constant)
Set attribute constant value.
Definition: gs.c:872
#define MASK_TL
Definition: ogsf.h:186
int gs_getall_surfaces(geosurf **gsurfs)
Get array of geosurf structs.
Definition: gs.c:108
#define MASK_BR
Definition: ogsf.h:188
int BM_get(struct BM *, int, int)
Gets &#39;val&#39; from the bitmap.
Definition: bitmap.c:220
int gs_free_surf(geosurf *fs)
Free geosurf struct.
Definition: gs.c:487
float vert_exag
Definition: ogsf.h:486
#define FROM
Definition: ogsf.h:141
struct BM * curmask
Definition: ogsf.h:275
int(* user_func)()
Definition: ogsf.h:250
#define Z
Definition: ogsf.h:139
int gs_get_xrange(float *min, float *max)
Get x-range.
Definition: gs.c:1126
int gs_get_zextents(geosurf *gs, float *min, float *max, float *mid)
Get z-extent values.
Definition: gs.c:998
double oy
Definition: ogsf.h:264
float GS_global_exag(void)
Get global z-exag value.
Definition: gs2.c:1999
gsurf_att att[MAX_ATTS]
Definition: ogsf.h:261
int y_modw
Definition: ogsf.h:271
int gs_set_att_src(geosurf *gs, int desc, int src)
Set attribute source.
Definition: gs.c:827
int mask_needupdate
Definition: ogsf.h:273
#define MASK_BL
Definition: ogsf.h:189
float y_trans
Definition: ogsf.h:267
int gs_malloc_lookup(geosurf *gs, int desc)
Allocate attribute lookup.
Definition: gs.c:746
#define Y
Definition: ogsf.h:138
#define LEGAL_TYPE(t)
Definition: ogsf.h:170
float xmin
Definition: ogsf.h:268
int gs_get_xextents(geosurf *gs, float *min, float *max)
Get x-extent values.
Definition: gs.c:1016
struct g_surf * next
Definition: ogsf.h:276
void print_256lookup(int *buff)
Debugging, 256 integer values from buffer.
Definition: gs.c:367
int gs_get_att_type(geosurf *gs, int desc)
Get attribute type.
Definition: gs.c:630
geosurf * gs_get_surf(int id)
Get geosurf struct.
Definition: gs.c:62
int gs_get_zrange0(float *min, float *max)
Get z-range.
Definition: gs.c:1054
int gs_setall_norm_needupdate(void)
Set for geosurf need-to-update mark.
Definition: gs.c:1290
float(* tfunc)(float, int)
Definition: ogsf.h:212
int infocus
Definition: ogsf.h:482
int gsurf_id
Definition: ogsf.h:259
int coord_sys
Definition: ogsf.h:480
geosurf * gs_get_last_surface(void)
Get last allocated geosurf struct from list.
Definition: gs.c:172
float ymax
Definition: ogsf.h:268
int look
Definition: ogsf.h:485
#define LEGAL_SRC(s)
Definition: ogsf.h:86
void G_warning(const char *,...) __attribute__((format(printf
Definition: ogsf.h:204
int gs_get_att_src(geosurf *gs, int desc)
Get attribute source.
Definition: gs.c:656
float real_to[4]
Definition: ogsf.h:486
geosurf * gsdiff_get_SDref(void)
ADD.
Definition: gsdiff.c:77
#define VCOL2DCOL(gs, vcol)
Definition: rowcol.h:32
int view_proj
Definition: ogsf.h:481
#define TO
Definition: ogsf.h:142
size_t gsds_alloc_typbuff(int, int *, int, int)
Allocates correct buffer according to type, keeps track of total mem.
Definition: gsds.c:482
#define X
Definition: ogsf.h:137
Point3 * gsdrape_get_segments(geosurf *, float *, float *, int *)
ADD.
Definition: gsdrape.c:350
int gs_init_normbuff(geosurf *gs)
Init geosurf normbuff.
Definition: gs.c:306
float zmax
Definition: ogsf.h:268
#define MAX_ATTS
Definition: ogsf.h:43
geosurf * gs_get_new_surface(void)
Allocate new geosurf struct.
Definition: gs.c:193
void gs_free_unshared_buffs(geosurf *fs)
Free unshared buffers of geosurf struct.
Definition: gs.c:557
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:969
#define ATT_MASK
Definition: ogsf.h:75
#define VROW2DROW(gs, vrow)
Definition: rowcol.h:31
int x_modw
Definition: ogsf.h:271
float z_trans
Definition: ogsf.h:267
double xres
Definition: ogsf.h:265
int gs_get_zrange(float *min, float *max)
Get z-range.
Definition: gs.c:1088
int gs_distance_onsurf(geosurf *gs, float *p1, float *p2, float *dist, int use_exag)
Calculate distance on surface.
Definition: gs.c:1417
#define CONST_ATT
Definition: ogsf.h:84
float * fb
Definition: ogsf.h:206
int G_debug(int, const char *,...) __attribute__((format(printf
int twist
Definition: ogsf.h:485
Definition: ogsf.h:257
struct BM * bm
Definition: ogsf.h:210
float constant
Definition: ogsf.h:251
#define IFLAG
Definition: ogsf.h:69
unsigned char * cb
Definition: ogsf.h:209
int gsds_free_datah(int)
Free allocated dataset.
Definition: gsds.c:329
float from_to[2][4]
Definition: ogsf.h:483
int nz_color
Definition: ogsf.h:272