Browse Source

v.net.alloc: add flag for unique and original categories (https://trac.osgeo.org/grass/ticket/517)

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@71194 15284696-431f-4ddb-bdfa-cd5b030d7da7
Markus Metz 8 years ago
parent
commit
0f5060d7f8
3 changed files with 277 additions and 12 deletions
  1. 2 2
      vector/v.net.alloc/Makefile
  2. 266 10
      vector/v.net.alloc/main.c
  3. 9 0
      vector/v.net.alloc/v.net.alloc.html

+ 2 - 2
vector/v.net.alloc/Makefile

@@ -3,8 +3,8 @@ MODULE_TOPDIR = ../..
 
 
 PGM = v.net.alloc
 PGM = v.net.alloc
 
 
-LIBES = $(VECTORLIB) $(GISLIB) $(GRAPHLIB)
-DEPENDENCIES = $(VECTORDEP) $(GISDEP)
+LIBES = $(VECTORLIB) $(DBMILIB) $(GISLIB) $(GRAPHLIB)
+DEPENDENCIES = $(VECTORDEP) $(DBMIDEP) $(GISDEP)
 EXTRA_INC = $(VECT_INC)
 EXTRA_INC = $(VECT_INC)
 EXTRA_CFLAGS = $(VECT_CFLAGS)
 EXTRA_CFLAGS = $(VECT_CFLAGS)
 
 

+ 266 - 10
vector/v.net.alloc/main.c

@@ -37,18 +37,25 @@ int main(int argc, char **argv)
     struct Option *map, *output, *method_opt;
     struct Option *map, *output, *method_opt;
     struct Option *afield_opt, *nfield_opt, *afcol, *abcol, *ncol, *type_opt,
     struct Option *afield_opt, *nfield_opt, *afcol, *abcol, *ncol, *type_opt,
 	*term_opt, *tfield_opt, *tucfield_opt;
 	*term_opt, *tfield_opt, *tucfield_opt;
-    struct Flag *geo_f, *turntable_f;
+    struct Flag *geo_f, *turntable_f, *ucat_f;
     struct GModule *module;
     struct GModule *module;
     struct Map_info Map, Out;
     struct Map_info Map, Out;
     struct cat_list *catlist;
     struct cat_list *catlist;
     CENTER *Centers = NULL;
     CENTER *Centers = NULL;
     int acenters = 0, ncenters = 0;
     int acenters = 0, ncenters = 0;
     NODE *Nodes;
     NODE *Nodes;
-    struct line_cats *Cats;
+    struct line_cats *Cats, *ICats, *OCats;
     struct line_pnts *Points, *SPoints;
     struct line_pnts *Points, *SPoints;
     int graph_version;
     int graph_version;
     int from_centers;
     int from_centers;
 
 
+    /* Attribute table */
+    int unique_cats, ucat, ocat, n;
+    char buf[2000];
+    dbString sql;
+    dbDriver *driver;
+    struct field_info *Fi;
+
     /* initialize GIS environment */
     /* initialize GIS environment */
     G_gisinit(argv[0]);		/* reads grass env, stores program name to G_program_name() */
     G_gisinit(argv[0]);		/* reads grass env, stores program name to G_program_name() */
 
 
@@ -150,12 +157,20 @@ int main(int argc, char **argv)
     geo_f->description =
     geo_f->description =
 	_("Use geodesic calculation for longitude-latitude locations");
 	_("Use geodesic calculation for longitude-latitude locations");
 
 
+    ucat_f = G_define_flag();
+    ucat_f->key = 'u';
+    ucat_f->label =
+	_("Create unique categories and attribute table");
+    ucat_f->description =
+	_("Default: same category like nearest center");
+
     if (G_parser(argc, argv))
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 	exit(EXIT_FAILURE);
 
 
     Vect_check_input_output_name(map->answer, output->answer, G_FATAL_EXIT);
     Vect_check_input_output_name(map->answer, output->answer, G_FATAL_EXIT);
 
 
     Cats = Vect_new_cats_struct();
     Cats = Vect_new_cats_struct();
+    OCats = Vect_new_cats_struct();
     Points = Vect_new_line_struct();
     Points = Vect_new_line_struct();
     SPoints = Vect_new_line_struct();
     SPoints = Vect_new_line_struct();
 
 
@@ -164,6 +179,8 @@ int main(int argc, char **argv)
     catlist = Vect_new_cat_list();
     catlist = Vect_new_cat_list();
     Vect_str_to_cat_list(term_opt->answer, catlist);
     Vect_str_to_cat_list(term_opt->answer, catlist);
 
 
+    unique_cats = ucat_f->answer;
+
     if (geo_f->answer)
     if (geo_f->answer)
 	geo = 1;
 	geo = 1;
     else
     else
@@ -274,13 +291,63 @@ int main(int argc, char **argv)
 
 
     Vect_hist_command(&Out);
     Vect_hist_command(&Out);
 
 
+    Fi = NULL;
+    driver = NULL;
+    if (unique_cats) {
+	/* create attribute table:
+	 * cat: new category
+	 * ocat: original category in afield
+	 * centre: nearest centre
+	 */
+	Fi = Vect_default_field_info(&Out, 1, NULL, GV_MTABLE);
+	Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
+			    Fi->driver);
+
+	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);
+	db_set_error_handler_driver(driver);
+
+	sprintf(buf,
+		"create table %s ( %s integer, ocat integer, center integer )",
+		Fi->table, GV_KEY_COLUMN);
+
+	db_init_string(&sql);
+	db_set_string(&sql, buf);
+	G_debug(2, "%s", db_get_string(&sql));
+
+	if (db_execute_immediate(driver, &sql) != DB_OK) {
+	    G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql));
+	}
+
+	if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK)
+	    G_warning(_("Cannot create index"));
+
+	if (db_grant_on_table
+	    (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK)
+	    G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table);
+
+	db_begin_transaction(driver);
+    }
+
     nlines = Vect_get_num_lines(&Map);
     nlines = Vect_get_num_lines(&Map);
