points.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <ctype.h>
  5. #include <grass/gis.h>
  6. #include <grass/dbmi.h>
  7. #include <grass/vector.h>
  8. #include <grass/glocale.h>
  9. #include "local_proto.h"
  10. /* Determine if the string is integer, e.g. 123, +123, -123,
  11. * return 1 if integer, 0 otherwise */
  12. static int is_int(char *str)
  13. {
  14. char *tail;
  15. if (strtol(str, &tail, 10), tail == str || *tail != '\0') {
  16. /* doesn't look like a number,
  17. or has extra characters after what looks to be a number */
  18. return 0;
  19. }
  20. return 1;
  21. }
  22. /* Determine if the string is double, e.g. 123.456, +123.456, -123.456, 1.23456e2
  23. * return 1 if double, 0 otherwise */
  24. static int is_double(char *str)
  25. {
  26. char *tail;
  27. if (strtod(str, &tail), tail == str || *tail != '\0') {
  28. /* doesn't look like a number,
  29. or has extra characters after what looks to be a number */
  30. return 0;
  31. }
  32. return 1;
  33. }
  34. /* Analyse points ascii file. Determine number of columns and column types.
  35. * ascii_tmp: write copy of tempfile to ascii_tmp:
  36. * rowlength: maximum row length
  37. * ncolumns: number of columns
  38. * minncolumns: minimum number of columns
  39. * nrows: number of rows
  40. * column_type: column types
  41. * column_length: column lengths (string only)
  42. */
  43. int points_analyse(FILE * ascii_in, FILE * ascii, char *fs, char *td,
  44. int *rowlength, int *ncolumns, int *minncolumns,
  45. int *nrows, int **column_type, int **column_length,
  46. int skip_lines, int xcol, int ycol, int zcol, int catcol,
  47. int region_flag, int ignore_flag)
  48. {
  49. int i;
  50. int buflen; /* buffer length */
  51. char *buf; /* buffer */
  52. int row = 1; /* line number, first is 1 */
  53. int ncols = 0; /* number of columns */
  54. int minncols = -1;
  55. int *coltype = NULL; /* column types */
  56. int *collen = NULL; /* column lengths */
  57. char **tokens;
  58. int ntokens; /* number of tokens */
  59. int len, rowlen = 0; /* maximum row length */
  60. struct Cell_head window;
  61. double northing = .0;
  62. double easting = .0;
  63. char *xtoken, *ytoken, *sav_buf;
  64. int skip = FALSE, skipped = 0;
  65. buflen = 4000;
  66. buf = (char *)G_malloc(buflen);
  67. xtoken = (char *)G_malloc(256);
  68. ytoken = (char *)G_malloc(256);
  69. G_message(_("Scanning input for column types..."));
  70. /* fetch projection for LatLong test */
  71. G_get_window(&window);
  72. /* points_to_bin() would be faster if we would write out
  73. * clean data to ascii
  74. * points_to_bin() would then not need G_chop() and
  75. * for latlon not G_scan_[easting|northing]() */
  76. while (1) {
  77. len = 0; /* not really needed, but what the heck */
  78. skip = FALSE; /* reset out-of-region check */
  79. sav_buf = NULL;
  80. if (G_getl2(buf, buflen - 1, ascii_in) == 0)
  81. break; /* EOF */
  82. if (row <= skip_lines) {
  83. G_debug(3, "skipping header row %d : %d chars", row,
  84. (int)strlen(buf));
  85. /* this fn is read-only, write to hist with points_to_bin() */
  86. fprintf(ascii, "%s\n", buf);
  87. len = strlen(buf) + 1;
  88. if (len > rowlen)
  89. rowlen = len;
  90. row++;
  91. continue;
  92. }
  93. if ((buf[0] == '#') || (buf[0] == '\0')) {
  94. G_debug(3, "skipping comment row %d : %d chars", row,
  95. (int)strlen(buf));
  96. continue;
  97. }
  98. /* no G_chop() as first/last column may be empty fs=tab value */
  99. G_debug(3, "row %d : %d chars", row, (int)strlen(buf));
  100. tokens = G_tokenize2(buf, fs, td);
  101. ntokens = G_number_of_tokens(tokens);
  102. if (ntokens == 0) {
  103. continue;
  104. }
  105. if (ncols > 0 && ntokens != ncols) {
  106. /* these rows can not be imported into the attribute table */
  107. if (ignore_flag) {
  108. G_warning(_("Row %d: '%s' can not be imported into the attribute table"),
  109. row, buf);
  110. }
  111. else {
  112. G_warning(_("Expected %d columns, found %d columns"), ncols, ntokens);
  113. G_fatal_error(_("Broken row %d: '%s'"), row, buf);
  114. }
  115. }
  116. if (xcol >= ntokens || ycol >= ntokens || zcol >= ntokens ||
  117. catcol >= ntokens) {
  118. if (ignore_flag) {
  119. G_debug(3, "Skipping broken row %d: '%s'", row, buf);
  120. continue;
  121. }
  122. else {
  123. G_warning(_("ntokens: %d, xcol: %d, ycol: %d, zcol: %d"), xcol, ycol, zcol);
  124. G_fatal_error(_("Broken row %d: '%s'"), row, buf);
  125. }
  126. }
  127. len = strlen(buf) + 1;
  128. if (len > rowlen)
  129. rowlen = len;
  130. if (ntokens > ncols) {
  131. coltype = (int *)G_realloc(coltype, ntokens * sizeof(int));
  132. collen = (int *)G_realloc(collen, ntokens * sizeof(int));
  133. for (i = ncols; i < ntokens; i++) {
  134. coltype[i] = DB_C_TYPE_INT; /* default type */
  135. collen[i] = 0;
  136. }
  137. ncols = ntokens;
  138. }
  139. if (minncols == -1 || minncols > ntokens)
  140. minncols = ntokens;
  141. /* Determine column types */
  142. for (i = 0; i < ntokens; i++) {
  143. G_chop(tokens[i]);
  144. if ((G_projection() == PROJECTION_LL)) {
  145. if (i == xcol || i == ycol) {
  146. if (i == 0) { /* Save position of original internal token buffer */
  147. /* Prevent memory leaks */
  148. sav_buf = tokens[0];
  149. }
  150. /* check if coordinates are DMS or decimal or not latlong at all */
  151. if (i == xcol) {
  152. if (G_scan_easting(tokens[i], &easting, window.proj)) {
  153. G_debug(4, "is_latlong east: %g", easting);
  154. sprintf(xtoken, "%.15g", easting);
  155. /* replace current DMS token by decimal degree */
  156. tokens[i] = xtoken;
  157. if (region_flag) {
  158. if ((window.east < easting) ||
  159. (window.west > easting))
  160. skip = TRUE;
  161. }
  162. }
  163. else {
  164. fprintf(stderr, _("Current row %d:\n%s\n"), row, buf);
  165. G_fatal_error(_("Unparsable longitude value in column %d: %s"),
  166. i + 1, tokens[i]);
  167. }
  168. }
  169. if (i == ycol) {
  170. if (G_scan_northing(tokens[i], &northing, window.proj)) {
  171. G_debug(4, "is_latlong north: %g", northing);
  172. sprintf(ytoken, "%.15g", northing);
  173. /* replace current DMS token by decimal degree */
  174. tokens[i] = ytoken;
  175. if (region_flag) {
  176. if ((window.north < northing) ||
  177. (window.south > northing))
  178. skip = TRUE;
  179. }
  180. }
  181. else {
  182. fprintf(stderr, _("Current row %d:\n%s\n"), row, buf);
  183. G_fatal_error(_("Unparsable latitude value in column %d: %s"),
  184. i + 1, tokens[i]);
  185. }
  186. }
  187. } /* if (x or y) */
  188. } /* PROJECTION_LL */
  189. else {
  190. if (strlen(tokens[i]) == 0) {
  191. if (i == xcol) {
  192. G_fatal_error(_("Unparsable longitude value in column %d: %s"),
  193. i + 1, tokens[i]);
  194. }
  195. if (i == ycol) {
  196. G_fatal_error(_("Unparsable latitude value in column %d: %s"),
  197. i + 1, tokens[i]);
  198. }
  199. }
  200. if (region_flag) {
  201. /* consider z range if -z flag is used? */
  202. /* change to if(>= east,north){skip=1;} to allow correct tiling */
  203. /* don't "continue;" so multiple passes will have the
  204. same column types and length for patching */
  205. if (i == xcol) {
  206. easting = atof(tokens[i]);
  207. if ((window.east < easting) ||
  208. (window.west > easting))
  209. skip = TRUE;
  210. }
  211. if (i == ycol) {
  212. northing = atof(tokens[i]);
  213. if ((window.north < northing) ||
  214. (window.south > northing))
  215. skip = TRUE;
  216. }
  217. }
  218. }
  219. len = strlen(tokens[i]);
  220. /* do not guess column type for missing values */
  221. if (len == 0)
  222. continue;
  223. G_debug(4, "row %d col %d: '%s' is_int = %d is_double = %d",
  224. row + 1, i + 1, tokens[i], is_int(tokens[i]),
  225. is_double(tokens[i]));
  226. if (is_int(tokens[i])) {
  227. continue; /* integer */
  228. }
  229. if (is_double(tokens[i])) { /* double */
  230. if (coltype[i] == DB_C_TYPE_INT) {
  231. coltype[i] = DB_C_TYPE_DOUBLE;
  232. }
  233. continue;
  234. }
  235. /* string */
  236. coltype[i] = DB_C_TYPE_STRING;
  237. if (len > collen[i])
  238. collen[i] = len;
  239. }
  240. /* write dataline to tmp file */
  241. if (!skip)
  242. fprintf(ascii, "%s\n", buf);
  243. else
  244. skipped++;
  245. if (sav_buf != NULL) {
  246. /* Restore original token buffer so free_tokens works */
  247. /* Only do this if tokens[0] was re-assigned */
  248. tokens[0] = sav_buf;
  249. sav_buf = NULL;
  250. }
  251. G_free_tokens(tokens);
  252. row++;
  253. }
  254. *rowlength = rowlen;
  255. *ncolumns = ncols;
  256. *minncolumns = minncols;
  257. *column_type = coltype;
  258. *column_length = collen;
  259. *nrows = row - 1; /* including skipped lines */
  260. G_free(buf);
  261. G_free(xtoken);
  262. G_free(ytoken);
  263. if (region_flag)
  264. G_message(n_("Skipping %d of %d row falling outside of current region",
  265. "Skipping %d of %d rows falling outside of current region",
  266. row - 1),
  267. skipped, row - 1);
  268. return 0;
  269. }
  270. /* Import points from ascii file.
  271. *
  272. * fs: field separator
  273. * xcol, ycol, zcol, catcol: x,y,z,cat column in input file, first column is 1,
  274. * zcol and catcol may be 0 (do not use)
  275. * rowlen: maximum row length
  276. * Note: column types (both in header or coldef) must be supported by driver
  277. */
  278. int points_to_bin(FILE * ascii, int rowlen, struct Map_info *Map,
  279. dbDriver * driver, char *table, char *fs, char *td,
  280. int nrows, int *coltype, int xcol, int ycol, int zcol,
  281. int catcol, int skip_lines)
  282. {
  283. char *buf, buf2[4000];
  284. int cat = 0;
  285. int row = 0;
  286. struct line_pnts *Points;
  287. struct line_cats *Cats;
  288. dbString sql, val;
  289. struct Cell_head window;
  290. G_message(_("Importing points..."));
  291. /* fetch projection for LatLong test */
  292. G_get_window(&window);
  293. rewind(ascii);
  294. Points = Vect_new_line_struct();
  295. Cats = Vect_new_cats_struct();
  296. /* actually last 2 characters won't be read */
  297. buf = (char *)G_malloc(rowlen + 2);
  298. db_init_string(&sql);
  299. db_init_string(&val);
  300. if (skip_lines > 0) {
  301. sprintf(buf2, "HEADER: (%d lines)\n", skip_lines);
  302. Vect_hist_write(Map, buf2);
  303. }
  304. /* rowlen + 2 to read till the end of line on both UNIX and Windows */
  305. while (G_getl2(buf, rowlen + 2, ascii) != 0) {
  306. int i, len;
  307. double x, y, z;
  308. char **tokens;
  309. int ntokens; /* number of tokens */
  310. G_percent(row, nrows, 2);
  311. row++;
  312. if (row <= skip_lines) {
  313. G_debug(4, "writing skip line %d to hist : %d chars", row,
  314. (int)strlen(buf));
  315. Vect_hist_write(Map, buf);
  316. Vect_hist_write(Map, "\n");
  317. continue;
  318. }
  319. len = strlen(buf);
  320. if (len == 0)
  321. continue; /* should not happen */
  322. G_debug(4, "row: %s", buf);
  323. tokens = G_tokenize2(buf, fs, td);
  324. ntokens = G_number_of_tokens(tokens);
  325. G_chop(tokens[xcol]);
  326. G_chop(tokens[ycol]);
  327. if ((G_projection() == PROJECTION_LL)) {
  328. G_scan_easting(tokens[xcol], &x, window.proj);
  329. G_scan_northing(tokens[ycol], &y, window.proj);
  330. }
  331. else {
  332. x = atof(tokens[xcol]);
  333. y = atof(tokens[ycol]);
  334. }
  335. G_debug(4, "x: %f, y: %f", x, y);
  336. if (zcol >= 0) {
  337. G_chop(tokens[zcol]);
  338. z = atof(tokens[zcol]);
  339. }
  340. else
  341. z = 0.0;
  342. if (catcol >= 0) {
  343. G_chop(tokens[catcol]);
  344. cat = atof(tokens[catcol]);
  345. }
  346. else
  347. cat++;
  348. Vect_reset_line(Points);
  349. Vect_reset_cats(Cats);
  350. Vect_append_point(Points, x, y, z);
  351. Vect_cat_set(Cats, 1, cat);
  352. Vect_write_line(Map, GV_POINT, Points, Cats);
  353. /* Attributes */
  354. if (driver) {
  355. sprintf(buf2, "insert into %s values ( ", table);
  356. db_set_string(&sql, buf2);
  357. if (catcol < 0) {
  358. sprintf(buf2, "%d, ", cat);
  359. db_append_string(&sql, buf2);
  360. }
  361. for (i = 0; i < ntokens; i++) {
  362. G_chop(tokens[i]);
  363. if (i > 0)
  364. db_append_string(&sql, ", ");
  365. if (strlen(tokens[i]) > 0) {
  366. if (coltype[i] == DB_C_TYPE_INT ||
  367. coltype[i] == DB_C_TYPE_DOUBLE) {
  368. if (G_projection() == PROJECTION_LL &&
  369. (i == xcol || i == ycol)) {
  370. if (i == xcol)
  371. sprintf(buf2, "%.15g", x);
  372. else
  373. sprintf(buf2, "%.15g", y);
  374. }
  375. else
  376. sprintf(buf2, "%s", tokens[i]);
  377. }
  378. else {
  379. db_set_string(&val, tokens[i]);
  380. /* TODO: strip leading and trailing "quotes" from input string */
  381. db_double_quote_string(&val);
  382. sprintf(buf2, "'%s'", db_get_string(&val));
  383. }
  384. }
  385. else {
  386. sprintf(buf2, "null");
  387. }
  388. db_append_string(&sql, buf2);
  389. }
  390. db_append_string(&sql, ")");
  391. G_debug(3, "%s", db_get_string(&sql));
  392. if (db_execute_immediate(driver, &sql) != DB_OK) {
  393. G_fatal_error(_("Unable to insert new record: %s"),
  394. db_get_string(&sql));
  395. }
  396. }
  397. G_free_tokens(tokens);
  398. }
  399. G_percent(nrows, nrows, 2);
  400. return 0;
  401. }