[GRASS-SVN] r47790 - grass/trunk/vector/v.extract

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Aug 21 07:01:07 EDT 2011


Author: martinl
Date: 2011-08-21 04:01:07 -0700 (Sun, 21 Aug 2011)
New Revision: 47790

Added:
   grass/trunk/vector/v.extract/copy_tab.c
   grass/trunk/vector/v.extract/local_proto.h
Modified:
   grass/trunk/vector/v.extract/extract.c
   grass/trunk/vector/v.extract/main.c
Log:
v.extract: major update for G7
	   experimental support for OGR write access


Added: grass/trunk/vector/v.extract/copy_tab.c
===================================================================
--- grass/trunk/vector/v.extract/copy_tab.c	                        (rev 0)
+++ grass/trunk/vector/v.extract/copy_tab.c	2011-08-21 11:01:07 UTC (rev 47790)
@@ -0,0 +1,111 @@
+#include <grass/gis.h>
+#include <grass/vector.h>
+#include <grass/dbmi.h>
+#include <grass/glocale.h>
+
+#include "local_proto.h"
+
+void copy_tabs(const struct Map_info *In, int field, int new_cat,
+	       struct Map_info *Out)
+{
+    int nlines, line, i;
+    int ttype, ntabs;
+    int **ocats, *nocats, nfields, *fields;
+    
+    struct field_info *IFi, *OFi;
+    struct line_cats *Cats;
+    
+    ntabs = 0;
+    
+    /* Collect list of output cats */
+    Cats = Vect_new_cats_struct();
+    nfields = Vect_cidx_get_num_fields(Out);
+    ocats = (int **)G_malloc(nfields * sizeof(int *));
+    nocats = (int *)G_malloc(nfields * sizeof(int));
+    fields = (int *)G_malloc(nfields * sizeof(int));
+    for (i = 0; i < nfields; i++) {
+	nocats[i] = 0;
+	ocats[i] =
+	    (int *)G_malloc(Vect_cidx_get_num_cats_by_index(Out, i) *
+			    sizeof(int));
+	fields[i] = Vect_cidx_get_field_number(Out, i);
+    }
+    
+    nlines = Vect_get_num_lines(Out);
+    for (line = 1; line <= nlines; line++) {
+	Vect_read_line(Out, NULL, Cats, line);
+	
+	for (i = 0; i < Cats->n_cats; i++) {
+	    int f, j;
+	    
+	    for (j = 0; j < nfields; j++) {	/* find field */
+		if (fields[j] == Cats->field[i]) {
+		    f = j;
+		    break;
+		}
+	    }
+	    ocats[f][nocats[f]] = Cats->cat[i];
+	    nocats[f]++;
+	}
+    }
+    
+    /* Copy tables */
+    G_message(_("Writing attributes..."));
+    
+    /* Number of output tabs */
+    for (i = 0; i < Vect_get_num_dblinks(In); i++) {
+	int j, f = -1;
+	
+	IFi = Vect_get_dblink(In, i);
+	
+	for (j = 0; j < nfields; j++) {	/* find field */
+	    if (fields[j] == IFi->number) {
+		f = j;
+		break;
+	    }
+	}
+	if (f >= 0 && nocats[f] > 0)
+	    ntabs++;
+    }
+    
+    if (ntabs > 1)
+	ttype = GV_MTABLE;
+    else
+	ttype = GV_1TABLE;
+    
+    for (i = 0; i < nfields; i++) {
+	int ret;
+	
+	if (fields[i] == 0)
+	    continue;
+	if (nocats[i] == 0)
+	    continue;
+	if (fields[i] == field && new_cat != -1)
+		continue;
+	
+	G_verbose_message(_("Writting attributes for layer %d"), fields[i]);
+	
+	/* Make a list of categories */
+	IFi = Vect_get_field(In, fields[i]);
+	if (!IFi) {		/* no table */
+	    G_message(_("No attribute table for layer %d"), fields[i]);
+	    continue;
+	}
+	
+	OFi = Vect_default_field_info(Out, IFi->number, NULL, ttype);
+	
+	ret = db_copy_table_by_ints(IFi->driver, IFi->database, IFi->table,
+				    OFi->driver,
+				    Vect_subst_var(OFi->database, Out),
+				    OFi->table, IFi->key, ocats[i],
+				    nocats[i]);
+	
+	if (ret == DB_FAILED) {
+	    G_warning(_("Unable to copy table <%s>"), IFi->table);
+	}
+	else {
+	    Vect_map_add_dblink(Out, OFi->number, OFi->name, OFi->table,
+				IFi->key, OFi->database, OFi->driver);
+	}
+    }
+}


