浏览代码

v.net.distance: fix path calculation, add new flag to produce single line paths

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@67985 15284696-431f-4ddb-bdfa-cd5b030d7da7
Markus Metz 9 年之前
父节点
当前提交
9e22d9113b
共有 2 个文件被更改,包括 73 次插入24 次删除
  1. 66 20
      vector/v.net.distance/main.c
  2. 7 4
      vector/v.net.distance/v.net.distance.html

+ 66 - 20
vector/v.net.distance/main.c

@@ -29,25 +29,26 @@
 int main(int argc, char *argv[])
 int main(int argc, char *argv[])
 {
 {
     struct Map_info In, Out;
     struct Map_info In, Out;
-    static struct line_pnts *Points;
+    static struct line_pnts *Points, *PPoints;
     struct line_cats *Cats, *TCats;
     struct line_cats *Cats, *TCats;
+    struct ilist *slist;
     struct GModule *module;	/* GRASS module for parsing arguments */
     struct GModule *module;	/* GRASS module for parsing arguments */
     struct Option *map_in, *map_out;
     struct Option *map_in, *map_out;
     struct Option *catf_opt, *fieldf_opt, *wheref_opt;
     struct Option *catf_opt, *fieldf_opt, *wheref_opt;
     struct Option *catt_opt, *fieldt_opt, *wheret_opt, *typet_opt;
     struct Option *catt_opt, *fieldt_opt, *wheret_opt, *typet_opt;
     struct Option *afield_opt, *nfield_opt, *abcol, *afcol, *ncol, *atype_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;
     int atype, ttype;
     struct varray *varrayf, *varrayt;
     struct varray *varrayf, *varrayt;
     int flayer, tlayer;
     int flayer, tlayer;
     int afield, nfield;
     int afield, nfield;
     dglGraph_s *graph;
     dglGraph_s *graph;
     struct ilist *nodest;
     struct ilist *nodest;
-    int i, nnodes, nlines;
+    int i, j, nnodes, nlines;
     int *dst, *nodes_to_features;
     int *dst, *nodes_to_features;
     int from_nr;			/* 'from' features not reachable */
     int from_nr;			/* 'from' features not reachable */
-    dglInt32_t **prev;
+    dglInt32_t **nxt;
     struct line_cats **on_path;
     struct line_cats **on_path;
     char buf[2000];
     char buf[2000];
 
 
@@ -156,6 +157,17 @@ 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");
 
 
+    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 */
     /* options and flags parser */
     if (G_parser(argc, argv))
     if (G_parser(argc, argv))
@@ -165,8 +177,10 @@ int main(int argc, char *argv[])
     ttype = Vect_option_to_types(typet_opt);
     ttype = Vect_option_to_types(typet_opt);
 
 
     Points = Vect_new_line_struct();
     Points = Vect_new_line_struct();
+    PPoints = Vect_new_line_struct();
     Cats = Vect_new_cats_struct();
     Cats = Vect_new_cats_struct();
     TCats = Vect_new_cats_struct();
     TCats = Vect_new_cats_struct();
+    slist = G_new_ilist();
 
 
     Vect_check_input_output_name(map_in->answer, map_out->answer,
     Vect_check_input_output_name(map_in->answer, map_out->answer,
 				 G_FATAL_EXIT);
 				 G_FATAL_EXIT);
@@ -192,16 +206,22 @@ int main(int argc, char *argv[])
     else
     else
 	geo = 0;
 	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);
     nnodes = Vect_get_num_nodes(&In);
     nlines = Vect_get_num_lines(&In);
     nlines = Vect_get_num_lines(&In);
 
 
     dst = (int *)G_calloc(nnodes + 1, sizeof(int));
     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));
     nodes_to_features = (int *)G_calloc(nnodes + 1, sizeof(int));
     on_path =
     on_path =
 	(struct line_cats **)G_calloc(nlines + 1, sizeof(struct line_cats *));
 	(struct line_cats **)G_calloc(nlines + 1, sizeof(struct line_cats *));
-    if (!dst || !prev || !nodes_to_features || !on_path)
+    if (!dst || !nxt || !nodes_to_features || !on_path)
 	G_fatal_error(_("Out of memory"));
 	G_fatal_error(_("Out of memory"));
 
 
     for (i = 1; i <= nlines; i++)
     for (i = 1; i <= nlines; i++)
