view.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. /*!
  2. * \file lib/gis/view.c
  3. *
  4. * \brief GIS Library - 3D View functions.
  5. *
  6. * (C) 2001-2014 by the GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public License
  9. * (>=v2). Read the file COPYING that comes with GRASS for details.
  10. *
  11. * \author Bill Brown - US Army CERL
  12. *
  13. * \date 1992-2008
  14. */
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <grass/gis.h>
  19. #include <grass/glocale.h>
  20. #define REQ_KEYS 8
  21. static int compare_wind(const struct Cell_head *, const struct Cell_head *);
  22. static int get_bool(const char *);
  23. static void pr_winerr(int, const char *);
  24. static void edge_sort(float sides[4]);
  25. static int read_old_format(struct G_3dview *, FILE *);
  26. static const int vers_major = 4;
  27. static const int vers_minor = 1;
  28. static int Suppress_warn = 0;
  29. /**
  30. * \brief Turns 3D View warnings on and off.
  31. *
  32. * If Suppress_warn is 0, a warning will be printed if less than 95% of
  33. * the window when the view was saved overlaps the current window.
  34. *
  35. * \param[in] b
  36. * \return
  37. */
  38. void G_3dview_warning(int b)
  39. {
  40. Suppress_warn = b ? 0 : 1;
  41. }
  42. /**
  43. * \brief Sets default for <b>v</b> based on <b>w</b>.
  44. *
  45. * \param[in,out] v
  46. * \param[in] w
  47. * \return always returns 1
  48. */
  49. int G_get_3dview_defaults(struct G_3dview *v, struct Cell_head *w)
  50. {
  51. if (!v || !w)
  52. return (-1);
  53. v->exag = 1.0;
  54. v->fov = 40.0;
  55. v->from_to[0][0] = (w->east + w->west) / 2.0;
  56. v->from_to[0][1] = w->south - (w->north - w->south);
  57. v->from_to[0][2] = w->north - w->south;
  58. v->from_to[1][0] = (w->east + w->west) / 2.0;
  59. v->from_to[1][1] = (w->north + w->south) / 2.0;
  60. v->from_to[1][2] = 0.0;
  61. v->twist = 0.0;
  62. v->mesh_freq = 15;
  63. v->poly_freq = 1;
  64. v->display_type = 2;
  65. v->colorgrid = v->fringe = v->surfonly = v->lightson = v->doavg = 0;
  66. v->dozero = v->shading = 1;
  67. strcpy(v->bg_col, "black");
  68. strcpy(v->grid_col, "white");
  69. strcpy(v->other_col, "red");
  70. v->ambient = v->shine = 0.3;
  71. v->lightcol[0] = v->lightcol[1] = v->lightcol[2] = 0.8;
  72. v->lightpos[0] = w->west;
  73. v->lightpos[1] = w->north;
  74. v->lightpos[2] = (w->east - w->west) / 2.0;
  75. v->lightpos[3] = 1.0; /* local source */
  76. v->vwin.north = w->north;
  77. v->vwin.south = w->south;
  78. v->vwin.east = w->east;
  79. v->vwin.west = w->west;
  80. v->vwin.format = w->format;
  81. v->vwin.compressed = w->compressed;
  82. v->vwin.proj = w->proj;
  83. v->vwin.zone = w->zone;
  84. v->vwin.ew_res = w->ew_res;
  85. v->vwin.ns_res = w->ns_res;
  86. v->vwin.cols = w->cols;
  87. v->vwin.rows = w->rows;
  88. return (1);
  89. }
  90. /**
  91. * \brief Saves info to a 3d.view file.
  92. *
  93. * The address of a window (struct Cell_head *) may be passed, or if
  94. * NULL is passed, the Cell_head structure inside the G_3dview struct
  95. * will be used. e.g., if you called <i>G_get_3dview_defaults</i> with
  96. * the Cell_head you want saved, the G_3dview returned already contains
  97. * the new Cell_head. But if you're using all the keywords, so didn't
  98. * need defaults, pass this routine the address of a Cell_head.<br>
  99. *
  100. * User should call <i>G_get_3dview_defaults</i> before filling a
  101. * G_3dview struct to be written if not using all of the optional
  102. * keywords.<br>
  103. *
  104. * These keywords are constant in all 3d.view files:<br>
  105. * PGM_ID<br>
  106. * <b>cell keywords:</b><br>
  107. * north<br>
  108. * south<br>
  109. * east<br>
  110. * west<br>
  111. * rows<br>
  112. * cols<br>
  113. * <b>required keywords:</b><br>
  114. * TO_EASTING<br>
  115. * TO_NORTHING<br>
  116. * TO_HEIGHT<br>
  117. * FROM_EASTING<br>
  118. * FROM_NORTHING<br>
  119. * FROM_HEIGHT<br>
  120. * Z_EXAG<br>
  121. * FIELD_VIEW<br>
  122. * <b>optional keywords:</b> (defaults provided when reading)<br>
  123. * TWIST<br>
  124. * MESH_FREQ<br>
  125. * POLY_RES<br>
  126. * DOAVG<br>
  127. * DISPLAY_TYPE<br>
  128. * DOZERO<br>
  129. * COLORGRID<br>
  130. * SHADING<br>
  131. * FRINGE<br>
  132. * BG_COL<br>
  133. * GRID_COL<br>
  134. * OTHER_COL<br>
  135. * LIGHTS_ON<br>
  136. * LIGHTPOS<br>
  137. * LIGHTCOL<br>
  138. * LIGHTAMBIENT<br>
  139. * SHINE<br>
  140. * SURFACEONLY<br>
  141. *
  142. * \param[in] fname file name
  143. * \param[in] mapset
  144. * \param[in] View
  145. * \param[in] Win
  146. * \return 1 on success
  147. * \return -1 on error
  148. */
  149. int G_put_3dview(const char *fname, const char *mapset,
  150. const struct G_3dview *View, const struct Cell_head *Win)
  151. {
  152. FILE *fp;
  153. if (NULL == (fp = G_fopen_new("3d.view", fname))) {
  154. G_warning(_("Unable to open %s for writing"), fname);
  155. return (-1);
  156. }
  157. fprintf(fp, "# %01d.%02d\n", vers_major, vers_minor);
  158. fprintf(fp, "PGM_ID: %s\n", View->pgm_id);
  159. if (Win) {
  160. fprintf(fp, "north: %f\n", Win->north);
  161. fprintf(fp, "south: %f\n", Win->south);
  162. fprintf(fp, "east: %f\n", Win->east);
  163. fprintf(fp, "west: %f\n", Win->west);
  164. fprintf(fp, "rows: %d\n", Win->rows);
  165. fprintf(fp, "cols: %d\n", Win->cols);
  166. }
  167. else {
  168. fprintf(fp, "north: %f\n", View->vwin.north);
  169. fprintf(fp, "south: %f\n", View->vwin.south);
  170. fprintf(fp, "east: %f\n", View->vwin.east);
  171. fprintf(fp, "west: %f\n", View->vwin.west);
  172. fprintf(fp, "rows: %d\n", View->vwin.rows);
  173. fprintf(fp, "cols: %d\n", View->vwin.cols);
  174. }
  175. fprintf(fp, "TO_EASTING: %f\n", View->from_to[1][0]);
  176. fprintf(fp, "TO_NORTHING: %f\n", View->from_to[1][1]);
  177. fprintf(fp, "TO_HEIGHT: %f\n", View->from_to[1][2]);
  178. fprintf(fp, "FROM_EASTING: %f\n", View->from_to[0][0]);
  179. fprintf(fp, "FROM_NORTHING: %f\n", View->from_to[0][1]);
  180. fprintf(fp, "FROM_HEIGHT: %f\n", View->from_to[0][2]);
  181. fprintf(fp, "Z_EXAG: %f\n", View->exag);
  182. fprintf(fp, "TWIST: %f\n", View->twist);
  183. fprintf(fp, "FIELD_VIEW: %f\n", View->fov);
  184. fprintf(fp, "MESH_FREQ: %d\n", View->mesh_freq);
  185. fprintf(fp, "POLY_RES: %d\n", View->poly_freq);
  186. fprintf(fp, "DOAVG: %d\n", View->doavg);
  187. fprintf(fp, "DISPLAY_TYPE: %d\n", View->display_type);
  188. fprintf(fp, "DOZERO: %d\n", View->dozero);
  189. fprintf(fp, "COLORGRID: %d\n", View->colorgrid); /* 1 = use color */
  190. fprintf(fp, "SHADING: %d\n", View->shading);
  191. fprintf(fp, "FRINGE: %d\n", View->fringe);
  192. fprintf(fp, "BG_COL: %s\n", View->bg_col);
  193. fprintf(fp, "GRID_COL: %s\n", View->grid_col);
  194. fprintf(fp, "OTHER_COL: %s\n", View->other_col);
  195. fprintf(fp, "SURFACEONLY: %d\n", View->surfonly);
  196. fprintf(fp, "LIGHTS_ON: %d\n", View->lightson);
  197. fprintf(fp, "LIGHTPOS: %f %f %f %f\n", View->lightpos[0],
  198. View->lightpos[1], View->lightpos[2], View->lightpos[3]);
  199. fprintf(fp, "LIGHTCOL: %f %f %f\n", View->lightcol[0], View->lightcol[1],
  200. View->lightcol[2]);
  201. fprintf(fp, "LIGHTAMBIENT: %f\n", View->ambient);
  202. fprintf(fp, "SHINE: %f\n", View->shine);
  203. fclose(fp);
  204. return (1);
  205. }
  206. /**
  207. * \brief Gets a 3D View.
  208. *
  209. * If reading an old format, the window boundaries are not checked
  210. * against the current window since boundaries weren't saved.
  211. *
  212. * \param[in] fname
  213. * \param[in] mapset
  214. * \param[in,out] View
  215. * \return -1 on error
  216. * \return 1 on success
  217. * \return 2 if <b>fname</b> was written with this version of routine
  218. * \return 0 if is older format (through 4.0)
  219. */
  220. int G_get_3dview(const char *fname, const char *mapset, struct G_3dview *View)
  221. {
  222. struct Cell_head curwin;
  223. FILE *fp;
  224. char buffer[80], keystring[24], boo[8], nbuf[128], ebuf[128];
  225. int lap, v_maj, v_min, wind_keys = 0, reqkeys = 0;
  226. int current = 0; /* current version flag */
  227. mapset = G_find_file2("3d.view", fname, mapset);
  228. if (mapset != NULL) {
  229. if (NULL == (fp = G_fopen_old("3d.view", fname, mapset))) {
  230. G_warning(_("Unable to open %s for reading"), fname);
  231. return (-1);
  232. }
  233. G_get_set_window(&curwin);
  234. G_get_3dview_defaults(View, &curwin);
  235. if (NULL != fgets(buffer, 80, fp)) {
  236. if (buffer[0] != '#') { /* old d.3d format */
  237. rewind(fp);
  238. if (0 <= read_old_format(View, fp))
  239. return (0);
  240. else
  241. return (-1);
  242. }
  243. else {
  244. sscanf(buffer, "#%d.%d\n", &v_maj, &v_min);
  245. if (v_maj == vers_major && v_min == vers_minor)
  246. current = 1; /* same version */
  247. }
  248. }
  249. while (NULL != fgets(buffer, 75, fp)) {
  250. if (buffer[0] != '#') {
  251. sscanf(buffer, "%[^:]:", keystring);
  252. if (!strcmp(keystring, "PGM_ID")) {
  253. sscanf(buffer, "%*s%s", (View->pgm_id));
  254. continue;
  255. }
  256. if (!strcmp(keystring, "north")) {
  257. sscanf(buffer, "%*s%lf", &(View->vwin.north));
  258. ++wind_keys;
  259. continue;
  260. }
  261. if (!strcmp(keystring, "south")) {
  262. sscanf(buffer, "%*s%lf", &(View->vwin.south));
  263. ++wind_keys;
  264. continue;
  265. }
  266. if (!strcmp(keystring, "east")) {
  267. sscanf(buffer, "%*s%lf", &(View->vwin.east));
  268. ++wind_keys;
  269. continue;
  270. }
  271. if (!strcmp(keystring, "west")) {
  272. sscanf(buffer, "%*s%lf", &(View->vwin.west));
  273. ++wind_keys;
  274. continue;
  275. }
  276. if (!strcmp(keystring, "rows")) {
  277. sscanf(buffer, "%*s%d", &(View->vwin.rows));
  278. ++wind_keys;
  279. continue;
  280. }
  281. if (!strcmp(keystring, "cols")) {
  282. sscanf(buffer, "%*s%d", &(View->vwin.cols));
  283. ++wind_keys;
  284. continue;
  285. }
  286. if (!strcmp(keystring, "TO_EASTING")) {
  287. sscanf(buffer, "%*s%f", &(View->from_to[1][0]));
  288. ++reqkeys;
  289. continue;
  290. }
  291. if (!strcmp(keystring, "TO_NORTHING")) {
  292. sscanf(buffer, "%*s%f", &(View->from_to[1][1]));
  293. ++reqkeys;
  294. continue;
  295. }
  296. if (!strcmp(keystring, "TO_HEIGHT")) {
  297. sscanf(buffer, "%*s%f", &(View->from_to[1][2]));
  298. ++reqkeys;
  299. continue;
  300. }
  301. if (!strcmp(keystring, "FROM_EASTING")) {
  302. sscanf(buffer, "%*s%f", &(View->from_to[0][0]));
  303. ++reqkeys;
  304. continue;
  305. }
  306. if (!strcmp(keystring, "FROM_NORTHING")) {
  307. sscanf(buffer, "%*s%f", &(View->from_to[0][1]));
  308. ++reqkeys;
  309. continue;
  310. }
  311. if (!strcmp(keystring, "FROM_HEIGHT")) {
  312. sscanf(buffer, "%*s%f", &(View->from_to[0][2]));
  313. ++reqkeys;
  314. continue;
  315. }
  316. if (!strcmp(keystring, "Z_EXAG")) {
  317. sscanf(buffer, "%*s%f", &(View->exag));
  318. ++reqkeys;
  319. continue;
  320. }
  321. if (!strcmp(keystring, "MESH_FREQ")) {
  322. sscanf(buffer, "%*s%d", &(View->mesh_freq));
  323. continue;
  324. }
  325. if (!strcmp(keystring, "POLY_RES")) {
  326. sscanf(buffer, "%*s%d", &(View->poly_freq));
  327. continue;
  328. }
  329. if (!strcmp(keystring, "DOAVG")) {
  330. sscanf(buffer, "%*s%d", &(View->doavg));
  331. continue;
  332. }
  333. if (!strcmp(keystring, "FIELD_VIEW")) {
  334. sscanf(buffer, "%*s%f", &(View->fov));
  335. ++reqkeys;
  336. continue;
  337. }
  338. if (!strcmp(keystring, "TWIST")) {
  339. sscanf(buffer, "%*s%f", &(View->twist));
  340. continue;
  341. }
  342. if (!strcmp(keystring, "DISPLAY_TYPE")) {
  343. sscanf(buffer, "%*s%d", &View->display_type);
  344. continue;
  345. }
  346. if (!strcmp(keystring, "DOZERO")) {
  347. sscanf(buffer, "%*s%s", boo);
  348. View->dozero = get_bool(boo);
  349. continue;
  350. }
  351. if (!strcmp(keystring, "COLORGRID")) {
  352. sscanf(buffer, "%*s%s", boo);
  353. View->colorgrid = get_bool(boo);
  354. continue;
  355. }
  356. if (!strcmp(keystring, "FRINGE")) {
  357. sscanf(buffer, "%*s%s", boo);
  358. View->fringe = get_bool(boo);
  359. continue;
  360. }
  361. if (!strcmp(keystring, "SHADING")) {
  362. sscanf(buffer, "%*s%s", boo);
  363. View->shading = get_bool(boo);
  364. continue;
  365. }
  366. if (!strcmp(keystring, "BG_COL")) {
  367. sscanf(buffer, "%*s%s", View->bg_col);
  368. continue;
  369. }
  370. if (!strcmp(keystring, "GRID_COL")) {
  371. sscanf(buffer, "%*s%s", View->grid_col);
  372. continue;
  373. }
  374. if (!strcmp(keystring, "OTHER_COL")) {
  375. sscanf(buffer, "%*s%s", View->other_col);
  376. continue;
  377. }
  378. if (!strcmp(keystring, "SURFACEONLY")) {
  379. sscanf(buffer, "%*s%s", boo);
  380. View->surfonly = get_bool(boo);
  381. continue;
  382. }
  383. if (!strcmp(keystring, "LIGHTS_ON")) {
  384. sscanf(buffer, "%*s%s", boo);
  385. View->lightson = get_bool(boo);
  386. continue;
  387. }
  388. if (!strcmp(keystring, "LIGHTPOS")) {
  389. sscanf(buffer, "%*s%f%f%f%f", &(View->lightpos[0]),
  390. &(View->lightpos[1]), &(View->lightpos[2]),
  391. &(View->lightpos[3]));
  392. continue;
  393. }
  394. if (!strcmp(keystring, "LIGHTCOL")) {
  395. sscanf(buffer, "%*s%f%f%f", &(View->lightcol[0]),
  396. &(View->lightcol[1]), &(View->lightcol[2]));
  397. continue;
  398. }
  399. if (!strcmp(keystring, "LIGHTAMBIENT")) {
  400. sscanf(buffer, "%*s%f", &(View->ambient));
  401. continue;
  402. }
  403. if (!strcmp(keystring, "SHINE")) {
  404. sscanf(buffer, "%*s%f", &(View->shine));
  405. continue;
  406. }
  407. }
  408. }
  409. fclose(fp);
  410. if (reqkeys != REQ_KEYS) /* required keys not found */
  411. return (-1);
  412. /* fill rest of View->vwin */
  413. if (wind_keys == 6) {
  414. View->vwin.ew_res = (View->vwin.east - View->vwin.west) /
  415. View->vwin.cols;
  416. View->vwin.ns_res = (View->vwin.north - View->vwin.south) /
  417. View->vwin.rows;
  418. }
  419. else
  420. return (0); /* older format */
  421. if (!Suppress_warn) {
  422. if (95 > (lap = compare_wind(&(View->vwin), &curwin))) {
  423. fprintf(stderr, _("GRASS window when view was saved:\n"));
  424. G_format_northing(View->vwin.north, nbuf, G_projection());
  425. fprintf(stderr, "north: %s\n", nbuf);
  426. G_format_northing(View->vwin.south, nbuf, G_projection());
  427. fprintf(stderr, "south: %s\n", nbuf);
  428. G_format_easting(View->vwin.east, ebuf, G_projection());
  429. fprintf(stderr, "east: %s\n", ebuf);
  430. G_format_easting(View->vwin.west, ebuf, G_projection());
  431. fprintf(stderr, "west: %s\n", ebuf);
  432. pr_winerr(lap, fname);
  433. }
  434. }
  435. }
  436. else {
  437. G_warning(_("Unable to open %s for reading"), fname);
  438. return (-1);
  439. }
  440. if (current)
  441. return (2);
  442. return (1);
  443. }
  444. /* returns the percentage of savedwin that overlaps curwin */
  445. static int compare_wind(const struct Cell_head *savedwin,
  446. const struct Cell_head *curwin)
  447. {
  448. float e_ings[4], n_ings[4], area_lap, area_saved;
  449. int outside = 0;
  450. if (savedwin->north < curwin->south)
  451. outside = 1;
  452. if (savedwin->south > curwin->north)
  453. outside = 1;
  454. if (savedwin->east < curwin->west)
  455. outside = 1;
  456. if (savedwin->west > curwin->east)
  457. outside = 1;
  458. if (outside)
  459. return (0);
  460. e_ings[0] = savedwin->west;
  461. e_ings[1] = savedwin->east;
  462. e_ings[2] = curwin->west;
  463. e_ings[3] = curwin->east;
  464. edge_sort(e_ings);
  465. n_ings[0] = savedwin->south;
  466. n_ings[1] = savedwin->north;
  467. n_ings[2] = curwin->south;
  468. n_ings[3] = curwin->north;
  469. edge_sort(n_ings);
  470. area_lap = (e_ings[2] - e_ings[1]) * (n_ings[2] - n_ings[1]);
  471. area_saved = (savedwin->east - savedwin->west) *
  472. (savedwin->north - savedwin->south);
  473. return ((int)(area_lap * 100.0 / area_saved));
  474. }
  475. static int get_bool(const char *str)
  476. {
  477. if (str[0] == 'y' || str[0] == 'Y')
  478. return (1);
  479. if (str[0] == 'n' || str[0] == 'N')
  480. return (0);
  481. return (atoi(str) ? 1 : 0);
  482. }
  483. static void pr_winerr(int vis, /* % of saved window overlapping current window */
  484. const char *viewname)
  485. {
  486. switch (vis) {
  487. case 0:
  488. G_warning(_(" Window saved in \"%s\" is completely outside of current GRASS window."),
  489. viewname);
  490. break;
  491. default:
  492. G_warning(_(" Only %d%% of window saved in \"%s\" overlaps with current GRASS window."),
  493. vis, viewname);
  494. break;
  495. }
  496. }
  497. /*********************************************************************/
  498. /* sorts 4 floats from lowest to highest */
  499. static void edge_sort(float sides[4])
  500. {
  501. int i, j;
  502. float temp;
  503. for (i = 0; i < 4; ++i) {
  504. for (j = i + 1; j < 4; ++j) {
  505. if (sides[j] < sides[i]) { /* then swap */
  506. temp = sides[i];
  507. sides[i] = sides[j];
  508. sides[j] = temp;
  509. }
  510. }
  511. }
  512. }
  513. static int read_old_format(struct G_3dview *v, FILE * fp)
  514. {
  515. char buffer[80];
  516. int req_keys = 0;
  517. double td;
  518. char boo[8];
  519. strcpy((v->pgm_id), "d.3d");
  520. if (1 == sscanf(fgets(buffer, 80, fp), "%f", &(v->from_to[1][0])))
  521. ++req_keys;
  522. if (1 == sscanf(fgets(buffer, 80, fp), "%f", &(v->from_to[1][1])))
  523. ++req_keys;
  524. if (1 == sscanf(fgets(buffer, 80, fp), "%f", &(v->from_to[1][2])))
  525. ++req_keys;
  526. if (1 == sscanf(fgets(buffer, 80, fp), "%f", &(v->from_to[0][0])))
  527. ++req_keys;
  528. if (1 == sscanf(fgets(buffer, 80, fp), "%f", &(v->from_to[0][1])))
  529. ++req_keys;
  530. if (1 == sscanf(fgets(buffer, 80, fp), "%f", &(v->from_to[0][2])))
  531. ++req_keys;
  532. if (1 == sscanf(fgets(buffer, 80, fp), "%f", &(v->exag)))
  533. ++req_keys;
  534. sscanf(fgets(buffer, 80, fp), "%d", &(v->mesh_freq));
  535. if (1 == sscanf(fgets(buffer, 80, fp), "%f", &(v->fov)))
  536. ++req_keys;
  537. if (1 == sscanf(fgets(buffer, 80, fp), "%lf", &td)) { /* resolution */
  538. v->vwin.rows = (v->vwin.north - v->vwin.south) / td;
  539. v->vwin.cols = (v->vwin.east - v->vwin.west) / td;
  540. v->vwin.ew_res = v->vwin.ns_res = td;
  541. }
  542. sscanf(fgets(buffer, 80, fp), "%s", boo); /* linesonly */
  543. v->display_type = get_bool(boo) ? 1 : 3;
  544. sscanf(fgets(buffer, 80, fp), "%s", boo);
  545. v->dozero = get_bool(boo);
  546. sscanf(fgets(buffer, 80, fp), "%s", v->grid_col);
  547. if (!strcmp(v->grid_col, "color"))
  548. v->colorgrid = 1;
  549. sscanf(fgets(buffer, 80, fp), "%s", v->other_col);
  550. sscanf(fgets(buffer, 80, fp), "%s", v->bg_col);
  551. sscanf(fgets(buffer, 80, fp), "%s", boo);
  552. v->doavg = get_bool(boo);
  553. if (v->exag) { /* old 3d.view files saved height with no exag */
  554. v->from_to[0][2] /= v->exag;
  555. v->from_to[1][2] /= v->exag;
  556. }
  557. fclose(fp);
  558. if (req_keys == REQ_KEYS)
  559. return (1);
  560. else
  561. return (-1);
  562. }