123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522 |
- /****************************************************************************
- *
- * MODULE: m.nviz.script (nee d.nviz)
- * AUTHOR(S): Bob Covill <bcovill@tekmap.ns.ca>
- * PURPOSE: interactively create fly-through script for NVIZ
- * Functions:
- * main -- parse parameters and get key frame coorinates
- * do_profile-- calculate camera and eye coordinates from
- * raster map
- * move -- part of screen coords
- * cont -- part of screen coords
- * read_rast -- return camera and eye coordinates
- *
- * COPYRIGHT: (C) 2000 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 <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <string.h>
- #include <grass/gis.h>
- #include <grass/raster.h>
- #include <grass/display.h>
- #include "local.h"
- #include <grass/glocale.h>
- int cut_val, frame = 0;
- int height_flag = 0;
- double OLD_DEPTH;
- char img_name[512];
- int no_frames;
- int cnt = 1;
- int key_frames = 0;
- int off_screen = 0;
- double key_time = 0.;
- FILE *fp, *fp2;
- int main(int argc, char *argv[])
- {
- const char *name;
- char outfile[GNAME_MAX];
- int fd, projection;
- char buf[512], buf1[1024], buf2[1024];
- int screen_x, screen_y;
- int i, k;
- int frame_start = 0;
- double e1, e2, n1, n2;
- RASTER_MAP_TYPE data_type;
- struct Cell_head window;
- struct
- {
- struct Option *opt1, *route, *name, *output, *dist, *ht, *frames,
- *start;
- struct Flag *f, *c, *k, *o, *e;
- }
- parm;
- struct GModule *module;
- G_gisinit(argv[0]);
- /* Set description */
- module = G_define_module();
- G_add_keyword(_("miscellaneous"));
- G_add_keyword(_("graphics"));
- G_add_keyword(_("raster"));
- G_add_keyword(_("raster3d"));
- G_add_keyword(_("vector"));
- G_add_keyword(_("visualization"));
- module->description = _("Creates fly-through script to run in NVIZ.");
- parm.opt1 = G_define_standard_option(G_OPT_R_INPUT);
- parm.output = G_define_standard_option(G_OPT_F_OUTPUT);
- parm.output->description = _("Name of output script");
- parm.name = G_define_option();
- parm.name->key = "name";
- parm.name->type = TYPE_STRING;
- parm.name->required = NO;
- parm.name->description = _("Prefix of output images (default = NVIZ)");
- parm.route = G_define_option();
- parm.route->key = "route";
- parm.route->type = TYPE_STRING;
- parm.route->required = NO;
- parm.route->multiple = YES;
- parm.route->key_desc = "east,north";
- parm.route->description = _("Route coordinates (east,north)");
- parm.dist = G_define_option();
- parm.dist->key = "dist";
- parm.dist->type = TYPE_DOUBLE;
- parm.dist->required = YES;
- parm.dist->description = _("Camera layback distance (in map units)");
- parm.ht = G_define_option();
- parm.ht->key = "ht";
- parm.ht->type = TYPE_DOUBLE;
- parm.ht->required = YES;
- parm.ht->description = _("Camera height above terrain");
- parm.frames = G_define_option();
- parm.frames->key = "frames";
- parm.frames->type = TYPE_INTEGER;
- parm.frames->required = YES;
- parm.frames->description = _("Number of frames");
- parm.start = G_define_option();
- parm.start->key = "start";
- parm.start->type = TYPE_INTEGER;
- parm.start->required = NO;
- parm.start->description = _("Start frame number (default=0)");
- parm.f = G_define_flag();
- parm.f->key = 'f';
- parm.f->description = _("Full render -- Save images");
- parm.c = G_define_flag();
- parm.c->key = 'c';
- parm.c->description = _("Fly at constant elevation (ht)");
- parm.k = G_define_flag();
- parm.k->key = 'k';
- parm.k->description =
- _("Include command in the script to output a KeyFrame file");
- parm.o = G_define_flag();
- parm.o->key = 'o';
- parm.o->description = _("Render images off-screen");
- parm.e = G_define_flag();
- parm.e->key = 'e';
- parm.e->description = _("Enable vector and sites drawing");
- if (G_parser(argc, argv))
- exit(EXIT_FAILURE);
- /* check arguments */
- if (!parm.route->answer)
- G_fatal_error(_("Either -i flag and/or route parameter must be used"));
- /* get GRASS parameters */
- G_get_window(&window);
- projection = G_projection();
- D_do_conversions(&window, 0, 1, 0, 1);
- /* setup screen coords */
- screen_x = ((int)D_get_d_west() + (int)D_get_d_east()) / 2;
- screen_y = ((int)D_get_d_north() + (int)D_get_d_south()) / 2;
- /* get camera parameters */
- DIST = atof(parm.dist->answer);
- HT = atof(parm.ht->answer);
- no_frames = atoi(parm.frames->answer);
- if (parm.start->answer)
- frame_start = atoi(parm.start->answer);
- if (parm.c->answer)
- height_flag = 1;
- if (parm.k->answer)
- key_frames = 1;
- if (parm.o->answer && !parm.f->answer)
- G_fatal_error(_("Off-screen only available with full render mode"));
- if (parm.o->answer)
- off_screen = 1;
- /* Initialize coords */
- e1 = e2 = n1 = n2 = -9999.;
- G_begin_distance_calculations();
- /* Open Input File for reading */
- name = parm.opt1->answer;
- /* Open Raster File */
- fd = Rast_open_old(name, "");
- /* Set Image name */
- if (parm.name->answer)
- sprintf(img_name, "%s", parm.name->answer);
- else
- sprintf(img_name, "NVIZ");
- /* Open ASCII file for output */
- /* append ".nvscr" to filename if it doesn't already have it */
- strncpy(outfile, parm.output->answer, GNAME_MAX - 7);
- outfile[GNAME_MAX - 7] = '\0'; /* strncpy() doesn't null terminate the string */
- if (strcmp(&outfile[strlen(outfile) - 6], ".nvscr") != 0)
- strcat(outfile, ".nvscr");
- if (NULL == (fp = fopen(outfile, "w")))
- G_fatal_error(_("Unable to open file <%s>"), outfile);
- /* Get Raster Type */
- data_type = Rast_get_map_type(fd);
- /* Done with file */
- /* Output initial startup stuff */
- sprintf(buf1,
- "## REGION: n=%f s=%f e=%f w=%f\n## Input=%s Dist=%f Ht=%f\n",
- window.north, window.south, window.east, window.west, outfile,
- DIST, HT);
- sprintf(buf2, "\nset FRAMES %d\n", no_frames);
- strcat(buf1, buf2);
- fprintf(fp, "%s", buf1);
- sprintf(buf1, "SendScriptLine \"Nclear_keys\"");
- sprintf(buf2, "\nSendScriptLine \"Nupdate_frames\"");
- strcat(buf1, buf2);
- fprintf(fp, "%s", buf1);
- sprintf(buf1, "\nSendScriptLine \"Nset_numsteps $FRAMES\"");
- sprintf(buf2, "\nSendScriptLine \"Nupdate_frames\"\n");
- strcat(buf1, buf2);
- fprintf(fp, "%s", buf1);
- /* Use Linear mode for smooth frame transition */
- sprintf(buf1, "\nSendScriptLine \"Nset_interp_mode linear\"");
- sprintf(buf2, "\nSendScriptLine \"Nupdate_frames\"\n\n");
- strcat(buf1, buf2);
- fprintf(fp, "%s", buf1);
- /* eanble vector and sites drawing */
- if (parm.e->answer) {
- sprintf(buf1, "\nSendScriptLine \"Nshow_vect on\"");
- sprintf(buf2, "\nSendScriptLine \"Nshow_sites on\"\n\n");
- strcat(buf1, buf2);
- fprintf(fp, "%s", buf1);
- }
- /* Coords from Command Line */
- k = 0;
- for (i = 0; parm.route->answers[i]; i += 2) {
- /* Test for number coordinate pairs */
- k = i;
- }
- if (k < 6) {
- /* Only one coordinate pair supplied */
- G_fatal_error(_("You must provide at least four points %d"), k);
- }
- else {
- for (i = 0; i <= k - 2; i += 2) {
- sscanf(parm.route->answers[i], "%lf", &e1);
- sscanf(parm.route->answers[i + 1], "%lf", &n1);
- sscanf(parm.route->answers[i + 2], "%lf", &e2);
- sscanf(parm.route->answers[i + 3], "%lf", &n2);
- /* Get profile info */
- do_profile(e1, e2, n1, n2, name, fd, data_type);
- /* Get last coord */
- if (i == k - 2)
- do_profile(e2, e2, n2, n2, name, fd, data_type);
- }
- }
- /* done with coordinates */
- /* Output final part of script */
- /* generate key-frame script */
- if (key_frames) {
- strcpy(buf, outfile);
- buf[strlen(outfile) - 6] = '\0'; /* skip extension */
- strcat(buf, ".kanim");
- fprintf(fp, "\n## The following saves the animation to a format\n");
- fprintf(fp, "## suitable for editing with the kanimator panel\n");
- fprintf(fp, "SendScriptLine \"Nprint_keys %s\"\n", buf);
- fprintf(fp, "puts \"Saving Key Frame file %s\"\n", buf);
- }
- /* output off-screen option */
- if (off_screen) {
- fprintf(fp, "\n## Off screen rendering enabled \n");
- fprintf(fp, "## Ensure main window is minimized before running\n");
- fprintf(fp, "SendScriptLine \"Noff_screen 1\"\n");
- }
- fprintf(fp, "\n\nset num %d", frame_start);
- fprintf(fp, "\n\nfor {set frame 1} {$frame <= $FRAMES} {incr frame} {");
- if (parm.f->answer) {
- /* Full render and save */
- fprintf(fp, "\nset name %s", img_name);
- fprintf(fp, "\nset num2 [format \"%%04d\" $num]");
- fprintf(fp, "\nappend name $num2 \".ppm\"");
- fprintf(fp, "\nSendScriptLine \"Ndo_framestep $frame 1\"");
- fprintf(fp, "\nSendScriptLine \"Nwrite_ppm $name \"");
- fprintf(fp, "\nincr num");
- }
- else {
- /* Quick draw wire */
- /* output full variables commented so can be easily changed */
- fprintf(fp, "\nset name %s", img_name);
- fprintf(fp, "\nset num2 [format \"%%04d\" $num]");
- fprintf(fp, "\nappend name $num2 \".ppm\"");
- fprintf(fp,
- "\n## To render in full set to 1 and uncomment Nwrite_ppm \"");
- fprintf(fp, "\nSendScriptLine \"Ndo_framestep $frame 0\"");
- fprintf(fp, "\n#SendScriptLine \"Nwrite_ppm $name \"");
- fprintf(fp, "\nincr num");
- }
- fprintf(fp, "\n}\n");
- if (off_screen)
- fprintf(fp, "SendScriptLine \"Noff_screen 0\"\n");
- fprintf(fp, "SendScriptLine \"set ScriptPlaying 0\"\n");
- fprintf(fp, "puts \"DONE!\"\n");
- Rast_close(fd);
- fclose(fp);
- G_done_msg(_("Created NVIZ script <%s>."), outfile);
- exit(EXIT_SUCCESS);
- } /* Done with main */
- /* ************************************
- * Calculate camera and eye coordinates
- **************************************/
- int do_profile(double e1, double e2, double n1, double n2,
- const char *name, int fd, int data_type)
- {
- float rows, cols, LEN;
- double Y, X, AZI;
- cols = e1 - e2;
- rows = n1 - n2;
- LEN = G_distance(e1, n1, e2, n2);
- /* Calculate Azimuth of Line */
- if (rows == 0 && cols == 0) {
- /* Special case for no movement */
- /* do nothing */
- return 0;
- }
- /* dist is not initialized ! */
- if (rows >= 0 && cols < 0) {
- /* SE Quad or due east */
- AZI = fabs(atan((rows / cols)));
- Y = (double)DIST *sin(AZI);
- X = (double)DIST *cos(AZI);
- if (e != 0.0 && (e != e1 || n != n1)) {
- dist -= G_distance(e, n, e1, n1);
- }
- read_rast(e2 - X, n2 + Y, LEN, fd, 1, data_type);
- read_rast(e2, n2, LEN, fd, 0, data_type);
- }
- if (rows < 0 && cols <= 0) {
- /* NE Quad or due north */
- AZI = fabs(atan((cols / rows)));
- X = (double)DIST *sin(AZI);
- Y = (double)DIST *cos(AZI);
- if (e != 0.0 && (e != e1 || n != n1)) {
- dist -= G_distance(e, n, e1, n1);
- }
- read_rast(e2 - X, n2 - Y, LEN, fd, 1, data_type);
- read_rast(e2, n2, LEN, fd, 0, data_type);
- }
- if (rows > 0 && cols >= 0) {
- /* SW Quad or due south */
- AZI = fabs(atan((rows / cols)));
- X = (double)DIST *cos(AZI);
- Y = (double)DIST *sin(AZI);
- if (e != 0.0 && (e != e1 || n != n1)) {
- dist -= G_distance(e, n, e1, n1);
- }
- read_rast(e2 + X, n2 + Y, LEN, fd, 1, data_type);
- read_rast(e2, n2, LEN, fd, 0, data_type);
- }
- if (rows <= 0 && cols > 0) {
- /* NW Quad or due west */
- AZI = fabs(atan((rows / cols)));
- X = (double)DIST *cos(AZI);
- Y = (double)DIST *sin(AZI);
- if (e != 0.0 && (e != e1 || n != n1)) {
- dist -= G_distance(e, n, e1, n1);
- }
- read_rast(e2 + X, n2 - Y, LEN, fd, 1, data_type);
- read_rast(e2, n2, LEN, fd, 0, data_type);
- }
- /* dist is not used ! */
- return 0;
- } /* done with do_profile */
- /*****************************
- * read_rast
- * function to get raster value at set location
- * and output nviz script
- *****************************/
- int read_rast
- (double east,
- double north,
- double rrdist, int fd, int out_type, RASTER_MAP_TYPE data_type)
- {
- int row, col, nrows, ncols;
- struct Cell_head window;
- CELL *cell;
- char buf[1024] = "";
- char buf2[1024];
- FCELL *fcell;
- DCELL *dcell;
- double camera_height;
- G_get_window(&window);
- nrows = window.rows;
- ncols = window.cols;
- row = (int)(0.5 + D_u_to_a_row(north));
- col = (int)(0.5 + D_u_to_a_col(east));
- if (row < 0 || row > nrows || col < 0 || col > ncols) {
- G_debug(3, "Fail: row=%d nrows=%d col=%d ncols=%d", row, nrows,
- col, ncols);
- G_warning(_("Skipping this point, selected point is outside region. "
- "Perhaps the camera setback distance puts it beyond the edge?"));
- frame++;
- return 1;
- }
- if (data_type == CELL_TYPE) {
- cell = Rast_allocate_c_buf();
- Rast_get_c_row(fd, cell, row);
- if (Rast_is_c_null_value(&cell[col]))
- camera_height = (double)9999.;
- else
- camera_height = (double)cell[col];
- G_free(cell);
- }
- if (data_type == FCELL_TYPE) {
- fcell = Rast_allocate_f_buf();
- Rast_get_f_row(fd, fcell, row);
- if (Rast_is_f_null_value(&fcell[col]))
- camera_height = (double)9999.;
- else
- camera_height = (double)fcell[col];
- G_free(fcell);
- }
- if (data_type == DCELL_TYPE) {
- dcell = Rast_allocate_d_buf();
- Rast_get_d_row(fd, dcell, row);
- if (Rast_is_d_null_value(&dcell[col]))
- camera_height = (double)9999.;
- else
- camera_height = (double)dcell[col];
- G_free(dcell);
- }
- /* Output script commands */
- /*************************/
- /* Set camera Height value */
- if (camera_height == 9999.)
- camera_height = OLD_DEPTH;
- if (height_flag && out_type)
- camera_height = HT;
- else if (!height_flag && out_type)
- camera_height = camera_height + HT;
- if (out_type) {
- /* Set Camera Position */
- sprintf(buf2, "\nSendScriptLine \"Nmove_to_real %f %f %f\"",
- east, north, camera_height);
- key_time += (rrdist + fabs(camera_height - OLD_DEPTH)) / 10000.;
- }
- else {
- /* Set Center of View */
- sprintf(buf2, "\nSendScriptLine \"Nset_focus %f %f %f\"",
- east - window.west - (window.ew_res / 2),
- north - window.south - (window.ns_res / 2), camera_height);
- /* Use frame number for now -- TODO figure even increment
- * based on no. of frames and distance */
- sprintf(buf,
- "\nSendScriptLine \"Nadd_key %f KF_ALL_MASK 1 0.0\"\n",
- key_time);
- strcat(buf2, buf);
- cnt++;
- }
- /* Out to file */
- fprintf(fp, "%s", buf2);
- OLD_DEPTH = camera_height;
- frame++;
- return 0;
- }
|