@@ -235,11 +255,14 @@ int main(int argc, char *argv[])
 	G_fatal_error(_("No 'to' features"));
 	G_fatal_error(_("No 'to' features"));
     
     
     if (0 != Vect_net_build_graph(&In, atype, afield, nfield, afcol->answer, abcol->answer,
     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));
         G_fatal_error(_("Unable to build graph for vector map <%s>"), Vect_get_full_name(&In));
 
 
     graph = Vect_net_get_graph(&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 */
     /* Create table */
     Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
     Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
@@ -303,11 +326,15 @@ int main(int argc, char *argv[])
 	    cost = dst[node] / (double)In.dgraph.cost_multip;
 	    cost = dst[node] / (double)In.dgraph.cost_multip;
 	    vertex = dglGetNode(graph, node);
 	    vertex = dglGetNode(graph, node);
 	    vertex_id = 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) {
+		if (segments)
+		    Vect_cat_set(on_path
+				 [abs(dglEdgeGet_Id(graph, nxt[vertex_id]))], 1,
+				 cat);
+		else
+		    G_ilist_add(slist, dglEdgeGet_Id(graph, nxt[vertex_id]));
+		vertex = dglEdgeGet_Tail(graph, nxt[vertex_id]);
 		vertex_id = dglNodeGet_Id(graph, vertex);
 		vertex_id = dglNodeGet_Id(graph, vertex);
 	    }
 	    }
 	    G_debug(3, "read line %d, vertex id %d", nodes_to_features[vertex_id], (int)vertex_id);
 	    G_debug(3, "read line %d, vertex id %d", nodes_to_features[vertex_id], (int)vertex_id);
@@ -318,22 +345,41 @@ int main(int argc, char *argv[])
 	    Vect_write_line(&Out, type, Points, Cats);
 	    Vect_write_line(&Out, type, Points, Cats);
 	    sprintf(buf, "insert into %s values (%d, %d, %f)", Fi->table, cat,
 	    sprintf(buf, "insert into %s values (%d, %d, %f)", Fi->table, cat,
 		    tcat, cost);
 		    tcat, cost);
-
 	    db_set_string(&sql, buf);
 	    db_set_string(&sql, buf);
 	    G_debug(3, "%s", db_get_string(&sql));
 	    G_debug(3, "%s", db_get_string(&sql));
 	    if (db_execute_immediate(driver, &sql) != DB_OK) {
 	    if (db_execute_immediate(driver, &sql) != DB_OK) {
 		G_fatal_error(_("Cannot insert new record: %s"),
 		G_fatal_error(_("Cannot insert new record: %s"),
 			      db_get_string(&sql));
 			      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_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 = 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_commit_transaction(driver);
     db_close_database_shutdown_driver(driver);
     db_close_database_shutdown_driver(driver);
@@ -348,7 +394,7 @@ int main(int argc, char *argv[])
     G_free(on_path);
     G_free(on_path);
     G_free(nodes_to_features);
     G_free(nodes_to_features);
     G_free(dst);
     G_free(dst);
-    G_free(prev);
+    G_free(nxt);
 
 
     if (from_nr)
     if (from_nr)
 	G_warning(n_("%d 'from' feature was not reachable",
 	G_warning(n_("%d 'from' feature was not reachable",

+ 7 - 4
vector/v.net.distance/v.net.distance.html

@@ -13,15 +13,18 @@ containing various information about the relation. More
 specifically, the table has three columns: <em>cat</em>, <em>tcat</em>
 specifically, the table has three columns: <em>cat</em>, <em>tcat</em>
 and <em>dist</em> storing category of each <em>from</em> 
 and <em>dist</em> storing category of each <em>from</em> 
 feature, category of the nearest <em>to</em> feature and the 
 feature, category of the nearest <em>to</em> feature and the 
-distance between them respectively. Furthemore, <b>output</b> map 
+distance between them respectively.
+<p>
+Furthemore, <b>output</b> map 
 contains the shorest path between each <em>cat</em>, <em>tcat</em> 
 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 
 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 
+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 
 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 
 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 
 more than one <em>from</em> feature. And so the shortest paths can 
 be easily obtained by querying lines with corresponding category 
 be easily obtained by querying lines with corresponding category 
-number.
+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.
 <br>
 <br>
 The costs of arcs in forward and backward direction are specified by 
 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_column</b> and <b>arc_backward_column</b> columns respectively. If
@@ -62,7 +65,7 @@ v.net input=streets_net1 points=hospitals output=streets_net2 \
 v.category in=streets_net2 op=report
 v.category in=streets_net2 op=report
 
 
 # shortest paths from schools (points in layer 2) to nearest hospitals (points in layer 3)
 # 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>
 </pre></div>
 
 
 <h3>Distance between point source of pollution and sample points along streams</h3>
 <h3>Distance between point source of pollution and sample points along streams</h3>