Property changes on: grass/trunk/vector/v.extract/copy_tab.c
___________________________________________________________________
Added: svn:mime-type
   + text/x-csrc
Added: svn:eol-style
   + native

Modified: grass/trunk/vector/v.extract/extract.c
===================================================================
--- grass/trunk/vector/v.extract/extract.c	2011-08-21 10:52:16 UTC (rev 47789)
+++ grass/trunk/vector/v.extract/extract.c	2011-08-21 11:01:07 UTC (rev 47790)
@@ -29,7 +29,7 @@
 }
 
 /* check if cat is in list */
-int in_list(int cat)
+static int in_list(int cat)
 {
     if (bsearch(&cat, cats_array, ncats_array, sizeof(int), cmp))
 	return 1;
@@ -38,8 +38,8 @@
 }
 
 /* output reclass cats */
-void extract_cats(struct line_cats *Cats, int type_only, int field, int new,
-		  int reverse)
+static void extract_cats(struct line_cats *Cats, int type_only, int field, int new,
+			 int reverse)
 {
     int i, tmp;
     static struct line_cats *TCats = NULL;
@@ -105,8 +105,8 @@
 }
 
 /* check if output cats of left and right area match */
-int areas_new_cats_match(struct Map_info *In, int area1, int area2,
-			 int type_only, int field, int new, int reverse)
+static int areas_new_cats_match(struct Map_info *In, int area1, int area2,
+				int type_only, int field, int new, int reverse)
 {
     int i, j, found;
     int centroid1, centroid2;
@@ -157,10 +157,9 @@
     return 1;
 }
 
-int
-xtract_line(int num_index, int *num_array, struct Map_info *In,
-	    struct Map_info *Out, int new, int select_type, int dissolve,
-	    int field, int type_only, int reverse)
+int extract_line(int num_index, int *num_array, struct Map_info *In,
+		 struct Map_info *Out, int new, int select_type, int dissolve,
+		 int field, int type_only, int reverse)
 {
     int line, nlines;
     struct line_pnts *Points;
@@ -352,6 +351,7 @@
 	}
 
     }				/* end lines section */
-
-    return (0);
+    G_percent(1, 1, 1);
+    
+    return 0;
 }

Added: grass/trunk/vector/v.extract/local_proto.h
===================================================================
--- grass/trunk/vector/v.extract/local_proto.h	                        (rev 0)
+++ grass/trunk/vector/v.extract/local_proto.h	2011-08-21 11:01:07 UTC (rev 47790)
@@ -0,0 +1,9 @@
+/* copy_tab.c */
+void copy_tabs(const struct Map_info *, int, int,
+	       struct Map_info *);
+
+/* extract.c */
+int cmp(const void *, const void *);
+int extract_line(int, int *, struct Map_info *,
+		 struct Map_info *, int, int, int,
+		 int, int, int);


Property changes on: grass/trunk/vector/v.extract/local_proto.h
___________________________________________________________________
Added: svn:mime-type
   + text/x-chdr
Added: svn:eol-style
   + native

Modified: grass/trunk/vector/v.extract/main.c
===================================================================
--- grass/trunk/vector/v.extract/main.c	2011-08-21 10:52:16 UTC (rev 47789)
+++ grass/trunk/vector/v.extract/main.c	2011-08-21 11:01:07 UTC (rev 47790)
@@ -4,19 +4,18 @@
  * MODULE:     v.extract
  * 
  * AUTHOR(S):  R.L.Glenn , Soil Conservation Service, USDA
