main.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /****************************************************************************
  2. *
  3. * MODULE: r.out.vrml
  4. * AUTHOR(S): Bill Brown (CERL/UIUC GMSL Laboratory) (original contributor),
  5. * Hamish Bowman <hamish_b yahoo.com>,
  6. * Jachym Cepicky <jachym les-ejk.cz>,
  7. * Markus Neteler <neteler itc.it>
  8. * PURPOSE: This module exports a GRASS raster map to the Virtual Reality
  9. * Modeling Language (VRML) format for 3D visualization.
  10. * COPYRIGHT: (C) 2006-2006 by the GRASS Development Team
  11. *
  12. * This program is free software under the GNU General Public
  13. * License (>=v2). Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. *****************************************************************************/
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <grass/gis.h>
  20. #include <grass/raster.h>
  21. #include <grass/glocale.h>
  22. #include "pv.h"
  23. struct Cell_head W;
  24. int main(int argc, char *argv[])
  25. {
  26. struct Option *rast_el, *rast_co, *out;
  27. struct Option *exag_opt;
  28. int elevfd = 0, colorfd = 0;
  29. FILE *vout = NULL;
  30. struct Colors colr;
  31. char outfile[GPATH_MAX];
  32. int shh, color_ok;
  33. double exag, min, max;
  34. struct GModule *module;
  35. G_gisinit(argv[0]);
  36. shh = color_ok = 0;
  37. module = G_define_module();
  38. G_add_keyword(_("raster"));
  39. G_add_keyword(_("export"));
  40. G_add_keyword(_("VRML"));
  41. module->description =
  42. _("Exports a raster map to the Virtual Reality Modeling Language (VRML).");
  43. rast_el = G_define_standard_option(G_OPT_R_ELEV);
  44. rast_co = G_define_standard_option(G_OPT_R_INPUT);
  45. rast_co->key = "color";
  46. rast_co->required = NO;
  47. rast_co->description = _("Name of input color map");
  48. exag_opt = G_define_option();
  49. exag_opt->key = "exaggeration";
  50. exag_opt->type = TYPE_DOUBLE;
  51. exag_opt->required = NO;
  52. exag_opt->answer = "1.0";
  53. exag_opt->description = _("Vertical exaggeration");
  54. out = G_define_standard_option(G_OPT_F_OUTPUT);
  55. out->required = YES;
  56. out->description = _("Name for output VRML file");
  57. if (G_parser(argc, argv))
  58. exit(EXIT_FAILURE);
  59. G_get_set_window(&W);
  60. elevfd = Rast_open_old(rast_el->answer, "");
  61. {
  62. CELL cmin, cmax;
  63. struct Range range;
  64. int is_fp;
  65. DCELL dmin, dmax;
  66. struct FPRange fp_range;
  67. is_fp = Rast_map_is_fp(rast_el->answer, "");
  68. if (is_fp) {
  69. if (Rast_read_fp_range(rast_el->answer, "", &fp_range) != 1) {
  70. G_fatal_error(_("Range info for [%s] not available (run r.support)"),
  71. rast_el->answer);
  72. }
  73. Rast_get_fp_range_min_max(&fp_range, &dmin, &dmax);
  74. min = dmin;
  75. max = dmax;
  76. }
  77. else {
  78. if (Rast_read_range(rast_el->answer, "", &range) == -1) {
  79. G_fatal_error(_("Range info for <%s> not available (run r.support)"),
  80. rast_el->answer);
  81. }
  82. Rast_get_range_min_max(&range, &cmin, &cmax);
  83. min = cmin;
  84. max = cmax;
  85. }
  86. }
  87. if (rast_co->answer) {
  88. colorfd = Rast_open_old(rast_co->answer, "");
  89. Rast_read_colors(rast_co->answer, "", &colr);
  90. color_ok = 1;
  91. }
  92. /* TODO: if file exists, just append new objects */
  93. if (out->answer) {
  94. char *p;
  95. /* look for .wrl suffix, add if not found */
  96. if (NULL == (p = strrchr(out->answer, '.'))) { /* no suffix */
  97. strcpy(outfile, out->answer);
  98. strcat(outfile, ".wrl");
  99. }
  100. else if (strncmp(p + 1, "wrl", 4)) { /* some other extension */
  101. strcpy(outfile, out->answer);
  102. strcat(outfile, ".wrl");
  103. }
  104. else
  105. strcpy(outfile, out->answer);
  106. /* open file for writing VRML */
  107. G_message(_("Opening %s for writing... "), outfile);
  108. if (NULL == (vout = fopen(outfile, "w"))) {
  109. G_fatal_error(_("Unable to open output file <%s>"), outfile);
  110. }
  111. }
  112. exag = 1.0;
  113. if (exag_opt->answer) {
  114. sscanf(exag_opt->answer, "%lf", &exag);
  115. }
  116. init_coordcnv(exag, &W, min, max);
  117. vrml_begin(vout);
  118. /*
  119. vrml_put_view(vout, NULL);
  120. */
  121. vrml_put_grid(vout, &W, elevfd, colorfd, &colr, color_ok,
  122. W.rows, W.cols, shh);
  123. vrml_end(vout);
  124. Rast_close(elevfd);
  125. if (color_ok)
  126. Rast_close(colorfd);
  127. return (EXIT_SUCCESS);
  128. }
  129. static double scaleXZ, scaleY;
  130. static double transX, transY, transZ;
  131. static double Xrange, Yrange, Zrange;
  132. /* REMEMBER -
  133. * Y is HEIGHT
  134. * Z is northing-W.south
  135. * X is adjusted easting-W.west
  136. */
  137. /*
  138. * This could be entered as a vrml scale to preserve real
  139. * geographic coords, but I'm not sure how good the average
  140. * vrml viewer is at setting appropriate z-depths, so testing
  141. * first like this.
  142. */
  143. /* TODO:
  144. * change scale & use G_distance for latlon to preserve meter units
  145. */
  146. int init_coordcnv(double exag, struct Cell_head *w, double min, double max)
  147. {
  148. Yrange = (max - min) * exag;
  149. Zrange = (w->rows - 1) * w->ns_res;
  150. Xrange = (w->cols - 1) * w->ew_res;
  151. transX = -(Rast_col_to_easting(0.5, w));
  152. transZ = -(Rast_row_to_northing(0.5, w));
  153. transY = -min;
  154. if (Zrange >= Xrange && Zrange >= Yrange) { /* northing biggest */
  155. scaleXZ = 1.0 / Zrange;
  156. scaleY = exag * scaleXZ;
  157. }
  158. else if (Xrange >= Zrange && Xrange >= Yrange) { /* easting biggest */
  159. scaleXZ = 1.0 / Xrange;
  160. scaleY = exag * scaleXZ;
  161. }
  162. else /* depth biggest */
  163. scaleY = scaleXZ = 1.0 / Yrange;
  164. return 0;
  165. }
  166. int do_coordcnv(double *dval, int axis)
  167. {
  168. double dret = 0.0;
  169. switch (axis) {
  170. case 'x':
  171. case 'X':
  172. dret = (*dval + transX) * scaleXZ;
  173. break;
  174. case 'z':
  175. case 'Z':
  176. dret = (Zrange - (*dval + transZ)) * scaleXZ;
  177. break;
  178. case 'y':
  179. case 'Y':
  180. dret = (*dval + transY) * scaleY;
  181. break;
  182. default:
  183. G_fatal_error("invalid axis: %c", axis);
  184. break;
  185. }
  186. *dval = dret;
  187. return 0;
  188. }