ascii.c 16 KB

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