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