+    ucat = 1;
     for (line = 1; line <= nlines; line++) {
     for (line = 1; line <= nlines; line++) {
-	ltype = Vect_read_line(&Map, Points, NULL, line);
+	ltype = Vect_read_line(&Map, Points, ICats, line);
 	if (!(ltype & type)) {
 	if (!(ltype & type)) {
 	    continue;
 	    continue;
 	}
 	}
 
 
+	if (unique_cats) {
+	    Vect_reset_cats(OCats);
+	    for (n = 0; n < ICats->n_cats; n++) {
+		if (ICats->field[n] == afield) {
+		    Vect_cat_set(OCats, 2, ICats->cat[n]);
+		}
+	    }
+	}
+
 	if (turntable_f->answer) {
 	if (turntable_f->answer) {
 	    center1 = Nodes[line * 2].center;
 	    center1 = Nodes[line * 2].center;
 	    center2 = Nodes[line * 2 + 1].center;
 	    center2 = Nodes[line * 2 + 1].center;
@@ -331,7 +398,30 @@ int main(int argc, char **argv)
 		    cat = Centers[center1].cat;	/* line reachable */
 		    cat = Centers[center1].cat;	/* line reachable */
 		else
 		else
 		    cat = Centers[center2].cat;
 		    cat = Centers[center2].cat;
-		Vect_cat_set(Cats, 1, cat);
+
+		if (unique_cats) {
+		    Vect_cat_set(Cats, 1, ucat);
+		    for (n = 0; n < OCats->n_cats; n++) {
+			Vect_cat_set(Cats, 2, OCats->cat[n]);
+		    }
+		    ocat = -1;
+		    Vect_cat_get(ICats, afield, &ocat);
+
+		    sprintf(buf,
+			    "insert into %s values ( %d, %d, %d')",
+			    Fi->table, ucat, ocat, cat);
+		    db_set_string(&sql, buf);
+		    G_debug(3, "%s", db_get_string(&sql));
+
+		    if (db_execute_immediate(driver, &sql) != DB_OK) {
+			G_fatal_error(_("Cannot insert new record: %s"),
+				      db_get_string(&sql));
+		    }
+		    ucat++;
+		}
+		else
+		    Vect_cat_set(Cats, 1, cat);
+
 		Vect_write_line(&Out, ltype, Points, Cats);
 		Vect_write_line(&Out, ltype, Points, Cats);
 	    }
 	    }
 	    else {		/* each node in different area */
 	    else {		/* each node in different area */
@@ -340,7 +430,30 @@ int main(int argc, char **argv)
 		    G_debug(3,
 		    G_debug(3,
 			    "    -> arc is not reachable from 1. node -> alloc to 2. node");
 			    "    -> arc is not reachable from 1. node -> alloc to 2. node");
 		    cat = Centers[center2].cat;
 		    cat = Centers[center2].cat;
-		    Vect_cat_set(Cats, 1, cat);
+
+		    if (unique_cats) {
+			Vect_cat_set(Cats, 1, ucat);
+			for (n = 0; n < OCats->n_cats; n++) {
+			    Vect_cat_set(Cats, 2, OCats->cat[n]);
+			}
+			ocat = -1;
+			Vect_cat_get(ICats, afield, &ocat);
+
+			sprintf(buf,
+				"insert into %s values ( %d, %d, %d')",
+				Fi->table, ucat, ocat, cat);
+			db_set_string(&sql, buf);
+			G_debug(3, "%s", db_get_string(&sql));
+
+			if (db_execute_immediate(driver, &sql) != DB_OK) {
+			    G_fatal_error(_("Cannot insert new record: %s"),
+					  db_get_string(&sql));
+			}
+			ucat++;
+		    }
+		    else
+			Vect_cat_set(Cats, 1, cat);
+
 		    Vect_write_line(&Out, ltype, Points, Cats);
 		    Vect_write_line(&Out, ltype, Points, Cats);
 		    continue;
 		    continue;
 		}
 		}
@@ -348,7 +461,30 @@ int main(int argc, char **argv)
 		    G_debug(3,
 		    G_debug(3,
 			    "    -> arc is not reachable from 2. node -> alloc to 1. node");
 			    "    -> arc is not reachable from 2. node -> alloc to 1. node");
 		    cat = Centers[center1].cat;
 		    cat = Centers[center1].cat;
-		    Vect_cat_set(Cats, 1, cat);
+
+		    if (unique_cats) {
+			Vect_cat_set(Cats, 1, ucat);
+			for (n = 0; n < OCats->n_cats; n++) {
+			    Vect_cat_set(Cats, 2, OCats->cat[n]);
+			}
+			ocat = -1;
+			Vect_cat_get(ICats, afield, &ocat);
+
+			sprintf(buf,
+				"insert into %s values ( %d, %d, %d')",
+				Fi->table, ucat, ocat, cat);
+			db_set_string(&sql, buf);
+			G_debug(3, "%s", db_get_string(&sql));
+
+			if (db_execute_immediate(driver, &sql) != DB_OK) {
+			    G_fatal_error(_("Cannot insert new record: %s"),
+					  db_get_string(&sql));
+			}
+			ucat++;
+		    }
+		    else
+			Vect_cat_set(Cats, 1, cat);
+
 		    Vect_write_line(&Out, ltype, Points, Cats);
 		    Vect_write_line(&Out, ltype, Points, Cats);
 		    continue;
 		    continue;
 		}
 		}
