GRASS 8 Programmer's Manual 8.6.0dev(2026)-55de52a352
Loading...
Searching...
No Matches
net_analyze.c
Go to the documentation of this file.
1/*!
2 * \file lib/vector/Vlib/net_analyze.c
3 *
4 * \brief Vector library - related fns for vector network analyses
5 *
6 * Higher level functions for reading/writing/manipulating vectors.
7 *
8 * SPDX-FileCopyrightText: 2001-2009, 2014 GRASS Development Team
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 *
11 * \author Radim Blazek
12 * \author Stepan Turek stepan.turek seznam.cz (turns support)
13 */
14
15#include <grass/dbmi.h>
16#include <grass/vector.h>
17#include <grass/glocale.h>
18
19static int
20 From_node; /* from node set in SP and used by clipper for first arc */
21
22static int clipper(dglGraph_s *pgraph, dglSPClipInput_s *pargIn,
24{ /* caller's pointer */
25 dglInt32_t cost;
26 dglInt32_t from;
27
28 G_debug(3, "Net: clipper()");
29
30 from = dglNodeGet_Id(pgraph, pargIn->pnNodeFrom);
31
32 G_debug(3, " Edge = %d NodeFrom = %d NodeTo = %d edge cost = %d",
33 (int)dglEdgeGet_Id(pgraph, pargIn->pnEdge), (int)from,
34 (int)dglNodeGet_Id(pgraph, pargIn->pnNodeTo),
35 (int)pargOut->nEdgeCost);
36
37 if (from != From_node) { /* do not clip first */
38 if (dglGet_NodeAttrSize(pgraph) > 0) {
39 memcpy(&cost, dglNodeGet_Attr(pgraph, pargIn->pnNodeFrom),
40 sizeof(cost));
41 if (cost == -1) { /* closed, cannot go from this node except it is
42 'from' node */
43 G_debug(3, " closed node");
44 return 1;
45 }
46 else {
47 G_debug(3, " EdgeCost += %d (node)", (int)cost);
48 pargOut->nEdgeCost += cost;
49 }
50 }
51 }
52 else {
53 G_debug(3, " don't clip first node");
54 }
55
56 return 0;
57}
58
59/*!
60 \brief Converts shortest path result, which is calculated by DGLib on
61 newtwork without turntable, into output format.
62 */
63static int convert_dgl_shortest_path_result(struct Map_info *Map,
65 struct ilist *List)
66{
67 int i, line;
68
70
71 for (i = 0; i < pSPReport->cArc; i++) {
72 line = dglEdgeGet_Id(&(Map->dgraph.graph_s), pSPReport->pArc[i].pnEdge);
73 G_debug(
74 2, "From %ld to %ld - cost %ld user %d distance %ld",
75 pSPReport->pArc[i].nFrom, pSPReport->pArc[i].nTo,
76 dglEdgeGet_Cost(&(Map->dgraph.graph_s), pSPReport->pArc[i].pnEdge) /
77 Map->dgraph.cost_multip, /* this is the cost from clip() */
78 line, pSPReport->pArc[i].nDistance);
80 }
81
82 return 0;
83}
84
85/*!
86 \brief Converts shortest path result, which is calculated by DGLib on
87 newtwork with turntable, into output format.
88 */
89static int ttb_convert_dgl_shortest_path_result(struct Map_info *Map,
91 int tucfield,
92 struct ilist *List)
93{
94 int i, line_id, type, tucfield_idx;
95 int line_ucat;
96
98
100
101 for (i = 0; i < pSPReport->cArc; i++) {
102 dglEdgeGet_Id(&(Map->dgraph.graph_s), pSPReport->pArc[i].pnEdge);
103
105 &(Map->dgraph.graph_s),
106 dglEdgeGet_Head(&(Map->dgraph.graph_s), pSPReport->pArc[i].pnEdge));
107
108 /* get standard ucat numbers (DGLib does not like negative node numbers)
109 */
110 if (line_ucat % 2 == 1)
111 line_ucat = ((line_ucat - 1) / -2);
112 else
113 line_ucat = (line_ucat) / 2;
114
115 /* skip virtual nodes */
117 &type, &line_id) == -1)
118 continue;
119
120 if (line_ucat < 0)
121 line_id *= -1;
122
123 G_debug(
124 2, "From %ld to %ld - cost %ld user %d distance %ld",
125 pSPReport->pArc[i].nFrom, pSPReport->pArc[i].nTo,
126 dglEdgeGet_Cost(&(Map->dgraph.graph_s), pSPReport->pArc[i].pnEdge) /
127 Map->dgraph.cost_multip, /* this is the cost from clip() */
128 line_ucat, pSPReport->pArc[i].nDistance);
129
131 }
132
133 return 0;
134}
135
136/*!
137 \brief Finds shortest path on network using DGLib
138
139
140 \param Map vector map with build DGLib graph (see Vect_net_ttb_build_graph
141 and Vect_net_build_graph) \param from from node id in build the network
142 \param to to node in build the network
143 \param UseTtb the graph is build with/without turntable
144 \param tucfield layer with unique cats for turntable (relevant only when
145 UseTtb = 1)
146 */
147static int find_shortest_path(struct Map_info *Map, int from, int to,
148 struct ilist *List, double *cost, int UseTtb,
149 int tucfield)
150{
151 int *pclip, cArc, nRet;
153 dglInt32_t nDistance;
154 int use_cache = 1; /* set to 0 to disable dglib cache */
155
156 G_debug(3, "find_shortest_path(): from = %d, to = %d", from, to);
157
158 /* Note : if from == to dgl goes to nearest node and returns back (dgl
159 * feature) => check here for from == to */
160
161 if (List != NULL)
163
164 /* Check if from and to are identical, otherwise dglib returns path to
165 * nearest node and back! */
166 if (from == to) {
167 if (cost != NULL)
168 *cost = 0;
169 return 0;
170 }
171
172 From_node = from;
173 pclip = NULL;
174 if (List != NULL) {
175 if (use_cache) {
176 nRet = dglShortestPath(&(Map->dgraph.graph_s), &pSPReport,
177 (dglInt32_t)from, (dglInt32_t)to, clipper,
178 pclip, &(Map->dgraph.spCache));
179 }
180 else {
181 nRet = dglShortestPath(&(Map->dgraph.graph_s), &pSPReport,
182 (dglInt32_t)from, (dglInt32_t)to, clipper,
183 pclip, NULL);
184 }
185 }
186 else {
187 if (use_cache) {
188 nRet = dglShortestDistance(&(Map->dgraph.graph_s), &nDistance,
189 (dglInt32_t)from, (dglInt32_t)to,
190 clipper, pclip, &(Map->dgraph.spCache));
191 }
192 else {
193 nRet = dglShortestDistance(&(Map->dgraph.graph_s), &nDistance,
194 (dglInt32_t)from, (dglInt32_t)to,
195 clipper, pclip, NULL);
196 }
197 }
198
199 if (nRet == 0) {
200 /* G_warning("Destination node %d is unreachable from node %d\n" , to ,
201 * from); */
202 if (cost != NULL)
203 *cost = PORT_DOUBLE_MAX;
204 return -1;
205 }
206 else if (nRet < 0) {
207 G_warning(_("dglShortestPath error: %s"),
208 dglStrerror(&(Map->dgraph.graph_s)));
209 return -1;
210 }
211
212 if (List != NULL) {
213 if (UseTtb)
214 ttb_convert_dgl_shortest_path_result(Map, pSPReport, tucfield,
215 List);
216 else
217 convert_dgl_shortest_path_result(Map, pSPReport, List);
218 }
219
220 if (cost != NULL) {
221 if (List != NULL)
222 *cost = (double)pSPReport->nDistance / Map->dgraph.cost_multip;
223 else
224 *cost = (double)nDistance / Map->dgraph.cost_multip;
225 }
226
227 if (List != NULL) {
228 cArc = pSPReport->cArc;
229 dglFreeSPReport(&(Map->dgraph.graph_s), pSPReport);
230 }
231 else
232 cArc = 0;
233
234 return cArc;
235}
236
237/*!
238 \brief Find shortest path on network.
239
240 Costs for 'from' and 'to' nodes are not considered (SP found even if
241 'from' or 'to' are 'closed' (costs = -1) and costs of these
242 nodes are not added to SP costs result.
243
244 \param Map vector map with build graph (see Vect_net_ttb_build_graph and
245 Vect_net_build_graph) \param from start of the path \param from_type if 0 -
246 node id (intersection), if 1 - line unique cat \param to end of the path
247 \param to_type if 0 - node id (intersection), if 1 - line unique cat
248 \param tucfield field with unique categories used in the turntable
249 \param[out] List list of line ids (path)
250 \param[out] cost costs value
251
252 \return number of segments
253 \return 0 is correct for from = to, or List == NULL ? sum of costs is better
254 return value, \return -1 : destination unreachable
255
256 */
258 int to, int to_type, int tucfield,
259 struct ilist *List, double *cost)
260{
261 double x, y, z;
262 struct bound_box box;
263 struct boxlist *box_List;
264 struct line_cats *Cats;
265 int f, t;
266 int i_line, line, type, cfound;
267
270
271 if (from_type ==
272 0) { /* TODO duplicite code with to_type, move into function */
273 /* select points at node */
274 Vect_get_node_coor(Map, from, &x, &y, &z);
275 box.E = box.W = x;
276 box.N = box.S = y;
277 box.T = box.B = z;
279
280 cfound = 0;
281
282 for (i_line = 0; i_line < box_List->n_values; i_line++) {
283 line = box_List->id[i_line];
284
285 type = Vect_read_line(Map, NULL, Cats, line);
286 if (!(type & GV_POINT))
287 continue;
288 if (Vect_cat_get(Cats, tucfield, &f)) {
289 ++cfound;
290 break;
291 }
292 }
293 if (!cfound)
294 G_fatal_error(_("Unable to find point with defined unique category "
295 "for node <%d>."),
296 from);
297 else if (cfound > 1)
298 G_warning(_("There exists more than one point on node <%d> with "
299 "unique category in field <%d>.\n"
300 "The unique category layer may not be valid."),
301 tucfield, from);
302
303 G_debug(2, "from node = %d, unique cat = %d ", from, f);
304 f = f * 2;
305 }
306 else {
307 if (from < 0)
308 f = from * -2 + 1;
309 else
310 f = from * 2;
311 G_debug(2, "from edge unique cat = %d", from);
312 }
313
314 if (to_type == 0) {
315 /* select points at node */
316 Vect_get_node_coor(Map, to, &x, &y, &z);
317 box.E = box.W = x;
318 box.N = box.S = y;
319 box.T = box.B = z;
321
322 cfound = 0;
323
324 for (i_line = 0; i_line < box_List->n_values; i_line++) {
325 line = box_List->id[i_line];
326 type = Vect_read_line(Map, NULL, Cats, line);
327 if (!(type & GV_POINT))
328 continue;
329 if (Vect_cat_get(Cats, tucfield, &t)) {
330 cfound = 1;
331 break;
332 }
333 }
334 if (!cfound)
335 G_fatal_error(_("Unable to find point with defined unique category "
336 "for node <%d>."),
337 to);
338 else if (cfound > 1)
339 G_warning(_("There exists more than one point on node <%d> with "
340 "unique category in field <%d>.\n"
341 "The unique category layer may not be valid."),
342 tucfield, to);
343
344 G_debug(2, "to node = %d, unique cat = %d ", to, t);
345 t = t * 2 + 1;
346 }
347 else {
348 if (to < 0)
349 t = to * -2 + 1;
350 else
351 t = to * 2;
352 G_debug(2, "to edge unique cat = %d", to);
353 }
354
357
358 return find_shortest_path(Map, f, t, List, cost, 1, tucfield);
359}
360
361/*!
362 \brief Find shortest path.
363
364 Costs for 'from' and 'to' nodes are not considered (SP found even if
365 'from' or 'to' are 'closed' (costs = -1) and costs of these
366 nodes are not added to SP costs result.
367
368 \param Map vector map with build graph (see Vect_net_ttb_build_graph and
369 Vect_net_build_graph) \param from from node \param to to node \param[out]
370 List list of line ids (path) \param[out] cost costs value
371
372 \return number of segments
373 \return 0 is correct for from = to, or List == NULL ? sum of costs is better
374 return value, \return -1 : destination unreachable
375
376 */
377int Vect_net_shortest_path(struct Map_info *Map, int from, int to,
378 struct ilist *List, double *cost)
379{
380 return find_shortest_path(Map, from, to, List, cost, 0, -1);
381}
382
383/*!
384 \brief Get graph structure
385
386 Graph is built by Vect_net_build_graph().
387
388 Returns NULL when graph is not built.
389
390 \param Map pointer to Map_info struct
391
392 \return pointer to dglGraph_s struct or NULL
393 */
395{
396 return &(Map->dgraph.graph_s);
397}
398
399/*!
400 \brief Returns in cost for given direction in *cost.
401
402 cost is set to -1 if closed.
403
404 \param Map vector map with build graph (see Vect_net_ttb_build_graph and
405 Vect_net_build_graph) \param line line id \param direction direction
406 (GV_FORWARD, GV_BACKWARD) \param[out] cost
407
408 \return 1 OK
409 \return 0 does not exist (was not inserted)
410 */
411int Vect_net_get_line_cost(struct Map_info *Map, int line, int direction,
412 double *cost)
413{
414 /* dglInt32_t *pEdge; */
415
416 G_debug(5, "Vect_net_get_line_cost(): line = %d, dir = %d", line,
417 direction);
418
419 if (direction == GV_FORWARD) {
420 /* V1 has no index by line-id -> array used */
421 /*
422 pEdge = dglGetEdge(&(Map->dgraph.graph_s), line);
423 if (pEdge == NULL)
424 return 0;
425 *cost = (double) dglEdgeGet_Cost(&(Map->dgraph.graph_s), pEdge);
426 */
427 if (Map->dgraph.edge_fcosts[line] == -1) {
428 *cost = -1;
429 return 0;
430 }
431 else
432 *cost = Map->dgraph.edge_fcosts[line];
433 }
434 else if (direction == GV_BACKWARD) {
435 /*
436 pEdge = dglGetEdge(&(Map->dgraph.graph_s), -line);
437 if (pEdge == NULL)
438 return 0;
439 *cost = (double) dglEdgeGet_Cost(&(Map->dgraph.graph_s), pEdge);
440 */
441 if (Map->dgraph.edge_bcosts[line] == -1) {
442 *cost = -1;
443 return 0;
444 }
445 else
446 *cost = Map->dgraph.edge_bcosts[line];
447 G_debug(5, "Vect_net_get_line_cost(): edge_bcosts = %f",
448 Map->dgraph.edge_bcosts[line]);
449 }
450 else {
451 G_fatal_error(_("Wrong line direction in Vect_net_get_line_cost()"));
452 }
453
454 return 1;
455}
456
457/*!
458 \brief Get cost of node
459
460 \param Map vector map with build graph (see Vect_net_ttb_build_graph and
461 Vect_net_build_graph) \param node node id \param[out] cost costs value
462
463 \return 1
464 */
465int Vect_net_get_node_cost(struct Map_info *Map, int node, double *cost)
466{
467 G_debug(3, "Vect_net_get_node_cost(): node = %d", node);
468
469 *cost = Map->dgraph.node_costs[node];
470
471 G_debug(3, " -> cost = %f", *cost);
472
473 return 1;
474}
475
476/*!
477 \brief Find nearest node(s) on network.
478
479 \param Map vector map with build graph (see Vect_net_ttb_build_graph and
480 Vect_net_build_graph)
481 \param x,y,z point coordinates (z coordinate NOT USED!)
482 \param direction (GV_FORWARD - from point to net, GV_BACKWARD - from net
483 to point)
484 \param maxdist maximum distance to the network
485 \param[out] node1 pointer where to store the node number (or NULL)
486 \param[out] node2 pointer where to store the node number (or NULL)
487 \param[out] ln pointer where to store the nearest line number (or NULL)
488 \param[out] costs1 pointer where to store costs on nearest line to node1 (not
489 costs from x,y,z to the line) (or NULL)
490 \param[out] costs2 pointer where to store costs on nearest line to node2
491 (not costs from x,y,z to the line) (or NULL)
492 \param[out] Points1 pointer to structure where to store vertices on nearest
493 line to node1 (or NULL)
494 \param[out] Points2 pointer to structure where to store vertices on nearest
495 line to node2 (or NULL)
496 \param[out] pointer where to distance to the line (or NULL)
497 \param[out] distance
498
499 \return number of nodes found (0,1,2)
500 */
501int Vect_net_nearest_nodes(struct Map_info *Map, double x, double y, double z,
502 int direction, double maxdist, int *node1,
503 int *node2, int *ln, double *costs1, double *costs2,
504 struct line_pnts *Points1, struct line_pnts *Points2,
505 double *distance)
506{
507 int line, n1, n2, nnodes;
508 int npoints;
509 int segment; /* nearest line segment (first is 1) */
510 static struct line_pnts *Points = NULL;
511 double cx, cy, cz, c1, c2;
512 double along; /* distance along the line to nearest point */
513 double length;
514
515 G_debug(3, "Vect_net_nearest_nodes() x = %f y = %f", x, y);
516
517 /* Reset */
518 if (node1)
519 *node1 = 0;
520 if (node2)
521 *node2 = 0;
522 if (ln)
523 *ln = 0;
524 if (costs1)
526 if (costs2)
528 if (Points1)
530 if (Points2)
532 if (distance)
533 *distance = PORT_DOUBLE_MAX;
534
535 if (!Points)
536 Points = Vect_new_line_struct();
537
538 /* Find nearest line */
539 line = Vect_find_line(Map, x, y, z, Map->dgraph.line_type, maxdist, 0, 0);
540
541 if (line < 1)
542 return 0;
543
544 Vect_read_line(Map, Points, NULL, line);
545 npoints = Points->n_points;
546 Vect_get_line_nodes(Map, line, &n1, &n2);
547
548 segment = Vect_line_distance(Points, x, y, z, 0, &cx, &cy, &cz, distance,
549 NULL, &along);
550
551 G_debug(4, "line = %d n1 = %d n2 = %d segment = %d", line, n1, n2, segment);
552
553 /* Check first or last point and return one node in that case */
554 G_debug(4, "cx = %f cy = %f first = %f %f last = %f %f", cx, cy,
555 Points->x[0], Points->y[0], Points->x[npoints - 1],
556 Points->y[npoints - 1]);
557
558 if (Points->x[0] == cx && Points->y[0] == cy) {
559 if (node1)
560 *node1 = n1;
561 if (ln)
562 *ln = line;
563 if (costs1)
564 *costs1 = 0;
565 if (Points1) {
568 }
569 G_debug(3, "first node nearest");
570 return 1;
571 }
572 if (Points->x[npoints - 1] == cx && Points->y[npoints - 1] == cy) {
573 if (node1)
574 *node1 = n2;
575 if (ln)
576 *ln = line;
577 if (costs1)
578 *costs1 = 0;
579 if (Points1) {
582 }
583 G_debug(3, "last node nearest");
584 return 1;
585 }
586
587 nnodes = 2;
588
589 /* c1 - costs to get from/to the first vertex */
590 /* c2 - costs to get from/to the last vertex */
591 if (direction == GV_FORWARD) { /* from point to net */
594 }
595 else {
598 }
599
600 if (c1 < 0)
601 nnodes--;
602 if (c2 < 0)
603 nnodes--;
604 if (nnodes == 0)
605 return 0; /* both directions closed */
606
607 length = Vect_line_length(Points);
608
609 if (ln)
610 *ln = line;
611
612 if (nnodes == 1 &&
613 c1 < 0) { /* first direction is closed, return node2 as node1 */
614 if (node1)
615 *node1 = n2;
616
617 if (costs1) { /* to node 2, i.e. forward */
618 *costs1 = c2 * (length - along) / length;
619 }
620
621 if (Points1) { /* to node 2, i.e. forward */
622 int i;
623
624 if (direction == GV_FORWARD) { /* from point to net */
627 for (i = segment; i < npoints; i++)
628 Vect_append_point(Points1, Points->x[i], Points->y[i],
629 Points->z[i]);
630 }
631 else {
632 for (i = npoints - 1; i >= segment; i--)
633 Vect_append_point(Points1, Points->x[i], Points->y[i],
634 Points->z[i]);
635
638 }
639 }
640 }
641 else {
642 if (node1)
643 *node1 = n1;
644 if (node2)
645 *node2 = n2;
646
647 if (costs1) { /* to node 1, i.e. backward */
648 *costs1 = c1 * along / length;
649 }
650
651 if (costs2) { /* to node 2, i.e. forward */
652 *costs2 = c2 * (length - along) / length;
653 }
654
655 if (Points1) { /* to node 1, i.e. backward */
656 int i;
657
658 if (direction == GV_FORWARD) { /* from point to net */
661 for (i = segment - 1; i >= 0; i--)
662 Vect_append_point(Points1, Points->x[i], Points->y[i],
663 Points->z[i]);
664 }
665 else {
666 for (i = 0; i < segment; i++)
667 Vect_append_point(Points1, Points->x[i], Points->y[i],
668 Points->z[i]);
669
672 }
673 }
674
675 if (Points2) { /* to node 2, i.e. forward */
676 int i;
677
678 if (direction == GV_FORWARD) { /* from point to net */
681 for (i = segment; i < npoints; i++)
682 Vect_append_point(Points2, Points->x[i], Points->y[i],
683 Points->z[i]);
684 }
685 else {
686 for (i = npoints - 1; i >= segment; i--)
687 Vect_append_point(Points2, Points->x[i], Points->y[i],
688 Points->z[i]);
689
692 }
693 }
694 }
695
696 return nnodes;
697}
698
699/*!
700 \brief Find shortest path on network between 2 points given by coordinates.
701
702 \param Map vector map with build graph (see Vect_net_ttb_build_graph and
703 Vect_net_build_graph) \param fx,fy,fz from point x coordinate (z ignored)
704 \param tx,ty,tz to point x coordinate (z ignored)
705 \param fmax maximum distance to the network from 'from'
706 \param tmax maximum distance to the network from 'to'
707 \param UseTtb the graph is build with/without turntable
708 \param tucfield field with unique categories used in the turntable
709 \param costs pointer where to store costs on the network (or NULL)
710 \param Points pointer to the structure where to store vertices of shortest
711 path (or NULL) \param List pointer to the structure where list of lines on
712 the network is stored (or NULL) \param NodesList pointer to the structure
713 where list of nodes on the network is stored (or NULL) \param FPoints pointer
714 to the structure where to store line from 'from' to first network node (or
715 NULL) \param TPoints pointer to the structure where to store line from last
716 network node to 'to' (or NULL) \param fdist distance from 'from' to the net
717 (or NULL) \param tdist distance from 'to' to the net (or NULL)
718
719 \return 1 OK, 0 not reachable
720 */
721static int
722find_shortest_path_coor(struct Map_info *Map, double fx, double fy, double fz,
723 double tx, double ty, double tz, double fmax,
724 double tmax, int UseTtb, int tucfield, double *costs,
725 struct line_pnts *Points, struct ilist *List,
726 struct ilist *NodesList, struct line_pnts *FPoints,
727 struct line_pnts *TPoints, double *fdist, double *tdist)
728{
729 int fnode[2],
730 tnode[2]; /* nearest nodes, *node[1] is 0 if only one was found */
731 double fcosts[2], tcosts[2],
732 cur_cst; /* costs to nearest nodes on the network */
733 int nfnodes, ntnodes, fline, tline;
734 static struct line_pnts *APoints, *SPoints, *fPoints[2], *tPoints[2];
735 static struct ilist *LList;
736 static int first = 1;
737 int reachable, shortcut;
738 int i, j, fn = 0, tn = 0;
739
740 /* from/to_point_node is set if from/to point projected to line
741 *falls exactly on node (shortcut -> fline == tline) */
742 int from_point_node = 0;
743 int to_point_node = 0;
744
745 G_debug(3, "Vect_net_shortest_path_coor()");
746
747 if (first) {
755 first = 0;
756 }
757
758 /* Reset */
759 if (costs)
761 if (Points)
762 Vect_reset_line(Points);
763 if (fdist)
764 *fdist = 0;
765 if (tdist)
766 *tdist = 0;
767 if (List)
768 List->n_values = 0;
769 if (FPoints)
771 if (TPoints)
773 if (NodesList != NULL)
775
776 /* Find nearest nodes */
777 fnode[0] = fnode[1] = tnode[0] = tnode[1] = 0;
778
780 Map, fx, fy, fz, GV_FORWARD, fmax, &(fnode[0]), &(fnode[1]), &fline,
781 &(fcosts[0]), &(fcosts[1]), fPoints[0], fPoints[1], fdist);
782 if (nfnodes == 0)
783 return 0;
784
785 if (nfnodes == 1 && fPoints[0]->n_points < 3) {
787 }
788
790 Map, tx, ty, tz, GV_BACKWARD, tmax, &(tnode[0]), &(tnode[1]), &tline,
791 &(tcosts[0]), &(tcosts[1]), tPoints[0], tPoints[1], tdist);
792 if (ntnodes == 0)
793 return 0;
794
795 if (ntnodes == 1 && tPoints[0]->n_points < 3) {
796 to_point_node = tnode[0];
797 }
798
799 G_debug(3, "fline = %d tline = %d", fline, tline);
800
801 reachable = shortcut = 0;
803
804 /* It may happen, that 2 points are at the same line. */
805 /* TODO?: it could also happen that fline != tline but both points are on
806 * the same line if they fall on node but a different line was found. This
807 * case is correctly handled as normal non shortcut, but it could be added
808 * here. In that case NodesList collection must be changed */
809 if (fline == tline && (nfnodes > 1 || ntnodes > 1)) {
810 double len, flen, tlen, c, fseg, tseg;
811 double fcx, fcy, fcz, tcx, tcy, tcz;
812
815
816 /* distance along the line */
818 NULL, NULL, &flen);
819 tseg = Vect_line_distance(APoints, tx, ty, tz, 0, &tcx, &tcy, &tcz,
820 NULL, NULL, &tlen);
821
823 if (flen == tlen) {
824 cur_cst = 0;
825
829
830 reachable = shortcut = 1;
831 }
832 else if (flen < tlen) {
834 if (c >= 0) {
835 cur_cst = c * (tlen - flen) / len;
836
839 for (i = fseg; i < tseg; i++)
841 APoints->z[i]);
842
845
846 reachable = shortcut = 1;
847 }
848 }
849 else { /* flen > tlen */
851 if (c >= 0) {
852 cur_cst = c * (flen - tlen) / len;
853
856 for (i = fseg - 1; i >= tseg; i--)
858 APoints->z[i]);
859
862
863 reachable = shortcut = 1;
864 }
865 }
866 }
867
868 /* Find the shortest variant from maximum 4 */
869 for (i = 0; i < nfnodes; i++) {
870 for (j = 0; j < ntnodes; j++) {
871 double ncst, cst;
872 int ret;
873
874 G_debug(3, "i = %d fnode = %d j = %d tnode = %d", i, fnode[i], j,
875 tnode[j]);
876
877 if (UseTtb)
879 tucfield, NULL, &ncst);
880 else
882 &ncst);
883 if (ret == -1)
884 continue; /* not reachable */
885
886 cst = fcosts[i] + ncst + tcosts[j];
887 if (reachable == 0 || cst < cur_cst) {
888 cur_cst = cst;
889 fn = i;
890 tn = j;
891 shortcut = 0;
892 }
893 reachable = 1;
894 }
895 }
896
897 G_debug(3, "reachable = %d shortcut = %d cur_cst = %f", reachable, shortcut,
898 cur_cst);
899 if (reachable) {
900 if (shortcut) {
901 if (Points)
903 if (NodesList) {
904 /* Check if from/to point projected to line falls on node and
905 *add it to the list */
906 if (from_point_node > 0)
908
909 if (to_point_node > 0)
911 }
912 }
913 else {
914 if (NodesList) {
915 /* it can happen that starting point falls on node but SP starts
916 * form the other node, add it in that case,
917 * similarly for to point below */
918 if (from_point_node > 0 && from_point_node != fnode[fn]) {
920 }
921
922 /* add starting net SP search node */
924 }
925
926 if (UseTtb)
929 else
931
932 G_debug(3, "Number of lines %d", LList->n_values);
933
934 if (Points)
936
937 if (FPoints)
939
940 for (i = 0; i < LList->n_values; i++) {
941 int line;
942
943 line = LList->value[i];
944 G_debug(3, "i = %d line = %d", i, line);
945
946 if (Points) {
948
949 if (line > 0)
951 else
953 Points->n_points--;
954 }
955 if (NodesList) {
956 int node, node1, node2;
957
959 /* add the second node, the first of first segmet was
960 * already added */
961 if (line > 0)
962 node = node2;
963 else
964 node = node1;
965
967 }
968
969 if (List)
970 Vect_list_append(List, line);
971 }
972
973 if (Points) {
974 if (LList->n_values)
975 Points->n_points++;
977 }
978
979 if (TPoints)
981
982 if (NodesList) {
983 if (to_point_node > 0 && to_point_node != tnode[tn]) {
985 }
986 }
987 }
988
989 if (costs)
990 *costs = cur_cst;
991 if (Points)
992 Vect_line_prune(Points);
993 }
994
995 return reachable;
996}
997
998/*!
999 \brief Find shortest path on network between 2 points given by coordinates.
1000
1001 \param Map vector map with build graph (see Vect_net_ttb_build_graph and
1002 Vect_net_build_graph) \param fx,fy,fz from point x coordinate (z ignored)
1003 \param tx,ty,tz to point x coordinate (z ignored)
1004 \param fmax maximum distance to the network from 'from'
1005 \param tmax maximum distance to the network from 'to'
1006 \param costs pointer where to store costs on the network (or NULL)
1007 \param Points pointer to the structure where to store vertices of shortest
1008 path (or NULL) \param List pointer to the structure where list of lines on
1009 the network is stored (or NULL) \param NodesList pointer to the structure
1010 where list of nodes on the network is stored (or NULL) \param FPoints pointer
1011 to the structure where to store line from 'from' to first network node (or
1012 NULL) \param TPoints pointer to the structure where to store line from last
1013 network node to 'to' (or NULL) \param fdist distance from 'from' to the net
1014 (or NULL) \param tdist distance from 'to' to the net (or NULL)
1015
1016 \return 1 OK, 0 not reachable
1017 */
1018int Vect_net_shortest_path_coor(struct Map_info *Map, double fx, double fy,
1019 double fz, double tx, double ty, double tz,
1020 double fmax, double tmax, double *costs,
1021 struct line_pnts *Points, struct ilist *List,
1022 struct ilist *NodesList,
1023 struct line_pnts *FPoints,
1024 struct line_pnts *TPoints, double *fdist,
1025 double *tdist)
1026{
1027 return find_shortest_path_coor(Map, fx, fy, fz, tx, ty, tz, fmax, tmax, 0,
1028 0, costs, Points, List, NodesList, FPoints,
1029 TPoints, fdist, tdist);
1030}
1031
1032/*!
1033 \brief Find shortest path on network with turntable between 2 points given by
1034 coordinates.
1035
1036 \param Map vector map with build graph (see Vect_net_ttb_build_graph and
1037 Vect_net_build_graph) \param fx,fy,fz from point x coordinate (z ignored)
1038 \param tx,ty,tz to point x coordinate (z ignored)
1039 \param fmax maximum distance to the network from 'from'
1040 \param tmax maximum distance to the network from 'to'
1041 \param tucfield field with unique categories used in the turntable
1042 \param costs pointer where to store costs on the network (or NULL)
1043 \param Points pointer to the structure where to store vertices of shortest
1044 path (or NULL) \param List pointer to the structure where list of lines on
1045 the network is stored (or NULL) \param NodesList pointer to the structure
1046 where list of nodes on the network is stored (or NULL) \param FPoints pointer
1047 to the structure where to store line from 'from' to first network node (or
1048 NULL) \param TPoints pointer to the structure where to store line from last
1049 network node to 'to' (or NULL) \param fdist distance from 'from' to the net
1050 (or NULL) \param tdist distance from 'to' to the net (or NULL)
1051
1052 \return 1 OK, 0 not reachable
1053 */
1055 double fz, double tx, double ty, double tz,
1056 double fmax, double tmax, int tucfield,
1057 double *costs, struct line_pnts *Points,
1058 struct ilist *List, struct ilist *NodesList,
1059 struct line_pnts *FPoints,
1060 struct line_pnts *TPoints, double *fdist,
1061 double *tdist)
1062{
1063 return find_shortest_path_coor(Map, fx, fy, fz, tx, ty, tz, fmax, tmax, 1,
1064 tucfield, costs, Points, List, NodesList,
1066}
#define NULL
Definition ccmath.h:32
Main header of GRASS DataBase Management Interface.
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
int Vect_get_line_nodes(struct Map_info *, int, int *, int *)
Get line nodes.
Definition level_two.c:302
int Vect_get_node_coor(struct Map_info *, int, double *, double *, double *)
Get node coordinates.
Definition level_two.c:272
double Vect_line_length(const struct line_pnts *)
Calculate line length, 3D-length in case of 3D vector line.
Definition line.c:573
int Vect_cidx_get_field_index(struct Map_info *, int)
Get layer index for given layer number.
int Vect_cidx_find_next(struct Map_info *, int, int, int, int, int *, int *)
Find next line/area id for given category, start_index and type_mask.
struct boxlist * Vect_new_boxlist(int)
Creates and initializes a struct boxlist.
int Vect_cat_get(const struct line_cats *, int, int *)
Get first found category of given field.
void Vect_destroy_boxlist(struct boxlist *)
Frees all memory associated with a struct boxlist, including the struct itself.
void Vect_destroy_cats_struct(struct line_cats *)
Frees all memory associated with line_cats structure, including the struct itself.
int Vect_list_append(struct ilist *, int)
Append new item to the end of list if not yet present.
int Vect_read_line(struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (topological level required)
int Vect_line_distance(const struct line_pnts *, double, double, double, int, double *, double *, double *, double *, double *, double *)
Calculate distance of point to line.
Definition line.c:646
int Vect_find_line(struct Map_info *, double, double, double, int, double, int, int)
Find the nearest line.
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
struct ilist * Vect_new_list(void)
Creates and initializes a struct ilist.
int Vect_select_lines_by_box(struct Map_info *, const struct bound_box *, int, struct boxlist *)
Select lines with bounding boxes by box.
Definition sindex.c:30
void Vect_reset_line(struct line_pnts *)
Reset line.
Definition line.c:127
int Vect_line_prune(struct line_pnts *)
Remove duplicate points, i.e. zero length segments.
Definition line.c:277
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:43
int Vect_reset_list(struct ilist *)
Reset ilist structure.
int Vect_append_point(struct line_pnts *, double, double, double)
Appends one point to the end of a line.
Definition line.c:146
int Vect_append_points(struct line_pnts *, const struct line_pnts *, int)
Appends points to the end of a line.
Definition line.c:333
#define GV_LINE
#define GV_POINT
Feature types used in memory on run time (may change)
#define PORT_DOUBLE_MAX
Limits for portable types.
Definition dig_defines.h:66
#define GV_FORWARD
Line direction indicator forward/backward.
#define GV_BACKWARD
#define G_UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
Definition gis.h:43
#define _(str)
Definition glocale.h:10
int Vect_net_shortest_path(struct Map_info *Map, int from, int to, struct ilist *List, double *cost)
Find shortest path.
int Vect_net_ttb_shortest_path_coor(struct Map_info *Map, double fx, double fy, double fz, double tx, double ty, double tz, double fmax, double tmax, int tucfield, double *costs, struct line_pnts *Points, struct ilist *List, struct ilist *NodesList, struct line_pnts *FPoints, struct line_pnts *TPoints, double *fdist, double *tdist)
Find shortest path on network with turntable between 2 points given by coordinates.
int Vect_net_shortest_path_coor(struct Map_info *Map, double fx, double fy, double fz, double tx, double ty, double tz, double fmax, double tmax, double *costs, struct line_pnts *Points, struct ilist *List, struct ilist *NodesList, struct line_pnts *FPoints, struct line_pnts *TPoints, double *fdist, double *tdist)
Find shortest path on network between 2 points given by coordinates.
dglGraph_s * Vect_net_get_graph(struct Map_info *Map)
Get graph structure.
int Vect_net_get_line_cost(struct Map_info *Map, int line, int direction, double *cost)
Returns in cost for given direction in *cost.
int Vect_net_ttb_shortest_path(struct Map_info *Map, int from, int from_type, int to, int to_type, int tucfield, struct ilist *List, double *cost)
Find shortest path on network.
int Vect_net_nearest_nodes(struct Map_info *Map, double x, double y, double z, int direction, double maxdist, int *node1, int *node2, int *ln, double *costs1, double *costs2, struct line_pnts *Points1, struct line_pnts *Points2, double *distance)
Find nearest node(s) on network.
int Vect_net_get_node_cost(struct Map_info *Map, int node, double *cost)
Get cost of node.
double t
Definition r_raster.c:37
Vector map info.
Bounding box.
Definition dig_structs.h:62
double W
West.
Definition dig_structs.h:78
double T
Top.
Definition dig_structs.h:82
double S
South.
Definition dig_structs.h:70
double N
North.
Definition dig_structs.h:66
double E
East.
Definition dig_structs.h:74
double B
Bottom.
Definition dig_structs.h:86
List of bounding boxes with id.
List of integers.
Definition gis.h:712
Feature category info.
Feature geometry info - coordinates.
double * y
Array of Y coordinates.
double * x
Array of X coordinates.
int n_points
Number of points.
double * z
Array of Z coordinates.
long dglInt32_t
Definition type.h:24
void dglFreeSPReport(dglGraph_s *pgraph, dglSPReport_s *pSPReport)
int dglGet_NodeAttrSize(dglGraph_s *pgraph)
int dglShortestPath(dglGraph_s *pGraph, dglSPReport_s **ppReport, dglInt32_t nStart, dglInt32_t nDestination, dglSPClip_fn fnClip, void *pvClipArg, dglSPCache_s *pCache)
dglInt32_t dglEdgeGet_Id(dglGraph_s *pGraph, dglInt32_t *pnEdge)
char * dglStrerror(dglGraph_s *pgraph)
int dglShortestDistance(dglGraph_s *pGraph, dglInt32_t *pnDistance, dglInt32_t nStart, dglInt32_t nDestination, dglSPClip_fn fnClip, void *pvClipArg, dglSPCache_s *pCache)
dglInt32_t * dglNodeGet_Attr(dglGraph_s *pGraph, dglInt32_t *pnNode)
dglInt32_t dglEdgeGet_Cost(dglGraph_s *pGraph, dglInt32_t *pnEdge)
dglInt32_t * dglEdgeGet_Head(dglGraph_s *pGraph, dglInt32_t *pnEdge)
dglInt32_t dglNodeGet_Id(dglGraph_s *pGraph, dglInt32_t *pnNode)
#define x