123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- /****************************************************************************
- *
- * MODULE: r.out.vrml
- * AUTHOR(S): Bill Brown (CERL/UIUC GMSL Laboratory) (original contributor),
- * Hamish Bowman <hamish_b yahoo.com>,
- * Jachym Cepicky <jachym les-ejk.cz>,
- * Markus Neteler <neteler itc.it>
- * PURPOSE: This module exports a GRASS raster map to the Virtual Reality
- * Modeling Language (VRML) format for 3D visualization.
- * COPYRIGHT: (C) 2006-2006 by the GRASS Development Team
- *
- * This program is free software under the GNU General Public
- * License (>=v2). Read the file COPYING that comes with GRASS
- * for details.
- *
- *****************************************************************************/
- #include <string.h>
- #include <stdlib.h>
- #include <grass/gis.h>
- #include <grass/raster.h>
- #include <grass/glocale.h>
- #include "pv.h"
- struct Cell_head W;
- int main(int argc, char *argv[])
- {
- struct Option *rast_el, *rast_co, *out;
- struct Option *exag_opt;
- int elevfd = 0, colorfd = 0;
- FILE *vout = NULL;
- struct Colors colr;
- char outfile[GPATH_MAX];
- int shh, color_ok;
- double exag, min, max;
- struct GModule *module;
- G_gisinit(argv[0]);
- shh = color_ok = 0;
- module = G_define_module();
- G_add_keyword(_("raster"));
- G_add_keyword(_("export"));
- G_add_keyword(_("VRML"));
- module->description =
- _("Exports a raster map to the Virtual Reality Modeling Language (VRML).");
- rast_el = G_define_standard_option(G_OPT_R_ELEV);
- rast_co = G_define_standard_option(G_OPT_R_INPUT);
- rast_co->key = "color";
- rast_co->required = NO;
- rast_co->description = _("Name of input color map");
- exag_opt = G_define_option();
- exag_opt->key = "exaggeration";
- exag_opt->type = TYPE_DOUBLE;
- exag_opt->required = NO;
- exag_opt->answer = "1.0";
- exag_opt->description = _("Vertical exaggeration");
- out = G_define_standard_option(G_OPT_F_OUTPUT);
- out->required = YES;
- out->description = _("Name for output VRML file");
- if (G_parser(argc, argv))
- exit(EXIT_FAILURE);
- G_get_set_window(&W);
- elevfd = Rast_open_old(rast_el->answer, "");
- {
- CELL cmin, cmax;
- struct Range range;
- int is_fp;
- DCELL dmin, dmax;
- struct FPRange fp_range;
- is_fp = Rast_map_is_fp(rast_el->answer, "");
- if (is_fp) {
- if (Rast_read_fp_range(rast_el->answer, "", &fp_range) != 1) {
- G_fatal_error(_("Range info for [%s] not available (run r.support)"),
- rast_el->answer);
- }
- Rast_get_fp_range_min_max(&fp_range, &dmin, &dmax);
- min = dmin;
- max = dmax;
- }
- else {
- if (Rast_read_range(rast_el->answer, "", &range) == -1) {
- G_fatal_error(_("Range info for <%s> not available (run r.support)"),
- rast_el->answer);
- }
- Rast_get_range_min_max(&range, &cmin, &cmax);
- min = cmin;
- max = cmax;
- }
- }
- if (rast_co->answer) {
- colorfd = Rast_open_old(rast_co->answer, "");
- Rast_read_colors(rast_co->answer, "", &colr);
- color_ok = 1;
- }
- /* TODO: if file exists, just append new objects */
- if (out->answer) {
- char *p;
- /* look for .wrl suffix, add if not found */
- if (NULL == (p = strrchr(out->answer, '.'))) { /* no suffix */
- strcpy(outfile, out->answer);
- strcat(outfile, ".wrl");
- }
- else if (strncmp(p + 1, "wrl", 4)) { /* some other extension */
- strcpy(outfile, out->answer);
- strcat(outfile, ".wrl");
- }
- else
- strcpy(outfile, out->answer);
- /* open file for writing VRML */
- G_message(_("Opening %s for writing... "), outfile);
- if (NULL == (vout = fopen(outfile, "w"))) {
- G_fatal_error(_("Unable to open output file <%s>"), outfile);
- }
- }
- exag = 1.0;
- if (exag_opt->answer) {
- sscanf(exag_opt->answer, "%lf", &exag);
- }
- init_coordcnv(exag, &W, min, max);
- vrml_begin(vout);
- /*
- vrml_put_view(vout, NULL);
- */
- vrml_put_grid(vout, &W, elevfd, colorfd, &colr, color_ok,
- W.rows, W.cols, shh);
- vrml_end(vout);
- Rast_close(elevfd);
- if (color_ok)
- Rast_close(colorfd);
- return (EXIT_SUCCESS);
- }
- static double scaleXZ, scaleY;
- static double transX, transY, transZ;
- static double Xrange, Yrange, Zrange;
- /* REMEMBER -
- * Y is HEIGHT
- * Z is northing-W.south
- * X is adjusted easting-W.west
- */
- /*
- * This could be entered as a vrml scale to preserve real
- * geographic coords, but I'm not sure how good the average
- * vrml viewer is at setting appropriate z-depths, so testing
- * first like this.
- */
- /* TODO:
- * change scale & use G_distance for latlon to preserve meter units
- */
- int init_coordcnv(double exag, struct Cell_head *w, double min, double max)
- {
- Yrange = (max - min) * exag;
- Zrange = (w->rows - 1) * w->ns_res;
- Xrange = (w->cols - 1) * w->ew_res;
- transX = -(Rast_col_to_easting(0.5, w));
- transZ = -(Rast_row_to_northing(0.5, w));
- transY = -min;
- if (Zrange >= Xrange && Zrange >= Yrange) { /* northing biggest */
- scaleXZ = 1.0 / Zrange;
- scaleY = exag * scaleXZ;
- }
- else if (Xrange >= Zrange && Xrange >= Yrange) { /* easting biggest */
- scaleXZ = 1.0 / Xrange;
- scaleY = exag * scaleXZ;
- }
- else /* depth biggest */
- scaleY = scaleXZ = 1.0 / Yrange;
- return 0;
- }
- int do_coordcnv(double *dval, int axis)
- {
- double dret = 0.0;
- switch (axis) {
- case 'x':
- case 'X':
- dret = (*dval + transX) * scaleXZ;
- break;
- case 'z':
- case 'Z':
- dret = (Zrange - (*dval + transZ)) * scaleXZ;
- break;
- case 'y':
- case 'Y':
- dret = (*dval + transY) * scaleY;
- break;
- default:
- G_fatal_error("invalid axis: %c", axis);
- break;
- }
- *dval = dret;
- return 0;
- }
|