@@ -362,12 +498,59 @@ int main(int argc, char **argv)
 		 * Note this check also possibility of (e1cost + e2cost) = 0 */
 		 * Note this check also possibility of (e1cost + e2cost) = 0 */
 		if (s1cost + e1cost <= s2cost) {	/* whole arc reachable from node1 */
 		if (s1cost + e1cost <= s2cost) {	/* whole arc reachable from node1 */
 		    cat = Centers[center1].cat;
 		    cat = Centers[center1].cat;
-		    Vect_cat_set(Cats, 1, cat);
+
+		    Vect_reset_cats(Cats);
+		    if (unique_cats) {
+			Vect_cat_set(Cats, 1, ucat);
+			for (n = 0; n < OCats->n_cats; n++) {
+			    Vect_cat_set(Cats, 2, OCats->cat[n]);
+			}
+			ocat = -1;
+			Vect_cat_get(ICats, afield, &ocat);
+
+			sprintf(buf,
+				"insert into %s values ( %d, %d, %d')",
+				Fi->table, ucat, ocat, cat);
+			db_set_string(&sql, buf);
+			G_debug(3, "%s", db_get_string(&sql));
+
+			if (db_execute_immediate(driver, &sql) != DB_OK) {
+			    G_fatal_error(_("Cannot insert new record: %s"),
+					  db_get_string(&sql));
+			}
+			ucat++;
+		    }
+		    else
+			Vect_cat_set(Cats, 1, cat);
+
 		    Vect_write_line(&Out, ltype, Points, Cats);
 		    Vect_write_line(&Out, ltype, Points, Cats);
 		}
 		}
 		else if (s2cost + e2cost <= s1cost) {	/* whole arc reachable from node2 */
 		else if (s2cost + e2cost <= s1cost) {	/* whole arc reachable from node2 */
 		    cat = Centers[center2].cat;
 		    cat = Centers[center2].cat;
-		    Vect_cat_set(Cats, 1, cat);
+
+		    if (unique_cats) {
+			Vect_cat_set(Cats, 1, ucat);
+			for (n = 0; n < OCats->n_cats; n++) {
+			    Vect_cat_set(Cats, 2, OCats->cat[n]);
+			}
+			ocat = -1;
+			Vect_cat_get(ICats, afield, &ocat);
+
+			sprintf(buf,
+				"insert into %s values ( %d, %d, %d')",
+				Fi->table, ucat, ocat, cat);
+			db_set_string(&sql, buf);
+			G_debug(3, "%s", db_get_string(&sql));
+
+			if (db_execute_immediate(driver, &sql) != DB_OK) {
+			    G_fatal_error(_("Cannot insert new record: %s"),
+					  db_get_string(&sql));
+			}
+			ucat++;
+		    }
+		    else
+			Vect_cat_set(Cats, 1, cat);
+
 		    Vect_write_line(&Out, ltype, Points, Cats);
 		    Vect_write_line(&Out, ltype, Points, Cats);
 		}
 		}
 		else {		/* split */
 		else {		/* split */
@@ -395,7 +578,30 @@ int main(int argc, char **argv)
 		    }
 		    }
 		    else {
 		    else {
 			cat = Centers[center1].cat;
 			cat = Centers[center1].cat;
-			Vect_cat_set(Cats, 1, cat);
+
+			if (unique_cats) {
+			    Vect_cat_set(Cats, 1, ucat);
+			    for (n = 0; n < OCats->n_cats; n++) {
+				Vect_cat_set(Cats, 2, OCats->cat[n]);
+			    }
+			    ocat = -1;
+			    Vect_cat_get(ICats, afield, &ocat);
+
+			    sprintf(buf,
+				    "insert into %s values ( %d, %d, %d')",
+				    Fi->table, ucat, ocat, cat);
+			    db_set_string(&sql, buf);
+			    G_debug(3, "%s", db_get_string(&sql));
+
+			    if (db_execute_immediate(driver, &sql) != DB_OK) {
+				G_fatal_error(_("Cannot insert new record: %s"),
+					      db_get_string(&sql));
+			    }
+			    ucat++;
+			}
+			else
+			    Vect_cat_set(Cats, 1, cat);
+
 			Vect_write_line(&Out, ltype, SPoints, Cats);
 			Vect_write_line(&Out, ltype, SPoints, Cats);
 		    }
 		    }
 
 
