1 /*!
2 \file lib/ogsf/gs3.c
3
4 \brief OGSF library - loading surfaces (lower level functions)
5
6 GRASS OpenGL gsurf OGSF Library
7
8 (C) 1999-2008 by the GRASS Development Team
9
10 This program is free software under the
11 GNU General Public License (>=v2).
12 Read the file COPYING that comes with GRASS
13 for details.
14
15 \author Bill Brown USACERL, GMSL/University of Illinois (January 1993)
16 \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
17 */
18
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include <grass/gis.h>
23 #include <grass/raster.h>
24 #include <grass/glocale.h>
25 #include <grass/bitmap.h>
26
27 #include <grass/ogsf.h>
28 /* for geoview & geodisplay in 3dview stuff */
29 #include "gsget.h"
30 /* for update_attrange - might be able to move this func now */
31
32 /*!
33 \brief Used in the function Gs_update_attrange()
34 */
35 #define INIT_MINMAX(p, nm, size, min, max, found) \
36 found = 0; \
37 p+=(size-1); \
38 while (size--) \
39 { \
40 if (!BM_GET_BYOFFSET(nm, size)) \
41 { \
42 min = max = *p; \
43 found = 1; \
44 break; \
45 } \
46 p--; \
47 }
48
49 /*!
50 \brief Used in the function Gs_update_attrange()
51 */
52 #define SET_MINMAX(p, nm, size, min, max) \
53 p+=(size-1); \
54 while(size--) \
55 { \
56 if (!BM_GET_BYOFFSET(nm, size)) \
57 { \
58 if (*p < min) \
59 { \
60 min = *p; \
61 } \
62 else if (*p > max) \
63 { \
64 max = *p; \
65 } \
66 } \
67 p--; \
68 }
69
70 typedef int FILEDESC;
71
72 #define NO_DATA_COL 0xffffff
73
74 /*!
75 \brief Calculates distance in METERS between two points in current projection (2D)
76
77 Uses G_distance().
78
79 \param from 'from' point (X, Y)
80 \param to 'to' point (X, Y)
81
82 \return distance
83 */
Gs_distance(double * from,double * to)84 double Gs_distance(double *from, double *to)
85 {
86 static int first = 1;
87
88 if (first) {
89 first = 0;
90 G_begin_distance_calculations();
91 }
92
93 return G_distance(from[0], from[1], to[0], to[1]);
94 }
95
96 /*!
97 \brief Load raster map as floating point map
98
99 Calling function must have already allocated space in buff for
100 wind->rows * wind->cols floats.
101
102 This routine simply loads the map into a 2d array by repetitve calls
103 to get_f_raster_row.
104
105 \param wind current window
106 \param map_name raster map name
107 \param[out] buff data buffer
108 \param[out] nullmap null map buffer
109 \param[out] has_null indicates if raster map contains null-data
110
111 \return 1 on success
112 \return 0 on failure
113 */
Gs_loadmap_as_float(struct Cell_head * wind,const char * map_name,float * buff,struct BM * nullmap,int * has_null)114 int Gs_loadmap_as_float(struct Cell_head *wind, const char *map_name,
115 float *buff, struct BM *nullmap, int *has_null)
116 {
117 FILEDESC cellfile;
118 const char *map_set;
119 int offset, row, col;
120
121 G_debug(3, "Gs_loadmap_as_float(): name=%s", map_name);
122
123 map_set = G_find_raster2(map_name, "");
124 if (!map_set) {
125 G_warning(_("Raster map <%s> not found"), map_name);
126 return 0;
127 }
128 *has_null = 0;
129
130 cellfile = Rast_open_old(map_name, map_set);
131
132 G_message(_("Loading raster map <%s>..."),
133 G_fully_qualified_name(map_name, map_set));
134
135 for (row = 0; row < wind->rows; row++) {
136 offset = row * wind->cols;
137 Rast_get_f_row(cellfile, &(buff[offset]), row);
138
139 G_percent(row, wind->rows, 2);
140
141 for (col = 0; col < wind->cols; col++) {
142 if (Rast_is_f_null_value(buff + offset + col)) {
143 *has_null = 1;
144 BM_set(nullmap, col, row, 1);
145 }
146 /* set nm */
147 }
148 }
149 G_percent(1, 1, 1);
150
151 G_debug(4, " has_null=%d", *has_null);
152
153 Rast_close(cellfile);
154
155 return (1);
156 }
157
158 /*!
159 \brief Load raster map as integer map
160
161 Calling function must have already allocated space in buff for
162 wind->rows * wind->cols floats.
163
164 This routine simply loads the map into a 2d array by repetitve calls
165 to get_f_raster_row.
166
167 \todo fn body of Gs_loadmap_as_float()
168
169 \param wind current window
170 \param map_name raster map name
171 \param[out] buff data buffer
172 \param[out] nullmap null map buffer
173 \param[out] has_null indicates if raster map contains null-data
174
175 \return 1 on success
176 \return 0 on failure
177 */
Gs_loadmap_as_int(struct Cell_head * wind,const char * map_name,int * buff,struct BM * nullmap,int * has_null)178 int Gs_loadmap_as_int(struct Cell_head *wind, const char *map_name, int *buff,
179 struct BM *nullmap, int *has_null)
180 {
181 FILEDESC cellfile;
182 const char *map_set;
183 int offset, row, col;
184
185 G_debug(3, "Gs_loadmap_as_int");
186
187 map_set = G_find_raster2(map_name, "");
188 if (!map_set) {
189 G_warning(_("Raster map <%s> not found"), map_name);
190 return 0;
191 }
192 *has_null = 0;
193
194 cellfile = Rast_open_old(map_name, map_set);
195
196 G_message(_("Loading raster map <%s>..."),
197 G_fully_qualified_name(map_name, map_set));
198
199 for (row = 0; row < wind->rows; row++) {
200 offset = row * wind->cols;
201 Rast_get_c_row(cellfile, &(buff[offset]), row);
202
203 G_percent(row, wind->rows, 2);
204
205 for (col = 0; col < wind->cols; col++) {
206 if (Rast_is_f_null_value(buff + offset + col)) {
207 *has_null = 1;
208 BM_set(nullmap, col, row, 1);
209 }
210
211 /* set nm */
212 }
213 }
214 G_percent(1, 1, 1);
215
216 Rast_close(cellfile);
217
218 return (1);
219 }
220
221 /*!
222 \brief Get map data type
223
224 \param filename raster map name
225 \param negflag
226
227 \return -1 if map is integer and Rast_read_range() fails
228 \return data type (ARRY_*)
229 */
Gs_numtype(const char * filename,int * negflag)230 int Gs_numtype(const char *filename, int *negflag)
231 {
232 CELL max = 0, min = 0;
233 struct Range range;
234 const char *mapset;
235 int shortbits, charbits, bitplace;
236 static int max_short, max_char;
237 static int first = 1;
238
239 if (first) {
240 max_short = max_char = 1;
241 shortbits = 8 * sizeof(short);
242
243 for (bitplace = 1; bitplace < shortbits; ++bitplace) {
244 /*1 bit for sign */
245 max_short *= 2;
246 }
247
248 max_short -= 1;
249
250 /* NO bits for sign, using unsigned char */
251 charbits = 8 * sizeof(unsigned char);
252
253 for (bitplace = 0; bitplace < charbits; ++bitplace) {
254 max_char *= 2;
255 }
256
257 max_char -= 1;
258
259 first = 0;
260 }
261
262 mapset = G_find_raster2(filename, "");
263 if (!mapset) {
264 G_warning(_("Raster map <%s> not found"), filename);
265 return -1;
266 }
267
268 if (Rast_map_is_fp(filename, mapset)) {
269 G_debug(3, "Gs_numtype(): fp map detected");
270
271 return (ATTY_FLOAT);
272 }
273
274 if (-1 == Rast_read_range(filename, mapset, &range)) {
275 return (-1);
276 }
277
278 Rast_get_range_min_max(&range, &min, &max);
279 *negflag = (min < 0);
280
281 if (max < max_char && min > 0) {
282 return (ATTY_CHAR);
283 }
284
285 if (max < max_short && min > -max_short) {
286 return (ATTY_SHORT);
287 }
288
289 return (ATTY_INT);
290 }
291
292 /*!
293 \brief Load raster map as integer map
294
295 Calling function must have already allocated space in buff for
296 wind->rows * wind->cols shorts.
297
298 This routine simply loads the map into a 2d array by repetitve calls
299 to get_map_row.
300
301 \param wind current window
302 \param map_name raster map name
303 \param[out] buff data buffer
304 \param[out] nullmap null map buffer
305 \param[out] has_null indicates if raster map contains null-data
306
307 \return 1 on success
308 \return -1 on failure,
309 \return -2 if read ok, but 1 or more values were too large (small)
310 to fit into a short (in which case the max (min) short is used)
311 */
Gs_loadmap_as_short(struct Cell_head * wind,const char * map_name,short * buff,struct BM * nullmap,int * has_null)312 int Gs_loadmap_as_short(struct Cell_head *wind, const char *map_name,
313 short *buff, struct BM *nullmap, int *has_null)
314 {
315 FILEDESC cellfile;
316 const char *map_set;
317 int *ti, *tmp_buf;
318 int offset, row, col, val, max_short, overflow, shortsize, bitplace;
319 short *ts;
320
321 G_debug(3, "Gs_loadmap_as_short");
322
323 overflow = 0;
324 shortsize = 8 * sizeof(short);
325
326 /* 1 bit for sign */
327 /* same as 2 << (shortsize-1) */
328 for (max_short = bitplace = 1; bitplace < shortsize; ++bitplace) {
329 max_short *= 2;
330 }
331
332 max_short -= 1;
333
334 map_set = G_find_raster2(map_name, "");
335 if (!map_set) {
336 G_warning(_("Raster map <%s> not found"), map_name);
337 return -1;
338 }
339 *has_null = 0;
340
341 cellfile = Rast_open_old(map_name, map_set);
342
343 tmp_buf = (int *)G_malloc(wind->cols * sizeof(int)); /* G_fatal_error */
344 if (!tmp_buf) {
345 return -1;
346 }
347
348 G_message(_("Loading raster map <%s>..."),
349 G_fully_qualified_name(map_name, map_set));
350
351 for (row = 0; row < wind->rows; row++) {
352 offset = row * wind->cols;
353 Rast_get_c_row(cellfile, tmp_buf, row);
354
355 G_percent(row, wind->rows, 2);
356
357 ts = &(buff[offset]);
358 ti = tmp_buf;
359
360 for (col = 0; col < wind->cols; col++) {
361 if (Rast_is_c_null_value(&tmp_buf[col])) {
362 *has_null = 1;
363 BM_set(nullmap, col, row, 1);
364 }
365 else {
366 val = *ti;
367 if (abs(val) > max_short) {
368 overflow = 1;
369 /* assign floor/ceiling value?
370 */
371 *ts = (short)(max_short * val / abs(val));
372 }
373 else {
374 *ts = (short)val;
375 }
376 }
377
378 ti++;
379 ts++;
380 }
381 }
382 G_percent(1, 1, 1);
383
384 Rast_close(cellfile);
385
386 G_free(tmp_buf);
387
388 return (overflow ? -2 : 1);
389 }
390
391 /*!
392 \brief Load raster map as integer map
393
394 Calling function must have already allocated space in buff for
395 wind->rows * wind->cols unsigned chars.
396
397 This routine simply loads the map into a 2d array by repetitve calls
398 to get_map_row.
399
400 Since signs of chars can be tricky, we only load positive chars
401 between 0-255.
402
403 \todo fn body Gs_loadmap_as_float()
404
405 \param wind current window
406 \param map_name raster map name
407 \param[out] buff data buffer
408 \param[out] nullmap null map buffer
409 \param[out] has_null indicates if raster map contains null-data
410
411 \return 1 on success
412 \return -1 on failure
413 \return -2 if read ok, but 1 or more values
414 were too large (small) to fit into an unsigned char.
415 (in which case the max (min) char is used)
416 */
Gs_loadmap_as_char(struct Cell_head * wind,const char * map_name,unsigned char * buff,struct BM * nullmap,int * has_null)417 int Gs_loadmap_as_char(struct Cell_head *wind, const char *map_name,
418 unsigned char *buff, struct BM *nullmap, int *has_null)
419 {
420 FILEDESC cellfile;
421 const char *map_set;
422 int *ti, *tmp_buf;
423 int offset, row, col, val, max_char, overflow, charsize, bitplace;
424 unsigned char *tc;
425
426 G_debug(3, "Gs_loadmap_as_char");
427
428 overflow = 0;
429 charsize = 8 * sizeof(unsigned char);
430
431 /* 0 bits for sign! */
432 max_char = 1;
433
434 for (bitplace = 0; bitplace < charsize; ++bitplace) {
435 max_char *= 2;
436 }
437
438 max_char -= 1;
439
440 map_set = G_find_raster2(map_name, "");
441 if (!map_set) {
442 G_warning(_("Raster map <%s> not found"), map_name);
443 return -1;
444 }
445 *has_null = 0;
446
447 cellfile = Rast_open_old(map_name, map_set);
448
449 tmp_buf = (int *)G_malloc(wind->cols * sizeof(int)); /* G_fatal_error */
450 if (!tmp_buf) {
451 return -1;
452 }
453
454 G_message(_("Loading raster map <%s>..."),
455 G_fully_qualified_name(map_name, map_set));
456
457 for (row = 0; row < wind->rows; row++) {
458 offset = row * wind->cols;
459 Rast_get_c_row(cellfile, tmp_buf, row);
460 tc = (unsigned char *)&(buff[offset]);
461 ti = tmp_buf;
462
463 G_percent(row, wind->rows, 2);
464
465 for (col = 0; col < wind->cols; col++) {
466 if (Rast_is_c_null_value(&tmp_buf[col])) {
467 *has_null = 1;
468 BM_set(nullmap, col, row, 1);
469 }
470 else {
471 val = *ti;
472 if (val > max_char) {
473 overflow = 1;
474 *tc = (unsigned char)max_char;
475 }
476 else if (val < 0) {
477 overflow = 1;
478 *tc = 0;
479 }
480 else {
481 *tc = (unsigned char)val;
482 }
483 }
484
485 ti++;
486 tc++;
487 }
488 }
489 G_percent(1, 1, 1);
490
491 Rast_close(cellfile);
492
493 G_free(tmp_buf);
494
495 return (overflow ? -2 : 1);
496 }
497
498 /*!
499 \brief Load raster map as integer map
500
501 Calling function must have already allocated space in buff for
502 struct BM of wind->rows & wind->cols.
503
504 This routine simply loads the map into the bitmap by repetitve calls
505 to get_map_row. Any value other than 0 in the map will set the bitmap.
506 (may want to change later to allow specific value to set)
507
508 Changed to use null.
509
510 \param wind current window
511 \param map_name raster map name
512 \param[out] buff data buffer
513
514 \returns 1 on success
515 \return -1 on failure
516 */
Gs_loadmap_as_bitmap(struct Cell_head * wind,const char * map_name,struct BM * buff)517 int Gs_loadmap_as_bitmap(struct Cell_head *wind, const char *map_name,
518 struct BM *buff)
519 {
520 FILEDESC cellfile;
521 const char *map_set;
522 int *tmp_buf;
523 int row, col;
524
525 G_debug(3, "Gs_loadmap_as_bitmap");
526
527 map_set = G_find_raster2(map_name, "");
528 if (!map_set) {
529 G_warning(_("Raster map <%s> not found"), map_name);
530 return -1;
531 }
532
533 cellfile = Rast_open_old(map_name, map_set);
534
535 tmp_buf = (int *)G_malloc(wind->cols * sizeof(int)); /* G_fatal_error */
536 if (!tmp_buf) {
537 return -1;
538 }
539
540 G_message(_("Loading raster map <%s>..."),
541 G_fully_qualified_name(map_name, map_set));
542
543 for (row = 0; row < wind->rows; row++) {
544 Rast_get_c_row(cellfile, tmp_buf, row);
545
546 for (col = 0; col < wind->cols; col++) {
547 if (Rast_is_c_null_value(&tmp_buf[col])) {
548 /* no data */
549 BM_set(buff, col, row, 1);
550 }
551 else {
552 BM_set(buff, col, row, 0);
553 }
554 }
555 }
556
557 Rast_close(cellfile);
558
559 G_free(tmp_buf);
560
561 return (1);
562 }
563
564 /*!
565 \brief Build color table (256)
566
567 Calling function must have already allocated space in buff for range of
568 data (256 for now) - simply calls get_color for each cat in color range
569
570 \param filename raster map name
571 \param[out] buff data buffer
572
573 \return 1 on success
574 \return 0 on failure
575 */
Gs_build_256lookup(const char * filename,int * buff)576 int Gs_build_256lookup(const char *filename, int *buff)
577 {
578 const char *mapset;
579 struct Colors colrules;
580 CELL min, max, cats[256];
581 int i;
582 unsigned char r[256], g[256], b[256], set[256];
583
584 G_debug(3, "building color table");
585
586 mapset = G_find_raster2(filename, "");
587 if (!mapset) {
588 G_warning(_("Raster map <%s> not found"), filename);
589 return 0;
590 }
591
592 Rast_read_colors(filename, mapset, &colrules);
593 Rast_get_c_color_range(&min, &max, &colrules);
594
595 if (min < 0 || max > 255) {
596 G_warning(_("Color table range doesn't match data (mincol=%d, maxcol=%d"),
597 min, max);
598
599 min = min < 0 ? 0 : min;
600 max = max > 255 ? 255 : max;
601 }
602
603 G_zero(cats, 256 * sizeof(CELL));
604
605 for (i = min; i <= max; i++) {
606 cats[i] = i;
607 }
608
609 Rast_lookup_c_colors(cats, r, g, b, set, 256, &colrules);
610
611 for (i = 0; i < 256; i++) {
612
613 if (set[i]) {
614 buff[i] =
615 (r[i] & 0xff) | ((g[i] & 0xff) << 8) | ((b[i] & 0xff) << 16);
616 }
617 else {
618 buff[i] = NO_DATA_COL;
619 }
620 }
621
622 return (1);
623 }
624
625 /*!
626 \brief Pack color table
627
628 Passed an array of 32 bit ints that is converted from cell values
629 to packed colors (0xbbggrr)
630
631 \param filename raster map name
632 \param buff
633 \param rows number of rows
634 \param cols number of cols
635 */
Gs_pack_colors(const char * filename,int * buff,int rows,int cols)636 void Gs_pack_colors(const char *filename, int *buff, int rows, int cols)
637 {
638 const char *mapset;
639 struct Colors colrules;
640 unsigned char *r, *g, *b, *set;
641 int *cur, i, j;
642
643 mapset = G_find_raster2(filename, "");
644 if (!mapset) {
645 G_warning(_("Raster map <%s> not found"), filename);
646 return;
647 }
648
649 r = (unsigned char *)G_malloc(cols);
650 g = (unsigned char *)G_malloc(cols);
651 b = (unsigned char *)G_malloc(cols);
652 set = (unsigned char *)G_malloc(cols);
653
654 Rast_read_colors(filename, mapset, &colrules);
655
656 cur = buff;
657
658 G_message(_("Translating colors from raster map <%s>..."),
659 G_fully_qualified_name(filename, mapset));
660
661 for (i = 0; i < rows; i++) {
662 Rast_lookup_c_colors(cur, r, g, b, set, cols, &colrules);
663 G_percent(i, rows, 2);
664
665 for (j = 0; j < cols; j++) {
666 if (set[j]) {
667 cur[j] =
668 (r[j] & 0xff) | ((g[j] & 0xff) << 8) | ((b[j] & 0xff) <<
669 16);
670 }
671 else {
672 cur[j] = NO_DATA_COL;
673 }
674 }
675
676 cur = &(cur[cols]);
677 }
678 G_percent(1, 1, 1);
679
680 Rast_free_colors(&colrules);
681
682 G_free(r);
683 G_free(g);
684 G_free(b);
685
686 G_free(set);
687
688 return;
689 }
690
691 /*!
692 \brief Pack color table (floating-point map)
693
694 Passed a array of floats that will be converted from cell values
695 to packed colors (0xbbggrr) and float to int
696 Floating point data not freed here, use:
697 gsds_free_data_buff(id, ATTY_FLOAT)
698
699 \param filename raster map name
700 \param fbuf
701 \param ibuf
702 \param rows number of rows
703 \param cols number of cols
704 */
Gs_pack_colors_float(const char * filename,float * fbuf,int * ibuf,int rows,int cols)705 void Gs_pack_colors_float(const char *filename, float *fbuf, int *ibuf,
706 int rows, int cols)
707 {
708 const char *mapset;
709 struct Colors colrules;
710 unsigned char *r, *g, *b, *set;
711 int i, j, *icur;
712 FCELL *fcur;
713
714 mapset = G_find_raster2(filename, "");
715 if (!mapset) {
716 G_warning(_("Raster map <%s> not found"), filename);
717 return;
718 }
719
720 r = (unsigned char *)G_malloc(cols);
721 g = (unsigned char *)G_malloc(cols);
722 b = (unsigned char *)G_malloc(cols);
723 set = (unsigned char *)G_malloc(cols);
724
725 Rast_read_colors(filename, mapset, &colrules);
726
727 fcur = fbuf;
728 icur = ibuf;
729
730 G_message(_("Translating colors from raster map <%s>..."),
731 G_fully_qualified_name(filename, mapset));
732
733 for (i = 0; i < rows; i++) {
734 Rast_lookup_f_colors(fcur, r, g, b, set, cols, &colrules);
735 G_percent(i, rows, 2);
736
737 for (j = 0; j < cols; j++) {
738 if (set[j]) {
739 icur[j] =
740 (r[j] & 0xff) | ((g[j] & 0xff) << 8) | ((b[j] & 0xff) <<
741 16);
742 }
743 else {
744 icur[j] = NO_DATA_COL;
745 }
746 }
747
748 icur = &(icur[cols]);
749 fcur = &(fcur[cols]);
750 }
751 G_percent(1, 1, 1);
752
753 Rast_free_colors(&colrules);
754
755 G_free(r);
756 G_free(g);
757 G_free(b);
758 G_free(set);
759
760 return;
761 }
762
763 /*!
764 \brief Get categories/labels
765
766 Formats label as in d.what.rast -> (catval) catlabel
767
768 \param filename raster map name
769 \param drow
770 \param dcol
771 \param catstr category string
772
773 \return 1 on success
774 \return 0 on failure
775 */
Gs_get_cat_label(const char * filename,int drow,int dcol,char * catstr)776 int Gs_get_cat_label(const char *filename, int drow, int dcol, char *catstr)
777 {
778 struct Categories cats;
779 const char *mapset;
780 CELL *buf;
781 DCELL *dbuf;
782 RASTER_MAP_TYPE map_type;
783 int fd = -1;
784
785 if ((mapset = G_find_raster2(filename, "")) == NULL) {
786 G_warning(_("Raster map <%s> not found"), filename);
787 return 0;
788 }
789
790 if (-1 != Rast_read_cats(filename, mapset, &cats)) {
791 fd = Rast_open_old(filename, mapset);
792 map_type = Rast_get_map_type(fd);
793
794 if (map_type == CELL_TYPE) {
795 buf = Rast_allocate_c_buf();
796
797 Rast_get_c_row(fd, buf, drow);
798 if (Rast_is_c_null_value(&buf[dcol])) {
799 sprintf(catstr, "(NULL) %s",
800 Rast_get_c_cat(&buf[dcol], &cats));
801 }
802 else {
803 sprintf(catstr, "(%d) %s", buf[dcol],
804 Rast_get_c_cat(&buf[dcol], &cats));
805 }
806
807 G_free(buf);
808 }
809
810 else {
811 /* fp map */
812 dbuf = Rast_allocate_d_buf();
813
814 Rast_get_d_row(fd, dbuf, drow);
815 if (Rast_is_d_null_value(&dbuf[dcol])) {
816 sprintf(catstr, "(NULL) %s",
817 Rast_get_d_cat(&dbuf[dcol], &cats));
818 }
819 else {
820 sprintf(catstr, "(%g) %s", dbuf[dcol],
821 Rast_get_d_cat(&dbuf[dcol], &cats));
822 }
823
824 G_free(dbuf);
825 }
826 }
827 else {
828 strcpy(catstr, "no category label");
829 return 0;
830 }
831
832 /* TODO: may want to keep these around for multiple queries */
833 Rast_free_cats(&cats);
834
835 if (fd >= 0)
836 Rast_close(fd);
837
838 return (1);
839 }
840
841 /*!
842 \brief Save 3dview
843
844 \param vname view name
845 \param gv pointer to geoview struct
846 \param gd pointer to geodisplay struct
847 \param w current window
848 \param defsurf default geosurf struct
849
850 \return -1 on error
851 \return ?
852 */
Gs_save_3dview(const char * vname,geoview * gv,geodisplay * gd,struct Cell_head * w,geosurf * defsurf)853 int Gs_save_3dview(const char *vname, geoview * gv, geodisplay * gd,
854 struct Cell_head *w, geosurf * defsurf)
855 {
856 const char *mapset;
857 struct G_3dview v;
858 float zmax, zmin;
859
860 GS_get_zrange(&zmin, &zmax, 0);
861
862 G_get_3dview_defaults(&v, w);
863 mapset = G_mapset();
864
865 if (mapset != NULL) {
866 if (defsurf) {
867 if (defsurf->draw_mode & DM_WIRE_POLY) {
868 v.display_type = 3;
869 }
870 else if (defsurf->draw_mode & DM_WIRE ||
871 defsurf->draw_mode & DM_COL_WIRE) {
872 v.display_type = 1;
873 }
874 else if (defsurf->draw_mode & DM_POLY) {
875 v.display_type = 2;
876 }
877
878 v.mesh_freq = defsurf->x_modw; /* mesh resolution */
879 v.poly_freq = defsurf->x_mod; /* poly resolution */
880 v.dozero = !(defsurf->nz_topo);
881 v.colorgrid = (defsurf->draw_mode & DM_COL_WIRE) ? 1 : 0;
882 v.shading = (defsurf->draw_mode & DM_GOURAUD) ? 1 : 0;
883 }
884
885 if (gv->infocus) {
886 GS_v3eq(v.from_to[TO], gv->real_to);
887 v.from_to[TO][Z] -= zmin;
888 GS_v3mult(v.from_to[TO], gv->scale);
889 v.from_to[TO][Z] *= gv->vert_exag;
890 }
891 else {
892 GS_v3eq(v.from_to[TO], gv->from_to[TO]);
893 }
894
895 gsd_model2real(v.from_to[TO]);
896
897 GS_v3eq(v.from_to[FROM], gv->from_to[FROM]);
898 gsd_model2real(v.from_to[FROM]);
899
900 v.exag = gv->vert_exag;
901 v.fov = gv->fov / 10.;
902 v.twist = gv->twist;
903 v.fringe = 0; /* not implemented here */
904
905 v.lightson = 1; /* always true, curently */
906
907 if (gv->lights[0].position[W] == 1) {
908 /* local */
909 v.lightpos[X] = gv->lights[0].position[X];
910 v.lightpos[Y] = gv->lights[0].position[Y];
911 v.lightpos[Z] = gv->lights[0].position[Z];
912 gsd_model2real(v.lightpos);
913 v.lightpos[W] = 1.0; /* local */
914 }
915 else {
916 v.lightpos[X] = gv->lights[0].position[X];
917 v.lightpos[Y] = gv->lights[0].position[Y];
918 v.lightpos[Z] = gv->lights[0].position[Z];
919 v.lightpos[W] = 0.0; /* inf */
920 }
921
922 v.lightcol[0] = gv->lights[0].color[0];
923 v.lightcol[1] = gv->lights[0].color[1];
924 v.lightcol[2] = gv->lights[0].color[2];
925
926 v.ambient = (gv->lights[0].ambient[0] + gv->lights[0].ambient[1] +
927 gv->lights[0].ambient[2]) / 3.;
928 v.shine = gv->lights[0].shine;
929
930 v.surfonly = 0; /* N/A - now uses constant color */
931 strcpy((v.pgm_id), "Nvision-ALPHA!");
932
933 return (G_put_3dview(vname, mapset, &v, w));
934 }
935 else {
936 return (-1);
937 }
938 }
939
940 /*!
941 \brief Load 3dview
942
943 \param vname view name
944 \param gv pointer to geoview struct
945 \param gd pointer to geodisplay struct
946 \param w current window
947 \param defsurf default geosurf struct
948
949 \return 1
950 */
Gs_load_3dview(const char * vname,geoview * gv,geodisplay * gd,struct Cell_head * w,geosurf * defsurf)951 int Gs_load_3dview(const char *vname, geoview * gv, geodisplay * gd,
952 struct Cell_head *w, geosurf * defsurf)
953 {
954 const char *mapset;
955 struct G_3dview v;
956 int ret = -1;
957 float pt[3];
958
959 mapset = G_find_file2("3d.view", vname, "");
960
961 if (mapset != NULL) {
962 ret = G_get_3dview(vname, mapset, &v);
963 }
964
965 if (ret >= 0) {
966 if (strcmp((v.pgm_id), "Nvision-ALPHA!")) {
967 G_warning(_("View not saved by this program,"
968 "there may be some inconsistancies"));
969 }
970
971 /* set poly and mesh resolutions */
972 v.mesh_freq = (int)(v.mesh_freq * v.vwin.ns_res / w->ns_res);
973 v.poly_freq = (int)(v.poly_freq * v.vwin.ns_res / w->ns_res);
974
975 /* Set To and FROM positions */
976 /* TO */
977 pt[0] = (v.from_to[TO][X] - w->west) - w->ew_res / 2.;
978 pt[1] = (v.from_to[TO][Y] - w->south) - w->ns_res / 2.;
979 pt[2] = v.from_to[TO][Z];
980 GS_set_focus(pt);
981
982 /* FROM */
983 pt[0] = (float)v.from_to[FROM][X];
984 pt[1] = (float)v.from_to[FROM][Y];
985 pt[2] = (float)v.from_to[FROM][Z];
986 GS_moveto_real(pt);
987
988 if (defsurf) {
989 int dmode = 0;
990
991 GS_setall_drawres(v.poly_freq, v.poly_freq,
992 v.mesh_freq, v.mesh_freq);
993
994 while (v.display_type >= 10) {
995 /* globe stuff not used */
996 v.display_type -= 10;
997 }
998
999 /* set drawing modes */
1000 if (v.colorgrid) {
1001 dmode |= DM_COL_WIRE;
1002 }
1003
1004 if (v.shading) {
1005 dmode |= DM_GOURAUD;
1006 }
1007
1008 switch (v.display_type) {
1009 case 1:
1010 dmode |= DM_WIRE;
1011
1012 break;
1013 case 2:
1014 dmode |= DM_POLY;
1015
1016 break;
1017 case 3:
1018 dmode |= DM_WIRE_POLY;
1019
1020 break;
1021 }
1022 GS_setall_drawmode(dmode);
1023
1024 /* should also set nozeros here */
1025 }
1026
1027 /* set exaggeration */
1028 if (v.exag)
1029 GS_set_global_exag(v.exag);
1030
1031 /* Set FOV */
1032 if (v.fov) {
1033 GS_set_fov((int)
1034 (v.fov > 0 ? v.fov * 10. + 0.5 : v.fov * 10. - 0.5));
1035 }
1036 else {
1037 /* TODO: do ortho */
1038 }
1039
1040 /* Set twist */
1041 if (v.twist)
1042 GS_set_twist((int)(v.twist > 0 ? v.twist + 0.5 : v.twist - 0.5));
1043
1044
1045 /* TODO: OK to here - need to unravel/reverse lights stuff*** */
1046
1047 if (v.lightson) {
1048 /* Lights are on */
1049
1050 /* Light Position */
1051 gv->lights[0].position[X] = v.lightpos[X];
1052 gv->lights[0].position[Y] = v.lightpos[Y];
1053 gv->lights[0].position[Z] = v.lightpos[Z];
1054
1055 /* Light Color */
1056 gv->lights[0].color[0] = v.lightcol[0];
1057 gv->lights[0].color[1] = v.lightcol[1];
1058 gv->lights[0].color[2] = v.lightcol[2];
1059
1060 /* Light Shininess */
1061 gv->lights[0].shine = v.shine;
1062
1063 /* Light Ambient */
1064 gv->lights[0].ambient[0] = gv->lights[0].ambient[1] =
1065 gv->lights[0].ambient[2] = v.ambient * 3.;
1066
1067
1068 } /* Done with lights */
1069
1070
1071 GS_alldraw_wire();
1072
1073 } /* Done with file */
1074 return (1);
1075
1076 }
1077
1078 /*!
1079 \brief Update no_zero ranges for attribute (actually no_null now)
1080
1081 \param gs pointer to geosurf struct
1082 \param desc attribute id (descriptor)
1083
1084 \return -1 on error
1085 \return 1 on success
1086 */
Gs_update_attrange(geosurf * gs,int desc)1087 int Gs_update_attrange(geosurf * gs, int desc)
1088 {
1089 long size;
1090 float min, max;
1091 typbuff *tb;
1092 struct BM *nm;
1093 int found;
1094
1095 gs->att[desc].max_nz = gs->att[desc].min_nz = gs->att[desc].range_nz =
1096 0.0;
1097
1098 if (CONST_ATT == gs_get_att_src(gs, desc)) {
1099 gs->att[desc].max_nz = gs->att[desc].min_nz = gs->att[desc].constant;
1100 min = max = gs->att[desc].constant;
1101 gs->att[desc].range_nz = 0.0;
1102 }
1103 else if (CF_COLOR_PACKED & gsds_get_changed(gs->att[desc].hdata)) {
1104 gs->att[desc].max_nz = 0xFFFFFF;
1105 gs->att[desc].min_nz = 0x010101;
1106 gs->att[desc].range_nz = 0xFFFFFF;
1107 }
1108 else {
1109 if (NULL == (tb = gsds_get_typbuff(gs->att[desc].hdata, 0))) {
1110 return (-1);
1111 }
1112
1113 nm = tb->nm;
1114
1115 if (tb->ib) {
1116 int *p;
1117
1118 size = gs->rows * gs->cols;
1119 p = tb->ib;
1120 INIT_MINMAX(p, nm, size, min, max, found);
1121
1122 if (!found) {
1123 /* all nulls! */
1124 return (-1);
1125 }
1126
1127 size = gs->rows * gs->cols;
1128 p = tb->ib;
1129 SET_MINMAX(p, nm, size, min, max);
1130 }
1131 else if (tb->sb) {
1132 short *p;
1133
1134 size = gs->rows * gs->cols;
1135 p = tb->sb;
1136 INIT_MINMAX(p, nm, size, min, max, found);
1137
1138 if (!found) {
1139 /* all nulls! */
1140 return (-1);
1141 }
1142
1143 size = gs->rows * gs->cols;
1144 p = tb->sb;
1145 SET_MINMAX(p, nm, size, min, max);
1146 }
1147 else if (tb->cb) {
1148 char *p;
1149
1150 size = gs->rows * gs->cols;
1151 p = (char *)tb->cb;
1152 INIT_MINMAX(p, nm, size, min, max, found);
1153
1154 if (!found) {
1155 /* all nulls! */
1156 return (-1);
1157 }
1158
1159 size = gs->rows * gs->cols;
1160 p = (char *)tb->cb;
1161 SET_MINMAX(p, nm, size, min, max);
1162 }
1163 else if (tb->fb) {
1164 float *p;
1165
1166 size = gs->rows * gs->cols;
1167 p = tb->fb;
1168 INIT_MINMAX(p, nm, size, min, max, found);
1169
1170 if (!found) {
1171 /* all nulls! */
1172 return (-1);
1173 }
1174
1175 size = gs->rows * gs->cols;
1176 p = tb->fb;
1177 SET_MINMAX(p, nm, size, min, max);
1178 }
1179
1180 gs->att[desc].max_nz = max;
1181 gs->att[desc].min_nz = min;
1182 gs->att[desc].range_nz = gs->att[desc].max_nz - gs->att[desc].min_nz;
1183 }
1184
1185 if (ATT_TOPO == desc) {
1186 gs->zmin = min;
1187 gs->zmax = max;
1188 gs->zrange = gs->zmax - gs->zmin;
1189 gs->zminmasked = gs->zmin;
1190 gs->zmax_nz = gs->zmax;
1191 gs->zmin_nz = gs->zmin;
1192 gs->zrange_nz = gs->zmax_nz - gs->zmin_nz;
1193 }
1194
1195 G_debug(3, "Gs_update_attrange(): min=%f max=%f", gs->zmin, gs->zmax);
1196
1197 return (1);
1198 }
1199