main.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /****************************************************************************
  2. *
  3. * MODULE: v.transform
  4. * AUTHOR(S): Eric G. Miller <egm2@jps.net>
  5. * Upgrade to 5.7 Radim Blazek
  6. * Column support & OGR support added by Martin Landa (09/2007)
  7. *
  8. * PURPOSE: To transform a vector map's coordinates via a set of tie
  9. * points.
  10. *
  11. * COPYRIGHT: (C) 2002-2014 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General Public
  14. * License (>=v2). Read the file COPYING that comes with GRASS
  15. * for details.
  16. *
  17. *****************************************************************************/
  18. /*
  19. *History:
  20. *- This takes an ascii digit file in one coordinate system and converts
  21. * the map to another coordinate system.
  22. * Uses the transform library: $(TRANSLIB)
  23. *
  24. * Written during the ice age of Illinois, 02/16/90, by the GRASS team, -mh.
  25. *
  26. *- Modified by Dave Gerdes 1/90 for dig_head stuff
  27. *- Modified by Radim Blazek to work on binary files 2002
  28. *- Interactive functionality disabled, 2007
  29. */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <grass/gis.h>
  34. #include <grass/vector.h>
  35. #include <grass/dbmi.h>
  36. #include <grass/glocale.h>
  37. #include "trans.h"
  38. #include "local_proto.h"
  39. int main(int argc, char *argv[])
  40. {
  41. struct file_info Current, Trans;
  42. struct GModule *module;
  43. struct Option *vold, *vnew, *xshift, *yshift, *zshift,
  44. *xscale, *yscale, *zscale, *zrot, *columns, *field_opt;
  45. struct Flag *tozero_flag, *no_topo;
  46. struct Flag *swap_flag, *swap_xz_flag, *swap_yz_flag, *swap_after_flag;
  47. char mon[4], date[40], buf[1000];
  48. struct Map_info Old, New;
  49. int day, yr;
  50. struct bound_box box;
  51. double ztozero;
  52. double trans_params[7]; /* xshift, ..., xscale, ..., zrot */
  53. /* columns */
  54. unsigned int i;
  55. int idx, out3d;
  56. char **tokens;
  57. char *columns_name[7]; /* xshift, yshift, zshift, xscale, yscale, zscale, zrot */
  58. int field;
  59. G_gisinit(argv[0]);
  60. module = G_define_module();
  61. G_add_keyword(_("vector"));
  62. G_add_keyword(_("transformation"));
  63. G_add_keyword(_("geometry"));
  64. G_add_keyword("GCP");
  65. module->description =
  66. _("Performs an affine transformation (shift, scale and rotate) "
  67. "on vector map.");
  68. tozero_flag = G_define_flag();
  69. tozero_flag->key = 't';
  70. tozero_flag->description = _("Shift all z values to bottom=0");
  71. swap_flag = G_define_flag();
  72. swap_flag->key = 'w';
  73. swap_flag->description =
  74. _("Swap coordinates x, y and then apply other parameters");
  75. swap_xz_flag = G_define_flag();
  76. swap_xz_flag->key = 'x';
  77. swap_xz_flag->description =
  78. _("Swap coordinates x, z and then apply other parameters");
  79. swap_yz_flag = G_define_flag();
  80. swap_yz_flag->key = 'y';
  81. swap_yz_flag->description =
  82. _("Swap coordinates y, z and then apply other parameters");
  83. swap_after_flag = G_define_flag();
  84. swap_after_flag->key = 'a';
  85. swap_after_flag->description =
  86. _("Swap coordinates after the other transformations");
  87. no_topo = G_define_flag();
  88. no_topo->key = 'b';
  89. no_topo->description = _("Do not build topology");
  90. vold = G_define_standard_option(G_OPT_V_INPUT);
  91. field_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);
  92. field_opt->guisection = _("Custom");
  93. vnew = G_define_standard_option(G_OPT_V_OUTPUT);
  94. xshift = G_define_option();
  95. xshift->key = "xshift";
  96. xshift->type = TYPE_DOUBLE;
  97. xshift->required = NO;
  98. xshift->multiple = NO;
  99. xshift->description = _("Shifting value for x coordinates");
  100. xshift->answer = "0.0";
  101. xshift->guisection = _("Custom");
  102. yshift = G_define_option();
  103. yshift->key = "yshift";
  104. yshift->type = TYPE_DOUBLE;
  105. yshift->required = NO;
  106. yshift->multiple = NO;
  107. yshift->description = _("Shifting value for y coordinates");
  108. yshift->answer = "0.0";
  109. yshift->guisection = _("Custom");
  110. zshift = G_define_option();
  111. zshift->key = "zshift";
  112. zshift->type = TYPE_DOUBLE;
  113. zshift->required = NO;
  114. zshift->multiple = NO;
  115. zshift->description = _("Shifting value for z coordinates");
  116. zshift->answer = "0.0";
  117. zshift->guisection = _("Custom");
  118. xscale = G_define_option();
  119. xscale->key = "xscale";
  120. xscale->type = TYPE_DOUBLE;
  121. xscale->required = NO;
  122. xscale->multiple = NO;
  123. xscale->description = _("Scaling factor for x coordinates");
  124. xscale->answer = "1.0";
  125. xscale->guisection = _("Custom");
  126. yscale = G_define_option();
  127. yscale->key = "yscale";
  128. yscale->type = TYPE_DOUBLE;
  129. yscale->required = NO;
  130. yscale->multiple = NO;
  131. yscale->description = _("Scaling factor for y coordinates");
  132. yscale->answer = "1.0";
  133. yscale->guisection = _("Custom");
  134. zscale = G_define_option();
  135. zscale->key = "zscale";
  136. zscale->type = TYPE_DOUBLE;
  137. zscale->required = NO;
  138. zscale->multiple = NO;
  139. zscale->description = _("Scaling factor for z coordinates");
  140. zscale->answer = "1.0";
  141. zscale->guisection = _("Custom");
  142. zrot = G_define_option();
  143. zrot->key = "zrotation";
  144. zrot->type = TYPE_DOUBLE;
  145. zrot->required = NO;
  146. zrot->multiple = NO;
  147. zrot->description =
  148. _("Rotation around z axis in degrees (counter-clockwise)");
  149. zrot->answer = "0.0";
  150. zrot->guisection = _("Custom");
  151. columns = G_define_standard_option(G_OPT_DB_COLUMNS);
  152. columns->label =
  153. _("Name of attribute column(s) used as transformation parameters");
  154. columns->description =
  155. _("Format: parameter:column, e.g. xshift:xs,yshift:ys,zrot:zr");
  156. columns->guisection = _("Custom");
  157. /* we don't define order of swapping, so only one can be used safely */
  158. G_option_exclusive(swap_flag, swap_xz_flag, swap_yz_flag, NULL);
  159. if (G_parser(argc, argv))
  160. exit(EXIT_FAILURE);
  161. strcpy(Current.name, vold->answer);
  162. strcpy(Trans.name, vnew->answer);
  163. Vect_check_input_output_name(vold->answer, vnew->answer, G_FATAL_EXIT);
  164. /* open input vector */
  165. if (Vect_open_old2(&Old, vold->answer, "", field_opt->answer) < 0)
  166. G_fatal_error(_("Unable to open vector map <%s>"), vold->answer);
  167. field = Vect_get_field_number(&Old, field_opt->answer);
  168. if (field < 1 && columns->answer) {
  169. G_fatal_error(_("Columns require a valid layer. Please use '%s' parameter."),
  170. field_opt->key);
  171. }
  172. out3d = Vect_is_3d(&Old);
  173. /* tokenize columns names */
  174. for (i = 0; i <= IDX_ZROT; i++) {
  175. columns_name[i] = NULL;
  176. }
  177. i = 0;
  178. if (columns->answer) {
  179. while (columns->answers[i]) {
  180. tokens = G_tokenize(columns->answers[i], ":");
  181. if (G_number_of_tokens(tokens) == 2) {
  182. if (strcmp(tokens[0], xshift->key) == 0)
  183. idx = IDX_XSHIFT;
  184. else if (strcmp(tokens[0], yshift->key) == 0)
  185. idx = IDX_YSHIFT;
  186. else if (strcmp(tokens[0], zshift->key) == 0)
  187. idx = IDX_ZSHIFT;
  188. else if (strcmp(tokens[0], xscale->key) == 0)
  189. idx = IDX_XSCALE;
  190. else if (strcmp(tokens[0], yscale->key) == 0)
  191. idx = IDX_YSCALE;
  192. else if (strcmp(tokens[0], zscale->key) == 0)
  193. idx = IDX_ZSCALE;
  194. else if (strcmp(tokens[0], zrot->key) == 0)
  195. idx = IDX_ZROT;
  196. else {
  197. G_warning(_("Unknown column parameter '%s'"),
  198. tokens[0]);
  199. idx = -1;
  200. }
  201. if (idx != -1)
  202. columns_name[idx] = G_store(tokens[1]);
  203. G_free_tokens(tokens);
  204. }
  205. else {
  206. G_fatal_error(_("Unable to tokenize column string: [%s]"),
  207. columns->answers[i]);
  208. }
  209. i++;
  210. }
  211. }
  212. /* determine transformation parameters */
  213. trans_params[IDX_XSHIFT] = atof(xshift->answer);
  214. trans_params[IDX_YSHIFT] = atof(yshift->answer);
  215. trans_params[IDX_ZSHIFT] = atof(zshift->answer);
  216. trans_params[IDX_XSCALE] = atof(xscale->answer);
  217. trans_params[IDX_YSCALE] = atof(yscale->answer);
  218. trans_params[IDX_ZSCALE] = atof(zscale->answer);
  219. trans_params[IDX_ZROT] = atof(zrot->answer);
  220. /* should output be 3D ?
  221. * note that z-scale and ztozero have no effect with input 2D */
  222. if (trans_params[IDX_ZSHIFT] != 0. || columns_name[IDX_ZSHIFT])
  223. out3d = WITH_Z;
  224. /* open output vector */
  225. if (Vect_open_new(&New, vnew->answer, out3d) < 0)
  226. G_fatal_error(_("Unable to create vector map <%s>"), vnew->answer);
  227. /* copy and set header */
  228. Vect_copy_head_data(&Old, &New);
  229. Vect_hist_copy(&Old, &New);
  230. Vect_hist_command(&New);
  231. sprintf(date, "%s", G_date());
  232. sscanf(date, "%*s%s%d%*s%d", mon, &day, &yr);
  233. sprintf(date, "%s %d %d", mon, day, yr);
  234. Vect_set_date(&New, date);
  235. Vect_set_person(&New, G_whoami());
  236. sprintf(buf, "transformed from %s", vold->answer);
  237. Vect_set_map_name(&New, buf);
  238. Vect_set_scale(&New, 1);
  239. Vect_set_zone(&New, 0);
  240. Vect_set_thresh(&New, 0.0);
  241. Vect_get_map_box(&Old, &box);
  242. /* z to zero */
  243. if (tozero_flag->answer)
  244. ztozero = 0 - box.B;
  245. else
  246. ztozero = 0;
  247. /* do the transformation */
  248. G_important_message(_("Transforming features..."));
  249. transform_digit_file(&Old, &New, ztozero, swap_flag->answer,
  250. swap_xz_flag->answer, swap_yz_flag->answer,
  251. swap_after_flag->answer, trans_params, columns_name,
  252. field);
  253. G_important_message(_("Copying attributes..."));
  254. if (Vect_copy_tables(&Old, &New, 0))
  255. G_warning(_("Failed to copy attribute table to output map"));
  256. Vect_close(&Old);
  257. if (!no_topo->answer)
  258. Vect_build(&New);
  259. Vect_get_map_box(&New, &box);
  260. G_verbose_message(_("New vector map <%s> boundary coordinates:"),
  261. vnew->answer);
  262. G_verbose_message(_(" N: %-10.3f S: %-10.3f"), box.N, box.S);
  263. G_verbose_message(_(" E: %-10.3f W: %-10.3f"), box.E, box.W);
  264. G_verbose_message(_(" B: %6.3f T: %6.3f"), box.B, box.T);
  265. Vect_close(&New);
  266. G_done_msg(" ");
  267. exit(EXIT_SUCCESS);
  268. }