GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
vector/neta/path.c
Go to the documentation of this file.
1/*!
2 \file vector/neta/path.c
3
4 \brief Network Analysis library - shortest path
5
6 Shortest paths from a set of nodes.
7
8 SPDX-FileCopyrightText: 2009-2010 Daniel Bundala
9 SPDX-FileCopyrightText: GRASS Development Team
10 SPDX-License-Identifier: GPL-2.0-or-later
11
12 \author Daniel Bundala (Google Summer of Code 2009)
13 \author Markus Metz
14 */
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <grass/gis.h>
19#include <grass/vector.h>
20#include <grass/glocale.h>
21#include <grass/dgl/graph.h>
22#include <grass/neta.h>
23
24/*!
25 \brief Computes shortest paths to every node from nodes in "from".
26
27 Array "dst" contains the cost of the path or -1 if the node is not
28 reachable. Prev contains edges from predecessor along the shortest
29 path.
30
31 \param graph input graph
32 \param from list of 'from' positions
33 \param[out] dst array of costs to reach nodes
34 \param[out] prev array of edges from predecessor along the shortest path
35
36 \return 0 on success
37 \return -1 on failure
38 */
39int NetA_distance_from_points(dglGraph_s *graph, struct ilist *from, int *dst,
40 dglInt32_t **prev)
41{
42 int i, nnodes;
46
49
50 /* initialize costs and edge list */
51 for (i = 1; i <= nnodes; i++) {
52 dst[i] = -1;
53 prev[i] = NULL;
54 }
55
56 ncost = 0;
58
60
61 for (i = 0; i < from->n_values; i++) {
62 int v = from->value[i];
63
64 if (dst[v] == 0)
65 continue; /* ignore duplicates */
66 dst[v] = 0; /* make sure all from nodes are processed first */
68
69 heap_data.ul = v;
71 }
72 while (1) {
73 dglInt32_t v, dist;
76 dglInt32_t *edge;
77 dglInt32_t *node;
78
80 break;
81 v = heap_node.value.ul;
82 dist = heap_node.key;
83 if (dst[v] < dist)
84 continue;
85
86 node = dglGetNode(graph, v);
87
88 if (have_node_costs && prev[v]) {
89 memcpy(&ncost, dglNodeGet_Attr(graph, node), sizeof(ncost));
90 if (ncost > 0)
91 dist += ncost;
92 /* do not go through closed nodes */
93 if (ncost < 0)
94 continue;
95 }
96
98
99 for (edge = dglEdgeset_T_First(&et); edge;
100 edge = dglEdgeset_T_Next(&et)) {
101 dglInt32_t *to = dglEdgeGet_Tail(graph, edge);
104
105 if (dst[to_id] < 0 || dst[to_id] > dist + d) {
106 dst[to_id] = dist + d;
107 prev[to_id] = edge;
108 heap_data.ul = to_id;
109 dglHeapInsertMin(&heap, dist + d, ' ', heap_data);
110 }
111 }
112
114 }
115
117
118 return 0;
119}
120
121/*!
122 \brief Computes shortest paths from every node to nodes in "to".
123
124 Array "dst" contains the cost of the path or -1 if the node is not
125 reachable. Nxt contains edges from successor along the shortest
126 path. This method does reverse search starting with "to" nodes and
127 going backward.
128
129 \param graph input graph
130 \param to list of 'to' positions
131 \param[out] dst array of costs to reach nodes
132 \param[out] nxt array of edges from successor along the shortest path
133
134 \return 0 on success
135 \return -1 on failure
136 */
138 dglInt32_t **nxt)
139{
140 int i, nnodes;
143 int have_node_costs;
145
147
148 /* initialize costs and edge list */
149 for (i = 1; i <= nnodes; i++) {
150 dst[i] = -1;
151 nxt[i] = NULL;
152 }
153
154 if (graph->Version < 2) {
155 G_warning("Directed graph must be version 2 or 3 for "
156 "NetA_distance_to_points()");
157 return -1;
158 }
159
160 ncost = 0;
162
164
165 for (i = 0; i < to->n_values; i++) {
166 int v = to->value[i];
167
168 if (dst[v] == 0)
169 continue; /* ignore duplicates */
170 dst[v] = 0; /* make sure all to nodes are processed first */
172
173 heap_data.ul = v;
175 }
176 while (1) {
177 dglInt32_t v, dist;
180 dglInt32_t *edge;
181 dglInt32_t *node;
182
184 break;
185 v = heap_node.value.ul;
186 dist = heap_node.key;
187 if (dst[v] < dist)
188 continue;
189
190 node = dglGetNode(graph, v);
191
192 if (have_node_costs && nxt[v]) {
193 memcpy(&ncost, dglNodeGet_Attr(graph, node), sizeof(ncost));
194 if (ncost > 0)
195 dist += ncost;
196 /* do not go through closed nodes */
197 if (ncost < 0)
198 continue;
199 }
200
202
203 for (edge = dglEdgeset_T_First(&et); edge;
204 edge = dglEdgeset_T_Next(&et)) {
205 dglInt32_t *from = dglEdgeGet_Head(graph, edge);
208
209 if (dst[from_id] < 0 || dst[from_id] > dist + d) {
210 dst[from_id] = dist + d;
211 nxt[from_id] = edge;
212 heap_data.ul = from_id;
213 dglHeapInsertMin(&heap, dist + d, ' ', heap_data);
214 }
215 }
216
218 }
219
221
222 return 0;
223}
224
225/*!
226 \brief Find a path (minimum number of edges) from 'from' to 'to'
227 using only edges flagged as valid in 'edges'. Edge costs are not
228 considered. Closed nodes are not traversed.
229
230 Precisely, edge with id I is used if edges[abs(i)] == 1. List
231 stores the indices of lines on the path. The method returns the
232 number of edges or -1 if no path exists.
233
234 \param graph input graph
235 \param from 'from' position
236 \param to 'to' position
237 \param edges array of edges indicating whether an edge should be used
238 \param[out] list list of edges
239
240 \return number of edges
241 \return -1 on failure
242 */
243int NetA_find_path(dglGraph_s *graph, int from, int to, int *edges,
244 struct ilist *list)
245{
246 dglInt32_t **prev, *queue;
248 char *vis;
249 int begin, end, cur, nnodes;
250 int have_node_costs;
252
254 prev = (dglInt32_t **)G_calloc(nnodes + 1, sizeof(dglInt32_t *));
255 queue = (dglInt32_t *)G_calloc(nnodes + 1, sizeof(dglInt32_t));
256 vis = (char *)G_calloc(nnodes + 1, sizeof(char));
257 if (!prev || !queue || !vis) {
258 G_fatal_error(_("Out of memory"));
259 return -1;
260 }
262
263 ncost = 0;
265
266 begin = 0;
267 end = 1;
268 vis[from] = 'y';
269 queue[0] = from;
270 prev[from] = NULL;
271 while (begin != end) {
273 dglInt32_t *edge = NULL, *node;
274
275 if (vertex == to)
276 break;
277
278 /* do not go through closed nodes */
279 if (have_node_costs && prev[vertex]) {
281 sizeof(ncost));
282 if (ncost < 0)
283 continue;
284 }
285
286 node = dglGetNode(graph, vertex);
287
289 for (edge = dglEdgeset_T_First(&et); edge;
290 edge = dglEdgeset_T_Next(&et)) {
294 if (edges[edge_id] && !vis[node_id]) {
295 vis[node_id] = 'y';
296 prev[node_id] = edge;
297 queue[end++] = node_id;
298 }
299 }
301 }
302 G_free(queue);
303 if (!vis[to]) {
304 G_free(prev);
305 G_free(vis);
306 return -1;
307 }
308
309 cur = to;
310 while (prev[cur] != NULL) {
312 cur = dglNodeGet_Id(graph, dglEdgeGet_Head(graph, prev[cur]));
313 }
314
315 G_free(prev);
316 G_free(vis);
317 return list->n_values;
318}
#define NULL
Definition ccmath.h:32
Definition queue.h:43
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_calloc(m, n)
Definition defs/gis.h:137
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
int Vect_list_append(struct ilist *, int)
Append new item to the end of list if not yet present.
int Vect_reset_list(struct ilist *)
Reset ilist structure.
#define _(str)
Definition glocale.h:10
void dglHeapInit(dglHeap_s *pheap)
Definition heap.c:15
int dglHeapInsertMin(dglHeap_s *pheap, long key, unsigned char flags, dglHeapData_u value)
Definition heap.c:38
void dglHeapFree(dglHeap_s *pheap, dglHeapCancelItem_fn pfnCancelItem)
Definition heap.c:23
int dglHeapExtractMin(dglHeap_s *pheap, dglHeapNode_s *pnoderet)
Definition heap.c:64
List of integers.
Definition gis.h:712
int n_values
Number of values in the list.
Definition gis.h:720
int * value
Array of values.
Definition gis.h:716
Definition manage.h:4
Definition path.h:10
long dglInt32_t
Definition type.h:24
dglInt32_t * dglGetNode(dglGraph_s *pGraph, dglInt32_t nNodeId)
int dglGet_NodeAttrSize(dglGraph_s *pgraph)
dglInt32_t * dglNodeGet_OutEdgeset(dglGraph_s *pGraph, dglInt32_t *pnNode)
int dglEdgeset_T_Initialize(dglEdgesetTraverser_s *pT, dglGraph_s *pGraph, dglInt32_t *pnEdgeset)
dglInt32_t * dglNodeGet_InEdgeset(dglGraph_s *pGraph, dglInt32_t *pnNode)
dglInt32_t dglEdgeGet_Id(dglGraph_s *pGraph, dglInt32_t *pnEdge)
dglInt32_t * dglEdgeset_T_First(dglEdgesetTraverser_s *pT)
dglInt32_t * dglEdgeset_T_Next(dglEdgesetTraverser_s *pT)
dglInt32_t * dglNodeGet_Attr(dglGraph_s *pGraph, dglInt32_t *pnNode)
int dglGet_NodeCount(dglGraph_s *pgraph)
dglInt32_t dglEdgeGet_Cost(dglGraph_s *pGraph, dglInt32_t *pnEdge)
void dglEdgeset_T_Release(dglEdgesetTraverser_s *pT)
dglInt32_t * dglEdgeGet_Head(dglGraph_s *pGraph, dglInt32_t *pnEdge)
dglInt32_t * dglEdgeGet_Tail(dglGraph_s *pGraph, dglInt32_t *pnEdge)
dglInt32_t dglNodeGet_Id(dglGraph_s *pGraph, dglInt32_t *pnNode)
int NetA_find_path(dglGraph_s *graph, int from, int to, int *edges, struct ilist *list)
Find a path (minimum number of edges) from 'from' to 'to' using only edges flagged as valid in 'edges...
int NetA_distance_to_points(dglGraph_s *graph, struct ilist *to, int *dst, dglInt32_t **nxt)
Computes shortest paths from every node to nodes in "to".
int NetA_distance_from_points(dglGraph_s *graph, struct ilist *from, int *dst, dglInt32_t **prev)
Computes shortest paths to every node from nodes in "from".