[GRASS-SVN] r68025 - in grass/branches/releasebranch_7_0/vector: v.net.components v.net.distance

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Mar 8 12:57:06 PST 2016


Author: mmetz
Date: 2016-03-08 12:57:06 -0800 (Tue, 08 Mar 2016)
New Revision: 68025

Modified:
   grass/branches/releasebranch_7_0/vector/v.net.components/main.c
   grass/branches/releasebranch_7_0/vector/v.net.components/v.net.components.html
   grass/branches/releasebranch_7_0/vector/v.net.distance/main.c
   grass/branches/releasebranch_7_0/vector/v.net.distance/v.net.distance.html
Log:
vector network analysis: backport bugfixes from trunk

Modified: grass/branches/releasebranch_7_0/vector/v.net.components/main.c
===================================================================
--- grass/branches/releasebranch_7_0/vector/v.net.components/main.c	2016-03-08 20:56:07 UTC (rev 68024)
+++ grass/branches/releasebranch_7_0/vector/v.net.components/main.c	2016-03-08 20:57:06 UTC (rev 68025)
@@ -4,6 +4,7 @@
  * MODULE:     v.net.components
  *
  * AUTHOR(S):  Daniel Bundala
+ *             Markus Metz
  *
  * PURPOSE:    Computes strongly and weakly connected components
  *
@@ -54,7 +55,7 @@
     int with_z;
     int afield, nfield, mask_type;
     dglGraph_s *graph;
-    int *component, nnodes, type, i, nlines, components, j, max_cat;
+    int *component, nnodes, type, i, nlines, components, max_cat;
     char buf[2000], *covered;
     char *desc;
 
@@ -158,7 +159,7 @@
     nfield = Vect_get_field_number(&In, nfield_opt->answer);
 
     if (0 != Vect_net_build_graph(&In, mask_type, afield, nfield, afcol->answer,
-                                  abcol->answer, ncol->answer, 0, 0))
+                                  abcol->answer, ncol->answer, 0, 2))
         G_fatal_error(_("Unable to build graph for vector map <%s>"), Vect_get_full_name(&In));
 
     graph = Vect_net_get_graph(&In);
@@ -198,21 +199,30 @@
 
     db_begin_transaction(driver);
 
-    if (method_opt->answer[0] == 'w')
+    if (method_opt->answer[0] == 'w') {
+	G_message(_("Computing weakly connected components..."));
 	components = NetA_weakly_connected_components(graph, component);
-    else
+    }
+    else {
+	G_message(_("Computing strongly connected components..."));
 	components = NetA_strongly_connected_components(graph, component);
+    }
 
     G_debug(3, "Components: %d", components);
 
+    G_message(_("Writing output..."));
+
     Vect_copy_head_data(&In, &Out);
     Vect_hist_copy(&In, &Out);
     Vect_hist_command(&Out);
 
     nlines = Vect_get_num_lines(&In);
+    max_cat = 1;
+    G_percent(0, nlines, 4);
     for (i = 1; i <= nlines; i++) {
 	int comp, cat;
 
+	G_percent(i, nlines, 4);
 	type = Vect_read_line(&In, Points, Cats, i);
 	if (!Vect_cat_get(Cats, afield, &cat))
 	    continue;
@@ -232,29 +242,23 @@
 
 	    /* Vect_get_line_nodes(&In, i, &node, NULL); */
 	    node = Vect_find_node(&In, Points->x[0], Points->y[0], Points->z[0], 0, 0);
+	    if (!node)
+		continue;
 	    comp = component[node];
 	    covered[node] = 1;
 	}
 	else
 	    continue;
+	
+	cat = max_cat++;
+	Vect_reset_cats(Cats);
+	Vect_cat_set(Cats, 1, cat);
 	Vect_write_line(&Out, type, Points, Cats);
 	insert_new_record(driver, Fi, &sql, cat, comp);
-	/*        for(j=0;j<Cats->n_cats;j++)
-	 * if(Cats->field[j] == layer)
-	 * insert_new_record(driver, Fi, &sql, Cats->cat[j], comp);
-	 */
-    };
+    }
+
     /*add points on nodes not covered by any point in the network */