- *             update to 5.7:  Radim Blazek
+ *             Updated for 5.7 by Radim Blazek
+ *             Updated for 7.0 by Martin Landa <landa.martin gmail.com>
  *               
- * PURPOSE:    Provides a means of generating vector (digit) files
- *             from an existing vector maplayer. Selects all vector
- *             boundaries for 1 or several areas of a list of
- *             user provided categories.
+ * PURPOSE:    Selects vector features from an existing vector map and
+ *             creates a new vector map containing only the selected
+ *             features.
  *
- * COPYRIGHT:  (C) 2002-2009 by the GRASS Development Team
+ * COPYRIGHT:  (C) 2002-2009, 2011 by the GRASS Development Team
  *
- *             This program is free software under the 
- *             GNU General Public License (>=v2). 
- *             Read the file COPYING that comes with GRASS
- *             for details.
+ *             This program is free software under the GNU General
+ *             Public License (>=v2). Read the file COPYING that
+ *             comes with GRASS for details.
  *
  * TODO:       - fix white space problems for file= option
  ****************************************************************/
@@ -28,62 +27,50 @@
 #include <search.h>
 #include <sys/types.h>
 #include <unistd.h>
+
 #include <grass/gis.h>
 #include <grass/vector.h>
 #include <grass/dbmi.h>
 #include <grass/gmath.h>
 #include <grass/glocale.h>
 
+#include "local_proto.h"
+
 static int *cat_array, cat_count, cat_size;
-int scan_cats(char *, int *, int *);
-int xtract_line(int, int[], struct Map_info *, struct Map_info *, int, int,
-		int, int, int, int);
 
