GRASS 8 Programmer's Manual 8.6.0dev(2026)-ddf66e9d5c
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
220 /* Vect_cat_set() has its range check commented out, so an
221 out-of-range value read here would be stored and only cause
222 trouble later, for example on export. */
223 if (catn < 1 || cat < 0) {
224 G_warning(_("Layer number or category number out of range: "
225 "[%s]"),
226 buff);
227 n_lines = -1;
228 goto cleanup_exit;
229 }
230
232 }
233
234 if (skip_feat)
235 continue;
236
237 /* Allocation is handled for line_pnts */
238 if (0 >
239 Vect_copy_xyz_to_pnts(Points, xarray, yarray, zarray, n_points)) {
240 G_warning(_("Unable to copy points"));
241 n_lines = -1;
242 goto cleanup_exit;
243 }
244
245 if (type > 0) {
246 if (-1 == Vect_write_line(Map, type, Points, Cats)) {
247 n_lines = -1;
248 goto cleanup_exit;
249 }
250 n_lines++;
251 }
252 }
253
254 if (nskipped_3d > 0)
255 G_warning(_("Vector map <%s> is 2D. %d 3D features (faces or kernels) "
256 "skipped."),
261 G_free(xarray);
262 G_free(yarray);
263 G_free(zarray);
264
265 return n_lines;
266}
267
268/*!
269 \brief Read header of GRASS ASCII vector format
270
271 \param dascii pointer to the ASCII file
272 \param Map pointer to Map_info structure
273
274 \return 0 on success
275 \return -1 on error
276 */
278{
279 char buff[1024];
280 char *ptr;
281
282 for (;;) {
283 if (0 == G_getl2(buff, sizeof(buff) - 1, dascii))
284 return (0);
285
286 /* Last line of header */
287 if (strncmp(buff, "VERTI:", 6) == 0)
288 return (0);
289
290 if (!(ptr = strchr(buff, ':'))) {
291 G_warning(_("Unexpected data in vector header:\n[%s]"), buff);
292 return -1;
293 }
294
295 ptr++; /* Search for the start of text */
296 while (*ptr == ' ')
297 ptr++;
298
299 if (strncmp(buff, "ORGANIZATION:", 13) == 0)
301 else if (strncmp(buff, "DIGIT DATE:", 11) == 0)
302 Vect_set_date(Map, ptr);
303 else if (strncmp(buff, "DIGIT NAME:", 11) == 0)
304 Vect_set_person(Map, ptr);
305 else if (strncmp(buff, "MAP NAME:", 9) == 0)
307 else if (strncmp(buff, "MAP DATE:", 9) == 0)
309 else if (strncmp(buff, "MAP SCALE:", 10) == 0)
310 Vect_set_scale(Map, atoi(ptr));
311 else if (strncmp(buff, "OTHER INFO:", 11) == 0)
312 Vect_set_comment(Map, ptr);
313 else if (strncmp(buff, "ZONE:", 5) == 0 ||
314 strncmp(buff, "UTM ZONE:", 9) == 0)
315 Vect_set_zone(Map, atoi(ptr));
316 else if (strncmp(buff, "WEST EDGE:", 10) == 0) {
317 }
318 else if (strncmp(buff, "EAST EDGE:", 10) == 0) {
319 }
320 else if (strncmp(buff, "SOUTH EDGE:", 11) == 0) {
321 }
322 else if (strncmp(buff, "NORTH EDGE:", 11) == 0) {
323 }
324 else if (strncmp(buff, "MAP THRESH:", 11) == 0)
325 Vect_set_thresh(Map, atof(ptr));
326 else {
327 G_warning(_("Unknown keyword <%s> in vector head"), buff);
328 }
329 }
330 /* NOTREACHED */
331}
332
333/*!
334 \brief Write data to GRASS ASCII vector format
335
336 Prints message if some features without category are skipped.
337
338 \param[out] ascii pointer to the output ASCII file
339 \param[out] att att file (< version 5 only)
340 \param Map pointer to Map_info structure
341 \param ver version number 4 or 5
342 \param format format GV_ASCII_FORMAT_POINT or GV_ASCII_FORMAT_STD
343 \param dp number of significant digits
344 \param fs field separator
345 \param region_flag check region
346 \param type feature type filter
347 \param field field number
348 \param Clist list of categories to filter features or NULL
349 \param where SQL select where statement to filter features or NULL
350 \param column_names array of columns to be included to the output or NULL
351 "*" as the first item in the array indicates all columns
352 \param header TRUE to print also header
353
354 \return number of written features
355 \return -1 on error
356 */
357int Vect_write_ascii(FILE *ascii, FILE *att, struct Map_info *Map, int ver,
358 int format, int dp, char *fs, int region_flag, int type,
359 int field, const struct cat_list *Clist, const char *where,
360 const char **column_names, int header)
361{
362 int ltype, ctype, i, cat, line, left, right, found;
363 double *xptr, *yptr, *zptr, x, y;
364 static struct line_pnts *Points;
365 struct line_cats *Cats, *ACats;
366 char *xstring, *ystring, *zstring;
367 size_t xsize, ysize, zsize;
368 struct Cell_head window;
369 struct ilist *fcats;
370 int count, n_skipped;
371
372 /* where || columns */
373 struct field_info *Fi;
375 dbValue value;
376 dbHandle handle;
377 int *cats, ncats, more;
378 dbTable *Table;
381 dbValue *Value;
382 char *buf;
383 size_t bufsize;
385
386 /* columns */
387 char **columns;
388 int *coltypes;
389 char *all_columns;
390
391 Fi = NULL;
392 driver = NULL;
393 columns = NULL;
394 coltypes = NULL;
396
397 G_zero(&value, sizeof(dbValue));
399
400 xstring = NULL;
401 ystring = NULL;
402 zstring = NULL;
403 xsize = 0;
404 ysize = 0;
405 zsize = 0;
406 buf = NULL;
407 bufsize = 0;
408
409 /* get the region */
410 G_get_window(&window);
411
412 count = ncats = 0;
414 cats = NULL;
415
416 if (field > 0 && (where || column_names)) {
417 Fi = Vect_get_field(Map, field);
418 if (!Fi) {
419 G_fatal_error(_("Database connection not defined for layer %d"),
420 field);
421 }
422
423 driver = db_start_driver(Fi->driver);
424 if (!driver)
425 G_fatal_error(_("Unable to start driver <%s>"), Fi->driver);
426
427 db_init_handle(&handle);
428 db_set_handle(&handle, Fi->database, NULL);
429
430 if (db_open_database(driver, &handle) != DB_OK)
431 G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
432 Fi->database, Fi->driver);
433
434 /* select cats (sorted array) */
435 ncats = db_select_int(driver, Fi->table, Fi->key, where, &cats);
436 G_debug(3, "%d categories selected from table <%s>", ncats, Fi->table);
437
438 if (!column_names) {
441 }
442 else {
443 int icol, ncols;
444 const char *col_name;
445 int len_all = 0;
446
447 db_set_string(&dbstring, Fi->table);
449 G_warning(_("Unable to describe table <%s>"), Fi->table);
452 return -1;
453 }
454
456 columns = (char **)G_malloc((ncols + 1) * sizeof(char *));
457
458 if (column_names[0] && strcmp(column_names[0], "*") == 0) {
459
460 /* all columns */
461 icol = 0;
462 for (i = 0; i < ncols; i++) {
463 col_name =
465 /* key column skipped */
466 if (strcmp(Fi->key, col_name) != 0)
468 }
469 columns[icol] = NULL;
470 }
471 else {
472 int j;
473
474 icol = 0;
475 i = 0;
476 while (column_names[i]) {
477 /* key column skipped */
478 if (strcmp(Fi->key, column_names[i]) != 0) {
479 found = 0;
480 for (j = 0; j < ncols; j++) {
483 if (strcmp(col_name, column_names[i]) == 0) {
485 found = 1;
486 break;
487 }
488 }
489 if (!found) {
490 G_warning(_("Column <%s> does not exist"),
491 column_names[i]);
492 G_important_message(_("Available columns:"));
493 for (j = 0; j < ncols; j++) {
497 }
498 G_warning(_("Export cancelled"));
502 free_col_arrays(NULL, NULL, columns);
503 return -1;
504 }
505 }
506 i++;
507 }
508 columns[icol] = NULL;
509 }
510
513 Table = NULL;
514
515 if (columns[0]) {
516 /* selected columns only */
517 i = 0;
518 while (columns[i])
519 len_all += strlen(columns[i++]);
520
521 coltypes = G_malloc(i * sizeof(int));
522
523 all_columns = G_malloc(len_all + i + 2);
524
525 i = 0;
527 while (columns[i]) {
528 /* get column types */
529 coltypes[i] =
530 db_column_Ctype(driver, Fi->table, columns[i]);
531 if (coltypes[i] < 0) {
534 G_warning(
535 _("Unknown type of column <%s>, export cancelled"),
536 columns[i]);
538 G_free(cats);
539 free_col_arrays(coltypes, all_columns, columns);
540 return -1;
541 }
542 if (i > 0) {
543 strcat(all_columns, ",");
545 }
546 i++;
547 }
548 }
549 else {
550 /* no column or only key column selected */
551 free_col_arrays(NULL, NULL, columns);
552 columns = NULL;
553
556 }
557 }
558 }
559
560 if (format == GV_ASCII_FORMAT_POINT && header) {
561
562 /* print header */
563 if (Map->head.with_z)
564 fprintf(ascii, "east%snorth%sheight%scat", fs, fs, fs);
565 else
566 fprintf(ascii, "east%snorth%scat", fs, fs);
567 if (columns) {
568 for (i = 0; columns[i]; i++) {
569 if (db_select_value(driver, Fi->table, Fi->key, 0, columns[i],
570 &value) < 0)
571 G_fatal_error(_("Unable to select record from table <%s> "
572 "(key %s, column %s)"),
573 Fi->table, Fi->key, columns[i]);
574 if (columns[i])
575 fprintf(ascii, "%s%s", fs, columns[i]);
576 else
577 fprintf(ascii, "%s", columns[i]); /* can not happen */
578 }
579 }
580 fprintf(ascii, "%s", HOST_NEWLINE);
581 }
582
583 Points = Vect_new_line_struct();
587
588 /* by default, read_next_line will NOT read Dead lines */
589 /* but we can override that (in Level I only) by specifying */
590 /* the type -1, which means match all line types */
591
593
594 count = n_skipped = line = 0;
595 while (TRUE) {
596 ltype = Vect_read_next_line(Map, Points, Cats);
597 if (ltype == -1) { /* failure */
598 if (columns) {
601
602 free_col_arrays(
604 column_names && strcmp(column_names[0], "*") == 0 ? columns
605 : NULL);
606 }
610 G_free(cats);
611
612 return -1;
613 }
614
615 if (ltype == -2) { /* EOF */
616 if (columns) {
619
620 free_col_arrays(
622 column_names && strcmp(column_names[0], "*") == 0 ? columns
623 : NULL);
624 }
625 break;
626 }
627
628 line++;
629
630 if (!(ltype & type))
631 continue;
632
633 if (format == GV_ASCII_FORMAT_POINT && !(ltype & GV_POINTS))
634 continue;
635
636 found = get_cat(Cats, Clist, cats, ncats, field, &cat);
637
638 if (!found && field > 0 && ltype == GV_BOUNDARY && type & GV_AREA &&
639 Vect_level(Map) > 1) {
640 Vect_get_line_areas(Map, line, &left, &right);
641 if (left < 0)
642 left = Vect_get_isle_area(Map, abs(left));
643 if (left > 0) {
645 found = get_cat(ACats, Clist, cats, ncats, field, &cat);
646 }
647 if (right < 0)
648 right = Vect_get_isle_area(Map, abs(right));
649 if (!found && right > 0) {
651 found = get_cat(ACats, Clist, cats, ncats, field, &cat);
652 }
653 }
654
655 if (!found) {
656 if (Cats->n_cats < 1)
657 n_skipped++;
658
659 continue;
660 }
661
662 if (ver < 5) {
663 Vect_cat_get(Cats, 1, &cat);
664 }
665
666 switch (ltype) {
667 case GV_BOUNDARY:
668 if (ver == 5)
669 ctype = 'B';
670 else
671 ctype = 'A';
672 break;
673 case GV_CENTROID:
674 if (ver < 5) {
675 if (att != NULL) {
676 if (cat > 0) {
677 G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]);
679 G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]);
681 fprintf(att, "A %s %s %d%s", xstring, ystring, cat,
683 }
684 }
685 continue;
686 }
687 ctype = 'C';
688 break;
689 case GV_LINE:
690 ctype = 'L';
691 break;
692 case GV_POINT:
693 ctype = 'P';
694 break;
695 case GV_FACE:
696 ctype = 'F';
697 break;
698 case GV_KERNEL:
699 ctype = 'K';
700 break;
701 default:
702 ctype = 'X';
703 G_warning(_("Unknown feature type %d"), (int)ltype);
704 break;
705 }
706
707 if (format == GV_ASCII_FORMAT_POINT) {
708 if (region_flag) {
709 if ((window.east < Points->x[0]) ||
710 (window.west > Points->x[0]))
711 continue;
712 }
713 G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]);
715
716 if (region_flag) {
717 if ((window.north < Points->y[0]) ||
718 (window.south > Points->y[0]))
719 continue;
720 }
721 G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]);
723
725
726 if (Map->head.with_z && ver == 5) {
727 if (region_flag) {
728 if ((window.top < Points->z[0]) ||
729 (window.bottom > Points->z[0]))
730 continue;
731 }
732 G_rasprintf(&zstring, &zsize, "%.*f", dp, Points->z[0]);
734 fprintf(ascii, "%s%s%s%s%s", xstring, fs, ystring, fs, zstring);
735 }
736 else {
737 fprintf(ascii, "%s%s%s", xstring, fs, ystring);
738 }
739
740 if (fcats->n_values > 0 && cat > -1) {
741 if (fcats->n_values > 1) {
742 G_warning(
743 _("Feature has more categories. Only one category (%d) "
744 "is exported."),
745 cat);
746 }
747 fprintf(ascii, "%s%d", fs, cat);
748
749 /* print attributes */
750 if (columns) {
751
752 G_rasprintf(&buf, &bufsize,
753 "SELECT %s FROM %s WHERE %s = %d", all_columns,
754 Fi->table, Fi->key, cat);
755 G_debug(2, "SQL: %s", buf);
756 db_set_string(&dbstring, buf);
757
759 DB_SEQUENTIAL) != DB_OK) {
763 _("Cannot select attributes for cat = %d"), cat);
764 }
765 if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
768 G_fatal_error(_("Unable to fetch data from table"));
769 }
770
772
773 for (i = 0; columns[i]; i++) {
776
778 fprintf(ascii, "%s", fs);
779 }
780 else {
781 switch (coltypes[i]) {
782 case DB_C_TYPE_INT: {
783 fprintf(ascii, "%s%d", fs,
785 break;
786 }
787 case DB_C_TYPE_DOUBLE: {
788 fprintf(ascii, "%s%.*f", fs, dp,
790 break;
791 }
792 case DB_C_TYPE_STRING: {
793 fprintf(ascii, "%s%s", fs,
795 break;
796 }
797 case DB_C_TYPE_DATETIME: {
798 break;
799 }
800 case -1:
802 _("Column <%s> not found in table <%s>"),
803 columns[i], Fi->table);
804 default:
806 _("Column <%s>: unsupported data type"),
807 columns[i]);
808 }
809 }
810 }
812 }
813 }
814
815 fprintf(ascii, "%s", HOST_NEWLINE);
816 }
817 else if (format == GV_ASCII_FORMAT_STD) {
818 /* FORMAT_STANDARD */
819 if (ver == 5 && Cats->n_cats > 0)
820 fprintf(ascii, "%c %d %d%s", ctype, Points->n_points,
821 Cats->n_cats, HOST_NEWLINE);
822 else
823 fprintf(ascii, "%c %d%s", ctype, Points->n_points,
825
826 xptr = Points->x;
827 yptr = Points->y;
828 zptr = Points->z;
829
830 while (Points->n_points--) {
831
832 G_rasprintf(&xstring, &xsize, "%.*f", dp, *xptr++);
834 G_rasprintf(&ystring, &ysize, "%.*f", dp, *yptr++);
836
837 if (ver == 5) {
838 if (Map->head.with_z) {
839 G_rasprintf(&zstring, &zsize, "%.*f", dp, *zptr++);
841 fprintf(ascii, " %-12s %-12s %s%s", xstring, ystring,
843 }
844 else {
845 fprintf(ascii, " %-12s %s%s", xstring, ystring,
847 }
848 } /*Version 4 */
849 else {
850 fprintf(ascii, " %-12s %-12s%s", ystring, xstring,
852 }
853 }
854
855 if (ver == 5) {
856 for (i = 0; i < Cats->n_cats; i++) {
857 fprintf(ascii, " %-5d %d%s", Cats->field[i], Cats->cat[i],
859 }
860 }
861 else {
862 if (cat > -1) {
863 if (ltype == GV_POINT) {
864 G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]);
866 G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]);
868 fprintf(att, "P %s %s %d%s", xstring, ystring, cat,
870 }
871 else {
872 x = (Points->x[1] + Points->x[0]) / 2;
873 y = (Points->y[1] + Points->y[0]) / 2;
874
875 G_rasprintf(&xstring, &xsize, "%.*f", dp, x);
877 G_rasprintf(&ystring, &ysize, "%.*f", dp, y);
879 fprintf(att, "L %s %s %d%s", xstring, ystring, cat,
881 }
882 }
883 }
884 }
885 else if (format == GV_ASCII_FORMAT_WKT) {
887 continue;
888 /* Well-Known Text */
890 count++;
891 }
892 else {
893 G_fatal_error(_("Unknown format"));
894 }
895 count++;
896 }
897
898 if (format == GV_ASCII_FORMAT_WKT) {
899 /* process areas - topology required */
900 int i, area, nareas, isle, nisles;
901
902 if (Vect_level(Map) < 2) {
903 G_warning(_("Topology not available, unable to process areas"));
904 nareas = 0;
905 }
906 else {
908 }
909 for (area = 1; area <= nareas; area++) {
910 if (!Vect_area_alive(Map, area)) /* skip dead areas */
911 continue;
912 if (Vect_get_area_cat(Map, area, field) < 0)
913 continue;
914 /* get boundary -> linearring */
915 if (Vect_get_area_points(Map, area, Points) < 0) {
916 G_warning(_("Unable to get boundary of area id %d"), area);
917 continue;
918 }
919 fprintf(ascii, "POLYGON(");
920 /* write outer ring */
922 ascii); /* boundary is always 2D */
923 /* get isles (holes) -> inner rings */
925 for (i = 0; i < nisles; i++) {
926 /* get isle boundary -> linearring */
927 isle = Vect_get_area_isle(Map, area, i);
928 if (Vect_get_isle_points(Map, isle, Points) < 0) {
929 G_warning(
930 _("Unable to get boundary of isle id %d (area id %d)"),
931 isle, area);
932 continue;
933 }
934 fprintf(ascii, ", ");
935 /* write inner ring */
937 ascii); /* boundary is always 2D */
938 }
939 fprintf(ascii, ")%s", HOST_NEWLINE);
940
941 count++;
942 }
943 }
944
945 if (n_skipped > 0)
947 _("%d features without category skipped. To export also "
948 "features without category use '%s=-1'."),
949 n_skipped, "layer");
950
956 G_free(cats);
957
958 return count;
959}
960
961int srch(const void *pa, const void *pb)
962{
963 int *p1 = (int *)pa;
964 int *p2 = (int *)pb;
965
966 if (*p1 < *p2)
967 return -1;
968 if (*p1 > *p2)
969 return 1;
970 return 0;
971}
972
973/*!
974 \brief Write data to GRASS ASCII vector format
975
976 \param[out] dascii pointer to the output ASCII file
977 \param Map pointer to Map_info structure
978 */
980{
981 fprintf(dascii, "ORGANIZATION: %s%s", Vect_get_organization(Map),
983 fprintf(dascii, "DIGIT DATE: %s%s", Vect_get_date(Map), HOST_NEWLINE);
984 fprintf(dascii, "DIGIT NAME: %s%s", Vect_get_person(Map), HOST_NEWLINE);
985 fprintf(dascii, "MAP NAME: %s%s", Vect_get_map_name(Map), HOST_NEWLINE);
986 fprintf(dascii, "MAP DATE: %s%s", Vect_get_map_date(Map), HOST_NEWLINE);
987 fprintf(dascii, "MAP SCALE: %d%s", Vect_get_scale(Map), HOST_NEWLINE);
988 fprintf(dascii, "OTHER INFO: %s%s", Vect_get_comment(Map), HOST_NEWLINE);
989 fprintf(dascii, "ZONE: %d%s", Vect_get_zone(Map), HOST_NEWLINE);
990 fprintf(dascii, "MAP THRESH: %f%s", Vect_get_thresh(Map), HOST_NEWLINE);
991}
992
993/* check category */
994int get_cat(const struct line_cats *Cats, const struct cat_list *Clist,
995 const int *cats, int ncats, int field, int *cat)
996{
997 int i;
998
999 *cat = -1;
1000
1001 if (field < 1)
1002 return TRUE;
1003
1004 if (Clist && Clist->field == field) {
1005 for (i = 0; i < Cats->n_cats; i++) {
1006 if (Cats->field[i] == field &&
1007 Vect_cat_in_cat_list(Cats->cat[i], Clist)) {
1008 *cat = Cats->cat[i];
1009 return TRUE;
1010 }
1011 }
1012 return FALSE;
1013 }
1014 if (cats) {
1015 int *found;
1016
1017 for (i = 0; i < Cats->n_cats; i++) {
1018 if (Cats->field[i] == field) {
1019 found = (int *)bsearch((void *)&(Cats->cat[i]), cats, ncats,
1020 sizeof(int), srch);
1021 if (found) {
1022 /* found */
1023 *cat = *found;
1024 return TRUE;
1025 }
1026 }
1027 }
1028 return FALSE;
1029 }
1030 if (!Clist && !cats && field > 0) {
1031 Vect_cat_get(Cats, field, cat);
1032 if (*cat > -1)
1033 return TRUE;
1034 }
1035
1036 return FALSE;
1037}
1038
1039/* free column arrays, see Vect_write_ascii() */
1040void free_col_arrays(int *coltypes, char *all_columns, char **columns)
1041{
1044 if (columns) {
1045 int i = 0;
1046
1047 while (columns[i])
1048 G_free(columns[i++]);
1049 G_free(columns);
1050 }
1051}
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:357
#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:277
void Vect_write_ascii_head(FILE *dascii, struct Map_info *Map)
Write data to GRASS ASCII vector format.
Definition ascii.c:979
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