ascii.c 16 KB

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