GRASS 8 Programmer's Manual 8.6.0dev(2026)-56a9afeb9f
Loading...
Searching...
No Matches
ascii.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/Vlib/ascii.c
3
4 \brief Vector library - GRASS ASCII vector format
5
6 Higher level functions for reading/writing/manipulating vectors.
7
8 (C) 2001-2015 by the GRASS Development Team
9
10 This program is free software under the GNU General Public License
11 (>=v2). Read the file COPYING that comes with GRASS for details.
12
13 \author Original author CERL
14 \author Updated for GRASS 7 (SF support) by Martin Landa <landa.martin
15 gmail.com>
16 */
17
18#include <stdlib.h>
19#include <stdio.h>
20#include <string.h>
21
22#include <grass/vector.h>
23#include <grass/dbmi.h>
24#include <grass/glocale.h>
25
26#define BUFFSIZE 128
27
28static int srch(const void *, const void *);
29static int get_cat(const struct line_cats *, const struct cat_list *,
30 const int *, int, int, int *);
31static void free_col_arrays(int *, char *, char **);
32
33/*!
34 \brief Read data in GRASS ASCII vector format
35
36 \param ascii pointer to the input ASCII file
37 \param[out] Map pointer to the output Map_info structure
38
39 \return number of read features
40 \return -1 on error
41 */
43{
44 char ctype;
45 char buff[BUFFSIZE];
46 char east_str[256], north_str[256];
47 double *xarray;
48 double *yarray;
49 double *zarray;
50 double *x, *y, *z;
51 int i, n_points, n_coors, n_cats, n_lines;
52 int type, with_z, skip_feat, nskipped_3d;
53 int alloc_points;
54 struct line_pnts *Points;
55 struct line_cats *Cats;
56 int catn, cat;
57
58 /* Must always use this to create an initialized line_pnts structure */
59 Points = Vect_new_line_struct();
61
62 /*alloc_points = 1000 ; */
63 alloc_points = 1;
64 xarray = (double *)G_calloc(alloc_points, sizeof(double));
65 yarray = (double *)G_calloc(alloc_points, sizeof(double));
66 zarray = (double *)G_calloc(alloc_points, sizeof(double));
67
68 n_lines = nskipped_3d = 0;
69
70 with_z = Vect_is_3d(Map);
71
72 while (G_getl2(buff, BUFFSIZE - 1, ascii) != 0) {
73 n_cats = 0;
75 if (buff[0] == '\0') {
76 G_debug(3, "a2b: skipping blank line");
77 continue;
78 }
79
80 if (sscanf(buff, "%1c%d%d", &ctype, &n_coors, &n_cats) < 2 ||
81 n_coors < 0 || n_cats < 0) {
82 if (ctype == '#') {
83 G_debug(2, "a2b: skipping commented line");
84 continue;
85 }
86 G_warning(_("Error reading ASCII file: (bad type) [%s]"), buff);
87 n_lines = -1;
88 goto cleanup_exit;
89 }
90 if (ctype == '#') {
91 G_debug(2, "a2b: Skipping commented line");
92 continue;
93 }
94
95 switch (ctype) {
96 case 'A':
97 type = GV_BOUNDARY;
98 break;
99 case 'B':
100 type = GV_BOUNDARY;
101 break;
102 case 'C':
103 type = GV_CENTROID;
104 break;
105 case 'L':
106 type = GV_LINE;
107 break;
108 case 'P':
109 type = GV_POINT;
110 break;
111 case 'F':
112 type = GV_FACE;
113 break;
114 case 'K':
115 type = GV_KERNEL;
116 break;
117 case 'a':
118 case 'b':
119 case 'c':
120 case 'l':
121 case 'p':
122 type = 0; /* dead -> ignore */
123 break;
124 default: {
125 G_warning(_("Error reading ASCII file: (unknown type) [%s]"), buff);
126 n_lines = -1;
127 goto cleanup_exit;
128 }
129 }
130 G_debug(5, "feature type = %d", type);
131
132 if ((type & (GV_FACE | GV_KERNEL)) && !with_z) {
133 skip_feat = TRUE;
134 nskipped_3d++;
135 }
136
137 n_points = 0;
138 x = xarray;
139 y = yarray;
140 z = zarray;
141
142 /* Collect the points */
143 for (i = 0; i < n_coors; i++) {
144 if (G_getl2(buff, BUFFSIZE - 1, ascii) == 0) {
145 G_warning(
146 _("End of ASCII file reached before end of coordinates"));
147 return -1;
148 }
149 if (buff[0] == '\0') {
150 G_debug(3, "a2b: skipping blank line while reading vertices");
151 i--;
152 continue;
153 }
154
155 *z = 0;
156 if (sscanf(buff, "%lf%lf%lf", x, y, z) < 2) {
157 if (sscanf(buff, " %s %s %lf", east_str, north_str, z) < 2) {
158 G_warning(_("Error reading ASCII file: (bad point) [%s]"),
159 buff);
160 n_lines = -1;
161 goto cleanup_exit;
162 }
163 else {
165 G_warning(_("Unparsable longitude value: [%s]"),
166 east_str);
167 n_lines = -1;
168 goto cleanup_exit;
169 }
171 G_warning(_("Unparsable latitude value: [%s]"),
172 north_str);
173 n_lines = -1;
174 goto cleanup_exit;
175 }
176 }
177 }
178
179 G_debug(5, "coor in: %s -> x = %f y = %f z = %f", G_chop(buff), *x,
180 *y, *z);
181
182 n_points++;
183 x++;
184 y++;
185 z++;
186
187 if (n_points >= alloc_points) {
188 alloc_points = n_points + 1000;
189 xarray = (double *)G_realloc((void *)xarray,
190 alloc_points * sizeof(double));
191 yarray = (double *)G_realloc((void *)yarray,
192 alloc_points * sizeof(double));
193 zarray = (double *)G_realloc((void *)zarray,
194 alloc_points * sizeof(double));
195 x = xarray + n_points;
196 y = yarray + n_points;
197 z = zarray + n_points;
198 }
199 }
200
201 /* Collect the cats */
203 for (i = 0; i < n_cats; i++) {
204 if (G_getl2(buff, BUFFSIZE - 1, ascii) == 0) {
205 G_warning(
206 _("End of ASCII file reached before end of categories"));
207 return -1;
208 }
209 if (buff[0] == '\0') {
210 G_debug(3,
211 "a2b: skipping blank line while reading category info");
212 i--;
213 continue;
214 }
215
216 if (sscanf(buff, "%d%d", &catn, &cat) != 2) {
217 G_warning(_("Error reading categories: [%s]"), buff);
218 n_lines = -1;
219 goto cleanup_exit;
220 }
221
223 }
224
225 if (skip_feat)
226 continue;
227
228 /* Allocation is handled for line_pnts */
229 if (0 >
230 Vect_copy_xyz_to_pnts(Points, xarray, yarray, zarray, n_points)) {
231 G_warning(_("Unable to copy points"));
232 n_lines = -1;
233 goto cleanup_exit;
234 }
235
236 if (type > 0) {
237 if (-1 == Vect_write_line(Map, type, Points, Cats)) {
238 n_lines = -1;
239 goto cleanup_exit;
240 }
241 n_lines++;
242 }
243 }
244
245 if (nskipped_3d > 0)
246 G_warning(_("Vector map <%s> is 2D. %d 3D features (faces or kernels) "
247 "skipped."),
252 G_free(xarray);
253 G_free(yarray);
254 G_free(zarray);
255
256 return n_lines;
257}
258
259/*!
260 \brief Read header of GRASS ASCII vector format
261
262 \param dascii pointer to the ASCII file
263 \param Map pointer to Map_info structure
264
265 \return 0 on success
266 \return -1 on error
267 */
269{
270 char buff[1024];
271 char *ptr;
272
273 for (;;) {
274 if (0 == G_getl2(buff, sizeof(buff) - 1, dascii))
275 return (0);
276
277 /* Last line of header */
278 if (strncmp(buff, "VERTI:", 6) == 0)
279 return (0);
280
281 if (!(ptr = strchr(buff, ':'))) {
282 G_warning(_("Unexpected data in vector header:\n[%s]"), buff);
283 return -1;
284 }
285
286 ptr++; /* Search for the start of text */
287 while (*ptr == ' ')
288 ptr++;
289
290 if (strncmp(buff, "ORGANIZATION:", 13) == 0)
292 else if (strncmp(buff, "DIGIT DATE:", 11) == 0)
293 Vect_set_date(Map, ptr);
294 else if (strncmp(buff, "DIGIT NAME:", 11) == 0)
295 Vect_set_person(Map, ptr);
296 else if (strncmp(buff, "MAP NAME:", 9) == 0)
298 else if (strncmp(buff, "MAP DATE:", 9) == 0)
300 else if (strncmp(buff, "MAP SCALE:", 10) == 0)
301 Vect_set_scale(Map, atoi(ptr));
302 else if (strncmp(buff, "OTHER INFO:", 11) == 0)
303 Vect_set_comment(Map, ptr);
304 else if (strncmp(buff, "ZONE:", 5) == 0 ||
305 strncmp(buff, "UTM ZONE:", 9) == 0)
306 Vect_set_zone(Map, atoi(ptr));
307 else if (strncmp(buff, "WEST EDGE:", 10) == 0) {
308 }
309 else if (strncmp(buff, "EAST EDGE:", 10) == 0) {
310 }
311 else if (strncmp(buff, "SOUTH EDGE:", 11) == 0) {
312 }
313 else if (strncmp(buff, "NORTH EDGE:", 11) == 0) {
314 }
315 else if (strncmp(buff, "MAP THRESH:", 11) == 0)
316 Vect_set_thresh(Map, atof(ptr));
317 else {
318 G_warning(_("Unknown keyword <%s> in vector head"), buff);
319 }
320 }
321 /* NOTREACHED */
322}
323
324/*!
325 \brief Write data to GRASS ASCII vector format
326
327 Prints message if some features without category are skipped.
328
329 \param[out] ascii pointer to the output ASCII file
330 \param[out] att att file (< version 5 only)
331 \param Map pointer to Map_info structure
332 \param ver version number 4 or 5
333 \param format format GV_ASCII_FORMAT_POINT or GV_ASCII_FORMAT_STD
334 \param dp number of significant digits
335 \param fs field separator
336 \param region_flag check region
337 \param type feature type filter
338 \param field field number
339 \param Clist list of categories to filter features or NULL
340 \param where SQL select where statement to filter features or NULL
341 \param column_names array of columns to be included to the output or NULL
342 "*" as the first item in the array indicates all columns
343 \param header TRUE to print also header
344
345 \return number of written features
346 \return -1 on error
347 */
348int Vect_write_ascii(FILE *ascii, FILE *att, struct Map_info *Map, int ver,
349 int format, int dp, char *fs, int region_flag, int type,
350 int field, const struct cat_list *Clist, const char *where,
351 const char **column_names, int header)
352{
353 int ltype, ctype, i, cat, line, left, right, found;
354 double *xptr, *yptr, *zptr, x, y;
355 static struct line_pnts *Points;
356 struct line_cats *Cats, *ACats;
357 char *xstring, *ystring, *zstring;
358 size_t xsize, ysize, zsize;
359 struct Cell_head window;
360 struct ilist *fcats;
361 int count, n_skipped;
362
363 /* where || columns */
364 struct field_info *Fi;
366 dbValue value;
367 dbHandle handle;
368 int *cats, ncats, more;
369 dbTable *Table;
372 dbValue *Value;
373 char *buf;
374 size_t bufsize;
376
377 /* columns */
378 char **columns;
379 int *coltypes;
380 char *all_columns;
381
382 Fi = NULL;
383 driver = NULL;
384 columns = NULL;
385 coltypes = NULL;
387
388 G_zero(&value, sizeof(dbValue));
390
391 xstring = NULL;
392 ystring = NULL;
393 zstring = NULL;
394 xsize = 0;
395 ysize = 0;
396 zsize = 0;
397 buf = NULL;
398 bufsize = 0;
399
400 /* get the region */
401 G_get_window(&window);
402
403 count = ncats = 0;
405 cats = NULL;
406
407 if (field > 0 && (where || column_names)) {
408 Fi = Vect_get_field(Map, field);
409 if (!Fi) {
410 G_fatal_error(_("Database connection not defined for layer %d"),
411 field);
412 }
413
414 driver = db_start_driver(Fi->driver);
415 if (!driver)
416 G_fatal_error(_("Unable to start driver <%s>"), Fi->driver);
417
418 db_init_handle(&handle);
419 db_set_handle(&handle, Fi->database, NULL);
420
421 if (db_open_database(driver, &handle) != DB_OK)
422 G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
423 Fi->database, Fi->driver);
424
425 /* select cats (sorted array) */
426 ncats = db_select_int(driver, Fi->table, Fi->key, where, &cats);
427 G_debug(3, "%d categories selected from table <%s>", ncats, Fi->table);
428
429 if (!column_names) {
432 }
433 else {
434 int icol, ncols;
435 const char *col_name;
436 int len_all = 0;
437
438 db_set_string(&dbstring, Fi->table);
440 G_warning(_("Unable to describe table <%s>"), Fi->table);
443 return -1;
444 }
445
447 columns = (char **)G_malloc((ncols + 1) * sizeof(char *));
448
449 if (column_names[0] && strcmp(column_names[0], "*") == 0) {
450
451 /* all columns */
452 icol = 0;
453 for (i = 0; i < ncols; i++) {
454 col_name =
456 /* key column skipped */
457 if (strcmp(Fi->key, col_name) != 0)
459 }
460 columns[icol] = NULL;
461 }
462 else {
463 int j;
464
465 icol = 0;
466 i = 0;
467 while (column_names[i]) {
468 /* key column skipped */
469 if (strcmp(Fi->key, column_names[i]) != 0) {
470 found = 0;
471 for (j = 0; j < ncols; j++) {
474 if (strcmp(col_name, column_names[i]) == 0) {
476 found = 1;
477 break;
478 }
479 }
480 if (!found) {
481 G_warning(_("Column <%s> does not exist"),
482 column_names[i]);
483 G_important_message(_("Available columns:"));
484 for (j = 0; j < ncols; j++) {
488 }
489 G_warning(_("Export cancelled"));
493 free_col_arrays(NULL, NULL, columns);
494 return -1;
495 }
496 }
497 i++;
498 }
499 columns[icol] = NULL;
500 }
501
504 Table = NULL;
505
506 if (columns[0]) {
507 /* selected columns only */
508 i = 0;
509 while (columns[i])
510 len_all += strlen(columns[i++]);
511
512 coltypes = G_malloc(i * sizeof(int));
513
514 all_columns = G_malloc(len_all + i + 2);
515
516 i = 0;
518 while (columns[i]) {
519 /* get column types */
520 coltypes[i] =
521 db_column_Ctype(driver, Fi->table, columns[i]);
522 if (coltypes[i] < 0) {
525 G_warning(
526 _("Unknown type of column <%s>, export cancelled"),
527 columns[i]);
529 G_free(cats);
530 free_col_arrays(coltypes, all_columns, columns);
531 return -1;
532 }
533 if (i > 0) {
534 strcat(all_columns, ",");
536 }
537 i++;
538 }
539 }
540 else {
541 /* no column or only key column selected */
542 free_col_arrays(NULL, NULL, columns);
543 columns = NULL;
544
547 }
548 }
549 }
550
551 if (format == GV_ASCII_FORMAT_POINT && header) {
552
553 /* print header */
554 if (Map->head.with_z)
555 fprintf(ascii, "east%snorth%sheight%scat", fs, fs, fs);
556 else
557 fprintf(ascii, "east%snorth%scat", fs, fs);
558 if (columns) {
559 for (i = 0; columns[i]; i++) {
560 if (db_select_value(driver, Fi->table, Fi->key, 0, columns[i],
561 &value) < 0)
562 G_fatal_error(_("Unable to select record from table <%s> "
563 "(key %s, column %s)"),
564 Fi->table, Fi->key, columns[i]);
565 if (columns[i])
566 fprintf(ascii, "%s%s", fs, columns[i]);
567 else
568 fprintf(ascii, "%s", columns[i]); /* can not happen */
569 }
570 }
571 fprintf(ascii, "%s", HOST_NEWLINE);
572 }
573
574 Points = Vect_new_line_struct();
578
579 /* by default, read_next_line will NOT read Dead lines */
580 /* but we can override that (in Level I only) by specifying */
581 /* the type -1, which means match all line types */
582
584
585 count = n_skipped = line = 0;
586 while (TRUE) {
587 ltype = Vect_read_next_line(Map, Points, Cats);
588 if (ltype == -1) { /* failure */
589 if (columns) {
592
593 free_col_arrays(
595 column_names && strcmp(column_names[0], "*") == 0 ? columns
596 : NULL);
597 }
601 G_free(cats);
602
603 return -1;
604 }
605
606 if (ltype == -2) { /* EOF */
607 if (columns) {
610
611 free_col_arrays(
613 column_names && strcmp(column_names[0], "*") == 0 ? columns
614 : NULL);
615 }
616 break;
617 }
618
619 line++;
620
621 if (!(ltype & type))
622 continue;
623
624 if (format == GV_ASCII_FORMAT_POINT && !(ltype & GV_POINTS))
625 continue;
626
627 found = get_cat(Cats, Clist, cats, ncats, field, &cat);
628
629 if (!found && field > 0 && ltype == GV_BOUNDARY && type & GV_AREA &&
630 Vect_level(Map) > 1) {
631 Vect_get_line_areas(Map, line, &left, &right);
632 if (left < 0)
633 left = Vect_get_isle_area(Map, abs(left));
634 if (left > 0) {
636 found = get_cat(ACats, Clist, cats, ncats, field, &cat);
637 }
638 if (right < 0)
639 right = Vect_get_isle_area(Map, abs(right));
640 if (!found && right > 0) {
642 found = get_cat(ACats, Clist, cats, ncats, field, &cat);
643 }
644 }
645
646 if (!found) {
647 if (Cats->n_cats < 1)
648 n_skipped++;
649
650 continue;
651 }
652
653 if (ver < 5) {
654 Vect_cat_get(Cats, 1, &cat);
655 }
656
657 switch (ltype) {
658 case GV_BOUNDARY:
659 if (ver == 5)
660 ctype = 'B';
661 else
662 ctype = 'A';
663 break;
664 case GV_CENTROID:
665 if (ver < 5) {
666 if (att != NULL) {
667 if (cat > 0) {
668 G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]);
670 G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]);
672 fprintf(att, "A %s %s %d%s", xstring, ystring, cat,
674 }
675 }
676 continue;
677 }
678 ctype = 'C';
679 break;
680 case GV_LINE:
681 ctype = 'L';
682 break;
683 case GV_POINT:
684 ctype = 'P';
685 break;
686 case GV_FACE:
687 ctype = 'F';
688 break;
689 case GV_KERNEL:
690 ctype = 'K';
691 break;
692 default:
693 ctype = 'X';
694 G_warning(_("Unknown feature type %d"), (int)ltype);
695 break;
696 }
697
698 if (format == GV_ASCII_FORMAT_POINT) {
699 if (region_flag) {
700 if ((window.east < Points->x[0]) ||
701 (window.west > Points->x[0]))
702 continue;
703 }
704 G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]);
706
707 if (region_flag) {
708 if ((window.north < Points->y[0]) ||
709 (window.south > Points->y[0]))
710 continue;
711 }
712 G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]);
714
716
717 if (Map->head.with_z && ver == 5) {
718 if (region_flag) {
719 if ((window.top < Points->z[0]) ||
720 (window.bottom > Points->z[0]))
721 continue;
722 }
723 G_rasprintf(&zstring, &zsize, "%.*f", dp, Points->z[0]);
725 fprintf(ascii, "%s%s%s%s%s", xstring, fs, ystring, fs, zstring);
726 }
727 else {
728 fprintf(ascii, "%s%s%s", xstring, fs, ystring);
729 }
730
731 if (fcats->n_values > 0 && cat > -1) {
732 if (fcats->n_values > 1) {
733 G_warning(
734 _("Feature has more categories. Only one category (%d) "
735 "is exported."),
736 cat);
737 }
738 fprintf(ascii, "%s%d", fs, cat);
739
740 /* print attributes */
741 if (columns) {
742
743 G_rasprintf(&buf, &bufsize,
744 "SELECT %s FROM %s WHERE %s = %d", all_columns,
745 Fi->table, Fi->key, cat);
746 G_debug(2, "SQL: %s", buf);
747 db_set_string(&dbstring, buf);
748
750 DB_SEQUENTIAL) != DB_OK) {
754 _("Cannot select attributes for cat = %d"), cat);
755 }
756 if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
759 G_fatal_error(_("Unable to fetch data from table"));
760 }
761
763
764 for (i = 0; columns[i]; i++) {
767
769 fprintf(ascii, "%s", fs);
770 }
771 else {
772 switch (coltypes[i]) {
773 case DB_C_TYPE_INT: {
774 fprintf(ascii, "%s%d", fs,
776 break;
777 }
778 case DB_C_TYPE_DOUBLE: {
779 fprintf(ascii, "%s%.*f", fs, dp,
781 break;
782 }
783 case DB_C_TYPE_STRING: {
784 fprintf(ascii, "%s%s", fs,
786 break;
787 }
788 case DB_C_TYPE_DATETIME: {
789 break;
790 }
791 case -1:
793 _("Column <%s> not found in table <%s>"),
794 columns[i], Fi->table);
795 default:
797 _("Column <%s>: unsupported data type"),
798 columns[i]);
799 }
800 }
801 }
803 }
804 }
805
806 fprintf(ascii, "%s", HOST_NEWLINE);
807 }
808 else if (format == GV_ASCII_FORMAT_STD) {
809 /* FORMAT_STANDARD */
810 if (ver == 5 && Cats->n_cats > 0)
811 fprintf(ascii, "%c %d %d%s", ctype, Points->n_points,
812 Cats->n_cats, HOST_NEWLINE);
813 else
814 fprintf(ascii, "%c %d%s", ctype, Points->n_points,
816
817 xptr = Points->x;
818 yptr = Points->y;
819 zptr = Points->z;
820
821 while (Points->n_points--) {
822
823 G_rasprintf(&xstring, &xsize, "%.*f", dp, *xptr++);
825 G_rasprintf(&ystring, &ysize, "%.*f", dp, *yptr++);
827
828 if (ver == 5) {
829 if (Map->head.with_z) {
830 G_rasprintf(&zstring, &zsize, "%.*f", dp, *zptr++);
832 fprintf(ascii, " %-12s %-12s %s%s", xstring, ystring,
834 }
835 else {
836 fprintf(ascii, " %-12s %s%s", xstring, ystring,
838 }
839 } /*Version 4 */
840 else {
841 fprintf(ascii, " %-12s %-12s%s", ystring, xstring,
843 }
844 }
845
846 if (ver == 5) {
847 for (i = 0; i < Cats->n_cats; i++) {
848 fprintf(ascii, " %-5d %d%s", Cats->field[i], Cats->cat[i],
850 }
851 }
852 else {
853 if (cat > -1) {
854 if (ltype == GV_POINT) {
855 G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]);
857 G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]);
859 fprintf(att, "P %s %s %d%s", xstring, ystring, cat,
861 }
862 else {
863 x = (Points->x[1] + Points->x[0]) / 2;
864 y = (Points->y[1] + Points->y[0]) / 2;
865
866 G_rasprintf(&xstring, &xsize, "%.*f", dp, x);
868 G_rasprintf(&ystring, &ysize, "%.*f", dp, y);
870 fprintf(att, "L %s %s %d%s", xstring, ystring, cat,
872 }
873 }
874 }
875 }
876 else if (format == GV_ASCII_FORMAT_WKT) {
878 continue;
879 /* Well-Known Text */
881 count++;
882 }
883 else {
884 G_fatal_error(_("Unknown format"));
885 }
886 count++;
887 }
888
889 if (format == GV_ASCII_FORMAT_WKT) {
890 /* process areas - topology required */
891 int i, area, nareas, isle, nisles;
892
893 if (Vect_level(Map) < 2) {
894 G_warning(_("Topology not available, unable to process areas"));
895 nareas = 0;
896 }
897 else {
899 }
900 for (area = 1; area <= nareas; area++) {
901 if (!Vect_area_alive(Map, area)) /* skip dead areas */
902 continue;
903 if (Vect_get_area_cat(Map, area, field) < 0)
904 continue;
905 /* get boundary -> linearring */
906 if (Vect_get_area_points(Map, area, Points) < 0) {
907 G_warning(_("Unable to get boundary of area id %d"), area);
908 continue;
909 }
910 fprintf(ascii, "POLYGON(");
911 /* write outer ring */
913 ascii); /* boundary is always 2D */
914 /* get isles (holes) -> inner rings */
916 for (i = 0; i < nisles; i++) {
917 /* get isle boundary -> linearring */
918 isle = Vect_get_area_isle(Map, area, i);
919 if (Vect_get_isle_points(Map, isle, Points) < 0) {
920 G_warning(
921 _("Unable to get boundary of isle id %d (area id %d)"),
922 isle, area);
923 continue;
924 }
925 fprintf(ascii, ", ");
926 /* write inner ring */
928 ascii); /* boundary is always 2D */
929 }
930 fprintf(ascii, ")%s", HOST_NEWLINE);
931
932 count++;
933 }
934 }
935
936 if (n_skipped > 0)
938 _("%d features without category skipped. To export also "
939 "features without category use '%s=-1'."),
940 n_skipped, "layer");
941
947 G_free(cats);
948
949 return count;
950}
951
952int srch(const void *pa, const void *pb)
953{
954 int *p1 = (int *)pa;
955 int *p2 = (int *)pb;
956
957 if (*p1 < *p2)
958 return -1;
959 if (*p1 > *p2)
960 return 1;
961 return 0;
962}
963
964/*!
965 \brief Write data to GRASS ASCII vector format
966
967 \param[out] dascii pointer to the output ASCII file
968 \param Map pointer to Map_info structure
969 */
971{
972 fprintf(dascii, "ORGANIZATION: %s%s", Vect_get_organization(Map),
974 fprintf(dascii, "DIGIT DATE: %s%s", Vect_get_date(Map), HOST_NEWLINE);
975 fprintf(dascii, "DIGIT NAME: %s%s", Vect_get_person(Map), HOST_NEWLINE);
976 fprintf(dascii, "MAP NAME: %s%s", Vect_get_map_name(Map), HOST_NEWLINE);
977 fprintf(dascii, "MAP DATE: %s%s", Vect_get_map_date(Map), HOST_NEWLINE);
978 fprintf(dascii, "MAP SCALE: %d%s", Vect_get_scale(Map), HOST_NEWLINE);
979 fprintf(dascii, "OTHER INFO: %s%s", Vect_get_comment(Map), HOST_NEWLINE);
980 fprintf(dascii, "ZONE: %d%s", Vect_get_zone(Map), HOST_NEWLINE);
981 fprintf(dascii, "MAP THRESH: %f%s", Vect_get_thresh(Map), HOST_NEWLINE);
982}
983
984/* check category */
985int get_cat(const struct line_cats *Cats, const struct cat_list *Clist,
986 const int *cats, int ncats, int field, int *cat)
987{
988 int i;
989
990 *cat = -1;
991
992 if (field < 1)
993 return TRUE;
994
995 if (Clist && Clist->field == field) {
996 for (i = 0; i < Cats->n_cats; i++) {
997 if (Cats->field[i] == field &&
998 Vect_cat_in_cat_list(Cats->cat[i], Clist)) {
999 *cat = Cats->cat[i];
1000 return TRUE;
1001 }
1002 }
1003 return FALSE;
1004 }
1005 if (cats) {
1006 int *found;
1007
1008 for (i = 0; i < Cats->n_cats; i++) {
1009 if (Cats->field[i] == field) {
1010 found = (int *)bsearch((void *)&(Cats->cat[i]), cats, ncats,
1011 sizeof(int), srch);
1012 if (found) {
1013 /* found */
1014 *cat = *found;
1015 return TRUE;
1016 }
1017 }
1018 }
1019 return FALSE;
1020 }
1021 if (!Clist && !cats && field > 0) {
1022 Vect_cat_get(Cats, field, cat);
1023 if (*cat > -1)
1024 return TRUE;
1025 }
1026
1027 return FALSE;
1028}
1029
1030/* free column arrays, see Vect_write_ascii() */
1031void free_col_arrays(int *coltypes, char *all_columns, char **columns)
1032{
1035 if (columns) {
1036 int i = 0;
1037
1038 while (columns[i])
1039 G_free(columns[i++]);
1040 G_free(columns);
1041 }
1042}
int Vect_write_ascii(FILE *ascii, FILE *att, struct Map_info *Map, int ver, int format, int dp, char *fs, int region_flag, int type, int field, const struct cat_list *Clist, const char *where, const char **column_names, int header)
Write data to GRASS ASCII vector format.
Definition ascii.c:348
#define BUFFSIZE
Definition ascii.c:26
int Vect_read_ascii_head(FILE *dascii, struct Map_info *Map)
Read header of GRASS ASCII vector format.
Definition ascii.c:268
void Vect_write_ascii_head(FILE *dascii, struct Map_info *Map)
Write data to GRASS ASCII vector format.
Definition ascii.c:970
int Vect_read_ascii(FILE *ascii, struct Map_info *Map)
Read data in GRASS ASCII vector format.
Definition ascii.c:42
int columns
Definition calc.c:11
#define NULL
Definition ccmath.h:32
Main header of GRASS DataBase Management Interface.
#define DB_C_TYPE_INT
Definition dbmi.h:108
#define DB_SEQUENTIAL
Definition dbmi.h:123
#define DB_C_TYPE_STRING
Definition dbmi.h:107
#define DB_C_TYPE_DOUBLE
Definition dbmi.h:109
#define DB_OK
Definition dbmi.h:71
#define DB_C_TYPE_DATETIME
Definition dbmi.h:110
#define DB_NEXT
Definition dbmi.h:114
int db_column_Ctype(dbDriver *, const char *, const char *)
Get column ctype.
int db_test_value_isnull(dbValue *)
Check of value is null.
Definition value.c:26
int db_describe_table(dbDriver *, dbString *, dbTable **)
Describe table.
int db_select_value(dbDriver *, const char *, const char *, int, const char *, dbValue *)
Select one (first) value from table/column for key/id.
dbColumn * db_get_table_column(dbTable *, int)
Returns column structure for given table and column number.
double db_get_value_double(dbValue *)
Get double precision value.
Definition value.c:50
int db_shutdown_driver(dbDriver *)
Closedown the driver, and free the driver structure.
Definition shutdown.c:36
dbValue * db_get_column_value(dbColumn *)
Returns column value for given column structure.
void db_free_table(dbTable *)
Free the table.
int db_open_database(dbDriver *, dbHandle *)
Open database connection.
Definition c_opendb.c:27
void db_zero_string(dbString *)
Zero string.
Definition string.c:79
int db_close_database_shutdown_driver(dbDriver *)
Close driver/database connection.
Definition db.c:61
dbTable * db_get_cursor_table(dbCursor *)
Get table allocated by cursor.
Definition cursor.c:67
int db_select_int(dbDriver *, const char *, const char *, const char *, int **)
Select array of ordered integers from table/column.
int db_set_string(dbString *, const char *)
Inserts string to dbString (enlarge string)
Definition string.c:41
const char * db_get_column_name(dbColumn *)
Returns column name for given column.
int db_set_handle(dbHandle *, const char *, const char *)
Set handle (database and schema name)
Definition handle.c:39
int db_close_database(dbDriver *)
Close database connection.
Definition c_closedb.c:26
int db_get_value_int(dbValue *)
Get integer value.
Definition value.c:38
dbDriver * db_start_driver(const char *)
Initialize a new dbDriver for db transaction.
Definition start.c:51
void db_init_handle(dbHandle *)
Initialize handle (i.e database/schema)
Definition handle.c:23
void db_init_string(dbString *)
Initialize dbString.
Definition string.c:25
int db_close_cursor(dbCursor *)
Close cursor.
Definition c_close_cur.c:27
int db_open_select_cursor(dbDriver *, dbString *, dbCursor *, int)
Open select cursor.
const char * db_get_value_string(dbValue *)
Get string value.
Definition value.c:92
int db_fetch(dbCursor *, int, int *)
Fetch data from open cursor.
Definition c_fetch.c:28
int db_get_table_number_of_columns(dbTable *)
Return the number of columns of the table.
int int G_rasprintf(char **, size_t *, const char *,...) __attribute__((format(printf
int G_getl2(char *, int, FILE *)
Gets a line of text from a file of any pedigree.
Definition getl.c:60
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition gis/zero.c:23
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:147
#define G_realloc(p, n)
Definition defs/gis.h:141
#define G_calloc(m, n)
Definition defs/gis.h:140
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
int G_scan_easting(const char *, double *, int)
ASCII easting to double.
Definition wind_scan.c:69
#define G_malloc(n)
Definition defs/gis.h:139
void G_trim_decimal(char *)
Removes trailing zeros from decimal number.
Definition trim_dec.c:24
void void void G_important_message(const char *,...) __attribute__((format(printf
char * G_chop(char *)
Chop leading and trailing white spaces.
Definition strings.c:332
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:87
int G_debug(int, const char *,...) __attribute__((format(printf
int G_scan_northing(const char *, double *, int)
ASCII northing to double.
Definition wind_scan.c:38
void G_get_window(struct Cell_head *)
Get the current region.
Definition get_window.c:47
int G_projection(void)
Query cartographic projection.
Definition proj1.c:32
void Vect_destroy_line_struct(struct line_pnts *)
Frees all memory associated with a line_pnts structure, including the structure itself.
Definition line.c:77
int Vect_set_map_name(struct Map_info *, const char *)
Set map name in map header.
plus_t Vect_get_num_areas(struct Map_info *)
Get number of areas in vector map.
Definition level_two.c:87
int Vect_cat_in_cat_list(int, const struct cat_list *)
Check if category number is in list.
int Vect_set_zone(struct Map_info *, int)
Set projection zone in map header.
int Vect_reset_cats(struct line_cats *)
Reset category structure to make sure cats structure is clean to be re-used.
int Vect_area_alive(struct Map_info *, int)
Check if area is alive or dead (topological level required)
const char * Vect_get_comment(struct Map_info *)
Get comment or other info string from map header.
int Vect_get_scale(struct Map_info *)
Get map scale from map header.
int Vect_cat_set(struct line_cats *, int, int)
Add new field/cat to category structure if doesn't exist yet.
int Vect_cat_get(const struct line_cats *, int, int *)
Get first found category of given field.
const char * Vect_get_organization(struct Map_info *)
Get organization string from map header.
int Vect_get_area_cats(struct Map_info *, int, struct line_cats *)
Get area categories.
int Vect_set_scale(struct Map_info *, int)
Set map scale in map header.
int Vect_get_isle_points(struct Map_info *, int, struct line_pnts *)
Returns polygon array of points for given isle.
const char * Vect_get_name(struct Map_info *)
Get name of vector map.
int Vect_get_area_points(struct Map_info *, int, struct line_pnts *)
Returns polygon array of points (outer ring) of given area.
const char * Vect_get_date(struct Map_info *)
Get date of digitization from map header.
void Vect_destroy_list(struct ilist *)
Frees all memory associated with a struct ilist, including the struct itself.
int Vect_level(struct Map_info *)
Returns level that Map is opened at.
Definition level.c:29
void Vect_destroy_cats_struct(struct line_cats *)
Frees all memory associated with line_cats structure, including the struct itself.
struct field_info * Vect_get_field(struct Map_info *, int)
Get information about link to database (by layer number)
Definition field.c:510
int Vect_set_map_date(struct Map_info *, const char *)
Set date when the source map was originally produced in map header.
int Vect_copy_xyz_to_pnts(struct line_pnts *, const double *, const double *, const double *, int)
Copy points from array to line_pnts structure.
Definition line.c:99
int Vect_set_comment(struct Map_info *, const char *)
Set comment or other info string in map header.
int Vect_get_zone(struct Map_info *)
Get projection zone from map header.
int Vect_get_area_isle(struct Map_info *, int, int)
Returns isle id for area.
int Vect_get_area_num_isles(struct Map_info *, int)
Returns number of isles for given area.
const char * Vect_get_person(struct Map_info *)
Get user name string who digitized the map from map header.
double Vect_get_thresh(struct Map_info *)
Get threshold used for digitization from map header.
const char * Vect_get_map_name(struct Map_info *)
Get map name from map header.
int Vect_set_organization(struct Map_info *, const char *)
Set organization string in map header.
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
struct ilist * Vect_new_list(void)
Creates and initializes a struct ilist.
int Vect_get_area_cat(struct Map_info *, int, int)
Find FIRST category of given field and area.
off_t Vect_write_line(struct Map_info *, int, const struct line_pnts *, const struct line_cats *)
Writes a new feature.
void Vect_destroy_field_info(struct field_info *)
Free a struct field_info and all memory associated with it.
Definition field.c:628
int Vect_set_date(struct Map_info *, const char *)
Set date of digitization in map header.
int Vect_rewind(struct Map_info *)
Rewind vector map to cause reads to start at beginning.
int Vect_read_next_line(struct Map_info *, struct line_pnts *, struct line_cats *)
Read next vector feature.
int Vect_sfa_line_astext(const struct line_pnts *, int, int, int, FILE *)
Export geometry to Well-Known Text.
int Vect_get_line_areas(struct Map_info *, int, int *, int *)
Get area id on the left and right side of the boundary.
Definition level_two.c:347
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:45
int Vect_field_cat_get(const struct line_cats *, int, struct ilist *)
Get list of categories of given field.
int Vect_set_person(struct Map_info *, const char *)
Set name of user who digitized the map in map header.
int Vect_set_thresh(struct Map_info *, double)
Set threshold used for digitization in map header.
int Vect_is_3d(struct Map_info *)
Check if vector map is 3D.
const char * Vect_get_map_date(struct Map_info *)
Get date when the source map was originally produced from map header.
int Vect_get_isle_area(struct Map_info *, int)
Returns area id for isle.
#define GV_ASCII_FORMAT_WKT
GRASS ASCII vector format - well-known-text format.
#define GV_CENTROID
#define GV_LINE
#define GV_POINT
Feature types used in memory on run time (may change)
#define GV_ASCII_FORMAT_STD
GRASS ASCII vector format - standard format.
#define GV_BOUNDARY
#define GV_FACE
#define GV_POINTS
#define GV_ASCII_FORMAT_POINT
GRASS ASCII vector format - point format.
#define GV_AREA
#define GV_KERNEL
#define HOST_NEWLINE
Definition gis.h:90
#define TRUE
Definition gis.h:78
#define FALSE
Definition gis.h:82
#define _(str)
Definition glocale.h:10
int count
#define strcpy
Definition parson.c:66
2D/3D raster map header (used also for region)
Definition gis.h:446
double north
Extent coordinates (north)
Definition gis.h:492
double bottom
Extent coordinates (bottom) - 3D data.
Definition gis.h:502
double east
Extent coordinates (east)
Definition gis.h:496
double top
Extent coordinates (top) - 3D data.
Definition gis.h:500
double south
Extent coordinates (south)
Definition gis.h:494
double west
Extent coordinates (west)
Definition gis.h:498
Vector map info.
Category list.
Layer (old: field) information.
char * driver
Name of DB driver ('sqlite', 'dbf', ...)
List of integers.
Definition gis.h:715
Feature category info.
int * field
Array of layers (fields)
int * cat
Array of categories.
int n_cats
Number of categories attached to element.
Feature geometry info - coordinates.
double * y
Array of Y coordinates.
double * x
Array of X coordinates.
int n_points
Number of points.
double * z
Array of Z coordinates.
#define x