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