-    /*find the maximum cat number */
     if (add_f->answer) {
-	max_cat = 0;
-	for (i = 1; i <= nlines; i++) {
-	    Vect_read_line(&In, NULL, Cats, i);
-	    for (j = 0; j < Cats->n_cats; j++)
-		if (Cats->cat[j] > max_cat)
-		    max_cat = Cats->cat[j];
-	}
-	max_cat++;
 	for (i = 1; i <= nnodes; i++)
 	    if (!covered[i]) {
 		Vect_reset_cats(Cats);
@@ -267,10 +271,12 @@
     db_commit_transaction(driver);
     db_close_database_shutdown_driver(driver);
 
+    Vect_close(&In);
+
     Vect_build(&Out);
-
-    Vect_close(&In);
     Vect_close(&Out);
 
+    G_done_msg(_("Found %d components."), components);
+
     exit(EXIT_SUCCESS);
 }

Modified: grass/branches/releasebranch_7_0/vector/v.net.components/v.net.components.html
===================================================================
--- grass/branches/releasebranch_7_0/vector/v.net.components/v.net.components.html	2016-03-08 20:56:07 UTC (rev 68024)
+++ grass/branches/releasebranch_7_0/vector/v.net.components/v.net.components.html	2016-03-08 20:57:06 UTC (rev 68025)
@@ -4,22 +4,28 @@
 components in a network.
 
 <h2>NOTES</h2>
-Two nodes, <em>u</em> and <em>v</em> are in the same strongly 
-connected component if there are directed paths from <em>u</em> to 
-<em>v</em> and from <em>v</em> to <em>u</em>. The nodes are in the 
-same weakly connected component if, ignoring orientation of the 
-edges, there is a path between them.
-<br>
-
+Two nodes, <em>u</em> and <em>v</em> are in the same strongly connected 
+component if there are directed paths from <em>u</em> to <em>v</em> and 
+from <em>v</em> to <em>u</em>. The nodes are in the same weakly 
+connected component if, ignoring edge directions, there is a path 
+between them.
+<p>
 The type of components is specified by <b>method</b> parameter. 
-<em>v.net.components</em> creates a table and links it to the given <b>layer</b>.
-This table contains only two integer columns: <em>cat</em> and <em>comp
-</em>. If a point or both endpoints of a line belong to the same 
-component then the point/line is written to the output map and 
+<em>v.net.components</em> creates a table and links it to layer 1. This 
+table contains only two integer columns: <em>cat</em> and 
+<em>comp</em>. If a point or both endpoints of a line belong to the 
+same component then the point/line is written to the output map and 
 appropriate information is stored in the table. If <b>-a</b> flag is 
-set then new points are added on the nodes without points. These 
-points have category numbers larger than any category used in the 
-input map.
+set then new points are added on the nodes without points. These points 
+have category numbers larger than any category used in the input map.
+<p>
+One-way roads can be defined by assigning a cost of -1 to the 
+appropriate cost column (<b>arc_column</b> or 
+<b>arc_backward_column</b>. This affects only strongly connected 
+components. Network nodes can be closed by assigning a cost of -1 to 
+the node cost column. All nodes with a cost < 0 can not be traversed 
+and are end points, while all nodes with a cost ≥ 0 can be traversed. 
+This affects both weakly and strongly connected components.
 
 <h2>EXAMPLES</h2>
 
@@ -39,6 +45,7 @@
 <h2>AUTHORS</h2>
 
 Daniel Bundala, Google Summer of Code 2009, Student<br>
-Wolf Bergenheim, Mentor
+Wolf Bergenheim, Mentor<br>
+Markus Metz
 
 <p><i>Last changed: $Date$</i>

Modified: grass/branches/releasebranch_7_0/vector/v.net.distance/main.c
===================================================================
--- grass/branches/releasebranch_7_0/vector/v.net.distance/main.c	2016-03-08 20:56:07 UTC (rev 68024)
+++ grass/branches/releasebranch_7_0/vector/v.net.distance/main.c	2016-03-08 20:57:06 UTC (rev 68025)
@@ -29,26 +29,28 @@
 int main(int argc, char *argv[])
 {
     struct Map_info In, Out;
-    static struct line_pnts *Points;
+    static struct line_pnts *Points, *PPoints;
     struct line_cats *Cats, *TCats;
+    struct ilist *slist;
     struct GModule *module;	/* GRASS module for parsing arguments */
     struct Option *map_in, *map_out;
     struct Option *catf_opt, *fieldf_opt, *wheref_opt;
     struct Option *catt_opt, *fieldt_opt, *wheret_opt, *typet_opt;
     struct Option *afield_opt, *nfield_opt, *abcol, *afcol, *ncol, *atype_opt;
-    struct Flag *geo_f;
-    int with_z, geo;
+    struct Flag *geo_f, *segments_f;
+    int with_z, geo, segments;
     int atype, ttype;
     struct varray *varrayf, *varrayt;
     int flayer, tlayer;
     int afield, nfield;
     dglGraph_s *graph;
     struct ilist *nodest;
-    int i, nnodes, nlines;
+    int i, j, nnodes, nlines;
     int *dst, *nodes_to_features;
     int from_nr;			/* 'from' features not reachable */
-    dglInt32_t **prev;
+    dglInt32_t **nxt;
     struct line_cats **on_path;
+    char *segdir;
     char buf[2000];
 
     /* Attribute table */
@@ -156,6 +158,17 @@
     geo_f->description =
 	_("Use geodesic calculation for longitude-latitude locations");
 
+    segments_f = G_define_flag();
+#if 0
+    /* use this to sync with v.net.path */
+    segments_f->key = 's';
+    segments_f->description = _("Write output as original input segments, "
+				"not each path as one line.");
+#else
+    segments_f->key = 'l';
+    segments_f->description = _("Write each output path as one line, "
+				"not as original input segments.");
+#endif
 
     /* options and flags parser */
     if (G_parser(argc, argv))
@@ -165,8 +178,10 @@
     ttype = Vect_option_to_types(typet_opt);
 
     Points = Vect_new_line_struct();
+    PPoints = Vect_new_line_struct();
     Cats = Vect_new_cats_struct();
     TCats = Vect_new_cats_struct();
+    slist = G_new_ilist();
 
     Vect_check_input_output_name(map_in->answer, map_out->answer,
 				 G_FATAL_EXIT);
@@ -192,20 +207,30 @@
     else
 	geo = 0;
 
+#if 0
+    /* use this to sync with v.net.path */
+    segments = segments_f->answer;
+#else
+    segments = !segments_f->answer;
+#endif
 
     nnodes = Vect_get_num_nodes(&In);
     nlines = Vect_get_num_lines(&In);
 
     dst = (int *)G_calloc(nnodes + 1, sizeof(int));
-    prev = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
+    nxt = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
     nodes_to_features = (int *)G_calloc(nnodes + 1, sizeof(int));
     on_path =
 	(struct line_cats **)G_calloc(nlines + 1, sizeof(struct line_cats *));
-    if (!dst || !prev || !nodes_to_features || !on_path)
+    segdir = (char *)G_calloc(nlines + 1, sizeof(char));
+
+    if (!dst || !nxt || !nodes_to_features || !on_path || !segdir)
 	G_fatal_error(_("Out of memory"));
 
-    for (i = 1; i <= nlines; i++)
+    for (i = 1; i <= nlines; i++) {
 	on_path[i] = Vect_new_cats_struct();
+	segdir[i] = 0;
+    }
 
     /*initialise varrays and nodes list appropriatelly */
     afield = Vect_get_field_number(&In, afield_opt->answer);
@@ -235,12 +260,15 @@
 	G_fatal_error(_("No 'to' features"));
     
     if (0 != Vect_net_build_graph(&In, atype, afield, nfield, afcol->answer, abcol->answer,
-                                   ncol->answer, geo, 0))
+                                   ncol->answer, geo, 2))
         G_fatal_error(_("Unable to build graph for vector map <%s>"), Vect_get_full_name(&In));
 
     graph = Vect_net_get_graph(&In);
-    NetA_distance_from_points(graph, nodest, dst, prev);
 
+    G_message(_("Distances to 'to' features ..."));
+
+    NetA_distance_to_points(graph, nodest, dst, nxt);
+
     /* Create table */
     Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
     Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
@@ -276,6 +304,7 @@
     Vect_hist_copy(&In, &Out);
     Vect_hist_command(&Out);
 
+    G_message(_("Tracing paths from 'from' features ..."));
     from_nr = 0;
     for (i = 1; i <= nlines; i++) {
 	if (varrayf->c[i]) {
@@ -303,11 +332,21 @@
 	    cost = dst[node] / (double)In.dgraph.cost_multip;
 	    vertex = dglGetNode(graph, node);
 	    vertex_id = node;
-	    while (prev[vertex_id] != NULL) {
-		Vect_cat_set(on_path
-			     [abs(dglEdgeGet_Id(graph, prev[vertex_id]))], 1,
-			     cat);
-		vertex = dglEdgeGet_Head(graph, prev[vertex_id]);
+	    slist->n_values = 0;
+	    while (nxt[vertex_id] != NULL) {
+		int edge_id;
+
+		edge_id = (int) dglEdgeGet_Id(graph, nxt[vertex_id]);
+		if (segments) {
+		    Vect_cat_set(on_path[abs(edge_id)], 1, cat);
+		    if (edge_id < 0) {
+			segdir[abs(edge_id)] = 1;
+		    }
+		}
+		else
+		    G_ilist_add(slist, edge_id);
+
+		vertex = dglEdgeGet_Tail(graph, nxt[vertex_id]);
 		vertex_id = dglNodeGet_Id(graph, vertex);
 	    }
 	    G_debug(3, "read line %d, vertex id %d", nodes_to_features[vertex_id], (int)vertex_id);
@@ -318,22 +357,51 @@
 	    Vect_write_line(&Out, type, Points, Cats);
 	    sprintf(buf, "insert into %s values (%d, %d, %f)", Fi->table, cat,
 		    tcat, cost);
-
 	    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));
 	    };
+
+	    if (!segments) {
+		Vect_reset_line(PPoints);
+		for (j = 0; j < slist->n_values; j++) {
+		    Vect_read_line(&In, Points, NULL, abs(slist->value[j]));
+		    if (slist->value[j] > 0)
+			Vect_append_points(PPoints, Points,
+					   GV_FORWARD);
+		    else
+			Vect_append_points(PPoints, Points,
+					   GV_BACKWARD);
+		    PPoints->n_points--;
+		}
+		PPoints->n_points++;
+		Vect_reset_cats(Cats);
+		Vect_cat_set(Cats, 1, cat);
+		Vect_write_line(&Out, GV_LINE, PPoints, Cats);
+	    }
+
 	}
     }
 