@@ -408,7 +614,30 @@ int main(int argc, char **argv)
 		    else {
 		    else {
 			Vect_reset_cats(Cats);
 			Vect_reset_cats(Cats);
 			cat = Centers[center2].cat;
 			cat = Centers[center2].cat;
-			Vect_cat_set(Cats, 1, cat);
+
+			if (unique_cats) {
+			    Vect_cat_set(Cats, 1, ucat);
+			    for (n = 0; n < OCats->n_cats; n++) {
+				Vect_cat_set(Cats, 2, OCats->cat[n]);
+			    }
+			    ocat = -1;
+			    Vect_cat_get(ICats, afield, &ocat);
+
+			    sprintf(buf,
+				    "insert into %s values ( %d, %d, %d')",
+				    Fi->table, ucat, ocat, cat);
+			    db_set_string(&sql, buf);
+			    G_debug(3, "%s", db_get_string(&sql));
+
+			    if (db_execute_immediate(driver, &sql) != DB_OK) {
+				G_fatal_error(_("Cannot insert new record: %s"),
+					      db_get_string(&sql));
+			    }
+			    ucat++;
+			}
+			else
+			    Vect_cat_set(Cats, 1, cat);
+
 			Vect_write_line(&Out, ltype, SPoints, Cats);
 			Vect_write_line(&Out, ltype, SPoints, Cats);
 		    }
 		    }
 		}
 		}
