Selaa lähdekoodia

vectorlib: +NetA_distance_to_points()

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@67984 15284696-431f-4ddb-bdfa-cd5b030d7da7
Markus Metz 9 vuotta sitten
vanhempi
commit
918c7c2a4b
3 muutettua tiedostoa jossa 100 lisäystä ja 7 poistoa
  1. 2 0
      include/defs/neta.h
  2. 8 5
      lib/vector/Vlib/net_build.c
  3. 90 2
      lib/vector/neta/path.c

+ 2 - 0
include/defs/neta.h

@@ -40,6 +40,8 @@ int NetA_betweenness_closeness(dglGraph_s * graph, double *betweenness,
 /*path.c */
 /*path.c */
 int NetA_distance_from_points(dglGraph_s * graph, struct ilist *from, int *dst,
 int NetA_distance_from_points(dglGraph_s * graph, struct ilist *from, int *dst,
 			      dglInt32_t ** prev);
 			      dglInt32_t ** prev);
+int NetA_distance_to_points(dglGraph_s * graph, struct ilist *to, int *dst,
+			      dglInt32_t ** nxt);
 int NetA_find_path(dglGraph_s * graph, int from, int to, int *edges,
 int NetA_find_path(dglGraph_s * graph, int from, int to, int *edges,
 		   struct ilist *list);
 		   struct ilist *list);
 
 

+ 8 - 5
lib/vector/Vlib/net_build.c

@@ -84,7 +84,7 @@ Vect_net_ttb_build_graph(struct Map_info *Map,
     /*TODO attributes of turntable shoud be stored in one place */
     /*TODO attributes of turntable shoud be stored in one place */
     const char *tcols[] = { "cat", "ln_from", "ln_to", "cost", "isec", NULL
     const char *tcols[] = { "cat", "ln_from", "ln_to", "cost", "isec", NULL
     };
     };
-    dbCatValArray tvarrs[5] = { };
+    dbCatValArray tvarrs[5];
     int tctype[5] = { 0 };
     int tctype[5] = { 0 };
     int tucfield_idx;
     int tucfield_idx;
 
 
@@ -687,7 +687,7 @@ Vect_net_ttb_build_graph(struct Map_info *Map,
    \param abcol column with backward costs for arc (if NULL, back costs = forward costs), 
    \param abcol column with backward costs for arc (if NULL, back costs = forward costs), 
    \param ncol column with costs for nodes (if NULL, do not use node costs), 
    \param ncol column with costs for nodes (if NULL, do not use node costs), 
    \param geo use geodesic calculation for length (LL), 
    \param geo use geodesic calculation for length (LL), 
-   \param algorithm not used (in future code for algorithm)
+   \param version graph version to create (1, 2, 3)
 
 
    \return 0 on success, 1 on error
    \return 0 on success, 1 on error
  */
  */
@@ -698,7 +698,7 @@ Vect_net_build_graph(struct Map_info *Map,
 		     int nfield,
 		     int nfield,
 		     const char *afcol,
 		     const char *afcol,
 		     const char *abcol,
 		     const char *abcol,
-		     const char *ncol, int geo, int algorithm)
+		     const char *ncol, int geo, int version)
 {
 {
     /* TODO long function, split into smaller ones */
     /* TODO long function, split into smaller ones */
     int i, j, from, to, line, nlines, nnodes, ret, type, cat, skipped, cfound;
     int i, j, from, to, line, nlines, nnodes, ret, type, cat, skipped, cfound;
@@ -761,11 +761,14 @@ Vect_net_build_graph(struct Map_info *Map,
 	Map->dgraph.node_costs[i] = 0;
 	Map->dgraph.node_costs[i] = 0;
     }
     }
 
 
+    if (version < 1 || version > 3)
+	version = 1;
+
     if (ncol != NULL)
     if (ncol != NULL)
-	dglInitialize(gr, (dglByte_t) 1, sizeof(dglInt32_t), (dglInt32_t) 0,
+	dglInitialize(gr, (dglByte_t) version, sizeof(dglInt32_t), (dglInt32_t) 0,
 		      opaqueset);
 		      opaqueset);
     else
     else
-	dglInitialize(gr, (dglByte_t) 1, (dglInt32_t) 0, (dglInt32_t) 0,
+	dglInitialize(gr, (dglByte_t) version, (dglInt32_t) 0, (dglInt32_t) 0,
 		      opaqueset);
 		      opaqueset);
 
 
     if (gr == NULL)
     if (gr == NULL)

+ 90 - 2
lib/vector/neta/path.c

@@ -22,7 +22,7 @@
 #include <grass/neta.h>
 #include <grass/neta.h>
 
 
 /*!
 /*!
-   \brief Computes shortests paths to every node from nodes in "from".
+   \brief Computes shortest paths to every node from nodes in "from".
 
 
    Array "dst" contains the length of the path or -1 if the node is not
    Array "dst" contains the length of the path or -1 if the node is not
    reachable. Prev contains edges from predecessor along the shortest
    reachable. Prev contains edges from predecessor along the shortest
@@ -57,7 +57,7 @@ int NetA_distance_from_points(dglGraph_s *graph, struct ilist *from,
 	int v = from->value[i];
 	int v = from->value[i];
 
 
 	if (dst[v] == 0)
 	if (dst[v] == 0)
-	    continue;		/*ingore duplicates */
+	    continue;		/* ignore duplicates */
 	dst[v] = 0;		/* make sure all from nodes are processed first */
 	dst[v] = 0;		/* make sure all from nodes are processed first */
 	dglHeapData_u heap_data;
 	dglHeapData_u heap_data;
 
 
@@ -105,6 +105,94 @@ int NetA_distance_from_points(dglGraph_s *graph, struct ilist *from,
 }
 }
 
 
 /*!
 /*!
+   \brief Computes shortest paths from every node to nodes in "to".
+
+   Array "dst" contains the length of the path or -1 if the node is not
+   reachable. Nxt contains edges from successor along the shortest
+   path.
+
+   \param graph input graph
+   \param from list of 'from' positions
+   \param dst list of 'to' positions
+   \param[out] nxt list of edges from successor along the shortest path
+
+   \return 0 on success
+   \return -1 on failure
+ */
+int NetA_distance_to_points(dglGraph_s *graph, struct ilist *to,
+			      int *dst, dglInt32_t **nxt)
+{
+    int i, nnodes;
+    dglHeap_s heap;
+    dglEdgesetTraverser_s et;
+
+    nnodes = dglGet_NodeCount(graph);
+
+    /* initialize costs and edge list */
+    for (i = 1; i <= nnodes; i++) {
+	dst[i] = -1;
+	nxt[i] = NULL;
+    }
+
+    if (graph->Version < 2) {
+	G_warning("Directed graph must be version 2 or 3 for NetA_distance_to_points()");
+	return -1;
+    }
+
+    dglHeapInit(&heap);
+
+    for (i = 0; i < to->n_values; i++) {
+	int v = to->value[i];
+
+	if (dst[v] == 0)
+	    continue;		/* ignore duplicates */
+	dst[v] = 0;		/* make sure all to nodes are processed first */
+	dglHeapData_u heap_data;
+
+	heap_data.ul = v;
+	dglHeapInsertMin(&heap, 0, ' ', heap_data);
+    }
+    while (1) {
+	dglInt32_t v, dist;
+	dglHeapNode_s heap_node;
+	dglHeapData_u heap_data;
+
+	if (!dglHeapExtractMin(&heap, &heap_node))
+	    break;
+	v = heap_node.value.ul;
+	dist = heap_node.key;
+	if (dst[v] < dist)
+	    continue;
+
+	dglInt32_t *edge;
+
+	dglEdgeset_T_Initialize(&et, graph,
+				dglNodeGet_InEdgeset(graph,
+						      dglGetNode(graph, v)));
+
+	for (edge = dglEdgeset_T_First(&et); edge;
+	     edge = dglEdgeset_T_Next(&et)) {
+	    dglInt32_t *from = dglEdgeGet_Head(graph, edge);
+	    dglInt32_t from_id = dglNodeGet_Id(graph, from);
+	    dglInt32_t d = dglEdgeGet_Cost(graph, edge);
+
+	    if (dst[from_id] < 0 || dst[from_id] > dist + d) {
+		dst[from_id] = dist + d;
+		nxt[from_id] = edge;
+		heap_data.ul = from_id;
+		dglHeapInsertMin(&heap, dist + d, ' ', heap_data);
+	    }
+	}
+
+	dglEdgeset_T_Release(&et);
+    }
+
+    dglHeapFree(&heap, NULL);
+
+    return 0;
+}
+
+/*!
    \brief Find a path (minimum number of edges) from 'from' to 'to' using only edges in 'edges'.
    \brief Find a path (minimum number of edges) from 'from' to 'to' using only edges in 'edges'.
 
 
    Precisely, edge with id I is used if edges[abs(i)] == 1. List
    Precisely, edge with id I is used if edges[abs(i)] == 1. List