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