-    for (i = 1; i <= nlines; i++)
-	if (on_path[i]->n_cats > 0) {
-	    int type = Vect_read_line(&In, Points, NULL, i);
+    if (segments) {
+	for (i = 1; i <= nlines; i++) {
+	    if (on_path[i]->n_cats > 0) {
+		int type; 
+		
+		if (segdir[i]) {
+		    type = Vect_read_line(&In, PPoints, NULL, i);
+		    Vect_reset_line(Points);
+		    Vect_append_points(Points, PPoints, GV_BACKWARD);
+		}
+		else
+		    type = Vect_read_line(&In, Points, NULL, i);
 
-	    Vect_write_line(&Out, type, Points, on_path[i]);
+		Vect_write_line(&Out, type, Points, on_path[i]);
+	    }
 	}
+    }
 
     db_commit_transaction(driver);
     db_close_database_shutdown_driver(driver);
@@ -348,7 +416,8 @@
     G_free(on_path);
     G_free(nodes_to_features);
     G_free(dst);
-    G_free(prev);
+    G_free(nxt);
+    G_free(segdir);
 
     if (from_nr)
 	G_warning(n_("%d 'from' feature was not reachable",

Modified: grass/branches/releasebranch_7_0/vector/v.net.distance/v.net.distance.html
===================================================================
--- grass/branches/releasebranch_7_0/vector/v.net.distance/v.net.distance.html	2016-03-08 20:56:07 UTC (rev 68024)
+++ grass/branches/releasebranch_7_0/vector/v.net.distance/v.net.distance.html	2016-03-08 20:57:06 UTC (rev 68025)
@@ -13,19 +13,22 @@
 specifically, the table has three columns: <em>cat</em>, <em>tcat</em>
 and <em>dist</em> storing category of each <em>from</em> 
 feature, category of the nearest <em>to</em> feature and the 
-distance between them respectively. Furthemore, <b>output</b> map 
-contains the shorest path between each <em>cat</em>, <em>tcat</em> 
-pair. Each path consist of several lines. If a line is on the 
-shorest path from a point then the category of this point is 
-assigned to the line. Note that every line may contain more than one 
-category value since a single line may be on the shortest path for 
-more than one <em>from</em> feature. And so the shortest paths can 
-be easily obtained by querying lines with corresponding category 
-number.
-<br>
+distance between them respectively.
+<p>
+Furthemore, the <b>output</b> map contains the shortest path between 
+each <em>cat</em>, <em>tcat</em> pair. Each path consists of several 
+lines. If a line is on the shortest path from a point then the category 
+of this point is assigned to the line. Note that every line may contain 
+more than one category value since a single line may be on the shortest 
+path for more than one <em>from</em> feature. And so the shortest paths 
+can be easily obtained by querying lines with corresponding category 
+number. Alternatively, unique paths can be created with the <em>-l</em> 
+flag where each path will be a separate single line in the output.
+<p>
 The costs of arcs in forward and backward direction are specified by 
-<b>arc_column</b> and <b>arc_backward_column</b> columns respectively. If
-<b>arc_backward_column</b> is not given, the same cost is used in both directions.  
+<b>arc_column</b> and <b>arc_backward_column</b> columns respectively. 
+If <b>arc_backward_column</b> is not given, the same cost is used in 
+both directions.  
 <p>
 <em>v.net.distance</em> will not work if you are trying to find the 
 nearest neighbors within a group of nodes, i.e. where <em>to</em> 
@@ -62,7 +65,7 @@
 v.category in=streets_net2 op=report
 
 # shortest paths from schools (points in layer 2) to nearest hospitals (points in layer 3)
-v.net.distance in=streets_net2 out=schools_to_hospitals flayer=2 turn_layer=3
+v.net.distance in=streets_net2 out=schools_to_hospitals flayer=2 to_layer=3
 </pre></div>
 
 <h3>Distance between point source of pollution and sample points along streams</h3>



More information about the grass-commit mailing list