|
@@ -22,7 +22,7 @@
|
|
|
#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
|
|
|
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];
|
|
|
|
|
|
if (dst[v] == 0)
|
|
|
- continue; /*ingore duplicates */
|
|
|
+ continue; /* ignore duplicates */
|
|
|
dst[v] = 0; /* make sure all from nodes are processed first */
|
|
|
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'.
|
|
|
|
|
|
Precisely, edge with id I is used if edges[abs(i)] == 1. List
|