GRASS GIS 8 Programmer's Manual 8.2.1RC1(2022)-exported
gs2.c
Go to the documentation of this file.
1/*!
2 \file lib/ogsf/gs2.c
3
4 \brief OGSF library - loading and manipulating surfaces (higher level functions)
5
6 GRASS OpenGL gsurf OGSF Library
7
8 Plans for handling color maps:
9 NOW:
10 if able to load as unsigned char, make lookup table containing palette
11 otherwise, load directly as packed color, set lookup = NULL
12 MAYBE LATER:
13 if able to load as POSITIVE short, make lookup table containing palette
14 - may want to calculate savings first (ie, numcells > 32768)
15 (not exactly, it's Friday & time to go home - figure it later)
16 otherwise, load directly as packed color, set lookup = NULL
17 MESSY! - need to fix up!
18
19 (C) 1999-2008 by the GRASS Development Team
20
21 This program is free software under the
22 GNU General Public License (>=v2).
23 Read the file COPYING that comes with GRASS
24 for details.
25
26 \author Bill Brown USACERL (1993)
27 \author Pierre de Mouveaux <p_de_mouveaux hotmail.com> (updated October 1999)
28 \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
29 */
30
31#include <stdlib.h>
32#include <string.h>
33#include <math.h>
34
35#include <grass/config.h>
36
37#if defined(OPENGL_X11) || defined(OPENGL_WINDOWS)
38#include <GL/gl.h>
39#include <GL/glu.h>
40#elif defined(OPENGL_AQUA)
41#include <OpenGL/gl.h>
42#include <OpenGL/glu.h>
43#endif
44
45#include <grass/gis.h>
46#include <grass/raster.h>
47#include <grass/ogsf.h>
48#include <grass/glocale.h>
49
50#include "gsget.h"
51#include "rowcol.h"
52#include "rgbpack.h"
53
54/* Hack to make NVIZ2.2 query functions.("What's Here" and "Look at")
55 * to work.
56 * Uses gs_los_intersect1() instead of gs_los_intersect().
57 * Pierre de Mouveaux - 31 oct. 1999. p_de_mouveaux@hotmail.com.
58 */
59#define NVIZ_HACK 1
60
61int gsd_getViewport(GLint *, GLint *);
62
63/* array of surface ids */
64static int Surf_ID[MAX_SURFS];
65static int Next_surf = 0;
66static int SDref_surf = 0;
67
68/* attributes array */
69static float Default_const[MAX_ATTS];
70static float Default_nulls[MAX_ATTS];
71
72/* largest dimension */
73static float Longdim;
74
75/* N, S, W, E */
76static float Region[4];
77static geoview Gv;
78static geodisplay Gd;
79static struct Cell_head wind;
80static int Buffermode;
81static int Numlights = 0;
82static int Resetlight = 1;
83static int Modelshowing = 0;
84
85void void_func(void)
86{
87 return;
88}
89
90/*!
91 \brief Initialize OGSF library
92
93 Get region settings - wind
94
95 Set Region (NSWE array) and compute scale
96 */
97void GS_libinit(void)
98{
99 static int first = 1;
100
101 G_get_set_window(&wind);
102
103 Region[0] = wind.north;
104 Region[1] = wind.south;
105 Region[2] = wind.west;
106 Region[3] = wind.east;
107
108 /* scale largest dimension to GS_UNIT_SIZE */
109 if ((wind.east - wind.west) > (wind.north - wind.south)) {
110 Longdim = (wind.east - wind.west);
111 }
112 else {
113 Longdim = (wind.north - wind.south);
114 }
115
116 Gv.scale = GS_UNIT_SIZE / Longdim;
117
118 G_debug(1, "GS_libinit(): n=%f s=%f w=%f e=%f scale=%f first=%d",
119 Region[0], Region[1], Region[2], Region[3], Gv.scale, first);
120
122
123
124 if (first) {
125 gs_init();
126 }
127
128 first = 0;
129
130 return;
131}
132
133/*!
134 \brief Get largest dimension
135
136 \param[out] dim dimension
137
138 \return 1
139 */
140int GS_get_longdim(float *dim)
141{
142 *dim = Longdim;
143
144 G_debug(3, "GS_get_longdim(): dim=%g", *dim);
145
146 return (1);
147}
148
149/*!
150 \brief Get 2D region extent
151
152 \param[out] n,s,w,e extent values
153
154 \return 1
155 */
156int GS_get_region(float *n, float *s, float *w, float *e)
157{
158 *n = Region[0];
159 *s = Region[1];
160 *w = Region[2];
161 *e = Region[3];
162
163 return (1);
164}
165
166/*!
167 \brief Set default attributes for map objects
168
169 \param defs attributes array (dim MAX_ATTS)
170 \param null_defs null attributes array (dim MAX_ATTS)
171 */
172void GS_set_att_defaults(float *defs, float *null_defs)
173{
174 int i;
175
176 G_debug(3, "GS_set_att_defaults");
177
178 for (i = 0; i < MAX_ATTS; i++) {
179 Default_const[i] = defs[i];
180 Default_nulls[i] = null_defs[i];
181 }
182
183 return;
184}
185
186/*!
187 Check if surface exists
188
189 \param id surface id
190
191 \return 0 not found
192 \return 1 found
193 */
194int GS_surf_exists(int id)
195{
196 int i, found = 0;
197
198 G_debug(3, "GS_surf_exists(): id=%d", id);
199
200
201 if (NULL == gs_get_surf(id)) {
202 return (0);
203 }
204
205 for (i = 0; i < Next_surf && !found; i++) {
206 if (Surf_ID[i] == id) {
207 found = 1;
208 }
209 }
210
211 return (found);
212}
213
214/*!
215 \brief Add new surface
216
217 Note that origin has 1/2 cell added to represent center of cells
218 because library assumes that east - west = (cols - 1) * ew_res,
219 since left and right columns are on the edges.
220
221 \return surface id
222 \return -1 on error (MAX_SURFS exceded)
223 */
225{
226 geosurf *ns;
227
228 G_debug(3, "GS_new_surface():");
229
230 if (Next_surf < MAX_SURFS) {
231 ns = gs_get_new_surface();
232 gs_init_surf(ns, wind.west + wind.ew_res / 2.,
233 wind.south + wind.ns_res / 2., wind.rows, wind.cols,
234 wind.ew_res, wind.ns_res);
235 gs_set_defaults(ns, Default_const, Default_nulls);
236
237 /* make default shine current */
238 gs_set_att_src(ns, ATT_SHINE, CONST_ATT);
239
240 Surf_ID[Next_surf] = ns->gsurf_id;
241 ++Next_surf;
242
243 G_debug(3, " id=%d", ns->gsurf_id);
244
245 return (ns->gsurf_id);
246 }
247
248
249
250 return (-1);
251}
253{
254 Resetlight = i;
255 if (i)
256 Numlights = 0;
257}
259{
260 return Resetlight;
261}
262/*!
263 \brief Add new model light
264
265 \return light model id
266 \return -1 on error (MAX_LIGHTS exceded)
267 */
269{
270 int i;
271
272 if (GS_get_light_reset()) {
273
275
276 for (i = 0; i < MAX_LIGHTS; i++) {
277 Gv.lights[i].position[X] = Gv.lights[i].position[Y] = 0.0;
278 Gv.lights[i].position[Z] = 1.0;
279 Gv.lights[i].position[W] = 0.0; /* infinite */
280 Gv.lights[i].color[0] = Gv.lights[i].color[1] =
281 Gv.lights[i].color[2] = 1.0;
282 Gv.lights[i].ambient[0] = Gv.lights[i].ambient[1] =
283 Gv.lights[i].ambient[2] = 0.2;
284 Gv.lights[i].shine = 32.0;
285 }
286
288 }
289
290 if (Numlights < MAX_LIGHTS) {
291 gsd_deflight(Numlights + 1, &(Gv.lights[Numlights]));
292 gsd_switchlight(Numlights + 1, 1);
293
294 return ++Numlights;
295 }
296
297 return -1;
298}
299
300/*!
301 \brief Set light position
302
303 \bug I think lights array doesnt match sgi_light array
304
305 \param num light id (starts with 1)
306 \param xpos,ypos,zpos coordinates (model)
307 \param local local coordinate (for viewport)
308 */
309void GS_setlight_position(int num, float xpos, float ypos, float zpos,
310 int local)
311{
312 if (num) {
313 num -= 1;
314 if (num < Numlights) {
315 Gv.lights[num].position[X] = xpos;
316 Gv.lights[num].position[Y] = ypos;
317 Gv.lights[num].position[Z] = zpos;
318 Gv.lights[num].position[W] = (float)local;
319
320 gsd_deflight(num + 1, &(Gv.lights[num]));
321 }
322 }
323
324 return;
325}
326
327
328/*!
329 \brief Get light position
330
331 \param num light id (starts at 1)
332 \param[out] xpos,ypos,zpos coordinates
333 \param[out] local ?
334 */
335void GS_getlight_position(int num, float *xpos, float *ypos, float *zpos,
336 int *local)
337{
338 if (num) {
339 num -= 1;
340 if (num < Numlights) {
341 *xpos = Gv.lights[num].position[X];
342 *ypos = Gv.lights[num].position[Y];
343 *zpos = Gv.lights[num].position[Z];
344 *local = (int)Gv.lights[num].position[W];
345
346 }
347 }
348
349 return;
350}
351
352/*!
353 \brief Set light color
354
355 \param num light id (starts at 1)
356 \param red,green,blue color values (from 0.0 to 1.0)
357 */
358void GS_setlight_color(int num, float red, float green, float blue)
359{
360 if (num) {
361 num -= 1;
362 if (num < Numlights) {
363 Gv.lights[num].color[0] = red;
364 Gv.lights[num].color[1] = green;
365 Gv.lights[num].color[2] = blue;
366
367 gsd_deflight(num + 1, &(Gv.lights[num]));
368 }
369 }
370
371 return;
372}
373
374/*!
375 \brief Get light color
376
377 \param num light id (starts at 1)
378 \param[out] red,green,blue color values
379 */
380void GS_getlight_color(int num, float *red, float *green, float *blue)
381{
382 if (num) {
383 num -= 1;
384 if (num < Numlights) {
385 *red = Gv.lights[num].color[0];
386 *green = Gv.lights[num].color[1];
387 *blue = Gv.lights[num].color[2];
388 }
389 }
390
391 return;
392}
393
394/*!
395 \brief Set light ambient
396
397 Red, green, blue from 0.0 to 1.0
398
399 \param num light id (starts at 1)
400 \param red,green,blue color values
401 */
402void GS_setlight_ambient(int num, float red, float green, float blue)
403{
404 if (num) {
405 num -= 1;
406 if (num < Numlights) {
407 Gv.lights[num].ambient[0] = red;
408 Gv.lights[num].ambient[1] = green;
409 Gv.lights[num].ambient[2] = blue;
410
411 gsd_deflight(num + 1, &(Gv.lights[num]));
412 }
413 }
414
415 return;
416}
417
418/*!
419 \brief Get light ambient
420
421 \param num light id (starts at 1)
422 \param[out] red,green,blue color values
423 */
424void GS_getlight_ambient(int num, float *red, float *green, float *blue)
425{
426 if (num) {
427 num -= 1;
428 if (num < Numlights) {
429 *red = Gv.lights[num].ambient[0];
430 *green = Gv.lights[num].ambient[1];
431 *blue = Gv.lights[num].ambient[2];
432 }
433 }
434
435 return;
436}
437
438
439/*!
440 \brief Switch off all lights
441 */
443{
444 int i;
445
446 for (i = 0; i < Numlights; i++) {
447 gsd_switchlight(i + 1, 0);
448 }
449
450 return;
451}
452
453/*!
454 \brief Switch on all lights
455 */
456void GS_lights_on(void)
457{
458 int i;
459
460 for (i = 0; i < Numlights; i++) {
461 gsd_switchlight(i + 1, 1);
462 }
463
464 return;
465}
466
467/*!
468 \brief Switch on/off light
469
470 \param num light id (starts at 1)
471 \param on non-zero for 'on' otherwise 'off'
472 */
473void GS_switchlight(int num, int on)
474{
475 if (num) {
476 num -= 1;
477
478 if (num < Numlights) {
479 gsd_switchlight(num + 1, on);
480 }
481 }
482
483 return;
484}
485
486/*!
487 \brief Check if transparency is set
488
489 \return 0 transparency not set
490 \return 1 transparency is set
491 */
493{
494 return (gs_att_is_set(NULL, ATT_TRANSP) || (FC_GREY == gsd_getfc()));
495}
496
497/*!
498 \brief Retrieves coordinates for lighting model position, at center of view
499
500 \param pos[out] coordinates
501 */
502void GS_get_modelposition1(float pos[])
503{
504 /* TODO: Still needs work to handle other cases */
505 /* this is a quick hack to get lighting adjustments debugged */
506 /*
507 GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], center);
508 GS_v3mult(center, 1000);
509 GS_v3add(center, Gv.from_to[FROM]);
510 */
511
513 gs_get_data_avg_zmax(&(pos[Z]));
514
515 G_debug(1, "GS_get_modelposition1(): model position: %f %f %f",
516 pos[X], pos[Y], pos[Z]);
517
518 return;
519}
520
521/*!
522 \brief Retrieves coordinates for lighting model position, at center of view
523
524 Position at nearclip * 2: tried nearclip + siz, but since need to
525 know position to calculate size, have two dependent variables
526 (nearclip * 2) from eye.
527
528 \param siz[out] size
529 \param pos[out] coordinates (X, Y, Z)
530 */
531void GS_get_modelposition(float *siz, float *pos)
532{
533 float dist, near_h, dir[3];
534
535 dist = 2. * Gd.nearclip;
536
537 near_h = 2.0 * tan(4.0 * atan(1.) * Gv.fov / 3600.) * dist;
538 *siz = near_h / 8.0;
539
540 /* prevent clipping - would only happen if fov > ~127 degrees, at
541 fov = 2.0 * atan(2.0) */
542
543 if (*siz > Gd.nearclip) {
544 *siz = Gd.nearclip;
545 }
546
547 GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], dir);
548
549 pos[X] = Gv.from_to[FROM][X] + dir[X] * dist;
550 pos[Y] = Gv.from_to[FROM][Y] + dir[Y] * dist;
551 pos[Z] = Gv.from_to[FROM][Z] + dir[Z] * dist;
552
553 return;
554}
555
556
557/*!
558 \brief Set decoration, north arrow ??
559
560 \todo scale used to calculate len of arrow still needs work
561 needs go function that returns center / eye distance
562 gsd_get_los function is not working correctly ??
563
564 \param pt point value in true world coordinates (?)
565 \param id surface id
566 \param[out] pos2 output coordinates
567 */
568void GS_set_Narrow(int *pt, int id, float *pos2)
569{
570 geosurf *gs;
571 float x, y, z;
572 GLdouble modelMatrix[16], projMatrix[16];
573 GLint viewport[4];
574
575 if (GS_get_selected_point_on_surface(pt[X], pt[Y], &id, &x, &y, &z)) {
576 gs = gs_get_surf(id);
577 if (gs) {
578 z = gs->zmax;
579 pos2[X] = (float)x - gs->ox + gs->x_trans;
580 pos2[Y] = (float)y - gs->oy + gs->y_trans;
581 pos2[Z] = (float)z + gs->z_trans;
582
583 return;
584 }
585 }
586 else {
587 gs = gs_get_surf(id);
588
589 /* Need to get model matrix, etc
590 * to run gluUnProject
591 */
593 gsd_do_scale(1);
594 glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
595 glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
596 glGetIntegerv(GL_VIEWPORT, viewport);
597
598 if (gs) {
599 GLdouble out_near[3], out_far[3];
600 GLdouble factor;
601 GLdouble out[3];
602
603 z = (float)gs->zmax + gs->z_trans;
604
605 gluUnProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) 0.,
606 modelMatrix, projMatrix, viewport,
607 &out_near[X], &out_near[Y], &out_near[Z]);
608 gluUnProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) 1.,
609 modelMatrix, projMatrix, viewport,
610 &out_far[X], &out_far[Y], &out_far[Z]);
611
612 glPopMatrix();
613
614 factor = (out_near[Z] - z) / (out_near[Z] - out_far[Z]);
615
616 out[X] = out_near[X] - ((out_near[X] - out_far[X]) * factor);
617 out[Y] = out_near[Y] - ((out_near[Y] - out_far[Y]) * factor);
618 out[Z] = z;
619
620 pos2[X] = (float)out[X];
621 pos2[Y] = (float)out[Y];
622 pos2[Z] = (float)out[Z];
623
624 return;
625
626 }
627 }
628 return;
629}
630
631/*!
632 \brief Draw place marker
633
634 Used to display query point for raster queries.
635
636 \param id surface id
637 \param pt point, X, Y value in true world coordinates
638 */
639void GS_draw_X(int id, float *pt)
640{
641 geosurf *gs;
642 Point3 pos;
643 float siz;
644 gvstyle style;
645
646 if ((gs = gs_get_surf(id))) {
647 GS_get_longdim(&siz);
648 style.size = siz / 200.;
649 pos[X] = pt[X] - gs->ox;
650 pos[Y] = pt[Y] - gs->oy;
651 _viewcell_tri_interp(gs, pos);
652
654
655 gsd_do_scale(1);
656 gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
657 gsd_linewidth(1);
658
659 if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) {
660 pos[Z] = gs->att[ATT_TOPO].constant;
661 gs = NULL; /* tells gpd_obj to use given Z val */
662 }
663 style.color = Gd.bgcol;
664 style.symbol = ST_GYRO;
665 gpd_obj(gs, &style, pos);
666 gsd_flush();
667
669 }
670
671 return;
672}
673
674/*!
675 \brief Draw line on surface
676
677 \param id surface id
678 \param x1,y1,x2,y2 line nodes
679 */
680void GS_draw_line_onsurf(int id, float x1, float y1, float x2, float y2)
681{
682 float p1[2], p2[2];
683 geosurf *gs;
684
685 if ((gs = gs_get_surf(id))) {
686 p1[X] = x1 - gs->ox;
687 p1[Y] = y1 - gs->oy;
688 p2[X] = x2 - gs->ox;
689 p2[Y] = y2 - gs->oy;
690
692
693 gsd_do_scale(1);
694 gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
695 gsd_linewidth(1);
696
698 gsd_line_onsurf(gs, p1, p2);
699
701 gsd_flush();
702 }
703
704 return;
705}
706
707/*!
708 \brief Draw multiline on surface
709
710 Like above but limits points in line to n or points found in segment,
711 whichever is smaller.
712
713 \param id surface id
714 \param x1,y1,x2,y2 line nodes
715
716 \return number of points used
717 */
718int GS_draw_nline_onsurf(int id, float x1, float y1, float x2, float y2,
719 float *lasp, int n)
720{
721 float p1[2], p2[2];
722 geosurf *gs;
723 int ret = 0;
724
725 if ((gs = gs_get_surf(id))) {
726 p1[X] = x1 - gs->ox;
727 p1[Y] = y1 - gs->oy;
728 p2[X] = x2 - gs->ox;
729 p2[Y] = y2 - gs->oy;
730
732
733 gsd_do_scale(1);
734 gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
735 gsd_linewidth(1);
737 ret = gsd_nline_onsurf(gs, p1, p2, lasp, n);
738 gsd_surf2real(gs, lasp);
739
741 gsd_flush();
742 }
743
744 return (ret);
745}
746
747/*!
748 \brief Draw flow-line on surace
749
750 This is slow - should be moved to gs_ but GS_ good for testing
751 and useful for app programmer
752
753 \param id surface id
754 \param x,y coordinates of flow-line
755 */
756void GS_draw_flowline_at_xy(int id, float x, float y)
757{
758 geosurf *gs;
759 float nv[3], pdir[2], mult;
760 float p1[2], p2[2], next[2];
761 int i = 0;
762
763 if ((gs = gs_get_surf(id))) {
764 p1[X] = x;
765 p1[Y] = y;
766 /* multiply by 1.5 resolutions to ensure a crossing ? */
767 mult = .1 * (VXRES(gs) > VYRES(gs) ? VXRES(gs) : VYRES(gs));
768
769 GS_coordpair_repeats(p1, p1, 50);
770
771 while (1 == GS_get_norm_at_xy(id, p1[X], p1[Y], nv)) {
772 if (nv[Z] == 1.0) {
773 if (pdir[X] == 0.0 && pdir[Y] == 0.0) {
774 break;
775 }
776
777 p2[X] = p1[X] + (pdir[X] * mult);
778 p2[Y] = p1[Y] + (pdir[Y] * mult);
779 }
780 else {
781 /* use previous direction */
782 GS_v2norm(nv);
783 p2[X] = p1[X] + (nv[X] * mult);
784 p2[Y] = p1[Y] + (nv[Y] * mult);
785 pdir[X] = nv[X];
786 pdir[Y] = nv[Y];
787 }
788
789 if (i > 2000) {
790 break;
791 }
792
793 if (GS_coordpair_repeats(p1, p2, 0)) {
794 break;
795 }
796
797 /* Think about this: */
798 /* degenerate line means edge or level edge ? */
799 /* next is filled with last point drawn */
800 if (2 > GS_draw_nline_onsurf(id, p1[X], p1[Y],
801 p2[X], p2[Y], next, 3)) {
802 break;
803 }
804
805 p1[X] = next[X];
806 p1[Y] = next[Y];
807 }
808
809 G_debug(3, "GS_draw_flowline_at_xy(): dir: %f %f", nv[X], nv[Y]);
810 }
811
812 return;
813}
814
815/*!
816 \brief Draw fringe around data (surface) at selected corners
817
818 \param id surface id
819 \param clr color
820 \param elev elevation value
821 \param where nw/ne/sw/se edges - 0 (turn off) 1 (turn on)
822 */
823void GS_draw_fringe(int id, unsigned long clr, float elev, int *where)
824{
825 geosurf *gs;
826
827 G_debug(3, "GS_draw_fringe(): id: %d clr: %ld elev %f edges: %d %d %d %d",
828 id, clr, elev, where[0], where[1], where[2], where[3]);
829 if ((gs = gs_get_surf(id)))
830 gsd_display_fringe(gs, clr, elev, where);
831
832}
833
834
835/*!
836 \brief Draw legend
837
838 \todo add legend from list option
839 make font loading more flexible
840
841 \param name legend name
842 \param fontbase font-base
843 \param size ?
844 \param flags legend flags
845 \param range values range
846 \param pt ?
847 */
848int GS_draw_legend(const char *name, GLuint fontbase, int size, int *flags,
849 float *range, int *pt)
850{
851 int list_no;
852
853 list_no = gsd_put_legend(name, fontbase, size, flags, range, pt);
854
855 return (list_no);
856}
857
858/*!
859 \brief Draw pre-defined list
860
861 Uses glFlush() to ensure all drawing is complete
862 before returning
863
864 \param list_id list id
865 */
866void GS_draw_list(GLuint list_id)
867{
868 gsd_calllist(list_id);
869 glFlush();
870 return;
871}
872
873/*!
874 \brief Draw all glLists
875
876 Uses glFlush() to ensure all drawing is complete
877 before returning
878 */
880{
881 gsd_calllists(0); /* not sure if 0 is right - MN */
882 glFlush();
883 return;
884}
885
886/*!
887 \brief Delete pre-defined list
888
889 \param list_id list id
890 */
891void GS_delete_list(GLuint list_id)
892{
893 gsd_deletelist(list_id, 1);
894
895 return;
896}
897
898/*!
899 \brief Draw lighting model
900 */
902{
903 static float center[3];
904 float tcenter[3];
905
906 if (!Modelshowing) {
907 GS_get_modelposition1(center);
908 }
909
910 GS_v3eq(tcenter, center);
911
912 gsd_zwritemask(0x0);
913 gsd_backface(1);
914
915 gsd_colormode(CM_AD);
916 gsd_shademodel(DM_GOURAUD);
918 gsd_do_scale(1);
919
920 if (Gv.vert_exag) {
921 tcenter[Z] *= Gv.vert_exag;
922 gsd_scale(1.0, 1.0, 1. / Gv.vert_exag);
923 }
924
925 gsd_drawsphere(tcenter, 0xDDDDDD, (float)(Longdim / 10.));
927 Modelshowing = 1;
928
929 gsd_backface(0);
930 gsd_zwritemask(0xffffffff);
931
932 return;
933}
934
935/*!
936 \brief Draw lighting model
937
938 Just turn off any cutting planes and draw it just outside near
939 clipping plane, since lighting is infinite now
940 */
942{
943 static float center[3], size;
944 float tcenter[3], tsize;
945 int i, wason[MAX_CPLANES];
946
948
949 for (i = 0; i < MAX_CPLANES; i++) {
950 if (wason[i]) {
952 }
953 }
954
955
956 if (!Modelshowing) {
957 GS_get_modelposition(&size, center);
958 }
959
960 GS_v3eq(tcenter, center);
961 tsize = size;
962
963 gsd_zwritemask(0x0);
964 gsd_backface(1);
965
966 gsd_colormode(CM_DIFFUSE);
967 gsd_shademodel(DM_GOURAUD);
969 gsd_drawsphere(tcenter, 0xDDDDDD, tsize);
971 Modelshowing = 1;
972
973 gsd_backface(0);
974 gsd_zwritemask(0xffffffff);
975
976 for (i = 0; i < MAX_CPLANES; i++) {
977 if (wason[i]) {
978 gsd_cplane_on(i);
979 }
980 }
981
982 gsd_flush();
983
984 return;
985}
986
987/*!
988 \brief Update current mask
989
990 May be called to update total mask for a surface at convenient times
991 instead of waiting until ready to redraw surface
992
993 \param id surface id
994
995 \return ?
996 */
998{
999 geosurf *gs;
1000
1001 gs = gs_get_surf(id);
1002 return (gs_update_curmask(gs));
1003}
1004
1005/*!
1006 \brief Check if point is masked ?
1007
1008 \param id surface id
1009 \param pt point
1010
1011 \return 1 masked
1012 \return 0 not masked
1013 \return -1 on error, invalid surface id
1014 */
1015int GS_is_masked(int id, float *pt)
1016{
1017 geosurf *gs;
1018 Point3 tmp;
1019
1020 if ((gs = gs_get_surf(id))) {
1021 tmp[X] = pt[X] - gs->ox;
1022 tmp[Y] = pt[Y] - gs->oy;
1023
1024 return (gs_point_is_masked(gs, tmp));
1025 }
1026
1027 return (-1);
1028}
1029
1030/*!
1031 \brief Unset Scaled Difference surface
1032 */
1034{
1036 SDref_surf = 0;
1037
1038 return;
1039}
1040
1041/*!
1042 \brief Set surface as Scaled Difference surface
1043
1044 \param id surface id
1045
1046 \return 1 on success
1047 \return 0 on error, invalid surface id
1048 */
1049int GS_set_SDsurf(int id)
1050{
1051 geosurf *gs;
1052
1053 if ((gs = gs_get_surf(id))) {
1054 gsdiff_set_SDref(gs);
1055 SDref_surf = id;
1056
1057 return (1);
1058 }
1059
1060 return (0);
1061}
1062
1063/*!
1064 \brief Set ?
1065
1066 \param scale scale value
1067
1068 \return 1
1069 */
1070int GS_set_SDscale(float scale)
1071{
1072 gsdiff_set_SDscale(scale);
1073
1074 return (1);
1075}
1076
1077/*!
1078 \brief Get ?
1079
1080 \param[out] id ?
1081
1082 \return 1 on success
1083 \return 0 on error
1084 */
1085int GS_get_SDsurf(int *id)
1086{
1087 geosurf *gs;
1088
1089 if ((gs = gsdiff_get_SDref())) {
1090 *id = SDref_surf;
1091
1092 return (1);
1093 }
1094
1095 return (0);
1096}
1097
1098/*!
1099 \brief Get ?
1100
1101 \param[out] scale value
1102
1103 \return 1
1104 */
1105int GS_get_SDscale(float *scale)
1106{
1107 *scale = gsdiff_get_SDscale();
1108
1109 return (1);
1110}
1111
1112/*!
1113 \brief Update normals
1114
1115 \param id surface id
1116
1117 \return ?
1118 */
1120{
1121 geosurf *gs;
1122
1123 gs = gs_get_surf(id);
1124
1125 return (gs_calc_normals(gs));
1126}
1127
1128/*!
1129 \brief Get attributes
1130
1131 \param id surface id
1132 \param att
1133 \param[out] set
1134 \param[out] constant
1135 \param[out] mapname
1136
1137 \return 1 on success
1138 \return -1 on error (invalid surface id)
1139 */
1140int GS_get_att(int id, int att, int *set, float *constant, char *mapname)
1141{
1142 int src;
1143 geosurf *gs;
1144
1145 gs = gs_get_surf(id);
1146 if (gs) {
1147 if (-1 != (src = gs_get_att_src(gs, att))) {
1148 *set = src;
1149
1150 if (src == CONST_ATT) {
1151 *constant = gs->att[att].constant;
1152 }
1153 else if (src == MAP_ATT) {
1154 strcpy(mapname, gsds_get_name(gs->att[att].hdata));
1155 }
1156
1157 return (1);
1158 }
1159
1160 return (-1);
1161 }
1162
1163 return (-1);
1164}
1165
1166/*!
1167 \brief Get surface category on given position
1168
1169 Prints "no data" or a description (i.e., "coniferous forest") to
1170 <i>catstr</i>. Usually call after GS_get_selected_point_on_surface().
1171 Define <i>att</i> as MAP_ATT
1172
1173 \todo Allocate catstr using G_store()
1174
1175 \param id surface id
1176 \param att attribute id (MAP_ATT)
1177 \param catstr cat string (must be allocated, dim?)
1178 \param x,y real coordinates
1179
1180 \return -1 if no category info or point outside of window
1181 \return 1 on success
1182*/
1183int GS_get_cat_at_xy(int id, int att, char *catstr, float x, float y)
1184{
1185 int offset, drow, dcol, vrow, vcol;
1186 float ftmp, pt[3];
1187 typbuff *buff;
1188 geosurf *gs;
1189
1190 *catstr = '\0';
1191 gs = gs_get_surf(id);
1192
1193 if (NULL == gs) {
1194 return -1;
1195 }
1196
1197 pt[X] = x;
1198 pt[Y] = y;
1199
1200 gsd_real2surf(gs, pt);
1201 if (gs_point_is_masked(gs, pt)) {
1202 return -1;
1203 }
1204
1205 if (!in_vregion(gs, pt)) {
1206 return -1;
1207 }
1208
1209 if (MAP_ATT != gs_get_att_src(gs, att)) {
1210 sprintf(catstr, _("no category info"));
1211 return -1;
1212 }
1213
1214 buff = gs_get_att_typbuff(gs, att, 0);
1215
1216 vrow = Y2VROW(gs, pt[Y]);
1217 vcol = X2VCOL(gs, pt[X]);
1218 drow = VROW2DROW(gs, vrow);
1219 dcol = VCOL2DCOL(gs, vcol);
1220
1221 offset = DRC2OFF(gs, drow, dcol);
1222
1223 if (GET_MAPATT(buff, offset, ftmp)) {
1224 return
1225 (Gs_get_cat_label(gsds_get_name(gs->att[att].hdata),
1226 drow, dcol, catstr));
1227 }
1228
1229 sprintf(catstr, _("no data"));
1230
1231 return 1;
1232}
1233
1234/*!
1235 \brief Get surface normal at x,y (real coordinates)
1236
1237 Usually call after GS_get_selected_point_on_surface()
1238
1239 \param id surface id
1240 \param x,y real coordinates
1241 \param[out] nv surface normal
1242
1243 \return -1 if point outside of window or masked
1244 \return 1 on success
1245 */
1246int GS_get_norm_at_xy(int id, float x, float y, float *nv)
1247{
1248 int offset, drow, dcol, vrow, vcol;
1249 float pt[3];
1250 geosurf *gs;
1251
1252 gs = gs_get_surf(id);
1253
1254 if (NULL == gs) {
1255 return (-1);
1256 }
1257
1258 if (gs->norm_needupdate) {
1259 gs_calc_normals(gs);
1260 }
1261
1262 pt[X] = x;
1263 pt[Y] = y;
1264
1265 gsd_real2surf(gs, pt);
1266 if (gs_point_is_masked(gs, pt)) {
1267 return (-1);
1268 }
1269
1270 if (!in_vregion(gs, pt)) {
1271 return (-1);
1272 }
1273
1274 vrow = Y2VROW(gs, pt[Y]);
1275 vcol = X2VCOL(gs, pt[X]);
1276 drow = VROW2DROW(gs, vrow);
1277 dcol = VCOL2DCOL(gs, vcol);
1278
1279 offset = DRC2OFF(gs, drow, dcol);
1280
1281 if (gs->norms) {
1282 FNORM(gs->norms[offset], nv);
1283 }
1284 else {
1285 /* otherwise must be a constant */
1286 nv[0] = 0.0;
1287 nv[1] = 0.0;
1288 nv[2] = 1.0;
1289 }
1290
1291 return (1);
1292}
1293
1294/*!
1295 \brief Get RGB color at given point
1296
1297 Colors are translated to rgb and returned as Rxxx Gxxx Bxxx Usually
1298 call after GS_get_selected_point_on_surface().
1299
1300 Prints NULL or the value (i.e., "921.5") to valstr
1301
1302 \param id surface id
1303 \param att attribute id
1304 \param[out] valstr value string (allocated, dim?)
1305 \param x,y real coordinates
1306
1307 \return -1 if point outside of window or masked
1308 \return 1 on success
1309 */
1310int GS_get_val_at_xy(int id, int att, char *valstr, float x, float y)
1311{
1312 int offset, drow, dcol, vrow, vcol;
1313 float ftmp, pt[3];
1314 typbuff *buff;
1315 geosurf *gs;
1316
1317 *valstr = '\0';
1318 gs = gs_get_surf(id);
1319
1320 if (NULL == gs) {
1321 return -1;
1322 }
1323
1324 pt[X] = x;
1325 pt[Y] = y;
1326
1327 gsd_real2surf(gs, pt);
1328
1329 if (gs_point_is_masked(gs, pt)) {
1330 return -1;
1331 }
1332
1333 if (!in_vregion(gs, pt)) {
1334 return (-1);
1335 }
1336
1337 if (CONST_ATT == gs_get_att_src(gs, att)) {
1338 if (att == ATT_COLOR) {
1339 int r, g, b, i;
1340
1341 i = gs->att[att].constant;
1342 sprintf(valstr, "R%d G%d B%d",
1343 INT_TO_RED(i, r), INT_TO_GRN(i, g), INT_TO_BLU(i, b));
1344 }
1345 else {
1346 sprintf(valstr, "%f", gs->att[att].constant);
1347 }
1348
1349 return 1;
1350 }
1351 else if (MAP_ATT != gs_get_att_src(gs, att)) {
1352 return -1;
1353 }
1354
1355 buff = gs_get_att_typbuff(gs, att, 0);
1356
1357 vrow = Y2VROW(gs, pt[Y]);
1358 vcol = X2VCOL(gs, pt[X]);
1359 drow = VROW2DROW(gs, vrow);
1360 dcol = VCOL2DCOL(gs, vcol);
1361
1362 offset = DRC2OFF(gs, drow, dcol);
1363
1364 if (GET_MAPATT(buff, offset, ftmp)) {
1365 if (att == ATT_COLOR) {
1366 int r, g, b, i;
1367
1368 i = gs_mapcolor(gs_get_att_typbuff(gs, ATT_COLOR, 0),
1369 &(gs->att[ATT_COLOR]), offset);
1370 sprintf(valstr, "R%d G%d B%d",
1371 INT_TO_RED(i, r), INT_TO_GRN(i, g), INT_TO_BLU(i, b));
1372 }
1373 else {
1374 sprintf(valstr, "%f", ftmp);
1375 }
1376
1377 return (1);
1378 }
1379
1380 sprintf(valstr, "NULL");
1381
1382 return (1);
1383}
1384
1385/*!
1386 \brief Unset attribute
1387
1388 \param id surface id
1389 \param att attribute id
1390
1391 \return ?
1392 */
1393int GS_unset_att(int id, int att)
1394{
1395 geosurf *gs;
1396
1397 gs = gs_get_surf(id);
1398 gs->mask_needupdate = 1;
1399
1400 return (gs_set_att_src(gs, att, NOTSET_ATT));
1401}
1402
1403/*!
1404 \brief Set attribute constant
1405
1406 \param id surface id
1407 \param att attribute id
1408 \param constant value
1409
1410 \return ?
1411 */
1412int GS_set_att_const(int id, int att, float constant)
1413{
1414 geosurf *gs;
1415 int ret;
1416
1417 gs = gs_get_surf(id);
1418 ret = (gs_set_att_const(gs, att, constant));
1419
1420 Gs_update_attrange(gs, att);
1421
1422 return (ret);
1423}
1424
1425/*!
1426 \brief Set mask mode
1427
1428 Mask attribute special: constant is set to indicate invert or no
1429
1430 \param id surface id
1431 \param mode id
1432
1433 \return mode id
1434 \return -1 on error (invalid surface id)
1435 */
1436int GS_set_maskmode(int id, int mode)
1437{
1438 geosurf *gs;
1439
1440 gs = gs_get_surf(id);
1441
1442 if (gs) {
1443 gs->att[ATT_MASK].constant = mode;
1444 gs->mask_needupdate = 1;
1445
1446 return (mode);
1447 }
1448
1449 return (-1);
1450}
1451
1452/*!
1453 \brief Get mask mode
1454
1455 \param id surface id
1456 \param[out] mode id
1457
1458 \return 1 on success
1459 \return -1 on error (invalid surface id)
1460 */
1461int GS_get_maskmode(int id, int *mode)
1462{
1463 geosurf *gs;
1464
1465 gs = gs_get_surf(id);
1466
1467 if (gs) {
1468 *mode = gs->att[ATT_MASK].constant;
1469
1470 return (1);
1471 }
1472
1473 return (-1);
1474}
1475
1476/*!
1477 \brief Set client data
1478
1479 \param id surface id
1480 \param clientd pointer to client data struct
1481
1482 \return 1 on success
1483 \return -1 on error (invalid surface id)
1484 */
1485int GS_Set_ClientData(int id, void *clientd)
1486{
1487 geosurf *gs;
1488
1489 gs = gs_get_surf(id);
1490 if (gs) {
1491 gs->clientdata = clientd;
1492
1493 return (1);
1494 }
1495
1496 return (-1);
1497}
1498
1499/*!
1500 \brief Get client data
1501
1502 \param id surface id
1503
1504 \return pointer to client data
1505 \return NULL on error
1506 */
1508{
1509 geosurf *gs;
1510
1511 gs = gs_get_surf(id);
1512 if (gs) {
1513 return (gs->clientdata);
1514 }
1515
1516 return (NULL);
1517}
1518
1519/*!
1520 \brief Get number of surfaces
1521
1522 \return number of surfaces
1523 */
1525{
1526 return (gs_num_surfaces());
1527}
1528
1529/*!
1530 \brief Get surface list
1531
1532 Must be freed when not neeed!
1533
1534 \param[out] numsurf number of available surfaces
1535
1536 \return pointer to surface array
1537 \return NULL on error
1538 */
1539int *GS_get_surf_list(int *numsurfs)
1540{
1541 int i, *ret;
1542
1543 *numsurfs = Next_surf;
1544
1545 if (Next_surf) {
1546 ret = (int *)G_malloc(Next_surf * sizeof(int));
1547
1548 for (i = 0; i < Next_surf; i++) {
1549 ret[i] = Surf_ID[i];
1550 }
1551
1552 return (ret);
1553 }
1554
1555 return (NULL);
1556}
1557
1558/*!
1559 \brief Delete surface
1560
1561 \param id surface id
1562
1563 \return 1 on success
1564 \return -1 on error
1565 */
1567{
1568 int i, j, found;
1569
1570 found = FALSE;
1571
1572 G_debug(1, "GS_delete_surface(): id=%d", id);
1573
1574 if (GS_surf_exists(id)) {
1575 gs_delete_surf(id);
1576 for (i = 0; i < Next_surf && !found; i++) {
1577 if (Surf_ID[i] == id) {
1578 found = TRUE;
1579
1580 for (j = i; j < Next_surf; j++) {
1581 Surf_ID[j] = Surf_ID[j + 1];
1582 }
1583 }
1584 }
1585
1587
1588 if (found) {
1589 --Next_surf;
1590 return 1;
1591 }
1592 }
1593
1594 return -1;
1595}
1596
1597
1598/*!
1599 \brief Load raster map as attribute
1600
1601 \param id surface id
1602 \param filename filename
1603 \param att attribute descriptor
1604
1605 \return -1 on error (invalid surface id)
1606 \return ?
1607 */
1608int GS_load_att_map(int id, const char *filename, int att)
1609{
1610 geosurf *gs;
1611 unsigned int changed;
1612 unsigned int atty;
1613 const char *mapset;
1614 struct Cell_head rast_head;
1615 int reuse, begin, hdata, ret, neg, has_null;
1616 typbuff *tbuff;
1617
1618 G_debug(3, "GS_load_att_map(): map=%s", filename);
1619
1620 reuse = ret = neg = has_null = 0;
1621 gs = gs_get_surf(id);
1622
1623 if (NULL == gs) {
1624 return -1;
1625 }
1626
1627 gs->mask_needupdate = (ATT_MASK == att || ATT_TOPO == att ||
1628 (gs->nz_topo && ATT_TOPO == att) ||
1629 (gs->nz_color && ATT_COLOR == att));
1630
1631 gs_set_att_src(gs, att, MAP_ATT);
1632
1633 /* Check against maps already loaded in memory */
1634 /* if to be color attribute:
1635 - if packed color for another surface, OK to reuse
1636 - if unchanged, ok to reuse IF it's of type char (will have lookup)
1637 */
1638 begin = hdata = 1;
1639
1640 /* Get MAPSET to ensure names are fully qualified */
1641 mapset = G_find_raster2(filename, "");
1642 if (mapset == NULL) {
1643 /* Check for valid filename */
1644 G_warning("Raster map <%s> not found", filename);
1645 return -1;
1646 }
1647
1648 /* Check to see if map is in Region */
1649 Rast_get_cellhd(filename, mapset, &rast_head);
1650 if (rast_head.north <= wind.south ||
1651 rast_head.south >= wind.north ||
1652 rast_head.east <= wind.west || rast_head.west >= wind.east) {
1653
1654 G_warning(_("Raster map <%s> is outside of current region. Load failed."),
1655 G_fully_qualified_name(filename, mapset));
1656 }
1657
1658 while (!reuse && (0 < hdata)) {
1659 changed = CF_COLOR_PACKED;
1660 atty = ATTY_FLOAT | ATTY_CHAR | ATTY_INT | ATTY_SHORT | ATTY_MASK;
1661
1662 if (0 < (hdata = gsds_findh(filename, &changed, &atty, begin))) {
1663
1664 G_debug(3, "GS_load_att_map(): %s already has data handle %d.CF=%x",
1665 filename, hdata, changed);
1666
1667 /* handle found */
1668 if (ATT_COLOR == att) {
1669 if ((changed == CF_COLOR_PACKED) ||
1670 (!changed && atty == ATTY_CHAR)) {
1671 reuse = 1;
1672 }
1673 }
1674 else if (atty == ATTY_MASK && att != ATT_MASK) {
1675 reuse = 0;
1676 /* should also free mask data & share new - but need backward
1677 reference? */
1678 }
1679 else if (!changed) {
1680 reuse = 1;
1681 }
1682 }
1683
1684 begin = 0;
1685 }
1686
1687 if (reuse) {
1688 gs->att[att].hdata = hdata;
1689 gs_set_att_type(gs, att, atty); /* ?? */
1690
1691 /* free lookup & set to NULL! */
1692 if (atty == ATTY_INT) {
1693 if (gs->att[att].lookup) {
1694 free(gs->att[att].lookup);
1695 gs->att[att].lookup = NULL;
1696 }
1697 }
1698 /* TODO: FIX THIS stuff with lookup sharing! */
1699
1700 G_debug(3, "GS_load_att_map(): %s is being reused. hdata=%d",
1701 filename, hdata);
1702 }
1703 else {
1704 G_debug(3, "GS_load_att_map(): %s not loaded in correct form - loading now",
1705 filename);
1706
1707 /* not loaded - need to get new dataset handle */
1708 gs->att[att].hdata = gsds_newh(filename);
1709
1710 tbuff = gs_get_att_typbuff(gs, att, 1);
1711
1712 /* TODO: Provide mechanism for loading certain attributes at
1713 specified sizes, allow scaling or capping, or scale non-zero */
1714 if (ATT_MASK == att) {
1715 atty = ATTY_MASK;
1716 }
1717 else {
1718 atty = Gs_numtype(filename, &neg);
1719 }
1720
1721#ifdef MAYBE_LATER
1722 if (att == ATT_COLOR && atty == ATTY_SHORT) {
1723 atty = (neg ? ATTY_INT : ATTY_SHORT);
1724 }
1725#endif
1726
1727 if (att == ATT_COLOR && atty == ATTY_SHORT) {
1728 atty = ATTY_INT;
1729 }
1730
1731 if (0 == gs_malloc_att_buff(gs, att, ATTY_NULL)) {
1732 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1733 }
1734
1735 switch (atty) {
1736 case ATTY_MASK:
1737 if (0 == gs_malloc_att_buff(gs, att, ATTY_MASK)) {
1738 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1739 }
1740
1741 ret = Gs_loadmap_as_bitmap(&wind, filename, tbuff->bm);
1742
1743 break;
1744 case ATTY_CHAR:
1745 if (0 == gs_malloc_att_buff(gs, att, ATTY_CHAR)) {
1746 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1747 }
1748
1749 ret = Gs_loadmap_as_char(&wind, filename, tbuff->cb,
1750 tbuff->nm, &has_null);
1751
1752 break;
1753 case ATTY_SHORT:
1754 if (0 == gs_malloc_att_buff(gs, att, ATTY_SHORT)) {
1755 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1756 }
1757
1758 ret = Gs_loadmap_as_short(&wind, filename, tbuff->sb,
1759 tbuff->nm, &has_null);
1760 break;
1761 case ATTY_FLOAT:
1762 if (0 == gs_malloc_att_buff(gs, att, ATTY_FLOAT)) {
1763 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1764 }
1765
1766 ret = Gs_loadmap_as_float(&wind, filename, tbuff->fb,
1767 tbuff->nm, &has_null);
1768
1769 break;
1770 case ATTY_INT:
1771 default:
1772 if (0 == gs_malloc_att_buff(gs, att, ATTY_INT)) {
1773 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1774 }
1775
1776 ret = Gs_loadmap_as_int(&wind, filename, tbuff->ib,
1777 tbuff->nm, &has_null);
1778 break;
1779
1780 } /* Done with switch */
1781
1782 if (ret == -1) {
1783 gsds_free_data_buff(gs->att[att].hdata, ATTY_NULL);
1784 return -1;
1785 }
1786
1787 G_debug(4, " has_null=%d", has_null);
1788
1789 if (!has_null) {
1790 gsds_free_data_buff(gs->att[att].hdata, ATTY_NULL);
1791 }
1792 else {
1794 }
1795
1796 } /* end if not reuse */
1797
1798 if (ATT_COLOR == att) {
1799#ifdef MAYBE_LATER
1800 if (ATTY_INT == atty) {
1801 Gs_pack_colors(filename, tbuff->ib, gs->rows, gs->cols);
1802 gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
1803 gs->att[att].lookup = NULL;
1804 }
1805 else {
1806 gs_malloc_lookup(gs, att);
1807 Gs_build_lookup(filename, gs->att[att].lookup);
1808 }
1809#else
1810
1811 if (ATTY_CHAR == atty) {
1812 if (!gs->att[att].lookup) {
1813 /* might already exist if reusing */
1814 gs_malloc_lookup(gs, att);
1815 Gs_build_256lookup(filename, gs->att[att].lookup);
1816 }
1817 }
1818 else if (ATTY_FLOAT == atty) {
1819 if (!reuse) {
1820 if (0 == gs_malloc_att_buff(gs, att, ATTY_INT)) {
1821 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1822 }
1823
1824 Gs_pack_colors_float(filename, tbuff->fb, tbuff->ib,
1825 gs->rows, gs->cols);
1826 gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
1827 gsds_free_data_buff(gs->att[att].hdata, ATTY_FLOAT);
1828 gs->att[att].lookup = NULL;
1829 }
1830 }
1831 else {
1832 if (!reuse) {
1833 Gs_pack_colors(filename, tbuff->ib, gs->rows, gs->cols);
1834 gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
1835 gs->att[att].lookup = NULL;
1836 }
1837 }
1838#endif
1839 }
1840
1841 if (ATT_TOPO == att) {
1842 gs_init_normbuff(gs);
1843 /* S_DIFF: should also check here to see if this surface is a
1844 reference surface for scaled differences, if so update references
1845 to it */
1846 }
1847
1848 if (ret < 0) {
1849 G_warning(_("Loading failed"));
1850 }
1851
1852 if (-1 == Gs_update_attrange(gs, att)) {
1853 G_warning(_("Error finding range"));
1854 }
1855
1856 return ret;
1857}
1858
1859/*!
1860 \brief Draw surface
1861
1862 \param id surface id
1863 */
1864void GS_draw_surf(int id)
1865{
1866 geosurf *gs;
1867
1868 G_debug(3, "GS_draw_surf(): id=%d", id);
1869
1870 gs = gs_get_surf(id);
1871 if (gs) {
1872 gsd_shademodel(gs->draw_mode & DM_GOURAUD);
1873
1874 if (gs->draw_mode & DM_POLY) {
1875 gsd_surf(gs);
1876 }
1877
1878 if (gs->draw_mode & DM_WIRE) {
1879 gsd_wire_surf(gs);
1880 }
1881
1882 /* TODO: write wire/poly draw routines */
1883 if (gs->draw_mode & DM_WIRE_POLY) {
1884 gsd_surf(gs);
1885 gsd_wire_surf(gs);
1886 }
1887 }
1888
1889 return;
1890}
1891
1892/*!
1893 \brief Draw surface wire
1894
1895 Overrides draw_mode for fast display
1896
1897 \param id surface id
1898 */
1899void GS_draw_wire(int id)
1900{
1901 geosurf *gs;
1902
1903 G_debug(3, "GS_draw_wire(): id=%d", id);
1904
1905 gs = gs_get_surf(id);
1906
1907 if (gs) {
1908 gsd_wire_surf(gs);
1909 }
1910
1911 return;
1912}
1913
1914/*!
1915 \brief Draw all wires
1916
1917 Overrides draw_mode for fast display
1918 */
1920{
1921 geosurf *gs;
1922 int i;
1923
1924 for (i = 0; i < Next_surf; i++) {
1925 if ((gs = gs_get_surf(Surf_ID[i]))) {
1926 gsd_wire_surf(gs);
1927 }
1928 }
1929
1930 return;
1931}
1932
1933/*!
1934 \brief Draw all surfaces
1935 */
1937{
1938 int i;
1939
1940 for (i = 0; i < Next_surf; i++) {
1941 GS_draw_surf(Surf_ID[i]);
1942 }
1943
1944 return;
1945}
1946
1947/*!
1948 \brief Set Z exag for surface
1949
1950 \param id surface id
1951 \param exag z-exag value
1952 */
1953void GS_set_exag(int id, float exag)
1954{
1955 geosurf *gs;
1956
1957 G_debug(3, "GS_set_exag");
1958
1959 gs = gs_get_surf(id);
1960
1961 if (gs) {
1962 if (gs->z_exag != exag) {
1963 gs->norm_needupdate = 1;
1964 }
1965
1966 gs->z_exag = exag;
1967 }
1968
1969 return;
1970}
1971
1972/*!
1973 \brief Set global z-exag value
1974
1975 \param exag exag value to be set up
1976 */
1977void GS_set_global_exag(float exag)
1978{
1979
1980 G_debug(3, "GS_set_global_exag");
1981
1982 Gv.vert_exag = exag;
1983 /* GL_NORMALIZE */
1984 /* Only need to update norms gs_norms.c
1985 * if exag is used in norm equation which
1986 * it is not! If GL_NORMALIZE is disabled
1987 * will need to include.
1988 gs_setall_norm_needupdate();
1989 */
1990
1991 return;
1992}
1993
1994/*!
1995 \brief Get global z-exag value
1996
1997 \return value
1998 */
2000{
2001 G_debug(3, "GS_global_exag(): %g", Gv.vert_exag);
2002
2003 return (Gv.vert_exag);
2004}
2005
2006/*!
2007 \brief Set wire color
2008
2009 \todo error-handling
2010
2011 \param id surface id
2012 \param colr color value
2013 */
2014void GS_set_wire_color(int id, int colr)
2015{
2016 geosurf *gs;
2017
2018 G_debug(3, "GS_set_wire_color");
2019
2020 gs = gs_get_surf(id);
2021
2022 if (gs) {
2023 gs->wire_color = colr;
2024 }
2025
2026 return;
2027}
2028
2029/*!
2030 \brief Get wire color
2031
2032 \param id surface id
2033 \param[out] colr color value
2034
2035 \return 1 on success
2036 \return -1 on error
2037 */
2038int GS_get_wire_color(int id, int *colr)
2039{
2040 geosurf *gs;
2041
2042 gs = gs_get_surf(id);
2043
2044 if (gs) {
2045 *colr = gs->wire_color;
2046
2047 return (1);
2048 }
2049
2050 return (-1);
2051}
2052
2053/*!
2054 \brief Set all draw-modes
2055
2056 \param mode mode id
2057
2058 \return 0 on success
2059 \return -1 on error
2060 */
2062{
2063 int i;
2064
2065 for (i = 0; i < Next_surf; i++) {
2066 if (0 != GS_set_drawmode(Surf_ID[i], mode)) {
2067 return (-1);
2068 }
2069 }
2070
2071 return (0);
2072}
2073
2074/*!
2075 \brief Set draw mode
2076
2077 \param id surface id
2078 \param mode mode type(s)
2079
2080 \return 0 on success
2081 \return -1 on error (invalid surface id)
2082 */
2083int GS_set_drawmode(int id, int mode)
2084{
2085 geosurf *gs;
2086
2087 G_debug(3, "GS_set_drawmode(): id=%d mode=%d", id, mode);
2088
2089 gs = gs_get_surf(id);
2090
2091 if (gs) {
2092 gs->draw_mode = mode;
2093
2094 return (0);
2095 }
2096
2097 return (-1);
2098}
2099
2100/*!
2101 \brief Get draw mode
2102
2103 \param id surface id
2104 \param[out] mode mode id
2105
2106 \return 1 on success
2107 \return -1 on error (invalid surface id)
2108 */
2109int GS_get_drawmode(int id, int *mode)
2110{
2111 geosurf *gs;
2112
2113 gs = gs_get_surf(id);
2114
2115 if (gs) {
2116 *mode = gs->draw_mode;
2117
2118 return (1);
2119 }
2120
2121 return (-1);
2122}
2123
2124/*!
2125 \brief Set no-zero ?
2126
2127 \param id surface id
2128 \param att attribute id
2129 \param mode mode id
2130 */
2131void GS_set_nozero(int id, int att, int mode)
2132{
2133 geosurf *gs;
2134
2135 G_debug(3, "GS_set_nozero");
2136
2137 gs = gs_get_surf(id);
2138
2139 if (gs) {
2140 if (att == ATT_TOPO) {
2141 gs->nz_topo = mode;
2142 gs->mask_needupdate = 1;
2143 }
2144
2145 if (att == ATT_COLOR) {
2146 gs->nz_color = mode;
2147 gs->mask_needupdate = 1;
2148 }
2149 }
2150
2151 return;
2152}
2153
2154/*!
2155 \brief Get no-zero ?
2156
2157 \param id surface id
2158 \param att attribute id
2159 \param[out] mode mode id
2160
2161 \return -1 on error (invalid surface id)
2162 \return 1 on success
2163 */
2164int GS_get_nozero(int id, int att, int *mode)
2165{
2166 geosurf *gs;
2167
2168 G_debug(3, "GS_set_nozero");
2169
2170 gs = gs_get_surf(id);
2171
2172 if (gs) {
2173 if (att == ATT_TOPO) {
2174 *mode = gs->nz_topo;
2175 }
2176 else if (att == ATT_COLOR) {
2177 *mode = gs->nz_color;
2178 }
2179 else {
2180 return (-1);
2181 }
2182
2183 return (1);
2184 }
2185
2186 return (-1);
2187}
2188
2189/*!
2190 \brief Set all draw resolutions
2191
2192 \param xres,yres x/y resolution value
2193 \param xwire,ywire x/y wire value
2194
2195 \return 0 on success
2196 \return -1 on error
2197 */
2198int GS_setall_drawres(int xres, int yres, int xwire, int ywire)
2199{
2200 int i;
2201
2202 for (i = 0; i < Next_surf; i++) {
2203 if (0 != GS_set_drawres(Surf_ID[i], xres, yres, xwire, ywire)) {
2204 return (-1);
2205 }
2206 }
2207
2208 return (0);
2209}
2210
2211/*!
2212 \brief Set draw resolution for surface
2213
2214 \param id surface id
2215 \param xres,yres x/y resolution value
2216 \param xwire,ywire x/y wire value
2217
2218 \return -1 on error
2219 \return 0 on success
2220 */
2221int GS_set_drawres(int id, int xres, int yres, int xwire, int ywire)
2222{
2223 geosurf *gs;
2224
2225 G_debug(3, "GS_set_drawres() id=%d xyres=%d/%d xywire=%d/%d",
2226 id, xres, yres, xwire, ywire);
2227
2228 if (xres < 1 || yres < 1 || xwire < 1 || ywire < 1) {
2229 return (-1);
2230 }
2231
2232 gs = gs_get_surf(id);
2233
2234 if (gs) {
2235 if (gs->x_mod != xres || gs->y_mod != yres) {
2236 gs->norm_needupdate = 1;
2237 }
2238
2239 gs->x_mod = xres;
2240 gs->y_mod = yres;
2241 gs->x_modw = xwire;
2242 gs->y_modw = ywire;
2243 }
2244
2245 return (0);
2246}
2247
2248/*!
2249 \brief Get draw resolution of surface
2250
2251 \param id surface id
2252 \param[out] xres,yres x/y resolution value
2253 \param[out] xwire,ywire x/y wire value
2254 */
2255void GS_get_drawres(int id, int *xres, int *yres, int *xwire, int *ywire)
2256{
2257 geosurf *gs;
2258
2259 G_debug(3, "GS_get_drawres");
2260
2261 gs = gs_get_surf(id);
2262
2263 if (gs) {
2264 *xres = gs->x_mod;
2265 *yres = gs->y_mod;
2266 *xwire = gs->x_modw;
2267 *ywire = gs->y_modw;
2268 }
2269
2270 return;
2271}
2272
2273/*!
2274 \brief Get dimension of surface
2275
2276 \param id surface id
2277 \param[out] rows,cols number of rows/cols
2278 */
2279void GS_get_dims(int id, int *rows, int *cols)
2280{
2281 geosurf *gs;
2282
2283 gs = gs_get_surf(id);
2284
2285 if (gs) {
2286 *rows = gs->rows;
2287 *cols = gs->cols;
2288 }
2289
2290 return;
2291}
2292
2293/*!
2294 \brief Get exag-value guess
2295
2296 Use no_zero range because if zero IS data, then range won't be that
2297 much off (it's just a GUESS, after all), but if zero is NO data, could
2298 drastically affect guess
2299
2300 \param id surface id
2301 \param[out] exag exag value
2302
2303 \return 1 on success
2304 \return -1 on error
2305 */
2306int GS_get_exag_guess(int id, float *exag)
2307{
2308 geosurf *gs;
2309 float guess;
2310
2311 gs = gs_get_surf(id);
2312 guess = 1.0;
2313
2314 /* if gs is type const return guess = 1.0 */
2315 if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) {
2316 *exag = guess;
2317 return (1);
2318 }
2319
2320 if (gs) {
2321 if (gs->zrange_nz == 0.0) {
2322 *exag = 0.0;
2323
2324 return (1);
2325 }
2326
2327 G_debug(3, "GS_get_exag_guess(): %f %f", gs->zrange_nz, Longdim);
2328
2329 while (gs->zrange_nz * guess / Longdim >= .25) {
2330 guess *= .1;
2331
2332 G_debug(3, "GS_get_exag_guess(): %f", guess);
2333 }
2334
2335 while (gs->zrange_nz * guess / Longdim < .025) {
2336 guess *= 10.;
2337
2338 G_debug(3, "GS_get_exag_guess(): %f", guess);
2339 }
2340
2341 *exag = guess;
2342
2343 return (1);
2344 }
2345
2346 return (-1);
2347}
2348
2349/*!
2350 \brief Get Z extents for all loaded surfaces
2351
2352 Treating zeros as "no data"
2353
2354 \param[out] min min value
2355 \param[out] max max value
2356 */
2357void GS_get_zrange_nz(float *min, float *max)
2358{
2359 int i, first = 1;
2360 geosurf *gs;
2361
2362 for (i = 0; i < Next_surf; i++) {
2363 if ((gs = gs_get_surf(Surf_ID[i]))) {
2364 if (first) {
2365 first = 0;
2366 *min = gs->zmin_nz;
2367 *max = gs->zmax_nz;
2368 }
2369
2370 if (gs->zmin_nz < *min) {
2371 *min = gs->zmin_nz;
2372 }
2373
2374 if (gs->zmax_nz > *max) {
2375 *max = gs->zmax_nz;
2376 }
2377 }
2378 }
2379
2380 G_debug(3, "GS_get_zrange_nz(): min=%g max=%g", *min, *max);
2381
2382 return;
2383}
2384
2385/*!
2386 \brief Set translation (surface position)
2387
2388 \param id surface id
2389 \param xtrans,ytrans,ztrans translation values
2390 */
2391void GS_set_trans(int id, float xtrans, float ytrans, float ztrans)
2392{
2393 geosurf *gs;
2394
2395 gs = gs_get_surf(id);
2396
2397 if (gs) {
2398 gs->x_trans = xtrans;
2399 gs->y_trans = ytrans;
2400 gs->z_trans = ztrans;
2401 }
2402
2403 G_debug(3, "GS_set_trans(): id=%d, x=%f, y=%f, z=%f",
2404 id, xtrans, ytrans, ztrans);
2405
2406 return;
2407}
2408
2409/*!
2410 \brief Get translation values (surface position)
2411
2412 \param id surface id
2413 \param[out] xtrans,ytrans,ztrans trans values
2414 */
2415void GS_get_trans(int id, float *xtrans, float *ytrans, float *ztrans)
2416{
2417 geosurf *gs;
2418
2419 gs = gs_get_surf(id);
2420
2421 if (gs) {
2422 *xtrans = gs->x_trans;
2423 *ytrans = gs->y_trans;
2424 *ztrans = gs->z_trans;
2425 }
2426
2427 G_debug(3, "GS_get_trans: id=%d, x=%f, y=%f, z=%f",
2428 id, *xtrans, *ytrans, *ztrans);
2429
2430 return;
2431}
2432
2433
2434/*!
2435 \brief Get default draw color
2436
2437 \return color value
2438 */
2439unsigned int GS_default_draw_color(void)
2440{
2441
2442 G_debug(3, "GS_default_draw_color");
2443
2444 return ((unsigned int)Gd.bgcol);
2445}
2446
2447/*!
2448 \brief Get background color
2449
2450 \return color value
2451 */
2452unsigned int GS_background_color(void)
2453{
2454 return ((unsigned int)Gd.bgcol);
2455}
2456
2457/*!
2458 \brief Sets which buffer to draw to
2459
2460 \param where GSD_BOTH, GSD_FRONT, GSD_BACK
2461 */
2462void GS_set_draw(int where)
2463{
2464 Buffermode = where;
2465
2466 switch (where) {
2467 case GSD_BOTH:
2469
2470 break;
2471 case GSD_FRONT:
2473
2474 break;
2475 case GSD_BACK:
2476 default:
2478
2479 break;
2480 }
2481
2482 return;
2483}
2484
2485/*
2486 \brief Ready to draw
2487 */
2489{
2490
2491 G_debug(3, "GS_ready_draw");
2492
2493 gsd_set_view(&Gv, &Gd);
2494
2495 return;
2496}
2497
2498/*!
2499 \brief Draw done, swap buffers
2500 */
2502{
2503
2504 G_debug(3, "GS_done_draw");
2505
2506 if (GSD_BACK == Buffermode) {
2508 }
2509
2510 gsd_flush();
2511
2512 return;
2513}
2514
2515/*!
2516 \brief Set focus
2517
2518 \param realto real coordinates to
2519 */
2520void GS_set_focus(float *realto)
2521{
2522
2523 G_debug(3, "GS_set_focus(): %f,%f,%f", realto[0], realto[1], realto[2]);
2524
2525 Gv.infocus = 1;
2526 GS_v3eq(Gv.real_to, realto);
2527
2528 gsd_set_view(&Gv, &Gd);
2529
2530 return;
2531}
2532
2533/*!
2534 \brief Set real focus
2535
2536 \param realto real coordinates to
2537 */
2538void GS_set_focus_real(float *realto)
2539{
2540
2541 G_get_set_window(&wind);
2542 realto[X] = realto[X] - wind.west - (wind.ew_res / 2.);
2543 realto[Y] = realto[Y] - wind.south - (wind.ns_res / 2.);
2544
2545 Gv.infocus = 1;
2546 GS_v3eq(Gv.real_to, realto);
2547
2548 gsd_set_view(&Gv, &Gd);
2549
2550 return;
2551}
2552
2553
2554/*!
2555 \brief Get focus
2556
2557 OK to call with NULL argument if just want to check state
2558
2559 \param realto real coordinates to
2560
2561 \return ?
2562 */
2563int GS_get_focus(float *realto)
2564{
2565
2566 G_debug(3, "GS_get_focus");
2567
2568 if (Gv.infocus) {
2569 if (realto) {
2570 GS_v3eq(realto, Gv.real_to);
2571 }
2572 }
2573
2574 return (Gv.infocus);
2575}
2576
2577/*!
2578 \brief Set focus to map center
2579
2580 \param id surface id
2581 */
2583{
2584 float center[3];
2585 geosurf *gs;
2586
2587 G_debug(3, "GS_set_focus_center_map");
2588
2589 gs = gs_get_surf(id);
2590
2591 if (gs) {
2592 center[X] = (gs->xmax - gs->xmin) / 2.;
2593 center[Y] = (gs->ymax - gs->ymin) / 2.;
2594 center[Z] = (gs->zmax_nz + gs->zmin_nz) / 2.;
2595
2596 /* not yet working
2597 buff = gs_get_att_typbuff(gs, ATT_TOPO, 0);
2598 offset = gs->rows*gs->cols/2 + gs->cols/2;
2599 if (buff)
2600 {
2601 if (GET_MAPATT(buff, offset, tmp))
2602 {
2603 center[Z] = tmp;
2604 }
2605 }
2606 */
2607
2608 GS_set_focus(center);
2609 }
2610}
2611
2612/*!
2613 \brief Move viewpoint
2614
2615 \param pt 'from' model coordinates
2616 */
2617void GS_moveto(float *pt)
2618{
2619 float ft[3];
2620
2621 G_debug(3, "GS_moveto(): %f,%f,%f", pt[0], pt[1], pt[2]);
2622
2623 if (Gv.infocus) {
2624 GS_v3eq(Gv.from_to[FROM], pt);
2625 /*
2626 GS_v3eq(Gv.from_to[TO], Gv.real_to);
2627 */
2628 GS_v3normalize(Gv.from_to[FROM], Gv.from_to[TO]);
2629 /* update inclination, look_dir if we're keeping these */
2630 }
2631 else {
2632 GS_v3eq(ft, Gv.from_to[TO]);
2633 GS_v3sub(ft, Gv.from_to[FROM]);
2634 GS_v3eq(Gv.from_to[FROM], pt);
2635 GS_v3eq(Gv.from_to[TO], pt);
2636 GS_v3add(Gv.from_to[TO], ft);
2637 }
2638
2639 return;
2640}
2641
2642/*!
2643 \brief Move position to (real)
2644
2645 \param pt point real coordinates
2646 */
2647void GS_moveto_real(float *pt)
2648{
2649 gsd_real2model(pt);
2650 GS_moveto(pt);
2651
2652 return;
2653}
2654
2655/*!
2656 \brief Get z-extent for a single surface
2657
2658 \param id surface id
2659 \param[out] min min z-value
2660 \param[out] max max z-value
2661 \param[out] mid middle z-value
2662
2663 \return -1 on error (invalid surface id)
2664 \return ?
2665 */
2666int GS_get_zextents(int id, float *min, float *max, float *mid)
2667{
2668 geosurf *gs;
2669
2670 if (NULL == (gs = gs_get_surf(id))) {
2671 return (-1);
2672 }
2673
2674 G_debug(3, "GS_get_zextents(): id=%d", id);
2675
2676 return (gs_get_zextents(gs, min, max, mid));
2677}
2678
2679/*!
2680 \brief Get z-extent for all loaded surfaces
2681
2682 \param[out] min min z-value
2683 \param[out] max max z-value
2684 \param doexag use z-exaggeration
2685
2686 \return 1 on success
2687 \return -1 on error
2688 */
2689int GS_get_zrange(float *min, float *max, int doexag)
2690{
2691 int ret_surf, ret_vol;
2692 float surf_min, surf_max;
2693 float vol_min, vol_max;
2694
2695 ret_surf = gs_get_zrange(&surf_min, &surf_max);
2696 ret_vol = gvl_get_zrange(&vol_min, &vol_max);
2697
2698 if (ret_surf > 0 && ret_vol > 0) {
2699 *min = (surf_min < vol_min) ? surf_min : vol_min;
2700 *max = (surf_max < vol_max) ? surf_max : vol_max;
2701 }
2702 else if (ret_surf > 0) {
2703 *min = surf_min;
2704 *max = surf_max;
2705 }
2706 else if (ret_vol > 0) {
2707 *min = vol_min;
2708 *max = vol_max;
2709 }
2710
2711 if (doexag) {
2712 *min *= Gv.vert_exag;
2713 *max *= Gv.vert_exag;
2714 }
2715
2716 G_debug(3, "GS_get_zrange(): min=%g max=%g", *min, *max);
2717 return ((ret_surf > 0 || ret_vol > 0) ? (1) : (-1));
2718}
2719
2720/*!
2721 \brief Get viewpoint 'from' position
2722
2723 \param[out] fr from model coordinates
2724 */
2725void GS_get_from(float *fr)
2726{
2727 GS_v3eq(fr, Gv.from_to[FROM]);
2728
2729 G_debug(3, "GS_get_from(): %f,%f,%f", fr[0], fr[1], fr[2]);
2730
2731 return;
2732}
2733
2734/*!
2735 \brief Get viewpoint 'from' real coordinates
2736
2737 \param[out] fr 'from' real coordinates
2738 */
2739void GS_get_from_real(float *fr)
2740{
2741 GS_v3eq(fr, Gv.from_to[FROM]);
2742 gsd_model2real(fr);
2743
2744 return;
2745}
2746
2747/*!
2748 \brief Get 'to' real coordinates
2749
2750 \param[out] to 'to' real coordinates
2751 */
2752void GS_get_to_real(float *to)
2753{
2754 float realto[3];
2755
2756 G_get_set_window(&wind);
2757 GS_get_focus(realto);
2758 to[X] = realto[X] + wind.west + (wind.ew_res / 2.);
2759 to[Y] = realto[Y] + wind.south + (wind.ns_res / 2.);
2760 to[Z] = realto[Z];
2761
2762 return;
2763}
2764
2765
2766/*!
2767 \brief Get zoom setup
2768
2769 \param[out] a,b,c,d current viewport settings
2770 \param[out] maxx,maxy max viewport size
2771 */
2772void GS_zoom_setup(int *a, int *b, int *c, int *d, int *maxx, int *maxy)
2773{
2774 GLint tmp[4];
2775 GLint num[2];
2776
2777 gsd_getViewport(tmp, num);
2778 *a = tmp[0];
2779 *b = tmp[1];
2780 *c = tmp[2];
2781 *d = tmp[3];
2782 *maxx = num[0];
2783 *maxy = num[1];
2784
2785 return;
2786}
2787
2788/*!
2789 \brief Get 'to' model coordinates
2790
2791 \todo need set_to? - just use viewdir?
2792
2793 \param[out] to 'to' model coordinates
2794 */
2795void GS_get_to(float *to)
2796{
2797 G_debug(3, "GS_get_to");
2798
2799 GS_v3eq(to, Gv.from_to[TO]);
2800
2801 return;
2802}
2803
2804/*!
2805 \brief Get viewdir
2806
2807 \param[out] dir viewdir value
2808 */
2809void GS_get_viewdir(float *dir)
2810{
2811 GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], dir);
2812
2813 return;
2814}
2815
2816/*!
2817 \brief Set viewdir
2818
2819 Automatically turns off focus
2820
2821 \param dir viewdir value
2822 */
2823void GS_set_viewdir(float *dir)
2824{
2825 float tmp[3];
2826
2827 GS_v3eq(tmp, dir);
2828 GS_v3norm(tmp);
2829 GS_v3eq(Gv.from_to[TO], Gv.from_to[FROM]);
2830 GS_v3add(Gv.from_to[TO], tmp);
2831
2833 gsd_set_view(&Gv, &Gd);
2834
2835 return;
2836}
2837
2838/*!
2839 \brief Set field of view
2840
2841 \param fov fov value
2842 */
2843void GS_set_fov(int fov)
2844{
2845 Gv.fov = fov;
2846
2847 return;
2848}
2849
2850/*!
2851 \brief Get fied of view
2852
2853 \return field of view, in 10ths of degrees
2854 */
2855int GS_get_fov(void)
2856{
2857 return (Gv.fov);
2858}
2859
2860/*!
2861 \brief Get twist value
2862
2863 10ths of degrees off twelve o'clock
2864 */
2866{
2867 return (Gv.twist);
2868}
2869
2870/*!
2871 \brief Set viewpoint twist value
2872
2873 10ths of degrees off twelve o'clock
2874
2875 \param t tenths of degrees clockwise from 12:00.
2876 */
2878{
2879 Gv.twist = t;
2880
2881 return;
2882}
2883
2884/*!
2885 \brief Set rotation params
2886 */
2887void GS_set_rotation(double angle, double x, double y, double z)
2888{
2889 Gv.rotate.rot_angle = angle;
2890 Gv.rotate.rot_axes[0] = x;
2891 Gv.rotate.rot_axes[1] = y;
2892 Gv.rotate.rot_axes[2] = z;
2893 Gv.rotate.do_rot = 1;
2894
2895 return;
2896}
2897
2898/*!
2899 \brief Stop scene rotation
2900 */
2902{
2903 Gv.rotate.do_rot = 0;
2904}
2905
2906/*!
2907 \brief Reset scene rotation
2908 */
2910{
2911 int i;
2912
2913 for (i = 0; i < 16; i++) {
2914 if (i == 0 || i == 5 || i == 10 || i == 15)
2915 Gv.rotate.rotMatrix[i] = 1.0;
2916 else
2917 Gv.rotate.rotMatrix[i] = 0.0;
2918 }
2919 Gv.rotate.rot_angle = 0.0;
2920 Gv.rotate.rot_axes[0] = 0.0;
2921 Gv.rotate.rot_axes[1] = 0.0;
2922 Gv.rotate.rot_axes[2] = 0.0;
2923 Gv.rotate.do_rot = 0;
2924
2925}
2926/*!
2927 * \brief Get rotation matrix
2928 */
2929void GS_get_rotation_matrix(double *matrix)
2930{
2931 int i;
2932
2933 for (i = 0; i < 16; i++) {
2934 matrix[i] = Gv.rotate.rotMatrix[i];
2935 }
2936}
2937
2938/*!
2939 * \brief Set rotation matrix
2940 */
2941void GS_set_rotation_matrix(double *matrix)
2942{
2943 int i;
2944
2945 for (i = 0; i < 16; i++) {
2946 Gv.rotate.rotMatrix[i] = matrix[i];
2947 }
2948}
2949
2950/*!
2951 \brief Unset focus
2952 */
2954{
2955 G_debug(3, "GS_set_nofocus");
2956
2957 Gv.infocus = 0;
2958
2959 return;
2960}
2961
2962/*!
2963 \brief Set focus
2964
2965 Make sure that the center of view is set
2966 */
2968{
2969 G_debug(3, "GS_set_infocus");
2970
2971 Gv.infocus = 1;
2972
2973 return;
2974}
2975
2976/*!
2977 \brief Set viewport
2978
2979 \param left,right,bottom,top viewport extent values
2980 */
2981void GS_set_viewport(int left, int right, int bottom, int top)
2982{
2983 G_debug(3, "GS_set_viewport(): left=%d, right=%d, "
2984 "bottom=%d, top=%d", left, right, bottom, top);
2985
2986 gsd_viewport(left, right, bottom, top);
2987
2988 return;
2989}
2990
2991/*!
2992 \brief Send screen coords sx and sy, lib traces through surfaces; sets
2993 new center to point of nearest intersection.
2994
2995 If no intersection, uses line of sight with length of current view
2996 ray (eye to center) to set new center.
2997
2998 Reset center of view to screen coordinates sx, sy.
2999
3000 \param sx,sy screen coordinates
3001
3002 \return 1 on success
3003 \return 0 on error (invalid surface id)
3004 */
3005int GS_look_here(int sx, int sy)
3006{
3007 float x, y, z, len, los[2][3];
3008 Point3 realto, dir;
3009 int id;
3010 geosurf *gs;
3011
3012 if (GS_get_selected_point_on_surface(sx, sy, &id, &x, &y, &z)) {
3013 gs = gs_get_surf(id);
3014 if (gs) {
3015 realto[X] = x - gs->ox + gs->x_trans;
3016 realto[Y] = y - gs->oy + gs->y_trans;
3017 realto[Z] = z + gs->z_trans;
3018 GS_set_focus(realto);
3019
3020 return (1);
3021 }
3022 }
3023 else {
3024 if (gsd_get_los(los, (short)sx, (short)sy)) {
3025 len = GS_distance(Gv.from_to[FROM], Gv.real_to);
3026 GS_v3dir(los[FROM], los[TO], dir);
3027 GS_v3mult(dir, len);
3028 realto[X] = Gv.from_to[FROM][X] + dir[X];
3029 realto[Y] = Gv.from_to[FROM][Y] + dir[Y];
3030 realto[Z] = Gv.from_to[FROM][Z] + dir[Z];
3031 GS_set_focus(realto);
3032
3033 return (1);
3034 }
3035 }
3036
3037 return (0);
3038}
3039
3040/*!
3041 \brief Get selected point of surface
3042
3043 Given screen coordinates sx and sy, find closest intersection of
3044 view ray with surfaces and return coordinates of intersection in x, y,
3045 z, and identifier of surface in id.
3046
3047 \param sx,sy screen coordinates
3048 \param[out] id surface id
3049 \param[out] x,y,z point on surface (model coordinates?)
3050
3051 \returns 0 if no intersections found
3052 \return number of intersections
3053 */
3054int GS_get_selected_point_on_surface(int sx, int sy, int *id, float *x,
3055 float *y, float *z)
3056{
3057 float los[2][3], find_dist[MAX_SURFS], closest;
3058 Point3 point, tmp, finds[MAX_SURFS];
3059 int surfs[MAX_SURFS], i, iclose, numhits = 0;
3060 geosurf *gs;
3061
3062 /* returns surface-world coords */
3063 gsd_get_los(los, (short)sx, (short)sy);
3064
3065 if (!gs_setlos_enterdata(los)) {
3066 G_debug(3, "gs_setlos_enterdata(los): returns false");
3067 return (0);
3068 }
3069
3070 for (i = 0; i < Next_surf; i++) {
3071 G_debug(3, "id=%d", i);
3072
3073 gs = gs_get_surf(Surf_ID[i]);
3074
3075 /* los_intersect expects surf-world coords (xy transl, no scaling) */
3076
3077#if NVIZ_HACK
3078 if (gs_los_intersect1(Surf_ID[i], los, point)) {
3079#else
3080 if (gs_los_intersect(Surf_ID[i], los, point)) {
3081#endif
3082 if (!gs_point_is_masked(gs, point)) {
3083 GS_v3eq(tmp, point);
3084 tmp[X] += gs->x_trans;
3085 tmp[Y] += gs->y_trans;
3086 tmp[Z] += gs->z_trans;
3087 find_dist[numhits] = GS_distance(los[FROM], tmp);
3088 gsd_surf2real(gs, point);
3089 GS_v3eq(finds[numhits], point);
3090 surfs[numhits] = Surf_ID[i];
3091 numhits++;
3092 }
3093 }
3094 }
3095
3096 for (i = iclose = 0; i < numhits; i++) {
3097 closest = find_dist[iclose];
3098
3099 if (find_dist[i] < closest) {
3100 iclose = i;
3101 }
3102 }
3103
3104 if (numhits) {
3105 *x = finds[iclose][X];
3106 *y = finds[iclose][Y];
3107 *z = finds[iclose][Z];
3108 *id = surfs[iclose];
3109 }
3110
3111 G_debug(3, "NumHits %d, next %d", numhits, Next_surf);
3112
3113 return (numhits);
3114}
3115
3116/*!
3117 \brief Set cplace rotation
3118
3119 \param num cplace id
3120 \param dx,dy,dz rotation values
3121 */
3122void GS_set_cplane_rot(int num, float dx, float dy, float dz)
3123{
3124 gsd_cplane_setrot(num, dx, dy, dz);
3125
3126 return;
3127}
3128
3129/*!
3130 \brief Set cplace trans
3131
3132 \param num cplace id
3133 \param dx,dy,dz rotation values
3134 */
3135void GS_set_cplane_trans(int num, float dx, float dy, float dz)
3136{
3137 gsd_cplane_settrans(num, dx, dy, dz);
3138
3139 return;
3140}
3141
3142
3143/*!
3144 \brief Draw cplace
3145
3146 \param num cplace id
3147 */
3148void GS_draw_cplane(int num)
3149{
3150 geosurf *gsurfs[MAX_SURFS];
3151 int nsurfs;
3152
3153 nsurfs = gs_num_surfaces();
3154 if (2 == nsurfs) {
3155 /* testing */
3156 gs_getall_surfaces(gsurfs);
3157 gsd_draw_cplane_fence(gsurfs[0], gsurfs[1], num);
3158 }
3159 else {
3160 gsd_draw_cplane(num);
3161 }
3162
3163 return;
3164}
3165
3166/*!
3167 \brief Draw cplace fence ?
3168
3169 \param hs1,hs2
3170 \param num cplane id
3171
3172 \return 0 on error
3173 \return 1 on success
3174 */
3175int GS_draw_cplane_fence(int hs1, int hs2, int num)
3176{
3177 geosurf *gs1, *gs2;
3178
3179 if (NULL == (gs1 = gs_get_surf(hs1))) {
3180 return (0);
3181 }
3182
3183 if (NULL == (gs2 = gs_get_surf(hs2))) {
3184 return (0);
3185 }
3186
3187 gsd_draw_cplane_fence(gs1, gs2, num);
3188
3189 return (1);
3190}
3191
3192/*!
3193 \brief Draw all cplace fences ?
3194 */
3196{
3197 int onstate[MAX_CPLANES], i;
3198
3199 gsd_get_cplanes_state(onstate);
3200
3201 for (i = 0; i < MAX_CPLANES; i++) {
3202 if (onstate[i]) {
3203 GS_draw_cplane_fence(Surf_ID[0], Surf_ID[1], i);
3204 }
3205 }
3206
3207 return;
3208}
3209
3210/*!
3211 \brief Set cplace
3212
3213 \param num cplane id
3214 */
3215void GS_set_cplane(int num)
3216{
3217 gsd_cplane_on(num);
3218
3219 return;
3220}
3221
3222/*!
3223 \brief Unset clip place (turn off)
3224
3225 \param num cplane id
3226 */
3227void GS_unset_cplane(int num)
3228{
3229 gsd_cplane_off(num);
3230
3231 return;
3232}
3233
3234/*!
3235 \brief Get axis scale
3236
3237 \param sx,sy,sz x/y/z scale values
3238 \param doexag use vertical exaggeration
3239 */
3240void GS_get_scale(float *sx, float *sy, float *sz, int doexag)
3241{
3242 float zexag;
3243
3244 zexag = doexag ? Gv.vert_exag : 1.;
3245 *sx = *sy = Gv.scale;
3246 *sz = Gv.scale * zexag;
3247
3248 return;
3249}
3250
3251/*!
3252 \brief Set fence color
3253
3254 \param mode mode id
3255 */
3256void GS_set_fencecolor(int mode)
3257{
3258 gsd_setfc(mode);
3259
3260 return;
3261}
3262
3263/*!
3264 \brief Get fence color
3265
3266 \return color value
3267 */
3269{
3270 return gsd_getfc();
3271}
3272
3273/*!
3274 \brief Measure distance "as the ball rolls" between two points on
3275 surface
3276
3277 \param hs surface id
3278 \param x1,y1,x2,y2 two points on surface
3279 \param[out] dist measured distance
3280 \param use_exag use exag. surface
3281
3282 \return 0 on error or if one or more points is not in region
3283 \return distance following terrain
3284 */
3285int GS_get_distance_alongsurf(int hs, float x1, float y1, float x2, float y2,
3286 float *dist, int use_exag)
3287{
3288 geosurf *gs;
3289 float p1[2], p2[2];
3290
3291 gs = gs_get_surf(hs);
3292 if (gs == NULL) {
3293 return 0;
3294 }
3295
3296 p1[X] = x1;
3297 p1[Y] = y1;
3298 p2[X] = x2;
3299 p2[Y] = y2;
3300 gsd_real2surf(gs, p1);
3301 gsd_real2surf(gs, p2);
3302
3303 G_debug(3, "GS_get_distance_alongsurf(): hs=%d p1=%f,%f p2=%f,%f",
3304 hs, x1, y1, x2, y2);
3305 return gs_distance_onsurf(gs, p1, p2, dist, use_exag);
3306}
3307
3308/*!
3309 \brief Save 3d view
3310
3311 \param vname view file name
3312 \param surfid surface id
3313
3314 \return ?
3315 */
3316int GS_save_3dview(const char *vname, int surfid)
3317{
3318 return (Gs_save_3dview(vname, &Gv, &Gd, &wind, gs_get_surf(surfid)));
3319}
3320
3321/*!
3322 \brief Load 3d view
3323
3324 \param vname view file name
3325 \param surfid surface id
3326
3327 \return ?
3328 */
3329int GS_load_3dview(const char *vname, int surfid)
3330{
3331
3332 return (Gs_load_3dview(vname, &Gv, &Gd, &wind, gs_get_surf(surfid)));
3333
3334 /* what to do about lights - I guess, delete all &
3335 create any that exist in 3dview file */
3336}
3337
3338/************************************************************************
3339* Following routines use Graphics Library
3340************************************************************************/
3341
3342/*!
3343 \brief Init viewpoint
3344
3345 \todo allow setting center?
3346 */
3348{
3349 static int first = 1;
3350
3351 G_debug(3, "GS_init_view");
3352
3353 if (first) {
3354 first = 0;
3355 glMatrixMode(GL_MODELVIEW);
3356
3357 /* OGLXXX doublebuffer: use GLX_DOUBLEBUFFER in attriblist */
3358 /* glxChooseVisual(*dpy, screen, *attriblist); */
3359 /* OGLXXX
3360 * ZMIN not needed -- always 0.
3361 * ZMAX not needed -- always 1.
3362 * getgdesc other posiblilties:
3363 * glxGetConfig();
3364 * glxGetCurrentContext();
3365 * glxGetCurrentDrawable();
3366 * GLint gdtmp;
3367 * getgdesc other posiblilties:
3368 * glxGetConfig();
3369 * glxGetCurrentContext();
3370 * glxGetCurrentDrawable();
3371 * GLint gdtmp;
3372 * glDepthRange params must be scaled to [0, 1]
3373 */
3374 glDepthRange(0.0, 1.0);
3375 glEnable(GL_DEPTH_TEST);
3376 glDepthFunc(GL_LEQUAL);
3377 /* } */
3378
3379 /* replace these with something meaningful */
3380 Gv.fov = 450;
3381 Gv.twist = 0;
3382
3384
3385 Gv.from_to[FROM][X] = Gv.from_to[FROM][Y] =
3386 Gv.from_to[FROM][Z] = GS_UNIT_SIZE / 2.;
3387
3388 Gv.from_to[TO][X] = GS_UNIT_SIZE / 2.;
3389 Gv.from_to[TO][Y] = GS_UNIT_SIZE / 2.;
3390 Gv.from_to[TO][Z] = 0.;
3391 Gv.from_to[TO][W] = Gv.from_to[FROM][W] = 1.;
3392
3393 Gv.real_to[W] = 1.;
3394 Gv.vert_exag = 1.;
3395
3396 GS_v3eq(Gv.real_to, Gv.from_to[TO]);
3397 GS_v3normalize(Gv.from_to[FROM], Gv.from_to[TO]);
3398
3399 /*
3400 Gd.nearclip = 50;
3401 Gd.farclip = 10000.;
3402 */
3403 Gd.nearclip = 10.;
3404 Gd.farclip = 10000.;
3405 Gd.aspect = (float)GS_get_aspect();
3406
3407 GS_set_focus(Gv.real_to);
3408 }
3409
3410 return;
3411}
3412
3413/*!
3414 \brief Clear view
3415
3416 \param col color value
3417 */
3418void GS_clear(int col)
3419{
3420 G_debug(3, "GS_clear");
3421
3422 col = col | 0xFF000000;
3423
3424 /* OGLXXX
3425 * change glClearDepth parameter to be in [0, 1]
3426 * ZMAX not needed -- always 1.
3427 * getgdesc other posiblilties:
3428 * glxGetConfig();
3429 * glxGetCurrentContext();
3430 * glxGetCurrentDrawable();
3431 * GLint gdtmp;
3432 */
3433 glClearDepth(1.0);
3434 glClearColor(((float)((col) & 0xff)) / 255.,
3435 (float)((col) >> 8 & 0xff) / 255.,
3436 (float)((col) >> 16 & 0xff) / 255.,
3437 (float)((col) >> 24 & 0xff) / 255.);
3438 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
3439
3440 Gd.bgcol = col;
3441 Modelshowing = 0;
3442 gsd_flush();
3443
3444 return;
3445}
3446
3447/*!
3448 \brief Get aspect value
3449
3450 \return aspect value
3451 */
3452double GS_get_aspect(void)
3453{
3454 int left, right, bottom, top;
3455 GLint tmp[4];
3456
3457 /* OGLXXX
3458 * get GL_VIEWPORT:
3459 * You can probably do better than this.
3460 */
3461 glGetIntegerv(GL_VIEWPORT, tmp);
3462 left = tmp[0];
3463 right = tmp[0] + tmp[2] - 1;
3464 bottom = tmp[1];
3465 top = tmp[1] + tmp[3] - 1;
3466
3467 G_debug(3, "GS_get_aspect(): left=%d, right=%d, top=%d, bottom=%d",
3468 left, right, top, bottom);
3469
3470 return ((double)(right - left) / (top - bottom));
3471}
3472
3473/*!
3474 \brief Check for transparency
3475
3476 Disabled.
3477
3478 \return 1
3479 */
3481{
3482 /* OGLXXX
3483 * getgdesc other posiblilties:
3484 * glxGetConfig();
3485 * glxGetCurrentContext();
3486 * glxGetCurrentDrawable();
3487 * GLint gdtmp;
3488 * blending is ALWAYS supported.
3489 * This function returns whether it is enabled.
3490 * return((glGetIntegerv(GL_BLEND, &gdtmp), gdtmp));
3491 */
3492
3493 return (1);
3494}
#define NULL
Definition: ccmath.h:32
#define TRUE
Definition: dbfopen.c:183
#define FALSE
Definition: dbfopen.c:182
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: debug.c:65
double b
double t
double r
const char * G_find_raster2(const char *name, const char *mapset)
Find a raster map (look but don't touch)
Definition: find_rast.c:76
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition: gis/error.c:160
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: gis/error.c:204
void G_get_set_window(struct Cell_head *window)
Get the current working window (region)
void gpd_obj(geosurf *gs, gvstyle *style, Point3 pt)
Draw point representing object.
Definition: gpd.c:71
void GS_unset_cplane(int num)
Unset clip place (turn off)
Definition: gs2.c:3227
void GS_zoom_setup(int *a, int *b, int *c, int *d, int *maxx, int *maxy)
Get zoom setup.
Definition: gs2.c:2772
int GS_get_twist(void)
Get twist value.
Definition: gs2.c:2865
void GS_set_cplane_rot(int num, float dx, float dy, float dz)
Set cplace rotation.
Definition: gs2.c:3122
int GS_get_zextents(int id, float *min, float *max, float *mid)
Get z-extent for a single surface.
Definition: gs2.c:2666
int GS_setall_drawres(int xres, int yres, int xwire, int ywire)
Set all draw resolutions.
Definition: gs2.c:2198
int GS_set_SDscale(float scale)
Set ?
Definition: gs2.c:1070
void GS_set_global_exag(float exag)
Set global z-exag value.
Definition: gs2.c:1977
int GS_new_surface(void)
Add new surface.
Definition: gs2.c:224
void GS_draw_list(GLuint list_id)
Draw pre-defined list.
Definition: gs2.c:866
void GS_alldraw_cplane_fences(void)
Draw all cplace fences ?
Definition: gs2.c:3195
void GS_get_zrange_nz(float *min, float *max)
Get Z extents for all loaded surfaces.
Definition: gs2.c:2357
void GS_draw_X(int id, float *pt)
Draw place marker.
Definition: gs2.c:639
void GS_set_cplane_trans(int num, float dx, float dy, float dz)
Set cplace trans.
Definition: gs2.c:3135
void GS_draw_surf(int id)
Draw surface.
Definition: gs2.c:1864
void GS_draw_all_list(void)
Draw all glLists.
Definition: gs2.c:879
void GS_set_focus(float *realto)
Set focus.
Definition: gs2.c:2520
void GS_getlight_color(int num, float *red, float *green, float *blue)
Get light color.
Definition: gs2.c:380
int GS_update_normals(int id)
Update normals.
Definition: gs2.c:1119
void GS_set_infocus(void)
Set focus.
Definition: gs2.c:2967
int GS_get_light_reset(void)
Definition: gs2.c:258
int GS_load_att_map(int id, const char *filename, int att)
Load raster map as attribute.
Definition: gs2.c:1608
unsigned int GS_default_draw_color(void)
Get default draw color.
Definition: gs2.c:2439
void GS_set_focus_real(float *realto)
Set real focus.
Definition: gs2.c:2538
void GS_set_rotation_matrix(double *matrix)
Set rotation matrix.
Definition: gs2.c:2941
void GS_get_from(float *fr)
Get viewpoint 'from' position.
Definition: gs2.c:2725
void GS_get_dims(int id, int *rows, int *cols)
Get dimension of surface.
Definition: gs2.c:2279
void GS_switchlight(int num, int on)
Switch on/off light.
Definition: gs2.c:473
void GS_draw_cplane(int num)
Draw cplace.
Definition: gs2.c:3148
void GS_get_viewdir(float *dir)
Get viewdir.
Definition: gs2.c:2809
void GS_alldraw_wire(void)
Draw all wires.
Definition: gs2.c:1919
void GS_clear(int col)
Clear view.
Definition: gs2.c:3418
void GS_getlight_ambient(int num, float *red, float *green, float *blue)
Get light ambient.
Definition: gs2.c:424
void GS_init_rotation(void)
Reset scene rotation.
Definition: gs2.c:2909
void GS_set_focus_center_map(int id)
Set focus to map center.
Definition: gs2.c:2582
int GS_set_drawres(int id, int xres, int yres, int xwire, int ywire)
Set draw resolution for surface.
Definition: gs2.c:2221
int GS_look_here(int sx, int sy)
Send screen coords sx and sy, lib traces through surfaces; sets new center to point of nearest inters...
Definition: gs2.c:3005
void GS_set_cplane(int num)
Set cplace.
Definition: gs2.c:3215
int GS_get_att(int id, int att, int *set, float *constant, char *mapname)
Get attributes.
Definition: gs2.c:1140
int GS_delete_surface(int id)
Delete surface.
Definition: gs2.c:1566
int GS_update_curmask(int id)
Update current mask.
Definition: gs2.c:997
int * GS_get_surf_list(int *numsurfs)
Get surface list.
Definition: gs2.c:1539
int GS_get_SDscale(float *scale)
Get ?
Definition: gs2.c:1105
double GS_get_aspect(void)
Get aspect value.
Definition: gs2.c:3452
int GS_get_selected_point_on_surface(int sx, int sy, int *id, float *x, float *y, float *z)
Get selected point of surface.
Definition: gs2.c:3054
int GS_get_SDsurf(int *id)
Get ?
Definition: gs2.c:1085
void GS_get_modelposition(float *siz, float *pos)
Retrieves coordinates for lighting model position, at center of view.
Definition: gs2.c:531
int GS_new_light(void)
Add new model light.
Definition: gs2.c:268
int GS_draw_nline_onsurf(int id, float x1, float y1, float x2, float y2, float *lasp, int n)
Draw multiline on surface.
Definition: gs2.c:718
void GS_get_trans(int id, float *xtrans, float *ytrans, float *ztrans)
Get translation values (surface position)
Definition: gs2.c:2415
int GS_get_distance_alongsurf(int hs, float x1, float y1, float x2, float y2, float *dist, int use_exag)
Measure distance "as the ball rolls" between two points on surface.
Definition: gs2.c:3285
int GS_get_zrange(float *min, float *max, int doexag)
Get z-extent for all loaded surfaces.
Definition: gs2.c:2689
int GS_save_3dview(const char *vname, int surfid)
Save 3d view.
Definition: gs2.c:3316
int GS_get_val_at_xy(int id, int att, char *valstr, float x, float y)
Get RGB color at given point.
Definition: gs2.c:1310
void GS_draw_line_onsurf(int id, float x1, float y1, float x2, float y2)
Draw line on surface.
Definition: gs2.c:680
void GS_set_viewdir(float *dir)
Set viewdir.
Definition: gs2.c:2823
void GS_draw_flowline_at_xy(int id, float x, float y)
Draw flow-line on surace.
Definition: gs2.c:756
void GS_moveto(float *pt)
Move viewpoint.
Definition: gs2.c:2617
void GS_get_scale(float *sx, float *sy, float *sz, int doexag)
Get axis scale.
Definition: gs2.c:3240
int GS_get_fov(void)
Get fied of view.
Definition: gs2.c:2855
int GS_transp_is_set(void)
Check if transparency is set.
Definition: gs2.c:492
void GS_libinit(void)
Initialize OGSF library.
Definition: gs2.c:97
void GS_setlight_color(int num, float red, float green, float blue)
Set light color.
Definition: gs2.c:358
int GS_get_fencecolor(void)
Get fence color.
Definition: gs2.c:3268
void void_func(void)
Definition: gs2.c:85
int GS_get_nozero(int id, int att, int *mode)
Get no-zero ?
Definition: gs2.c:2164
void GS_set_trans(int id, float xtrans, float ytrans, float ztrans)
Set translation (surface position)
Definition: gs2.c:2391
int GS_get_region(float *n, float *s, float *w, float *e)
Get 2D region extent.
Definition: gs2.c:156
void GS_get_drawres(int id, int *xres, int *yres, int *xwire, int *ywire)
Get draw resolution of surface.
Definition: gs2.c:2255
void GS_delete_list(GLuint list_id)
Delete pre-defined list.
Definition: gs2.c:891
void GS_get_rotation_matrix(double *matrix)
Get rotation matrix.
Definition: gs2.c:2929
void GS_unset_SDsurf(void)
Unset Scaled Difference surface.
Definition: gs2.c:1033
void GS_set_nozero(int id, int att, int mode)
Set no-zero ?
Definition: gs2.c:2131
void GS_set_Narrow(int *pt, int id, float *pos2)
Set decoration, north arrow ??
Definition: gs2.c:568
int GS_get_focus(float *realto)
Get focus.
Definition: gs2.c:2563
int GS_num_surfs(void)
Get number of surfaces.
Definition: gs2.c:1524
void GS_draw_fringe(int id, unsigned long clr, float elev, int *where)
Draw fringe around data (surface) at selected corners.
Definition: gs2.c:823
void GS_unset_rotation(void)
Stop scene rotation.
Definition: gs2.c:2901
int GS_get_wire_color(int id, int *colr)
Get wire color.
Definition: gs2.c:2038
int GS_is_masked(int id, float *pt)
Check if point is masked ?
Definition: gs2.c:1015
void GS_draw_lighting_model(void)
Draw lighting model.
Definition: gs2.c:941
void GS_set_fencecolor(int mode)
Set fence color.
Definition: gs2.c:3256
int GS_get_exag_guess(int id, float *exag)
Get exag-value guess.
Definition: gs2.c:2306
void GS_set_rotation(double angle, double x, double y, double z)
Set rotation params.
Definition: gs2.c:2887
void GS_set_light_reset(int i)
Definition: gs2.c:252
int GS_get_maskmode(int id, int *mode)
Get mask mode.
Definition: gs2.c:1461
int GS_get_drawmode(int id, int *mode)
Get draw mode.
Definition: gs2.c:2109
void GS_get_to(float *to)
Get 'to' model coordinates.
Definition: gs2.c:2795
void GS_set_wire_color(int id, int colr)
Set wire color.
Definition: gs2.c:2014
void GS_lights_on(void)
Switch on all lights.
Definition: gs2.c:456
void GS_set_exag(int id, float exag)
Set Z exag for surface.
Definition: gs2.c:1953
void GS_ready_draw(void)
Definition: gs2.c:2488
int GS_surf_exists(int id)
Definition: gs2.c:194
int gsd_getViewport(GLint *, GLint *)
int GS_draw_cplane_fence(int hs1, int hs2, int num)
Draw cplace fence ?
Definition: gs2.c:3175
void GS_setlight_position(int num, float xpos, float ypos, float zpos, int local)
Set light position.
Definition: gs2.c:309
unsigned int GS_background_color(void)
Get background color.
Definition: gs2.c:2452
int GS_set_drawmode(int id, int mode)
Set draw mode.
Definition: gs2.c:2083
void GS_alldraw_surf(void)
Draw all surfaces.
Definition: gs2.c:1936
int GS_setall_drawmode(int mode)
Set all draw-modes.
Definition: gs2.c:2061
void GS_init_view(void)
Init viewpoint.
Definition: gs2.c:3347
int GS_set_SDsurf(int id)
Set surface as Scaled Difference surface.
Definition: gs2.c:1049
void GS_setlight_ambient(int num, float red, float green, float blue)
Set light ambient.
Definition: gs2.c:402
void GS_set_draw(int where)
Sets which buffer to draw to.
Definition: gs2.c:2462
int GS_get_cat_at_xy(int id, int att, char *catstr, float x, float y)
Get surface category on given position.
Definition: gs2.c:1183
int GS_draw_legend(const char *name, GLuint fontbase, int size, int *flags, float *range, int *pt)
Draw legend.
Definition: gs2.c:848
void GS_moveto_real(float *pt)
Move position to (real)
Definition: gs2.c:2647
void GS_get_from_real(float *fr)
Get viewpoint 'from' real coordinates.
Definition: gs2.c:2739
int GS_set_att_const(int id, int att, float constant)
Set attribute constant.
Definition: gs2.c:1412
int GS_Set_ClientData(int id, void *clientd)
Set client data.
Definition: gs2.c:1485
int GS_load_3dview(const char *vname, int surfid)
Load 3d view.
Definition: gs2.c:3329
void GS_set_att_defaults(float *defs, float *null_defs)
Set default attributes for map objects.
Definition: gs2.c:172
void GS_draw_lighting_model1(void)
Draw lighting model.
Definition: gs2.c:901
void GS_set_nofocus(void)
Unset focus.
Definition: gs2.c:2953
int GS_get_longdim(float *dim)
Get largest dimension.
Definition: gs2.c:140
int GS_unset_att(int id, int att)
Unset attribute.
Definition: gs2.c:1393
void GS_set_viewport(int left, int right, int bottom, int top)
Set viewport.
Definition: gs2.c:2981
void GS_getlight_position(int num, float *xpos, float *ypos, float *zpos, int *local)
Get light position.
Definition: gs2.c:335
void GS_done_draw(void)
Draw done, swap buffers.
Definition: gs2.c:2501
void GS_set_fov(int fov)
Set field of view.
Definition: gs2.c:2843
void GS_get_modelposition1(float pos[])
Retrieves coordinates for lighting model position, at center of view.
Definition: gs2.c:502
int GS_get_norm_at_xy(int id, float x, float y, float *nv)
Get surface normal at x,y (real coordinates)
Definition: gs2.c:1246
int GS_set_maskmode(int id, int mode)
Set mask mode.
Definition: gs2.c:1436
void * GS_Get_ClientData(int id)
Get client data.
Definition: gs2.c:1507
int GS_has_transparency(void)
Check for transparency.
Definition: gs2.c:3480
void GS_draw_wire(int id)
Draw surface wire.
Definition: gs2.c:1899
void GS_lights_off(void)
Switch off all lights.
Definition: gs2.c:442
void GS_get_to_real(float *to)
Get 'to' real coordinates.
Definition: gs2.c:2752
void GS_set_twist(int t)
Set viewpoint twist value.
Definition: gs2.c:2877
float GS_global_exag(void)
Get global z-exag value.
Definition: gs2.c:1999
int Gs_load_3dview(const char *vname, geoview *gv, geodisplay *gd, struct Cell_head *w, const geosurf *defsurf)
Load 3dview.
Definition: gs3.c:951
int Gs_loadmap_as_short(struct Cell_head *wind, const char *map_name, short *buff, struct BM *nullmap, int *has_null)
Load raster map as integer map.
Definition: gs3.c:312
int Gs_loadmap_as_bitmap(struct Cell_head *wind, const char *map_name, struct BM *buff)
Load raster map as integer map.
Definition: gs3.c:517
int Gs_numtype(const char *filename, int *negflag)
Get map data type.
Definition: gs3.c:230
void Gs_pack_colors(const char *filename, int *buff, int rows, int cols)
Pack color table.
Definition: gs3.c:636
void Gs_pack_colors_float(const char *filename, float *fbuf, int *ibuf, int rows, int cols)
Pack color table (floating-point map)
Definition: gs3.c:705
int Gs_loadmap_as_char(struct Cell_head *wind, const char *map_name, unsigned char *buff, struct BM *nullmap, int *has_null)
Load raster map as integer map.
Definition: gs3.c:417
int Gs_save_3dview(const char *vname, geoview *gv, geodisplay *gd, struct Cell_head *w, geosurf *defsurf)
Save 3dview.
Definition: gs3.c:853
int Gs_loadmap_as_float(struct Cell_head *wind, const char *map_name, float *buff, struct BM *nullmap, int *has_null)
Load raster map as floating point map.
Definition: gs3.c:114
int Gs_get_cat_label(const char *filename, int drow, int dcol, char *catstr)
Get categories/labels.
Definition: gs3.c:776
int Gs_build_256lookup(const char *filename, int *buff)
Build color table (256)
Definition: gs3.c:576
int Gs_update_attrange(geosurf *gs, int desc)
Update no_zero ranges for attribute (actually no_null now)
Definition: gs3.c:1087
int Gs_loadmap_as_int(struct Cell_head *wind, const char *map_name, int *buff, struct BM *nullmap, int *has_null)
Load raster map as integer map.
Definition: gs3.c:178
int gs_get_datacenter(float *cen)
Get data center point.
Definition: gs.c:1232
int gs_get_zextents(geosurf *gs, float *min, float *max, float *mid)
Get z-extent values.
Definition: gs.c:998
int gs_get_zrange(float *min, float *max)
Get z-range.
Definition: gs.c:1088
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:827
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
geosurf * gs_get_surf(int id)
Get geosurf struct.
Definition: gs.c:62
int gs_set_att_const(geosurf *gs, int desc, float constant)
Set attribute constant value.
Definition: gs.c:872
int gs_malloc_lookup(geosurf *gs, int desc)
Allocate attribute lookup.
Definition: gs.c:746
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:803
int gs_getall_surfaces(geosurf **gsurfs)
Get array of geosurf structs.
Definition: gs.c:108
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
void gs_init(void)
Initialize library.
Definition: gs.c:47
geosurf * gs_get_new_surface(void)
Allocate new geosurf struct.
Definition: gs.c:193
int gs_distance_onsurf(geosurf *gs, float *p1, float *p2, float *dist, int use_exag)
Calculate distance on surface.
Definition: gs.c:1417
int gs_num_surfaces(void)
Get number of surfaces.
Definition: gs.c:127
int gs_init_normbuff(geosurf *gs)
Init geosurf normbuff.
Definition: gs.c:306
typbuff * gs_get_att_typbuff(geosurf *gs, int desc, int to_write)
Get attribute data buffer.
Definition: gs.c:681
int gs_point_is_masked(geosurf *gs, float *pt)
Check if point is masked.
Definition: gs.c:1317
int gs_get_data_avg_zmax(float *azmax)
Get average z-max value.
Definition: gs.c:1203
int gs_att_is_set(geosurf *surf, IFLAG att)
Check if attribute is set.
Definition: gs.c:149
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
int gs_update_curmask(geosurf *surf)
Update current maps.
Definition: gs_bm.c:232
int gs_calc_normals(geosurf *gs)
Calculate normals.
Definition: gs_norms.c:124
int gs_los_intersect1(int surfid, float(*los)[3], float *point)
Crude method of intersecting line of sight with closest part of surface.
Definition: gs_query.c:52
int gs_setlos_enterdata(Point3 *los)
Definition: gs_query.c:529
int gs_los_intersect(int surfid, float **los, float *point)
Crude method of intersecting line of sight with closest part of surface.
Definition: gs_query.c:191
void GS_v3sub(float *v1, float *v2)
Subtract vectors.
Definition: gs_util.c:212
void GS_v3mult(float *v1, float k)
Multiple vectors.
Definition: gs_util.c:229
int GS_coordpair_repeats(float *p1, float *p2, int nhist)
ADD.
Definition: gs_util.c:443
float GS_distance(float *from, float *to)
Calculate distance.
Definition: gs_util.c:141
int GS_v2norm(float *v1)
Change v1 so that it is a unit vector (3D)
Definition: gs_util.c:271
void GS_v3add(float *v1, float *v2)
Sum vectors.
Definition: gs_util.c:195
int GS_v3norm(float *v1)
Change v1 so that it is a unit vector (2D)
Definition: gs_util.c:246
void GS_v3eq(float *v1, float *v2)
Copy vector values.
Definition: gs_util.c:178
int GS_v3dir(float *v1, float *v2, float *v3)
Get a normalized direction from v1 to v2, store in v3.
Definition: gs_util.c:353
int GS_v3normalize(float *v1, float *v2)
Change v2 so that v1v2 is a unit vector.
Definition: gs_util.c:322
void gsd_cplane_off(int num)
Turn off clip plane.
Definition: gsd_cplane.c:126
void gsd_get_cplanes_state(int *onstate)
Get cplane state.
Definition: gsd_cplane.c:142
void gsd_cplane_settrans(int num, float tx, float ty, float tz)
ADD.
Definition: gsd_cplane.c:229
void gsd_draw_cplane_fence(geosurf *surf1, geosurf *surf2, int cpnum)
ADD.
Definition: gsd_cplane.c:247
void gsd_draw_cplane(int num)
Draw cplane.
Definition: gsd_cplane.c:296
void gsd_cplane_setrot(int num, float rx, float ry, float rz)
ADD.
Definition: gsd_cplane.c:211
void gsd_cplane_on(int num)
ADD.
Definition: gsd_cplane.c:104
void gsd_display_fringe(geosurf *surf, unsigned long clr, float elev, int where[4])
Display fridge.
Definition: gsd_fringe.c:51
GLuint gsd_put_legend(const char *name, GLuint fontbase, int size, int *flags, float *rangef, int *pt)
Put legend.
Definition: gsd_legend.c:202
void gsd_line_onsurf(geosurf *gs, float *v1, float *v2)
Line on surface, fix z-values.
Definition: gsd_objs.c:189
void gsd_drawsphere(float *center, unsigned long colr, float siz)
Draw sphere.
Definition: gsd_objs.c:565
int gsd_nline_onsurf(geosurf *gs, float *v1, float *v2, float *pt, int n)
Multiline on surface, fix z-values.
Definition: gsd_objs.c:235
void gsd_viewport(int l, int r, int b, int t)
Set the viewport.
Definition: gsd_prim.c:1079
void gsd_backface(int n)
ADD.
Definition: gsd_prim.c:253
void gsd_pushmatrix(void)
Push the current matrix stack.
Definition: gsd_prim.c:510
void gsd_calllist(int listno)
ADD.
Definition: gsd_prim.c:1176
void gsd_zwritemask(unsigned long n)
Write out z-mask.
Definition: gsd_prim.c:240
void gsd_deflight(int num, struct lightdefs *vals)
Define light.
Definition: gsd_prim.c:839
void gsd_switchlight(int num, int on)
Switch light on/off.
Definition: gsd_prim.c:880
#define INT_TO_GRN(i, g)
Definition: gsd_prim.c:53
void gsd_colormode(int cm)
Set color mode.
Definition: gsd_prim.c:97
void gsd_init_lightmodel(void)
Initialize model light.
Definition: gsd_prim.c:722
void gsd_swapbuffers(void)
Swap buffers.
Definition: gsd_prim.c:481
#define INT_TO_RED(i, r)
Definition: gsd_prim.c:52
#define INT_TO_BLU(i, b)
Definition: gsd_prim.c:54
void gsd_backbuffer(void)
Draw to the back buffer.
Definition: gsd_prim.c:469
void gsd_popmatrix(void)
Pop the current matrix stack.
Definition: gsd_prim.c:500
void gsd_flush(void)
Mostly for flushing drawing commands across a network.
Definition: gsd_prim.c:83
void gsd_calllists(int listno)
ADD.
Definition: gsd_prim.c:1189
void gsd_deletelist(GLuint listno, int range)
Delete list.
Definition: gsd_prim.c:1156
void gsd_scale(float xs, float ys, float zs)
Multiply the current matrix by a general scaling matrix.
Definition: gsd_prim.c:524
void gsd_translate(float dx, float dy, float dz)
Multiply the current matrix by a translation matrix.
Definition: gsd_prim.c:538
void gsd_color_func(unsigned int col)
Set current color.
Definition: gsd_prim.c:701
void gsd_shademodel(int shade)
Set shaded model.
Definition: gsd_prim.c:418
void gsd_bothbuffers(void)
Draw to the front and back buffers.
Definition: gsd_prim.c:445
void gsd_frontbuffer(void)
Draw to the front buffer.
Definition: gsd_prim.c:457
void gsd_linewidth(short n)
Set width of rasterized lines.
Definition: gsd_prim.c:266
int gsd_getfc(void)
ADD.
Definition: gsd_surf.c:1220
void gsd_setfc(int mode)
ADD.
Definition: gsd_surf.c:1208
int gsd_surf(geosurf *surf)
ADD.
Definition: gsd_surf.c:81
void gsd_real2model(Point3 point)
Convert real to model coordinates.
Definition: gsd_views.c:373
void gsd_surf2real(geosurf *gs, Point3 point)
Convert surface to real coordinates.
Definition: gsd_views.c:464
int gsd_get_los(float(*vect)[3], short sx, short sy)
ADD.
Definition: gsd_views.c:40
void gsd_real2surf(geosurf *gs, Point3 point)
Convert real to surface coordinates.
Definition: gsd_views.c:480
void gsd_model2real(Point3 point)
Convert model to real coordinates.
Definition: gsd_views.c:393
void gsd_do_scale(int doexag)
Set current scale.
Definition: gsd_views.c:355
void gsd_set_view(geoview *gv, geodisplay *gd)
Set view.
Definition: gsd_views.c:146
int gsd_wire_surf(geosurf *surf)
Draw surface wire.
Definition: gsd_wire.c:47
void gsdiff_set_SDscale(float scale)
Set scale.
Definition: gsdiff.c:42
float gsdiff_get_SDscale(void)
Get scale.
Definition: gsdiff.c:54
void gsdiff_set_SDref(geosurf *gsref)
ADD.
Definition: gsdiff.c:64
geosurf * gsdiff_get_SDref(void)
ADD.
Definition: gsdiff.c:77
int in_vregion(geosurf *gs, float *pt)
ADD.
Definition: gsdrape.c:696
int _viewcell_tri_interp(geosurf *gs, Point3 pt)
ADD.
Definition: gsdrape.c:467
char * gsds_get_name(int id)
Get name.
Definition: gsds.c:303
int gsds_newh(const char *name)
Get handle to gsds.
Definition: gsds.c:219
int gsds_findh(const char *name, IFLAG *changes, IFLAG *types, int begin)
Get handle to gsds.
Definition: gsds.c:188
int gsds_set_changed(int id, IFLAG reason)
ADD.
Definition: gsds.c:635
int gsds_free_data_buff(int id, int typ)
Free allocated buffer.
Definition: gsds.c:369
#define FNORM(i, nv)
Definition: gsget.h:50
#define GET_MAPATT(buff, offset, att)
Definition: gsget.h:27
void(* Cxl_func)()
Definition: gsx.c:21
void gv_update_drapesurfs(void)
Update drape surfaces.
Definition: gv.c:154
int gvl_get_zrange(float *min, float *max)
Get volume z-range value.
Definition: gvl.c:476
float g
Definition: named_colr.c:8
const char * name
Definition: named_colr.c:7
char * G_fully_qualified_name(const char *name, const char *mapset)
Get fully qualified element name.
Definition: nme_in_mps.c:101
#define min(a, b)
#define max(a, b)
#define VYRES(gs)
Definition: rowcol.h:10
#define Y2VROW(gs, py)
Definition: rowcol.h:27
#define VXRES(gs)
Definition: rowcol.h:9
#define DRC2OFF(gs, drow, dcol)
Definition: rowcol.h:17
#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 x
#define Y(j)