@@ -417,10 +646,37 @@ int main(int argc, char **argv)
 	else {
 	else {
 	    /* arc is not reachable */
 	    /* arc is not reachable */
 	    G_debug(3, "  -> arc is not reachable");
 	    G_debug(3, "  -> arc is not reachable");
+	    if (unique_cats) {
+		Vect_cat_set(Cats, 1, ucat);
+		for (n = 0; n < OCats->n_cats; n++) {
+		    Vect_cat_set(Cats, 2, OCats->cat[n]);
+		}
+		ocat = -1;
+		Vect_cat_get(ICats, afield, &ocat);
+
+		sprintf(buf,
+			"insert into %s values ( %d, %d, %d)",
+			Fi->table, ucat, ocat, -1);
+		db_set_string(&sql, buf);
+		G_debug(3, "%s", db_get_string(&sql));
+
+		if (db_execute_immediate(driver, &sql) != DB_OK) {
+		    G_fatal_error(_("Cannot insert new record: %s"),
+				  db_get_string(&sql));
+		}
+		ucat++;
+	    }
 	    Vect_write_line(&Out, ltype, Points, Cats);
 	    Vect_write_line(&Out, ltype, Points, Cats);
 	}
 	}
     }
     }
 
 
+    if (unique_cats) {
+	db_commit_transaction(driver);
+	db_close_database_shutdown_driver(driver);
+
+	Vect_copy_table(&Map, &Out, afield, 2, NULL, GV_MTABLE);
+    }
+
     Vect_build(&Out);
     Vect_build(&Out);
 
 
     /* Free, ... */
     /* Free, ... */

+ 9 - 0
vector/v.net.alloc/v.net.alloc.html

@@ -23,6 +23,15 @@ The nearest center can be determined using either costs from the
 nearest center or costs to the nearest center with option 
 nearest center or costs to the nearest center with option 
 <b>method</b>. See example below.
 <b>method</b>. See example below.
 <p>
 <p>
+By default, the category value of the nearest center is used as 
+category value for output lines. With the <b>-u</b> flag, output lines 
+become unique categories and an attribute table is created with the 
+fields <em>cat, ocat, center</em>. The <em>ocat</em> field holds the 
+original line category in <b>arc_layer</b> and the <em>center</em> 
+field holds the center category in <b>node_layer</b>. Additionally, 
+original line categories are copied from the input <b>arc_layer</b> to 
+layer 2 in the output, together with any attribute table.
+<p>
 Application of flag <b>-t</b> enables a turntable support. 
 Application of flag <b>-t</b> enables a turntable support. 
 This flag requires additional parameters <b>turn_layer</b> and <b>turn_cat_layer</b> 
 This flag requires additional parameters <b>turn_layer</b> and <b>turn_cat_layer</b> 
 that are otherwise ignored.
 that are otherwise ignored.