main.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. /*
  2. ****************************************************************************
  3. *
  4. * MODULE: d.vect
  5. * AUTHOR(S): CERL, Radim Blazek, others
  6. * Updated to GRASS7 by Martin Landa <landa.martin gmail.com>
  7. * Support for vector legend by Adam Laza <ad.laza32 gmail.com >
  8. * PURPOSE: Display the vector map in map display
  9. * COPYRIGHT: (C) 2004-2014 by the GRASS Development Team
  10. *
  11. * This program is free software under the GNU General
  12. * Public License (>=v2). Read the file COPYING that
  13. * comes with GRASS for details.
  14. *
  15. *****************************************************************************/
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <sys/types.h>
  19. #include <dirent.h>
  20. #include <grass/gis.h>
  21. #include <grass/raster.h>
  22. #include <grass/display.h>
  23. #include <grass/dbmi.h>
  24. #include <grass/glocale.h>
  25. #include "plot.h"
  26. #include "local_proto.h"
  27. static int cmp(const void *, const void *);
  28. static char *icon_files(void);
  29. int main(int argc, char **argv)
  30. {
  31. int ret, level;
  32. int stat, type, display;
  33. int chcat;
  34. int has_color, has_fcolor;
  35. struct color_rgb color, fcolor;
  36. double size;
  37. int default_width;
  38. double width_scale;
  39. double minreg, maxreg, reg;
  40. char map_name[GNAME_MAX];
  41. struct GModule *module;
  42. struct Option *map_opt;
  43. struct Option *color_opt, *fcolor_opt, *rgbcol_opt, *zcol_opt;
  44. struct Option *type_opt, *display_opt;
  45. struct Option *icon_opt, *size_opt, *sizecolumn_opt, *rotcolumn_opt;
  46. struct Option *where_opt;
  47. struct Option *field_opt, *cat_opt, *lfield_opt;
  48. struct Option *lcolor_opt, *bgcolor_opt, *bcolor_opt;
  49. struct Option *lsize_opt, *font_opt, *enc_opt, *xref_opt, *yref_opt;
  50. struct Option *attrcol_opt, *maxreg_opt, *minreg_opt;
  51. struct Option *width_opt, *wcolumn_opt, *wscale_opt;
  52. struct Option *leglab_opt;
  53. struct Option *icon_line_opt, *icon_area_opt;
  54. struct Flag *id_flag, *cats_acolors_flag, *sqrt_flag, *legend_flag;
  55. char *desc;
  56. struct cat_list *Clist;
  57. LATTR lattr;
  58. struct Map_info Map;
  59. struct Cell_head window;
  60. struct bound_box box;
  61. double overlap;
  62. stat = 0;
  63. /* Initialize the GIS calls */
  64. G_gisinit(argv[0]);
  65. module = G_define_module();
  66. G_add_keyword(_("display"));
  67. G_add_keyword(_("graphics"));
  68. G_add_keyword(_("vector"));
  69. module->description = _("Displays user-specified vector map "
  70. "in the active graphics frame.");
  71. map_opt = G_define_standard_option(G_OPT_V_MAP);
  72. field_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);
  73. field_opt->answer = "1";
  74. field_opt->guisection = _("Selection");
  75. display_opt = G_define_option();
  76. display_opt->key = "display";
  77. display_opt->type = TYPE_STRING;
  78. display_opt->required = YES;
  79. display_opt->multiple = YES;
  80. display_opt->answer = "shape";
  81. display_opt->options = "shape,cat,topo,vert,dir,zcoor";
  82. display_opt->description = _("Display");
  83. desc = NULL;
  84. G_asprintf(&desc,
  85. "shape;%s;cat;%s;topo;%s;vert;%s;dir;%s;zcoor;%s",
  86. _("Display geometry of features"),
  87. _("Display category numbers of features"),
  88. _("Display topology information (nodes, edges)"),
  89. _("Display vertices of features"),
  90. _("Display direction of linear features"),
  91. _("Display z-coordinate of features (only for 3D vector maps)"));
  92. display_opt->descriptions = desc;
  93. /* Query */
  94. type_opt = G_define_standard_option(G_OPT_V_TYPE);
  95. type_opt->answer = "point,line,area,face";
  96. type_opt->options = "point,line,boundary,centroid,area,face";
  97. type_opt->guisection = _("Selection");
  98. cat_opt = G_define_standard_option(G_OPT_V_CATS);
  99. cat_opt->guisection = _("Selection");
  100. where_opt = G_define_standard_option(G_OPT_DB_WHERE);
  101. where_opt->guisection = _("Selection");
  102. /* Colors */
  103. color_opt = G_define_standard_option(G_OPT_CN);
  104. color_opt->label = _("Feature color");
  105. color_opt->guisection = _("Colors");
  106. fcolor_opt = G_define_standard_option(G_OPT_CN);
  107. fcolor_opt->key = "fill_color";
  108. fcolor_opt->answer = "200:200:200";
  109. fcolor_opt->label = _("Area fill color");
  110. fcolor_opt->guisection = _("Colors");
  111. rgbcol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  112. rgbcol_opt->key = "rgb_column";
  113. rgbcol_opt->guisection = _("Colors");
  114. rgbcol_opt->label = _("Colorize features according color definition column");
  115. rgbcol_opt->description = _("Color definition in R:G:B form");
  116. zcol_opt = G_define_standard_option(G_OPT_M_COLR);
  117. zcol_opt->key = "zcolor";
  118. zcol_opt->description = _("Colorize point or area features according to z-coordinate");
  119. zcol_opt->guisection = _("Colors");
  120. /* Lines */
  121. width_opt = G_define_option();
  122. width_opt->key = "width";
  123. width_opt->type = TYPE_INTEGER;
  124. width_opt->answer = "0";
  125. width_opt->guisection = _("Lines");
  126. width_opt->description = _("Line width");
  127. wcolumn_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  128. wcolumn_opt->key = "width_column";
  129. wcolumn_opt->guisection = _("Lines");
  130. wcolumn_opt->label = _("Name of numeric column containing line width");
  131. wcolumn_opt->description = _("These values will be scaled by width_scale");
  132. wscale_opt = G_define_option();
  133. wscale_opt->key = "width_scale";
  134. wscale_opt->type = TYPE_DOUBLE;
  135. wscale_opt->answer = "1";
  136. wscale_opt->guisection = _("Lines");
  137. wscale_opt->description = _("Scale factor for width_column");
  138. /* Symbols */
  139. icon_opt = G_define_option();
  140. icon_opt->key = "icon";
  141. icon_opt->type = TYPE_STRING;
  142. icon_opt->required = NO;
  143. icon_opt->multiple = NO;
  144. icon_opt->guisection = _("Symbols");
  145. icon_opt->answer = "basic/x";
  146. /* This could also use ->gisprompt = "old,symbol,symbol" instead of ->options */
  147. icon_opt->options = icon_files();
  148. icon_opt->description = _("Point and centroid symbol");
  149. size_opt = G_define_option();
  150. size_opt->key = "size";
  151. size_opt->type = TYPE_DOUBLE;
  152. size_opt->answer = "5";
  153. size_opt->guisection = _("Symbols");
  154. size_opt->label = _("Symbol size");
  155. size_opt->description =
  156. _("When used with the size_column option this becomes the scale factor");
  157. sizecolumn_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  158. sizecolumn_opt->key = "size_column";
  159. sizecolumn_opt->guisection = _("Symbols");
  160. sizecolumn_opt->description =
  161. _("Name of numeric column containing symbol size");
  162. rotcolumn_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  163. rotcolumn_opt->key = "rotation_column";
  164. rotcolumn_opt->guisection = _("Symbols");
  165. rotcolumn_opt->label =
  166. _("Name of numeric column containing symbol rotation angle");
  167. rotcolumn_opt->description =
  168. _("Measured in degrees CCW from east");
  169. icon_area_opt = G_define_option();
  170. icon_area_opt->key = "icon_area";
  171. icon_area_opt->type = TYPE_STRING;
  172. icon_area_opt->required = NO;
  173. icon_area_opt->multiple = NO;
  174. icon_area_opt->guisection = _("Legend");
  175. icon_area_opt->answer = "legend/area";
  176. icon_area_opt->options = icon_files();
  177. icon_area_opt->description = _("Area/boundary symbol for legend");
  178. icon_line_opt = G_define_option();
  179. icon_line_opt->key = "icon_line";
  180. icon_line_opt->type = TYPE_STRING;
  181. icon_line_opt->required = NO;
  182. icon_line_opt->multiple = NO;
  183. icon_line_opt->guisection = _("Legend");
  184. icon_line_opt->answer = "legend/line";
  185. icon_line_opt->options = icon_files();
  186. icon_line_opt->description = _("Line symbol for legend");
  187. leglab_opt = G_define_option();
  188. leglab_opt->key = "legend_label";
  189. leglab_opt->type = TYPE_STRING;
  190. leglab_opt->guisection = _("Legend");
  191. leglab_opt->description = _("Label to display after symbol in vector legend");
  192. /* Labels */
  193. lfield_opt = G_define_standard_option(G_OPT_V_FIELD);
  194. lfield_opt->key = "label_layer";
  195. lfield_opt->required = NO;
  196. lfield_opt->guisection = _("Labels");
  197. lfield_opt->label =
  198. _("Layer number for labels (default: the given layer number)");
  199. attrcol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  200. attrcol_opt->key = "attribute_column";
  201. attrcol_opt->multiple = NO; /* or fix attr.c, around line 102 */
  202. attrcol_opt->guisection = _("Labels");
  203. attrcol_opt->description = _("Name of column to be displayed as a label");
  204. lcolor_opt = G_define_standard_option(G_OPT_C);
  205. lcolor_opt->key = "label_color";
  206. lcolor_opt->answer = "red";
  207. lcolor_opt->label = _("Label color");
  208. lcolor_opt->guisection = _("Labels");
  209. bgcolor_opt = G_define_standard_option(G_OPT_CN);
  210. bgcolor_opt->key = "label_bgcolor";
  211. bgcolor_opt->answer = "none";
  212. bgcolor_opt->guisection = _("Labels");
  213. bgcolor_opt->label = _("Label background color");
  214. bcolor_opt = G_define_standard_option(G_OPT_CN);
  215. bcolor_opt->key = "label_bcolor";
  216. bcolor_opt->type = TYPE_STRING;
  217. bcolor_opt->answer = "none";
  218. bcolor_opt->guisection = _("Labels");
  219. bcolor_opt->label = _("Label border color");
  220. lsize_opt = G_define_option();
  221. lsize_opt->key = "label_size";
  222. lsize_opt->type = TYPE_INTEGER;
  223. lsize_opt->answer = "8";
  224. lsize_opt->guisection = _("Labels");
  225. lsize_opt->description = _("Label size (pixels)");
  226. font_opt = G_define_option();
  227. font_opt->key = "font";
  228. font_opt->type = TYPE_STRING;
  229. font_opt->guisection = _("Labels");
  230. font_opt->description = _("Font name");
  231. enc_opt = G_define_option();
  232. enc_opt->key = "encoding";
  233. enc_opt->type = TYPE_STRING;
  234. enc_opt->guisection = _("Labels");
  235. enc_opt->description = _("Text encoding");
  236. xref_opt = G_define_option();
  237. xref_opt->key = "xref";
  238. xref_opt->type = TYPE_STRING;
  239. xref_opt->guisection = _("Labels");
  240. xref_opt->answer = "left";
  241. xref_opt->options = "left,center,right";
  242. xref_opt->description = _("Label horizontal justification");
  243. yref_opt = G_define_option();
  244. yref_opt->key = "yref";
  245. yref_opt->type = TYPE_STRING;
  246. yref_opt->guisection = _("Labels");
  247. yref_opt->answer = "center";
  248. yref_opt->options = "top,center,bottom";
  249. yref_opt->description = _("Label vertical justification");
  250. minreg_opt = G_define_option();
  251. minreg_opt->key = "minreg";
  252. minreg_opt->type = TYPE_DOUBLE;
  253. minreg_opt->required = NO;
  254. minreg_opt->description =
  255. _("Minimum region size (average from height and width) "
  256. "when map is displayed");
  257. maxreg_opt = G_define_option();
  258. maxreg_opt->key = "maxreg";
  259. maxreg_opt->type = TYPE_DOUBLE;
  260. maxreg_opt->required = NO;
  261. maxreg_opt->description =
  262. _("Maximum region size (average from height and width) "
  263. "when map is displayed");
  264. /* Colors */
  265. cats_acolors_flag = G_define_flag();
  266. cats_acolors_flag->key = 'c';
  267. cats_acolors_flag->guisection = _("Colors");
  268. cats_acolors_flag->description =
  269. _("Random colors according to category number "
  270. "(or layer number if 'layer=-1' is given)");
  271. /* Query */
  272. id_flag = G_define_flag();
  273. id_flag->key = 'i';
  274. id_flag->guisection = _("Selection");
  275. id_flag->description = _("Use values from 'cats' option as feature id");
  276. sqrt_flag = G_define_flag();
  277. sqrt_flag->key = 'r';
  278. sqrt_flag->label = _("Use square root of the value of size_column");
  279. sqrt_flag->description =
  280. _("This makes circle areas proportionate to the size_column values "
  281. "instead of circle radius");
  282. sqrt_flag->guisection = _("Symbols");
  283. legend_flag = G_define_flag();
  284. legend_flag->key = 's';
  285. legend_flag->label = _("Do not show this layer in vector legend");
  286. legend_flag->guisection = _("Legend");
  287. G_option_exclusive(zcol_opt, rgbcol_opt, cats_acolors_flag, NULL);
  288. /* Check command line */
  289. if (G_parser(argc, argv))
  290. exit(EXIT_FAILURE);
  291. D_open_driver();
  292. G_get_set_window(&window);
  293. /* Check min/max region */
  294. reg = ((window.east - window.west) + (window.north - window.south)) / 2;
  295. if (minreg_opt->answer) {
  296. minreg = atof(minreg_opt->answer);
  297. if (reg < minreg) {
  298. G_important_message(_("Region size is lower than minreg, nothing displayed"));
  299. exit(EXIT_SUCCESS);
  300. }
  301. }
  302. if (maxreg_opt->answer) {
  303. maxreg = atof(maxreg_opt->answer);
  304. if (reg > maxreg) {
  305. G_important_message(_("Region size is greater than maxreg, nothing displayed"));
  306. exit(EXIT_SUCCESS);
  307. }
  308. }
  309. strcpy(map_name, map_opt->answer);
  310. default_width = atoi(width_opt->answer);
  311. if (default_width < 0)
  312. default_width = 0;
  313. width_scale = atof(wscale_opt->answer);
  314. if (cats_acolors_flag->answer && rgbcol_opt->answer) {
  315. G_warning(_("The -%c flag and <%s> option cannot be used together, "
  316. "the -%c flag will be ignored!"),
  317. cats_acolors_flag->key, rgbcol_opt->key, cats_acolors_flag->key);
  318. cats_acolors_flag->answer = FALSE;
  319. }
  320. color = G_standard_color_rgb(WHITE);
  321. has_color = option_to_color(&color, color_opt->answer);
  322. fcolor = G_standard_color_rgb(WHITE);
  323. has_fcolor = option_to_color(&fcolor, fcolor_opt->answer);
  324. size = atof(size_opt->answer);
  325. /* if where_opt was specified select categories from db
  326. * otherwise parse cat_opt */
  327. Clist = Vect_new_cat_list();
  328. Clist->field = atoi(field_opt->answer);
  329. /* open vector */
  330. level = Vect_open_old2(&Map, map_name, "", field_opt->answer);
  331. chcat = 0;
  332. if (where_opt->answer) {
  333. if (Clist->field < 1)
  334. G_fatal_error(_("Option <%s> must be > 0"), field_opt->key);
  335. chcat = 1;
  336. option_to_where(&Map, Clist, where_opt->answer);
  337. }
  338. else if (cat_opt->answer) {
  339. if (Clist->field < 1 && !id_flag->answer)
  340. G_fatal_error(_("Option <%s> must be > 0"), field_opt->key);
  341. chcat = 1;
  342. ret = Vect_str_to_cat_list(cat_opt->answer, Clist);
  343. if (ret > 0)
  344. G_warning(n_("%d error in cat option", "%d errors in cat option", ret), ret);
  345. }
  346. type = Vect_option_to_types(type_opt);
  347. display = option_to_display(display_opt);
  348. /* labels */
  349. options_to_lattr(&lattr, lfield_opt->answer,
  350. lcolor_opt->answer, bgcolor_opt->answer, bcolor_opt->answer,
  351. atoi(lsize_opt->answer), font_opt->answer, enc_opt->answer,
  352. xref_opt->answer, yref_opt->answer);
  353. D_setup(0);
  354. D_set_reduction(1.0);
  355. G_verbose_message(_("Plotting..."));
  356. overlap = 1;
  357. if (level >= 2 && window.proj != PROJECTION_LL) {
  358. Vect_get_map_box(&Map, &box);
  359. overlap = G_window_percentage_overlap(&window, box.N, box.S,
  360. box.E, box.W);
  361. G_debug(1, "overlap = %f \n", overlap);
  362. }
  363. if (overlap == 0) {
  364. G_warning(_("The bounding box of the map is outside the current region, "
  365. "nothing drawn"));
  366. }
  367. else {
  368. if (overlap < 1)
  369. Vect_set_constraint_region(&Map, window.north, window.south,
  370. window.east, window.west,
  371. PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX);
  372. /* default line width */
  373. if (!wcolumn_opt->answer)
  374. D_line_width(default_width);
  375. if (display & DISP_SHAPE) {
  376. stat += display_shape(&Map, type, Clist, &window,
  377. has_color ? &color : NULL, has_fcolor ? &fcolor : NULL, chcat,
  378. icon_opt->answer, size, sizecolumn_opt->answer,
  379. sqrt_flag->answer ? TRUE : FALSE, rotcolumn_opt->answer,
  380. id_flag->answer ? TRUE : FALSE,
  381. cats_acolors_flag->answer ? TRUE : FALSE, rgbcol_opt->answer,
  382. default_width, wcolumn_opt->answer, width_scale,
  383. zcol_opt->answer);
  384. if (wcolumn_opt->answer)
  385. D_line_width(default_width);
  386. }
  387. if (has_color) {
  388. D_RGB_color(color.r, color.g, color.b);
  389. if (display & DISP_DIR)
  390. stat += display_dir(&Map, type, Clist, chcat, size);
  391. }
  392. if (!legend_flag->answer) {
  393. write_into_legfile(&Map, type, leglab_opt->answer, map_name,
  394. icon_opt->answer, size_opt->answer,
  395. color_opt->answer, fcolor_opt->answer,
  396. width_opt->answer, icon_area_opt->answer,
  397. icon_line_opt->answer, sizecolumn_opt->answer);
  398. }
  399. /* reset line width: Do we need to get line width from display
  400. * driver (not implemented)? It will help restore previous line
  401. * width (not just 0) determined by another module (e.g.,
  402. * d.linewidth). */
  403. if (!wcolumn_opt->answer)
  404. D_line_width(0);
  405. if (display & DISP_CAT)
  406. stat += display_label(&Map, type, Clist, &lattr, chcat);
  407. if (attrcol_opt->answer)
  408. stat += display_attr(&Map, type, attrcol_opt->answer, Clist, &lattr, chcat);
  409. if (display & DISP_ZCOOR)
  410. stat += display_zcoor(&Map, type, &lattr);
  411. if (display & DISP_VERT)
  412. stat += display_vert(&Map, type, &lattr, size);
  413. if (display & DISP_TOPO)
  414. stat += display_topo(&Map, type, &lattr, size);
  415. }
  416. D_save_command(G_recreate_command());
  417. D_close_driver();
  418. Vect_close(&Map);
  419. Vect_destroy_cat_list(Clist);
  420. if (stat != 0) {
  421. G_fatal_error(_("Rendering failed"));
  422. }
  423. G_done_msg(" ");
  424. exit(EXIT_SUCCESS);
  425. }
  426. int cmp(const void *a, const void *b)
  427. {
  428. return (strcmp(*(char **)a, *(char **)b));
  429. }
  430. /* adopted from r.colors */
  431. char *icon_files(void)
  432. {
  433. char **list, *ret;
  434. char buf[GNAME_MAX], path[GPATH_MAX], path_i[GPATH_MAX];
  435. int i, count;
  436. size_t len;
  437. DIR *dir, *dir_i;
  438. struct dirent *d, *d_i;
  439. list = NULL;
  440. len = 0;
  441. sprintf(path, "%s/etc/symbol", G_gisbase());
  442. dir = opendir(path);
  443. if (!dir)
  444. return NULL;
  445. count = 0;
  446. /* loop over etc/symbol */
  447. while ((d = readdir(dir))) {
  448. if (d->d_name[0] == '.')
  449. continue;
  450. sprintf(path_i, "%s/etc/symbol/%s", G_gisbase(), d->d_name);
  451. dir_i = opendir(path_i);
  452. if (!dir_i)
  453. continue;
  454. /* loop over each directory in etc/symbols */
  455. while ((d_i = readdir(dir_i))) {
  456. if (d_i->d_name[0] == '.')
  457. continue;
  458. list = G_realloc(list, (count + 1) * sizeof(char *));
  459. sprintf(buf, "%s/%s", d->d_name, d_i->d_name);
  460. list[count++] = G_store(buf);
  461. len += strlen(d->d_name) + strlen(d_i->d_name) + 2; /* '/' + ',' */
  462. }
  463. closedir(dir_i);
  464. }
  465. closedir(dir);
  466. qsort(list, count, sizeof(char *), cmp);
  467. if (len > 0) {
  468. ret = G_malloc((len + 1) * sizeof(char)); /* \0 */
  469. *ret = '\0';
  470. for (i = 0; i < count; i++) {
  471. if (i > 0)
  472. strcat(ret, ",");
  473. strcat(ret, list[i]);
  474. G_free(list[i]);
  475. }
  476. G_free(list);
  477. }
  478. else {
  479. ret = G_store("");
  480. }
  481. return ret;
  482. }