main.c 9.9 KB

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