ascii.c 16 KB

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