-static void add_cat(int x)
-{
-    G_debug(2, "add_cat %d", x);
+static int scan_cats(char *, int *, int *);
+static void add_cat(int);
 
-    if (cat_count >= cat_size) {
-	cat_size = (cat_size < 1000) ? 1000 : cat_size * 2;
-	cat_array = G_realloc(cat_array, cat_size * sizeof(int));
-    }
-
-    cat_array[cat_count++] = x;
-}
-
-/* Comparison function for *search */
-static int cmp(const void *pa, const void *pb)
-{
-    int *p1 = (int *)pa;
-    int *p2 = (int *)pb;
-
-    if (*p1 < *p2)
-	return -1;
-    if (*p1 > *p2)
-	return 1;
-    return 0;
-}
-
 int main(int argc, char **argv)
 {
-    int i, new_cat, type, ncats, *cats, c;
-    int **ocats, *nocats, nfields, *fields;
-    int field;
-    int dissolve = 0, x, y, type_only;
+    int i, new_cat, type, ncats, *cats, c, is_ogr;
+    int field, dissolve, x, y, type_only;
     char buffr[1024], text[80];
     char *input, *output;
+
+    FILE *in;
+
     struct GModule *module;
-    struct Option *inopt, *outopt, *fileopt, *newopt, *typopt, *listopt,
-	*fieldopt, *whereopt, *nrandopt;
-    struct Flag *t_flag, *d_flag, *r_flag;
+    struct {
+	struct Option *input, *output, *file, *new, *type, *list,
+	    *field, *where, *nrand;
+    } opt;
+    struct {
+	struct Flag *t, *d, *r;
+    } flag;
+    
     struct Map_info In, Out;
     struct field_info *Fi;
-    FILE *in;
+    
     dbDriver *driver;
-    struct line_cats *Cats;
+    
     struct Cat_index *ci;
-    int ucat_count, *ucat_array = NULL, prnd, seed, nrandom, nfeatures;
+    
+    int ucat_count, *ucat_array, prnd, seed, nrandom, nfeatures;
 
+    Fi = NULL;
+    ucat_array = NULL;
+    
     G_gisinit(argv[0]);
 
     /* set up the options and flags for the command line parser */
@@ -91,160 +78,159 @@
     G_add_keyword(_("vector"));
     G_add_keyword(_("extract"));
     module->description =
-	_("Selects vector objects from an existing vector map and "
-	  "creates a new map containing only the selected objects.");
+	_("Selects vector features from an existing vector map and "
+	  "creates a new vector map containing only the selected features.");
 
-    d_flag = G_define_flag();
-    d_flag->key = 'd';
-    d_flag->description = _("Dissolve common boundaries (default is no)");
+    flag.d = G_define_flag();
+    flag.d->key = 'd';
+    flag.d->description = _("Dissolve common boundaries (default is no)");
 
-    t_flag = G_define_flag();
-    t_flag->key = 't';
-    t_flag->description = _("Do not copy table (see also 'new' parameter)");
+    flag.t = G_define_flag();
+    flag.t->key = 't';
+    flag.t->description = _("Do not copy attributes (see also 'new' parameter)");
+    flag.t->guisection = _("Attributes");
 
-    r_flag = G_define_flag();
-    r_flag->key = 'r';
-    r_flag->description = _("Reverse selection");
-    r_flag->guisection = _("Selection");
+    flag.r = G_define_flag();
+    flag.r->key = 'r';
+    flag.r->description = _("Reverse selection");
+    flag.r->guisection = _("Selection");
 
-    inopt = G_define_standard_option(G_OPT_V_INPUT);
+    opt.input = G_define_standard_option(G_OPT_V_INPUT);
 
-    fieldopt = G_define_standard_option(G_OPT_V_FIELD);
-    fieldopt->guisection = _("Selection");
+    opt.field = G_define_standard_option(G_OPT_V_FIELD);
+    opt.field->guisection = _("Selection");
     
-    typopt = G_define_standard_option(G_OPT_V_TYPE);
-    typopt->answer = "point,line,boundary,centroid,area,face";
-    typopt->options = "point,line,boundary,centroid,area,face";
-    typopt->label = _("Types to be extracted");
-    typopt->guisection = _("Selection");
+    opt.type = G_define_standard_option(G_OPT_V_TYPE);
+    opt.type->answer = "point,line,boundary,centroid,area,face";
+    opt.type->options = "point,line,boundary,centroid,area,face";
+    opt.type->label = _("Types to be extracted");
+    opt.type->guisection = _("Selection");
 
-    listopt = G_define_standard_option(G_OPT_V_CATS);
-    listopt->key = "list";
-    listopt->guisection = _("Selection");
+    opt.list = G_define_standard_option(G_OPT_V_CATS);
+    opt.list->guisection = _("Selection");
 
-    whereopt = G_define_standard_option(G_OPT_DB_WHERE);
-    whereopt->guisection = _("Selection");
+    opt.where = G_define_standard_option(G_OPT_DB_WHERE);
+    opt.where->guisection = _("Selection");
     
-    outopt = G_define_standard_option(G_OPT_V_OUTPUT);
+    opt.output = G_define_standard_option(G_OPT_V_OUTPUT);
     
-    fileopt = G_define_standard_option(G_OPT_F_INPUT);
-    fileopt->key = "file";
-    fileopt->required = NO;
-    fileopt->label =
+    opt.file = G_define_standard_option(G_OPT_F_INPUT);
+    opt.file->key = "file";
+    opt.file->required = NO;
+    opt.file->label =
 	_("Input text file with category numbers/number ranges to be extracted");
-    fileopt->description = _("If '-' given reads from standard input");
-    fileopt->guisection = _("Selection");
+    opt.file->description = _("If '-' given reads from standard input");
+    opt.file->guisection = _("Selection");
 
-    nrandopt = G_define_option();
-    nrandopt->key = "random";
-    nrandopt->type = TYPE_INTEGER;
-    nrandopt->required = NO;
-    nrandopt->label =
+    opt.nrand = G_define_option();
+    opt.nrand->key = "random";
+    opt.nrand->type = TYPE_INTEGER;
+    opt.nrand->required = NO;
+    opt.nrand->label =
 	_("Number of random categories matching vector objects to extract");
-    nrandopt->description =
+    opt.nrand->description =
 	_("Number must be smaller than unique cat count in layer");
-    nrandopt->guisection = _("Selection");
+    opt.nrand->guisection = _("Selection");
 
-    newopt = G_define_option();
-    newopt->key = "new";
-    newopt->type = TYPE_INTEGER;
-    newopt->required = NO;
-    newopt->answer = "-1";
-    newopt->label =
-	_("Enter -1 to keep original categories or the desired NEW category value");
-    newopt->description = _("If new >= 0, table is not copied");
+    opt.new = G_define_option();
+    opt.new->key = "new";
+    opt.new->type = TYPE_INTEGER;
+    opt.new->required = NO;
+    opt.new->answer = "-1";
+    opt.new->label = _("Desired new category value "
+		       "(enter -1 to keep original categories)");
+    opt.new->description = _("If new >= 0, attributes is not copied");
+    opt.new->guisection = _("Attributes");
     
-    /* heeeerrrrrre's the   PARSER */
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
-
-
+    
     /* start checking options and flags */
     c = 0;
-    if (fileopt->answer != NULL)
+    if (opt.file->answer != NULL)
 	c++;
-    if (listopt->answers != NULL)
+    if (opt.list->answers != NULL)
 	c++;
-    if (whereopt->answer != NULL)
+    if (opt.where->answer != NULL)
 	c++;
-    if (nrandopt->answer != NULL)
+    if (opt.nrand->answer != NULL)
 	c++;
     if (c > 1)
-	G_fatal_error(_("List, file, where and random options are exclusive. "
-			"Please specify only one of them"));
-    c = 0;
-
-    type_only = 0;
-    if (!listopt->answers && !fileopt->answer && !whereopt->answer &&
-	!nrandopt->answer) {
-	type_only = 1;
+	G_fatal_error(_("Options <%s>, <%s>, <%s> and <%s> options are exclusive. "
+			"Please specify only one of them."),
+		      opt.list->key, opt.file->key, opt.where->key,
+		      opt.nrand->key);
+    
+    type_only = FALSE;
+    if (!opt.list->answers && !opt.file->answer && !opt.where->answer &&
+	!opt.nrand->answer) {
+	type_only = TRUE;
     }
 
-    Vect_check_input_output_name(inopt->answer, outopt->answer,
+    input = opt.input->answer;
+    output = opt.output->answer;
+    Vect_check_input_output_name(input, output,
 				 GV_FATAL_EXIT);
-
-    /* set input vector map name and mapset */
-    input = inopt->answer;
-
-    /* set output vector map name */
-    output = outopt->answer;
-
-    if (d_flag->answer)
-	dissolve = 1;
-
-    if (!newopt->answer)
+    
+    if (flag.d->answer)
+	dissolve = TRUE;
+    else
+	dissolve = FALSE;
+	
+    if (!opt.new->answer)
 	new_cat = 0;
     else
-	new_cat = atoi(newopt->answer);
+	new_cat = atoi(opt.new->answer);
 
     /* Do initial read of input file */
     Vect_set_open_level(2); /* topology required */
-    Vect_open_old2(&In, input, "", fieldopt->answer);
+    Vect_open_old2(&In, input, "", opt.field->answer);
     
-    field = Vect_get_field_number(&In, fieldopt->answer);
+    field = Vect_get_field_number(&In, opt.field->answer);
     
-    type = Vect_option_to_types(typopt);
+    type = Vect_option_to_types(opt.type);
     if (type & GV_AREA) {
 	type |= GV_CENTROID;
     }
 
     /* Read categoy list */
     cat_count = 0;
-    if (listopt->answer != NULL) {
+    if (opt.list->answer != NULL) {
 	/* no file of categories to read, process cat list */
 	/* first check for valid list */
-	for (i = 0; listopt->answers[i]; i++) {
-	    G_debug(2, "catlist item: %s", listopt->answers[i]);
-	    if (!scan_cats(listopt->answers[i], &x, &y))
+	for (i = 0; opt.list->answers[i]; i++) {
+	    G_debug(2, "catlist item: %s", opt.list->answers[i]);
+	    if (!scan_cats(opt.list->answers[i], &x, &y))
 		G_fatal_error(_("Category value in '%s' not valid"),
-			      listopt->answers[i]);
+			      opt.list->answers[i]);
 	}
 
 	/* valid list, put into cat value array */
-	for (i = 0; listopt->answers[i]; i++) {
-	    scan_cats(listopt->answers[i], &x, &y);
+	for (i = 0; opt.list->answers[i]; i++) {
+	    scan_cats(opt.list->answers[i], &x, &y);
 	    while (x <= y)
 		add_cat(x++);
 	}
     }
-    else if (fileopt->answer != NULL) {	/* got a file of category numbers */
-	if (G_strcasecmp(fileopt->answer, "-") == 0) {
+    else if (opt.file->answer != NULL) {	/* got a file of category numbers */
+	if (strcmp(opt.file->answer, "-") == 0) {
 	    in = stdin;
 	}
 	else {
-	    G_message(_("Process file <%s> for category numbers"),
-		      fileopt->answer);
+	    G_verbose_message(_("Process file <%s> for category numbers..."),
+			      opt.file->answer);
 
 	    /* open input file */
-	    if ((in = fopen(fileopt->answer, "r")) == NULL)
+	    if ((in = fopen(opt.file->answer, "r")) == NULL)
 		G_fatal_error(_("Unable to open specified file <%s>"),
-			      fileopt->answer);
+			      opt.file->answer);
 	}
 
-	while (1) {
+	while (TRUE) {
 	    if (!fgets(buffr, 39, in))
 		break;
-	    G_chop(buffr);	/* eliminate some white space, we accept numbers and dashes only */
+	    /* eliminate some white space, we accept numbers and dashes only */
+	    G_chop(buffr);	
 	    sscanf(buffr, "%[-0-9]", text);
 	    if (strlen(text) == 0)
 		G_warning(_("Ignored text entry: %s"), buffr);
@@ -256,31 +242,30 @@
 		add_cat(x++);
 	}
 
-	if (G_strcasecmp(fileopt->answer, "-") != 0)
+	if (strcmp(opt.file->answer, "-") != 0)
 	    fclose(in);
-
     }
-    else if (whereopt->answer != NULL) {
+    else if (opt.where->answer != NULL) {
 	Fi = Vect_get_field(&In, field);
 	if (!Fi) {
 	    G_fatal_error(_("Database connection not defined for layer <%s>"),
-			  fieldopt->answer);
+			  opt.field->answer);
 	}
 
-	G_debug(1, "Loading categories from table <%s>", Fi->table);
+	G_verbose_message(_("Loading categories from table <%s>..."), Fi->table);
 
 	driver = db_start_driver_open_database(Fi->driver, Fi->database);
 	if (driver == NULL)
 	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
 			  Fi->database, Fi->driver);
 	
-	ncats = db_select_int(driver, Fi->table, Fi->key, whereopt->answer,
+	ncats = db_select_int(driver, Fi->table, Fi->key, opt.where->answer,
 			      &cats);
 	if (ncats == -1)
-		G_fatal_error(_("Unable select records from table <%s>"), Fi->table);
-	G_message(_("%d categories loaded from table <%s>"), ncats,
-		  Fi->table);
-
+		G_fatal_error(_("Unable select records from table <%s>"),
+			      Fi->table);
+	G_verbose_message(_("%d categories loaded"), ncats);
+	    
 	db_close_database(driver);
 	db_shutdown_driver(driver);
 
@@ -289,23 +274,23 @@
 	if (ncats >= 0)
 	    G_free(cats);
     }
-    else if (nrandopt->answer != NULL) {	/* Generate random category list */
-
+    else if (opt.nrand->answer != NULL) { /* Generate random category list */
 	/* We operate on layer's CAT's and thus valid layer is required */
 	if (Vect_cidx_get_field_index(&In, field) < 0)
 	    G_fatal_error(_("This map has no categories attached. "
-			    "Use v.category to attach categories to this vector map."));
+			    "Use v.category to attach categories to "
+			    "this vector map."));
 
 	/* Don't do any processing, if user input is wrong */
-	nrandom = atoi(nrandopt->answer);
+	nrandom = atoi(opt.nrand->answer);
 	if (nrandom < 1)
 	    G_fatal_error(_("Please specify random number larger than 0"));
 
 	nfeatures = Vect_cidx_get_type_count(&In, field, type);
 	if (nrandom >= nfeatures)
 	    G_fatal_error(_("Random category count must be smaller than feature count. "
-			   "There are only %d features of type(s): %s"),
-			  nfeatures, typopt->answer);
+			    "There are only %d features of type(s): %s"),
+			  nfeatures, opt.type->answer);
 
 	/* Let's create an array of uniq CAT values
 	   According to Vlib/build.c, cidx should be allready sorted by dig_cidx_sort() */
@@ -326,14 +311,14 @@
 	}
 
 	if (nrandom >= ucat_count)
-	    G_fatal_error(_("Random category count is larger or equal to uniq \"%s\" feature category count %d"),
-			  typopt->answer, ucat_count);
+	    G_fatal_error(_("Random category count is larger or equal to "
+			    "uniq <%s> feature category count %d"),
+			  opt.type->answer, ucat_count);
 
 	if (ucat_count >= RAND_MAX)
-	    G_fatal_error
-		("There are more categories than random number generator can reach. "
-		 "Report this as a GRASS bug.");
-
+	    G_fatal_error(_("There are more categories than random number "
+			    "generator can reach. Report this as a GRASS bug."));
+	
 	seed = getpid();
 	/* Initialise random number generator */
 	G_math_rand(-1 * seed);
@@ -341,11 +326,11 @@
 	/* Fill cat_array with list of valid random numbers */
 	while (cat_count < nrandom) {
 	    /* Random number in range from 0 to largest CAT value */
-	    prnd =
-		(int)floor(G_math_rand(seed) *
-			   (ucat_array[ucat_count - 1] + 1));
+	    prnd = (int) floor(G_math_rand(seed) *
+			       (ucat_array[ucat_count - 1] + 1));
 	    qsort(cat_array, cat_count, sizeof(int), cmp);
-	    /* Check if generated number isn't already in final list and is in list of existing CATs */
+	    /* Check if generated number isn't already in 
+	       final list and is in list of existing CATs */
 	    if (bsearch(&prnd, cat_array, cat_count, sizeof(int), cmp) == NULL
 		&& bsearch(&prnd, ucat_array, ucat_count, sizeof(int),
 			   cmp) != NULL)
@@ -355,7 +340,6 @@
 	qsort(cat_array, cat_count, sizeof(int), cmp);
     }
 
-    /* Open output file only when it's required */
     Vect_open_new(&Out, output, Vect_is_3d(&In));
     Vect_hist_copy(&In, &Out);
     Vect_hist_command(&Out);
@@ -364,116 +348,31 @@
     Vect_copy_head_data(&In, &Out);
     
     G_message(_("Extracting features..."));
-    xtract_line(cat_count, cat_array, &In, &Out, new_cat, type, dissolve, field,
-		type_only, r_flag->answer ? 1 : 0);
+    
+    is_ogr = Vect_maptype(&Out) == GV_FORMAT_OGR_DIRECT;
+    if (!flag.t->answer && is_ogr) {
+	/* Copy attributes for OGR output */
+	if (!Fi)
+	    Fi = Vect_get_field(&In, field);
+	if (!Fi)
+	    G_fatal_error(_("Database connection not defined for layer <%s>"),
+			  opt.field->answer);
+	Vect_map_add_dblink(&Out, Fi->number, Fi->name, Fi->table, Fi->key,
+			    Fi->database, Fi->driver);
+    }
 
+    extract_line(cat_count, cat_array, &In, &Out, new_cat, type, dissolve, field,
+		 type_only, flag.r->answer ? 1 : 0);
+
     Vect_build(&Out);
 
     /* Copy tables */
-    if (!t_flag->answer) {
-	int nlines, line;
-	int ttype, ntabs = 0;
-	struct field_info *IFi, *OFi;
-
-	/* Collect list of output cats */
-	Cats = Vect_new_cats_struct();
-	nfields = Vect_cidx_get_num_fields(&Out);
-	ocats = (int **)G_malloc(nfields * sizeof(int *));
-	nocats = (int *)G_malloc(nfields * sizeof(int));
-	fields = (int *)G_malloc(nfields * sizeof(int));
-	for (i = 0; i < nfields; i++) {
-	    nocats[i] = 0;
-	    ocats[i] =
-		(int *)G_malloc(Vect_cidx_get_num_cats_by_index(&Out, i) *
-				sizeof(int));
-	    fields[i] = Vect_cidx_get_field_number(&Out, i);
-	}
-
-	nlines = Vect_get_num_lines(&Out);
-	for (line = 1; line <= nlines; line++) {
-	    Vect_read_line(&Out, NULL, Cats, line);
-
-	    for (i = 0; i < Cats->n_cats; i++) {
-		int f, j;
-
-		for (j = 0; j < nfields; j++) {	/* find field */
-		    if (fields[j] == Cats->field[i]) {
-			f = j;
-			break;
-		    }
-		}
-		ocats[f][nocats[f]] = Cats->cat[i];
-		nocats[f]++;
-	    }
-	}
-
-	/* Copy tables */
-	G_message(_("Writing attributes..."));
-
-	/* Number of output tabs */
-	for (i = 0; i < Vect_get_num_dblinks(&In); i++) {
-	    int j, f = -1;
-
-	    IFi = Vect_get_dblink(&In, i);
-
-	    for (j = 0; j < nfields; j++) {	/* find field */
-		if (fields[j] == IFi->number) {
-		    f = j;
-		    break;
-		}
-	    }
-	    if (f >= 0 && nocats[f] > 0)
-		ntabs++;
-	}
-
-	if (ntabs > 1)
-	    ttype = GV_MTABLE;
-	else
-	    ttype = GV_1TABLE;
-
-	for (i = 0; i < nfields; i++) {
-	    int ret;
-
-	    if (fields[i] == 0)
-		continue;
-	    if (nocats[i] == 0)
-		continue;
-	    if (fields[i] == atoi(fieldopt->answer) && new_cat != -1)
-		continue;
-
-	    G_verbose_message(_("Layer %d"), fields[i]);
-
-	    /* Make a list of categories */
-	    IFi = Vect_get_field(&In, fields[i]);
-	    if (!IFi) {		/* no table */
-		G_verbose_message(_("No table"));
-		continue;
-	    }
-
-	    OFi =
-		Vect_default_field_info(&Out, IFi->number, IFi->name, ttype);
-
-	    ret =
-		db_copy_table_by_ints(IFi->driver, IFi->database, IFi->table,
-				      OFi->driver,
-				      Vect_subst_var(OFi->database, &Out),
-				      OFi->table, IFi->key, ocats[i],
-				      nocats[i]);
-
-	    if (ret == DB_FAILED) {
-		G_warning(_("Unable to copy table"));
-	    }
-	    else {
-		Vect_map_add_dblink(&Out, OFi->number, OFi->name, OFi->table,
-				    IFi->key, OFi->database, OFi->driver);
-	    }
-	    G_done_msg(" ");
-	}
+    if (!flag.t->answer && !is_ogr) {
+	copy_tabs(&In, field, new_cat, &Out);
     }
-
+    
     Vect_close(&In);
-
-
+    
     /* remove duplicate centroids */
     if (dissolve) {
 	int line, nlines, ltype, area;
@@ -497,14 +396,24 @@
 	Vect_build_partial(&Out, GV_BUILD_NONE);
 	Vect_build(&Out);
     }
-
+    
     Vect_close(&Out);
-
+    
     exit(EXIT_SUCCESS);
 }
 
+void add_cat(int x)
+{
+    G_debug(2, "add_cat %d", x);
 
+    if (cat_count >= cat_size) {
+	cat_size = (cat_size < 1000) ? 1000 : cat_size * 2;
+	cat_array = G_realloc(cat_array, cat_size * sizeof(int));
+    }
 
+    cat_array[cat_count++] = x;
+}
+
 int scan_cats(char *s, int *x, int *y)
 {
     char dummy[2];



More information about the grass-commit mailing list