ascii.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. /*!
  2. \file vector/Vlib/ascii.c
  3. \brief Vector library - GRASS ASCII vector format
  4. Higher level functions for reading/writing/manipulating vectors.
  5. (C) 2001-2009 by the GRASS Development Team
  6. This program is free software under the GNU General Public License
  7. (>=v2). Read the file COPYING that comes with GRASS for details.
  8. \author Original author CERL
  9. */
  10. #include <stdio.h>
  11. #include <grass/vector.h>
  12. #include <grass/dbmi.h>
  13. #include <grass/glocale.h>
  14. #define BUFFSIZE 128
  15. static int srch(const void *, const void *);
  16. /*!
  17. \brief Read data in GRASS ASCII vector format
  18. \param ascii pointer to the ASCII file
  19. \param Map pointer to Map_info structure
  20. \return number of read features
  21. \return -1 on error
  22. */
  23. int Vect_read_ascii(FILE *ascii, struct Map_info *Map)
  24. {
  25. char ctype;
  26. char buff[BUFFSIZE];
  27. double *xarray;
  28. double *yarray;
  29. double *zarray;
  30. double *x, *y, *z;
  31. int i, n_points, n_coors, n_cats, n_lines;
  32. int type;
  33. int alloc_points;
  34. int end_of_file;
  35. struct line_pnts *Points;
  36. struct line_cats *Cats;
  37. int catn, cat;
  38. /* Must always use this to create an initialized line_pnts structure */
  39. Points = Vect_new_line_struct();
  40. Cats = Vect_new_cats_struct();
  41. end_of_file = 0;
  42. /*alloc_points = 1000 ; */
  43. alloc_points = 1;
  44. xarray = (double *)G_calloc(alloc_points, sizeof(double));
  45. yarray = (double *)G_calloc(alloc_points, sizeof(double));
  46. zarray = (double *)G_calloc(alloc_points, sizeof(double));
  47. n_lines = 0;
  48. while (G_getl2(buff, BUFFSIZE - 1, ascii) != 0) {
  49. n_cats = 0;
  50. if (buff[0] == '\0') {
  51. G_debug(3, "a2b: skipping blank line");
  52. continue;
  53. }
  54. if (sscanf(buff, "%1c%d%d", &ctype, &n_coors, &n_cats) < 2 ||
  55. n_coors < 0 || n_cats < 0) {
  56. if (ctype == '#') {
  57. G_debug(2, "a2b: skipping commented line");
  58. continue;
  59. }
  60. G_fatal_error(_("Error reading ASCII file: (bad type) [%s]"),
  61. buff);
  62. }
  63. if (ctype == '#') {
  64. G_debug(2, "a2b: Skipping commented line");
  65. continue;
  66. }
  67. switch (ctype) {
  68. case 'A':
  69. type = GV_BOUNDARY;
  70. break;
  71. case 'B':
  72. type = GV_BOUNDARY;
  73. break;
  74. case 'C':
  75. type = GV_CENTROID;
  76. break;
  77. case 'L':
  78. type = GV_LINE;
  79. break;
  80. case 'P':
  81. type = GV_POINT;
  82. break;
  83. case 'F':
  84. type = GV_FACE;
  85. break;
  86. case 'K':
  87. type = GV_KERNEL;
  88. break;
  89. case 'a':
  90. case 'b':
  91. case 'c':
  92. case 'l':
  93. case 'p':
  94. type = 0; /* dead -> ignore */
  95. break;
  96. default:
  97. G_fatal_error(_("Error reading ASCII file: (unknown type) [%s]"),
  98. buff);
  99. }
  100. G_debug(5, "feature type = %d", type);
  101. n_points = 0;
  102. x = xarray;
  103. y = yarray;
  104. z = zarray;
  105. /* Collect the points */
  106. for (i = 0; i < n_coors; i++) {
  107. if (G_getl2(buff, BUFFSIZE - 1, ascii) == 0)
  108. G_fatal_error(_("End of ASCII file reached before end of coordinates"));
  109. if (buff[0] == '\0') {
  110. G_debug(3, "a2b: skipping blank line while reading vertices");
  111. i--;
  112. continue;
  113. }
  114. *z = 0;
  115. if (sscanf(buff, "%lf%lf%lf", x, y, z) < 2)
  116. G_fatal_error(_("Error reading ASCII file: (bad point) [%s]"),
  117. buff);
  118. G_debug(5, "coor in: %s -> x = %f y = %f z = %f", G_chop(buff),
  119. *x, *y, *z);
  120. n_points++;
  121. x++;
  122. y++;
  123. z++;
  124. if (n_points >= alloc_points) {
  125. alloc_points = n_points + 1000;
  126. xarray =
  127. (double *)G_realloc((void *)xarray,
  128. alloc_points * sizeof(double));
  129. yarray =
  130. (double *)G_realloc((void *)yarray,
  131. alloc_points * sizeof(double));
  132. zarray =
  133. (double *)G_realloc((void *)zarray,
  134. alloc_points * sizeof(double));
  135. x = xarray + n_points;
  136. y = yarray + n_points;
  137. z = zarray + n_points;
  138. }
  139. }
  140. /* Collect the cats */
  141. for (i = 0; i < n_cats; i++) {
  142. if (G_getl2(buff, BUFFSIZE - 1, ascii) == 0)
  143. G_fatal_error(_("End of ASCII file reached before end of categories"));
  144. if (buff[0] == '\0') {
  145. G_debug(3,
  146. "a2b: skipping blank line while reading category info");
  147. i--;
  148. continue;
  149. }
  150. if (sscanf(buff, "%u%u", &catn, &cat) != 2)
  151. G_fatal_error(_("Error reading categories: [%s]"), buff);
  152. Vect_cat_set(Cats, catn, cat);
  153. }
  154. /* Allocation is handled for line_pnts */
  155. if (0 >
  156. Vect_copy_xyz_to_pnts(Points, xarray, yarray, zarray, n_points))
  157. G_fatal_error(_("Out of memory"));
  158. if (type > 0) {
  159. Vect_write_line(Map, type, Points, Cats);
  160. n_lines++;
  161. }
  162. Vect_reset_cats(Cats);
  163. }
  164. return n_lines;
  165. }
  166. /*!
  167. \brief Read header of GRASS ASCII vector format
  168. \param dascii pointer to the ASCII file
  169. \param Map pointer to Map_info structure
  170. \return 0 on success
  171. \return -1 on error
  172. */
  173. int Vect_read_ascii_head(FILE *dascii, struct Map_info *Map)
  174. {
  175. char buff[1024];
  176. char *ptr;
  177. for (;;) {
  178. if (0 == G_getl2(buff, sizeof(buff) - 1, dascii))
  179. return (0);
  180. /* Last line of header */
  181. if (strncmp(buff, "VERTI:", 6) == 0)
  182. return (0);
  183. if (!(ptr = G_index(buff, ':')))
  184. G_fatal_error(_("Unexpected data in vector head:\n[%s]"), buff);
  185. ptr++; /* Search for the start of text */
  186. while (*ptr == ' ')
  187. ptr++;
  188. if (strncmp(buff, "ORGANIZATION:", 12) == 0)
  189. Vect_set_organization(Map, ptr);
  190. else if (strncmp(buff, "DIGIT DATE:", 11) == 0)
  191. Vect_set_date(Map, ptr);
  192. else if (strncmp(buff, "DIGIT NAME:", 11) == 0)
  193. Vect_set_person(Map, ptr);
  194. else if (strncmp(buff, "MAP NAME:", 9) == 0)
  195. Vect_set_map_name(Map, ptr);
  196. else if (strncmp(buff, "MAP DATE:", 9) == 0)
  197. Vect_set_map_date(Map, ptr);
  198. else if (strncmp(buff, "MAP SCALE:", 10) == 0)
  199. Vect_set_scale(Map, atoi(ptr));
  200. else if (strncmp(buff, "OTHER INFO:", 11) == 0)
  201. Vect_set_comment(Map, ptr);
  202. else if (strncmp(buff, "ZONE:", 5) == 0 ||
  203. strncmp(buff, "UTM ZONE:", 9) == 0)
  204. Vect_set_zone(Map, atoi(ptr));
  205. else if (strncmp(buff, "WEST EDGE:", 10) == 0) {
  206. }
  207. else if (strncmp(buff, "EAST EDGE:", 10) == 0) {
  208. }
  209. else if (strncmp(buff, "SOUTH EDGE:", 11) == 0) {
  210. }
  211. else if (strncmp(buff, "NORTH EDGE:", 11) == 0) {
  212. }
  213. else if (strncmp(buff, "MAP THRESH:", 11) == 0)
  214. Vect_set_thresh(Map, atof(ptr));
  215. else {
  216. G_warning(_("Unknown keyword <%s> in vector head"), buff);
  217. }
  218. }
  219. /* NOTREACHED */
  220. }
  221. /*!
  222. \brief Write data to GRASS ASCII vector format
  223. \param dascii pointer to the ASCII file
  224. \param Map pointer to Map_info structure
  225. \return number of written features
  226. \return -1 on error
  227. */
  228. int Vect_write_ascii(FILE *ascii,
  229. FILE *att, struct Map_info *Map, int ver,
  230. int format, int dp, char *fs, int region_flag,
  231. int field, char* where, char **columns)
  232. {
  233. int type, ctype, i, cat, proj, n_lines;
  234. double *xptr, *yptr, *zptr, x, y;
  235. static struct line_pnts *Points;
  236. struct line_cats *Cats;
  237. char *xstring = NULL, *ystring = NULL, *zstring = NULL;
  238. struct Cell_head window;
  239. struct ilist *fcats;
  240. /* where */
  241. struct field_info *Fi;
  242. dbDriver *driver;
  243. dbValue value = {0};
  244. dbHandle handle;
  245. int *cats, ncats;
  246. /* get the region */
  247. G_get_window(&window);
  248. n_lines = 0;
  249. ncats = 0;
  250. cats = NULL;
  251. if (where || columns) {
  252. Fi = Vect_get_field(Map, field);
  253. if (!Fi) {
  254. G_fatal_error(_("Database connection not defined for layer %d"),
  255. field);
  256. }
  257. driver = db_start_driver(Fi->driver);
  258. if (!driver)
  259. G_fatal_error(_("Unable to start driver <%s>"), Fi->driver);
  260. db_init_handle(&handle);
  261. db_set_handle(&handle, Fi->database, NULL);
  262. if (db_open_database(driver, &handle) != DB_OK)
  263. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  264. Fi->database, Fi->driver);
  265. /* select cats (sorted array) */
  266. ncats = db_select_int(driver, Fi->table, Fi->key, where, &cats);
  267. G_debug(3, "%d categories selected from table <%s>", ncats, Fi->table);
  268. if (!columns) {
  269. db_close_database(driver);
  270. db_shutdown_driver(driver);
  271. }
  272. }
  273. Points = Vect_new_line_struct(); /* init line_pnts struct */
  274. Cats = Vect_new_cats_struct();
  275. fcats = Vect_new_list();
  276. proj = Vect_get_proj(Map);
  277. /* by default, read_next_line will NOT read Dead lines */
  278. /* but we can override that (in Level I only) by specifying */
  279. /* the type -1, which means match all line types */
  280. Vect_rewind(Map);
  281. while (1) {
  282. if (-1 == (type = Vect_read_next_line(Map, Points, Cats))) {
  283. if (columns) {
  284. db_close_database(driver);
  285. db_shutdown_driver(driver);
  286. }
  287. return -1;
  288. }
  289. if (type == -2) { /* EOF */
  290. if (columns) {
  291. db_close_database(driver);
  292. db_shutdown_driver(driver);
  293. }
  294. return n_lines;
  295. }
  296. if (format == GV_ASCII_FORMAT_POINT && !(type & GV_POINTS))
  297. continue;
  298. if (cats) {
  299. /* check category */
  300. for (i = 0; i < Cats->n_cats; i++) {
  301. if ((int *)bsearch((void *) &(Cats->cat[i]), cats, ncats, sizeof(int),
  302. srch)) {
  303. /* found */
  304. break;
  305. }
  306. }
  307. if (i == Cats->n_cats)
  308. continue;
  309. }
  310. if (ver < 5) {
  311. Vect_cat_get(Cats, 1, &cat);
  312. }
  313. switch (type) {
  314. case GV_BOUNDARY:
  315. if (ver == 5)
  316. ctype = 'B';
  317. else
  318. ctype = 'A';
  319. break;
  320. case GV_CENTROID:
  321. if (ver < 5) {
  322. if (att != NULL) {
  323. if (cat > 0) {
  324. G_asprintf(&xstring, "%.*f", dp, Points->x[0]);
  325. G_trim_decimal(xstring);
  326. G_asprintf(&ystring, "%.*f", dp, Points->y[0]);
  327. G_trim_decimal(ystring);
  328. fprintf(att, "A %s %s %d\n", xstring, ystring, cat);
  329. }
  330. }
  331. continue;
  332. }
  333. ctype = 'C';
  334. break;
  335. case GV_LINE:
  336. ctype = 'L';
  337. break;
  338. case GV_POINT:
  339. ctype = 'P';
  340. break;
  341. case GV_FACE:
  342. ctype = 'F';
  343. break;
  344. case GV_KERNEL:
  345. ctype = 'K';
  346. break;
  347. default:
  348. ctype = 'X';
  349. G_warning(_("Uknown feature type %d"), (int)type);
  350. break;
  351. }
  352. if (format == GV_ASCII_FORMAT_POINT) {
  353. if (region_flag) {
  354. if ((window.east < Points->x[0]) ||
  355. (window.west > Points->x[0]))
  356. continue;
  357. }
  358. G_asprintf(&xstring, "%.*f", dp, Points->x[0]);
  359. G_trim_decimal(xstring);
  360. if (region_flag) {
  361. if ((window.north < Points->y[0]) ||
  362. (window.south > Points->y[0]))
  363. continue;
  364. }
  365. G_asprintf(&ystring, "%.*f", dp, Points->y[0]);
  366. G_trim_decimal(ystring);
  367. if (Map->head.with_z && ver == 5) {
  368. if (region_flag) {
  369. if ((window.top < Points->z[0]) ||
  370. (window.bottom > Points->z[0]))
  371. continue;
  372. }
  373. G_asprintf(&zstring, "%.*f", dp, Points->z[0]);
  374. G_trim_decimal(zstring);
  375. fprintf(ascii, "%s%s%s%s%s", xstring, fs, ystring, fs,
  376. zstring);
  377. }
  378. else {
  379. fprintf(ascii, "%s%s%s", xstring, fs, ystring);
  380. }
  381. Vect_field_cat_get(Cats, field, fcats);
  382. if (fcats->n_values > 0) {
  383. if (fcats->n_values > 1) {
  384. G_warning(_("Feature has more categories. Only first category (%d) "
  385. "is exported."), fcats->value[0]);
  386. }
  387. fprintf(ascii, "%s%d", fs, fcats->value[0]);
  388. /* print attributes */
  389. if (columns) {
  390. for(i = 0; columns[i]; i++) {
  391. if (db_select_value(driver, Fi->table, Fi->key, fcats->value[0],
  392. columns[i], &value) < 0)
  393. G_fatal_error(_("Unable to select record from table <%s> (key %s, column %s)"),
  394. Fi->table, Fi->key, columns[i]);
  395. if (db_test_value_isnull(&value)) {
  396. fprintf(ascii, "%s", fs);
  397. }
  398. else {
  399. switch(db_column_Ctype(driver, Fi->table, columns[i]))
  400. {
  401. case DB_C_TYPE_INT: {
  402. fprintf(ascii, "%s%d", fs, db_get_value_int(&value));
  403. break;
  404. }
  405. case DB_C_TYPE_DOUBLE: {
  406. fprintf(ascii, "%s%.*f", fs, dp, db_get_value_double(&value));
  407. break;
  408. }
  409. case DB_C_TYPE_STRING: {
  410. fprintf(ascii, "%s%s", fs, db_get_value_string(&value));
  411. break;
  412. }
  413. case DB_C_TYPE_DATETIME: {
  414. break;
  415. }
  416. case -1:
  417. G_fatal_error(_("Column <%s> not found in table <%s>"),
  418. columns[i], Fi->table);
  419. default: G_fatal_error(_("Column <%s>: unsupported data type"),
  420. columns[i]);
  421. }
  422. }
  423. }
  424. }
  425. }
  426. fprintf(ascii, "\n");
  427. }
  428. else if (format == GV_ASCII_FORMAT_STD) {
  429. /* FORMAT_STANDARD */
  430. if (ver == 5 && Cats->n_cats > 0)
  431. fprintf(ascii, "%c %d %d\n", ctype, Points->n_points,
  432. Cats->n_cats);
  433. else
  434. fprintf(ascii, "%c %d\n", ctype, Points->n_points);
  435. xptr = Points->x;
  436. yptr = Points->y;
  437. zptr = Points->z;
  438. while (Points->n_points--) {
  439. G_asprintf(&xstring, "%.*f", dp, *xptr++);
  440. G_trim_decimal(xstring);
  441. G_asprintf(&ystring, "%.*f", dp, *yptr++);
  442. G_trim_decimal(ystring);
  443. if (ver == 5) {
  444. if (Map->head.with_z) {
  445. G_asprintf(&zstring, "%.*f", dp, *zptr++);
  446. G_trim_decimal(zstring);
  447. fprintf(ascii, " %-12s %-12s %-12s\n", xstring,
  448. ystring, zstring);
  449. }
  450. else {
  451. fprintf(ascii, " %-12s %-12s\n", xstring, ystring);
  452. }
  453. } /*Version 4 */
  454. else {
  455. fprintf(ascii, " %-12s %-12s\n", ystring, xstring);
  456. }
  457. }
  458. if (ver == 5) {
  459. for (i = 0; i < Cats->n_cats; i++) {
  460. fprintf(ascii, " %-5d %-10d\n", Cats->field[i],
  461. Cats->cat[i]);
  462. }
  463. }
  464. else {
  465. if (cat > 0) {
  466. if (type == GV_POINT) {
  467. G_asprintf(&xstring, "%.*f", dp, Points->x[0]);
  468. G_trim_decimal(xstring);
  469. G_asprintf(&ystring, "%.*f", dp, Points->y[0]);
  470. G_trim_decimal(ystring);
  471. fprintf(att, "P %s %s %d\n", xstring, ystring, cat);
  472. }
  473. else {
  474. x = (Points->x[1] + Points->x[0]) / 2;
  475. y = (Points->y[1] + Points->y[0]) / 2;
  476. G_asprintf(&xstring, "%.*f", dp, x);
  477. G_trim_decimal(xstring);
  478. G_asprintf(&ystring, "%.*f", dp, y);
  479. G_trim_decimal(ystring);
  480. fprintf(att, "L %s %s %d\n", xstring, ystring, cat);
  481. }
  482. }
  483. }
  484. }
  485. else if (format == GV_ASCII_FORMAT_WKT) {
  486. /* Well-Known Text */
  487. Vect_sfa_write_line_wkt(Points, type, Vect_is_3d(Map), dp, ascii);
  488. }
  489. else {
  490. G_fatal_error(_("Unknown format"));
  491. }
  492. n_lines++;
  493. }
  494. /* not reached */
  495. return n_lines;
  496. }
  497. int srch(const void *pa, const void *pb)
  498. {
  499. int *p1 = (int *)pa;
  500. int *p2 = (int *)pb;
  501. if (*p1 < *p2)
  502. return -1;
  503. if (*p1 > *p2)
  504. return 1;
  505. return 0;
  506. }
  507. /*!
  508. \brief Write data to GRASS ASCII vector format
  509. \param dascii pointer to the ASCII file
  510. \param Map pointer to Map_info structure
  511. */
  512. void Vect_write_ascii_head(FILE *dascii, struct Map_info *Map)
  513. {
  514. fprintf(dascii, "ORGANIZATION: %s\n", Vect_get_organization(Map));
  515. fprintf(dascii, "DIGIT DATE: %s\n", Vect_get_date(Map));
  516. fprintf(dascii, "DIGIT NAME: %s\n", Vect_get_person(Map));
  517. fprintf(dascii, "MAP NAME: %s\n", Vect_get_map_name(Map));
  518. fprintf(dascii, "MAP DATE: %s\n", Vect_get_map_date(Map));
  519. fprintf(dascii, "MAP SCALE: %d\n", Vect_get_scale(Map));
  520. fprintf(dascii, "OTHER INFO: %s\n", Vect_get_comment(Map));
  521. fprintf(dascii, "ZONE: %d\n", Vect_get_zone(Map));
  522. fprintf(dascii, "MAP THRESH: %f\n", Vect_get_thresh(Map));
  523. }