[GRASS-SVN] r71212 - in grass/trunk/vector: v.net.alloc v.net.iso
svn_grass at osgeo.org
svn_grass at osgeo.org
Thu Jun 22 23:55:26 PDT 2017
Author: mmetz
Date: 2017-06-22 23:55:26 -0700 (Thu, 22 Jun 2017)
New Revision: 71212
Added:
grass/trunk/vector/v.net.iso/alloc.c
grass/trunk/vector/v.net.iso/alloc.h
Modified:
grass/trunk/vector/v.net.alloc/alloc.c
grass/trunk/vector/v.net.alloc/alloc.h
grass/trunk/vector/v.net.alloc/main.c
grass/trunk/vector/v.net.alloc/v.net.alloc.html
grass/trunk/vector/v.net.iso/Makefile
grass/trunk/vector/v.net.iso/main.c
grass/trunk/vector/v.net.iso/v.net.iso.html
Log:
sync v.net.alloc and v.net.iso
Modified: grass/trunk/vector/v.net.alloc/alloc.c
===================================================================
--- grass/trunk/vector/v.net.alloc/alloc.c 2017-06-23 06:37:41 UTC (rev 71211)
+++ grass/trunk/vector/v.net.alloc/alloc.c 2017-06-23 06:55:26 UTC (rev 71212)
@@ -87,6 +87,85 @@
return 0;
}
+int alloc_to_centers_loop_tt(struct Map_info *Map, NODE *Nodes,
+ CENTER *Centers, int ncenters,
+ int tucfield)
+{
+ int center, line, nlines, i;
+ int node1;
+ int cat;
+ struct line_cats *Cats;
+ struct line_pnts *Points;
+ double cost, n1cost, n2cost;
+ int ret;
+
+ Cats = Vect_new_cats_struct();
+ Points = Vect_new_line_struct();
+
+ nlines = Vect_get_num_lines(Map);
+
+ for (i = 2; i <= (nlines * 2 + 2); i++) {
+ Nodes[i].center = -1;/* NOTE: first two items of Nodes are not used */
+ Nodes[i].cost = -1;
+ Nodes[i].edge = 0;
+ }
+
+ for (line = 1; line <= nlines; line++) {
+ G_debug(5, " line = %d", line);
+ Vect_net_get_node_cost(Map, line, &n2cost);
+ /* closed, left it as not attached */
+
+ if (Vect_read_line(Map, Points, Cats, line) < 0)
+ continue;
+ if (Vect_get_line_type(Map, line) != GV_LINE)
+ continue;
+ if (!Vect_cat_get(Cats, tucfield, &cat))
+ continue;
+
+ for (center = 0; center < ncenters; center++) {
+ G_percent(center, ncenters, 1);
+ node1 = Centers[center].node;
+ Vect_net_get_node_cost(Map, node1, &n1cost);
+ G_debug(2, "center = %d node = %d cat = %d", center, node1,
+ Centers[center].cat);
+
+ for (i = 0; i < 2; i++) {
+ if (i == 1)
+ cat *= -1;
+
+ ret =
+ Vect_net_ttb_shortest_path(Map, cat, 1, node1, 0,
+ tucfield, NULL,
+ &cost);
+ if (ret == -1) {
+ continue;
+ } /* node unreachable */
+
+ /* We must add center node costs (not calculated by Vect_net_shortest_path() ), but
+ * only if center and node are not identical, because at the end node cost is add later */
+ if (ret != 1)
+ cost += n1cost;
+
+ G_debug(5,
+ "Arc nodes: %d %d cost: %f (x old cent: %d old cost %f",
+ node1, line, cost, Nodes[line * 2 + i].center,
+ Nodes[line * 2 + i].cost);
+ if (Nodes[line * 2 + i].center == -1 ||
+ Nodes[line * 2 + i].cost > cost) {
+ Nodes[line * 2 + i].cost = cost;
+ Nodes[line * 2 + i].center = center;
+ }
+ }
+ }
+ }
+ G_percent(1, 1, 1);
+
+ Vect_destroy_cats_struct(Cats);
+ Vect_destroy_line_struct(Points);
+
+ return 0;
+}
+
int alloc_from_centers(dglGraph_s *graph, NODE *Nodes, CENTER *Centers, int ncenters)
{
int i, nnodes;
Modified: grass/trunk/vector/v.net.alloc/alloc.h
===================================================================
--- grass/trunk/vector/v.net.alloc/alloc.h 2017-06-23 06:37:41 UTC (rev 71211)
+++ grass/trunk/vector/v.net.alloc/alloc.h 2017-06-23 06:55:26 UTC (rev 71212)
@@ -15,6 +15,9 @@
int alloc_from_centers_loop_tt(struct Map_info *Map, NODE *Nodes,
CENTER *Centers, int ncenters,
int tucfield);
+int alloc_to_centers_loop_tt(struct Map_info *Map, NODE *Nodes,
+ CENTER *Centers, int ncenters,
+ int tucfield);
int alloc_from_centers(dglGraph_s *graph, NODE *Nodes, CENTER *Centers, int ncenters);
int alloc_to_centers(dglGraph_s *graph, NODE *Nodes, CENTER *Centers, int ncenters);
Modified: grass/trunk/vector/v.net.alloc/main.c
===================================================================
--- grass/trunk/vector/v.net.alloc/main.c 2017-06-23 06:37:41 UTC (rev 71211)
+++ grass/trunk/vector/v.net.alloc/main.c 2017-06-23 06:55:26 UTC (rev 71212)
@@ -5,11 +5,11 @@
*
* AUTHOR(S): Radim Blazek
* Stepan Turek <stepan.turek seznam.cz> (turns support)
- * Markus Metz (costs from/to centers)
+ * Markus Metz (costs from/to centers; attributes)
*
* PURPOSE: Allocate subnets for nearest centers
*
- * COPYRIGHT: (C) 2001, 2016 by the GRASS Development Team
+ * COPYRIGHT: (C) 2001, 2016,2017 by the GRASS Development Team
*
* This program is free software under the
* GNU General Public License (>=v2).
@@ -30,8 +30,8 @@
int main(int argc, char **argv)
{
int i, ret, line, center1, center2;
- int nlines, nnodes, type, ltype, afield, nfield, geo, cat, tfield,
- tucfield;
+ int nlines, nnodes, type, ltype, afield, nfield, geo, cat;
+ int tfield, tucfield;
int node1, node2;
double e1cost, e2cost, n1cost, n2cost, s1cost, s2cost, l, l1, l2;
struct Option *map, *output, *method_opt;
@@ -57,20 +57,18 @@
struct field_info *Fi;
/* initialize GIS environment */
- G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */
+ G_gisinit(argv[0]);
/* initialize module */
module = G_define_module();
G_add_keyword(_("vector"));
G_add_keyword(_("network"));
G_add_keyword(_("cost allocation"));
- module->label =
- _("Allocates subnets for nearest centers (direction from center).");
+ module->label = _("Allocates subnets for nearest centers.");
module->description =
- _("center node must be opened (costs >= 0). "
- "Costs of center node are used in calculation");
+ _("Center node must be opened (costs >= 0). "
+ "Costs of center node are used in calculation.");
-
map = G_define_standard_option(G_OPT_V_INPUT);
output = G_define_standard_option(G_OPT_V_OUTPUT);
@@ -110,24 +108,19 @@
nfield_opt->required = YES;
nfield_opt->label = _("Node layer");
- afcol = G_define_option();
+ afcol = G_define_standard_option(G_OPT_DB_COLUMN);
afcol->key = "arc_column";
- afcol->type = TYPE_STRING;
- afcol->required = NO;
- afcol->description = _("Arc forward/both direction(s) cost column (number)");
+ afcol->description =
+ _("Arc forward/both direction(s) cost column (number)");
afcol->guisection = _("Cost");
- abcol = G_define_option();
+ abcol = G_define_standard_option(G_OPT_DB_COLUMN);
abcol->key = "arc_backward_column";
- abcol->type = TYPE_STRING;
- abcol->required = NO;
abcol->description = _("Arc backward direction cost column (number)");
abcol->guisection = _("Cost");
- ncol = G_define_option();
+ ncol = G_define_standard_option(G_OPT_DB_COLUMN);
ncol->key = "node_column";
- ncol->type = TYPE_STRING;
- ncol->required = NO;
ncol->description = _("Node cost column (number)");
ncol->guisection = _("Cost");
@@ -199,9 +192,10 @@
/* Build graph */
graph_version = 1;
from_centers = 1;
- if (method_opt->answer[0] == 't' && !turntable_f->answer) {
- graph_version = 2;
+ if (method_opt->answer[0] == 't') {
from_centers = 0;
+ if (!turntable_f->answer)
+ graph_version = 2;
}
if (turntable_f->answer)
Vect_net_ttb_build_graph(&Map, type, afield, nfield, tfield, tucfield,
@@ -235,7 +229,7 @@
if (Vect_cat_in_cat_list(cat, catlist)) {
Vect_net_get_node_cost(&Map, node, &n1cost);
if (n1cost == -1) { /* closed */
- G_warning("Centre at closed node (costs = -1) ignored");
+ G_warning(_("Center at closed node (costs = -1) ignored"));
}
else {
if (acenters == ncenters) {
@@ -246,34 +240,47 @@
}
Centers[ncenters].cat = cat;
Centers[ncenters].node = node;
- G_debug(2, "centre = %d node = %d cat = %d", ncenters,
+ G_debug(2, "center = %d node = %d cat = %d", ncenters,
node, cat);
ncenters++;
}
}
}
- G_message(_("Number of centers: [%d] (nlayer: [%d])"), ncenters, nfield);
+ G_message(_("Number of centers: %d (nlayer %d)"), ncenters, nfield);
if (ncenters == 0)
- G_warning(_("Not enough centers for selected nlayer. "
- "Nothing will be allocated."));
+ G_warning(_("Not enough centers for selected nlayer. Nothing will be allocated."));
- /* alloc and reset space for all lines */
+ /* alloc and reset space for all nodes */
if (turntable_f->answer) {
- /* if turntable is used we are looking for lines as destinations, not the intersections (nodes) */
+ /* if turntable is used we are looking for lines as destinations, instead of the intersections (nodes) */
Nodes = (NODE *) G_calloc((nlines * 2 + 2), sizeof(NODE));
+ for (i = 2; i <= (nlines * 2 + 2); i++) {
+ Nodes[i].center = -1;/* NOTE: first two items of Nodes are not used */
+ }
+
}
else {
Nodes = (NODE *) G_calloc((nnodes + 1), sizeof(NODE));
+ for (i = 1; i <= nnodes; i++) {
+ Nodes[i].center = -1;
+ }
}
/* Fill Nodes by nearest center and costs from that center */
if (turntable_f->answer) {
- G_message(_("Calculating costs from centers ..."));
- alloc_from_centers_loop_tt(&Map, Nodes, Centers, ncenters,
- tucfield);
+ if (from_centers) {
+ G_message(_("Calculating costs from centers ..."));
+ alloc_from_centers_loop_tt(&Map, Nodes, Centers, ncenters,
+ tucfield);
+ }
+ else {
+ G_message(_("Calculating costs to centers ..."));
+ alloc_to_centers_loop_tt(&Map, Nodes, Centers, ncenters,
+ tucfield);
+ }
}
else {
if (from_centers) {
@@ -298,7 +305,7 @@
/* create attribute table:
* cat: new category
* ocat: original category in afield
- * centre: nearest centre
+ * center: nearest center
*/
Fi = Vect_default_field_info(&Out, 1, NULL, GV_MTABLE);
Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
@@ -332,9 +339,12 @@
db_begin_transaction(driver);
}
+ G_message(_("Allocating subnets..."));
nlines = Vect_get_num_lines(&Map);
ucat = 1;
for (line = 1; line <= nlines; line++) {
+ G_percent(line, nlines, 2);
+
ltype = Vect_read_line(&Map, Points, ICats, line);
if (!(ltype & type)) {
continue;
@@ -362,6 +372,10 @@
center2 = Nodes[node2].center;
s1cost = Nodes[node1].cost;
s2cost = Nodes[node2].cost;
+ if (s1cost > 0)
+ s1cost /= Map.dgraph.cost_multip;
+ if (s2cost > 0)
+ s2cost /= Map.dgraph.cost_multip;
Vect_net_get_node_cost(&Map, node1, &n1cost);
Vect_net_get_node_cost(&Map, node2, &n2cost);
Modified: grass/trunk/vector/v.net.alloc/v.net.alloc.html
===================================================================
--- grass/trunk/vector/v.net.alloc/v.net.alloc.html 2017-06-23 06:37:41 UTC (rev 71211)
+++ grass/trunk/vector/v.net.alloc/v.net.alloc.html 2017-06-23 06:55:26 UTC (rev 71212)
@@ -32,17 +32,15 @@
original line categories are copied from the input <b>arc_layer</b> to
layer 2 in the output, together with any attribute table.
<p>
-Application of flag <b>-t</b> enables a turntable support.
-This flag requires additional parameters <b>turn_layer</b> and <b>turn_cat_layer</b>
-that are otherwise ignored.
- The turntable allows
-to model e.g. traffic code, where some turns may be prohibited.
-This means that the input layer is expanded by
-turntable with costs of every possible turn on any possible node
-(intersection) in both directions.
- Turntable can be created by
- the <em><a href="v.net.html">v.net</a></em> module.
-For more information about turns in the vector network analyses see
+Application of flag <b>-t</b> enables a turntable support. This flag
+requires additional parameters <b>turn_layer</b> and
+<b>turn_cat_layer</b> that are otherwise ignored. The turntable allows
+to model e.g. traffic code, where some turns may be prohibited. This
+means that the input layer is expanded by turntable with costs of every
+possible turn on any possible node (intersection) in both directions.
+Turntable can be created by the <em><a href="v.net.html">v.net</a></em>
+module. For more information about turns in the vector network analyses
+see
<a href="http://grasswiki.osgeo.org/wiki/Turns_in_the_vector_network_analysis">wiki page</a>.
<h2>NOTES</h2>
Modified: grass/trunk/vector/v.net.iso/Makefile
===================================================================
--- grass/trunk/vector/v.net.iso/Makefile 2017-06-23 06:37:41 UTC (rev 71211)
+++ grass/trunk/vector/v.net.iso/Makefile 2017-06-23 06:55:26 UTC (rev 71212)
@@ -3,7 +3,7 @@
PGM = v.net.iso
-LIBES = $(VECTORLIB) $(DBMILIB) $(GISLIB)
+LIBES = $(VECTORLIB) $(DBMILIB) $(GISLIB) $(GRAPHLIB)
DEPENDENCIES = $(VECTORDEP) $(DBMIDEP) $(GISDEP)
EXTRA_INC = $(VECT_INC)
EXTRA_CFLAGS = $(VECT_CFLAGS)
Copied: grass/trunk/vector/v.net.iso/alloc.c (from rev 71192, grass/trunk/vector/v.net.alloc/alloc.c)
===================================================================
--- grass/trunk/vector/v.net.iso/alloc.c (rev 0)
+++ grass/trunk/vector/v.net.iso/alloc.c 2017-06-23 06:55:26 UTC (rev 71212)
@@ -0,0 +1,345 @@
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <grass/gis.h>
+#include <grass/vector.h>
+#include <grass/dbmi.h>
+#include <grass/dgl/graph.h>
+#include <grass/glocale.h>
+#include "alloc.h"
+
+int alloc_from_centers_loop_tt(struct Map_info *Map, NODE *Nodes,
+ CENTER *Centers, int ncenters,
+ int tucfield)
+{
+ int center, line, nlines, i;
+ int node1;
+ int cat;
+ struct line_cats *Cats;
+ struct line_pnts *Points;
+ double cost, n1cost, n2cost;
+ int ret;
+
+ Cats = Vect_new_cats_struct();
+ Points = Vect_new_line_struct();
+
+ nlines = Vect_get_num_lines(Map);
+
+ for (i = 2; i <= (nlines * 2 + 2); i++) {
+ Nodes[i].center = -1;/* NOTE: first two items of Nodes are not used */
+ Nodes[i].cost = -1;
+ Nodes[i].edge = 0;
+ }
+
+ for (center = 0; center < ncenters; center++) {
+ G_percent(center, ncenters, 1);
+ node1 = Centers[center].node;
+ Vect_net_get_node_cost(Map, node1, &n1cost);
+ G_debug(2, "center = %d node = %d cat = %d", center, node1,
+ Centers[center].cat);
+
+ for (line = 1; line <= nlines; line++) {
+ G_debug(5, " node1 = %d line = %d", node1, line);
+ Vect_net_get_node_cost(Map, line, &n2cost);
+ /* closed, left it as not attached */
+
+ if (Vect_read_line(Map, Points, Cats, line) < 0)
+ continue;
+ if (Vect_get_line_type(Map, line) != GV_LINE)
+ continue;
+ if (!Vect_cat_get(Cats, tucfield, &cat))
+ continue;
+
+ for (i = 0; i < 2; i++) {
+ if (i == 1)
+ cat *= -1;
+
+ ret =
+ Vect_net_ttb_shortest_path(Map, node1, 0, cat, 1,
+ tucfield, NULL,
+ &cost);
+ if (ret == -1) {
+ continue;
+ } /* node unreachable */
+
+ /* We must add center node costs (not calculated by Vect_net_shortest_path() ), but
+ * only if center and node are not identical, because at the end node cost is add later */
+ if (ret != 1)
+ cost += n1cost;
+
+ G_debug(5,
+ "Arc nodes: %d %d cost: %f (x old cent: %d old cost %f",
+ node1, line, cost, Nodes[line * 2 + i].center,
+ Nodes[line * 2 + i].cost);
+ if (Nodes[line * 2 + i].center == -1 ||
+ Nodes[line * 2 + i].cost > cost) {
+ Nodes[line * 2 + i].cost = cost;
+ Nodes[line * 2 + i].center = center;
+ }
+ }
+ }
+ }
+ G_percent(1, 1, 1);
+
+ Vect_destroy_cats_struct(Cats);
+ Vect_destroy_line_struct(Points);
+
+ return 0;
+}
+
+int alloc_to_centers_loop_tt(struct Map_info *Map, NODE *Nodes,
+ CENTER *Centers, int ncenters,
+ int tucfield)
+{
+ int center, line, nlines, i;
+ int node1;
+ int cat;
+ struct line_cats *Cats;
+ struct line_pnts *Points;
+ double cost, n1cost, n2cost;
+ int ret;
+
+ Cats = Vect_new_cats_struct();
+ Points = Vect_new_line_struct();
+
+ nlines = Vect_get_num_lines(Map);
+
+ for (i = 2; i <= (nlines * 2 + 2); i++) {
+ Nodes[i].center = -1;/* NOTE: first two items of Nodes are not used */
+ Nodes[i].cost = -1;
+ Nodes[i].edge = 0;
+ }
+
+ for (line = 1; line <= nlines; line++) {
+ G_debug(5, " line = %d", line);
+ Vect_net_get_node_cost(Map, line, &n2cost);
+ /* closed, left it as not attached */
+
+ if (Vect_read_line(Map, Points, Cats, line) < 0)
+ continue;
+ if (Vect_get_line_type(Map, line) != GV_LINE)
+ continue;
+ if (!Vect_cat_get(Cats, tucfield, &cat))
+ continue;
+
+ for (center = 0; center < ncenters; center++) {
+ G_percent(center, ncenters, 1);
+ node1 = Centers[center].node;
+ Vect_net_get_node_cost(Map, node1, &n1cost);
+ G_debug(2, "center = %d node = %d cat = %d", center, node1,
+ Centers[center].cat);
+
+ for (i = 0; i < 2; i++) {
+ if (i == 1)
+ cat *= -1;
+
+ ret =
+ Vect_net_ttb_shortest_path(Map, cat, 1, node1, 0,
+ tucfield, NULL,
+ &cost);
+ if (ret == -1) {
+ continue;
+ } /* node unreachable */
+
+ /* We must add center node costs (not calculated by Vect_net_shortest_path() ), but
+ * only if center and node are not identical, because at the end node cost is add later */
+ if (ret != 1)
+ cost += n1cost;
+
+ G_debug(5,
+ "Arc nodes: %d %d cost: %f (x old cent: %d old cost %f",
+ node1, line, cost, Nodes[line * 2 + i].center,
+ Nodes[line * 2 + i].cost);
+ if (Nodes[line * 2 + i].center == -1 ||
+ Nodes[line * 2 + i].cost > cost) {
+ Nodes[line * 2 + i].cost = cost;
+ Nodes[line * 2 + i].center = center;
+ }
+ }
+ }
+ }
+ G_percent(1, 1, 1);
+
+ Vect_destroy_cats_struct(Cats);
+ Vect_destroy_line_struct(Points);
+
+ return 0;
+}
+
+int alloc_from_centers(dglGraph_s *graph, NODE *Nodes, CENTER *Centers, int ncenters)
+{
+ int i, nnodes;
+ dglHeap_s heap;
+ dglEdgesetTraverser_s et;
+ int have_node_costs;
+ dglInt32_t ncost;
+
+ nnodes = dglGet_NodeCount(graph);
+
+ /* initialize nodes */
+ for (i = 1; i <= nnodes; i++) {
+ Nodes[i].cost = -1;
+ Nodes[i].center = -1;
+ Nodes[i].edge = 0;
+ }
+
+ ncost = 0;
+ have_node_costs = dglGet_NodeAttrSize(graph);
+
+ dglHeapInit(&heap);
+
+ for (i = 0; i < ncenters; i++) {
+ int v = Centers[i].node;
+
+ if (Nodes[v].cost == 0)
+ continue; /* ignore duplicates */
+ Nodes[v].cost = 0; /* make sure all centers are processed first */
+ Nodes[v].center = i;
+ 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;
+ dglInt32_t *edge;
+ dglInt32_t *node;
+
+ if (!dglHeapExtractMin(&heap, &heap_node))
+ break;
+ v = heap_node.value.ul;
+ dist = heap_node.key;
+ if (Nodes[v].cost < dist)
+ continue;
+
+ node = dglGetNode(graph, v);
+
+ if (have_node_costs && Nodes[v].edge) {
+ memcpy(&ncost, dglNodeGet_Attr(graph, node),
+ sizeof(ncost));
+ if (ncost > 0)
+ dist += ncost;
+ /* do not go through closed nodes */
+ if (ncost < 0)
+ continue;
+ }
+
+ dglEdgeset_T_Initialize(&et, graph,
+ dglNodeGet_OutEdgeset(graph, node));
+
+ for (edge = dglEdgeset_T_First(&et); edge;
+ edge = dglEdgeset_T_Next(&et)) {
+ dglInt32_t *to = dglEdgeGet_Tail(graph, edge);
+ dglInt32_t to_id = dglNodeGet_Id(graph, to);
+ dglInt32_t d = dglEdgeGet_Cost(graph, edge);
+
+ if (Nodes[to_id].cost < 0 || Nodes[to_id].cost > dist + d) {
+ Nodes[to_id].cost = dist + d;
+ Nodes[to_id].edge = dglEdgeGet_Id(graph, edge);
+ Nodes[to_id].center = Nodes[v].center;
+ heap_data.ul = to_id;
+ dglHeapInsertMin(&heap, dist + d, ' ', heap_data);
+ }
+ }
+
+ dglEdgeset_T_Release(&et);
+ }
+
+ dglHeapFree(&heap, NULL);
+
+ return 0;
+}
+
+int alloc_to_centers(dglGraph_s *graph, NODE *Nodes, CENTER *Centers, int ncenters)
+{
+ int i, nnodes;
+ dglHeap_s heap;
+ dglEdgesetTraverser_s et;
+ int have_node_costs;
+ dglInt32_t ncost;
+
+ if (graph->Version < 2) {
+ G_warning("Directed graph must be version 2 or 3 for distances to centers");
+ return -1;
+ }
+
+ nnodes = dglGet_NodeCount(graph);
+
+ /* initialize nodes */
+ for (i = 1; i <= nnodes; i++) {
+ Nodes[i].cost = -1;
+ Nodes[i].center = -1;
+ Nodes[i].edge = 0;
+ }
+
+ ncost = 0;
+ have_node_costs = dglGet_NodeAttrSize(graph);
+
+ dglHeapInit(&heap);
+
+ for (i = 0; i < ncenters; i++) {
+ int v = Centers[i].node;
+
+ if (Nodes[v].cost == 0)
+ continue; /* ignore duplicates */
+ Nodes[v].cost = 0; /* make sure all centers are processed first */
+ Nodes[v].center = i;
+ 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;
+ dglInt32_t *edge;
+ dglInt32_t *node;
+
+ if (!dglHeapExtractMin(&heap, &heap_node))
+ break;
+ v = heap_node.value.ul;
+ dist = heap_node.key;
+ if (Nodes[v].cost < dist)
+ continue;
+
+ node = dglGetNode(graph, v);
+
+ if (have_node_costs && Nodes[v].edge) {
+ memcpy(&ncost, dglNodeGet_Attr(graph, node),
+ sizeof(ncost));
+ if (ncost > 0)
+ dist += ncost;
+ /* do not go through closed nodes */
+ if (ncost < 0)
+ continue;
+ }
+
+ dglEdgeset_T_Initialize(&et, graph,
+ dglNodeGet_InEdgeset(graph, node));
+
+ 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 (Nodes[from_id].cost < 0 || Nodes[from_id].cost > dist + d) {
+ Nodes[from_id].cost = dist + d;
+ Nodes[from_id].edge = dglEdgeGet_Id(graph, edge);
+ Nodes[from_id].center = Nodes[v].center;
+ heap_data.ul = from_id;
+ dglHeapInsertMin(&heap, dist + d, ' ', heap_data);
+ }
+ }
+
+ dglEdgeset_T_Release(&et);
+ }
+
+ dglHeapFree(&heap, NULL);
+
+ return 0;
+}
+
Copied: grass/trunk/vector/v.net.iso/alloc.h (from rev 71192, grass/trunk/vector/v.net.alloc/alloc.h)
===================================================================
--- grass/trunk/vector/v.net.iso/alloc.h (rev 0)
+++ grass/trunk/vector/v.net.iso/alloc.h 2017-06-23 06:55:26 UTC (rev 71212)
@@ -0,0 +1,23 @@
+
+typedef struct
+{
+ int cat; /* category number */
+ int node; /* node number */
+} CENTER;
+
+typedef struct
+{
+ int center; /* neares center, initially -1 */
+ double cost; /* costs from this center, initially not defined */
+ int edge; /* edge to follow from this node */
+} NODE;
+
+int alloc_from_centers_loop_tt(struct Map_info *Map, NODE *Nodes,
+ CENTER *Centers, int ncenters,
+ int tucfield);
+int alloc_to_centers_loop_tt(struct Map_info *Map, NODE *Nodes,
+ CENTER *Centers, int ncenters,
+ int tucfield);
+
+int alloc_from_centers(dglGraph_s *graph, NODE *Nodes, CENTER *Centers, int ncenters);
+int alloc_to_centers(dglGraph_s *graph, NODE *Nodes, CENTER *Centers, int ncenters);
Modified: grass/trunk/vector/v.net.iso/main.c
===================================================================
--- grass/trunk/vector/v.net.iso/main.c 2017-06-23 06:37:41 UTC (rev 71211)
+++ grass/trunk/vector/v.net.iso/main.c 2017-06-23 06:55:26 UTC (rev 71212)
@@ -1,21 +1,22 @@
/****************************************************************
*
- * MODULE: v.net.iso
- *
- * AUTHOR(S): Radim Blazek
- * Stepan Turek <stepan.turek seznam.cz> (turns support)
+ * MODULE: v.net.iso
+ *
+ * AUTHOR(S): Radim Blazek
+ * Stepan Turek <stepan.turek seznam.cz> (turns support)
+ * Markus Metz (costs from/to centers; attributes)
*
- * PURPOSE: Split net to bands between isolines.
+ * PURPOSE: Split net to bands between isolines.
*
- * COPYRIGHT: (C) 2001-2008,2014 by the GRASS Development Team
+ * COPYRIGHT: (C) 2001-2008,2014,2017 by the GRASS Development Team
*
- * This program is free software under the
- * GNU General Public License (>=v2).
- * Read the file COPYING that comes with GRASS
- * for details.
+ * This program is free software under the
+ * GNU General Public License (>=v2).
+ * Read the file COPYING that comes with GRASS
+ * for details.
*
- **************************************************************/
+ ****************************************************************/
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -23,33 +24,23 @@
#include <grass/vector.h>
#include <grass/dbmi.h>
#include <grass/glocale.h>
+#include "alloc.h"
typedef struct
-{
- int cat; /* category number */
- int node; /* node number */
-} CENTER;
-
-typedef struct
-{
- int centre; /* nearest centre, initially -1 *//* currently not used */
- double cost; /* costs from this centre, initially not undefined */
-} NODE;
-
-typedef struct
{ /* iso point along the line */
int iso; /* index of iso line in iso array of costs */
double distance; /* distance along the line from the beginning for both directions */
- int centre; /* nearest centre */
+ int center; /* nearest center */
} ISOPOINT;
int main(int argc, char **argv)
{
- int i, j, ret, centre, line, centre1, centre2, tfield, tucfield;
+ int i, ret, line, center1, center2;
int nlines, nnodes, type, ltype, afield, nfield, geo, cat;
- int node, node1, node2;
- double cost, e1cost, e2cost, n1cost, n2cost, s1cost, s2cost, l, l1;
- struct Option *map, *output;
+ int tfield, tucfield;
+ int node1, node2;
+ double e1cost, e2cost, n1cost, n2cost, s1cost, s2cost, l, l1;
+ struct Option *map, *output, *method_opt;
struct Option *afield_opt, *nfield_opt, *afcol, *abcol, *ncol, *type_opt,
*term_opt, *cost_opt, *tfield_opt, *tucfield_opt;
struct Flag *geo_f, *turntable_f, *ucat_f;
@@ -57,10 +48,12 @@
struct Map_info Map, Out;
struct cat_list *catlist;
CENTER *Centers = NULL;
- int acentres = 0, ncentres = 0;
+ int acenters = 0, ncenters = 0;
NODE *Nodes;
struct line_cats *Cats, *ICats, *OCats;
struct line_pnts *Points, *SPoints;
+ int graph_version;
+ int from_centers;
int niso, aiso;
double *iso;
char **isolbl;
@@ -75,22 +68,33 @@
dbDriver *driver;
struct field_info *Fi;
+ /* initialize GIS environment */
G_gisinit(argv[0]);
+ /* initialize module */
module = G_define_module();
G_add_keyword(_("vector"));
G_add_keyword(_("network"));
+ G_add_keyword(_("cost allocation"));
G_add_keyword(_("isolines"));
- module->label = _("Splits net by cost isolines.");
+ module->label = _("Splits subnets for nearest centers by cost isolines.");
module->description =
- _
- ("Splits net to bands between cost isolines (direction from center). "
- "Center node must be opened (costs >= 0). "
- "Costs of center node are used in calculation.");
+ _("Splits net to bands between cost isolines (direction from center). "
+ "Center node must be opened (costs >= 0). "
+ "Costs of center node are used in calculation.");
map = G_define_standard_option(G_OPT_V_INPUT);
output = G_define_standard_option(G_OPT_V_OUTPUT);
+ method_opt = G_define_option();
+ method_opt->key = "method";
+ method_opt->type = TYPE_STRING;
+ method_opt->required = NO;
+ method_opt->options = "from,to";
+ method_opt->answer = "from";
+ method_opt->description = _("Use costs from centers or costs to centers");
+ method_opt->guisection = _("Cost");
+
term_opt = G_define_standard_option(G_OPT_V_CATS);
term_opt->key = "center_cats";
term_opt->required = YES;
@@ -244,19 +248,28 @@
tucfield = Vect_get_field_number(&Map, tucfield_opt->answer);
/* Build graph */
+ graph_version = 1;
+ from_centers = 1;
+ if (method_opt->answer[0] == 't') {
+ from_centers = 0;
+ if (!turntable_f->answer)
+ graph_version = 2;
+ }
if (turntable_f->answer)
Vect_net_ttb_build_graph(&Map, type, afield, nfield, tfield, tucfield,
afcol->answer, abcol->answer, ncol->answer,
geo, 0);
else
Vect_net_build_graph(&Map, type, afield, nfield, afcol->answer,
- abcol->answer, ncol->answer, geo, 0);
+ abcol->answer, ncol->answer, geo, graph_version);
nnodes = Vect_get_num_nodes(&Map);
nlines = Vect_get_num_lines(&Map);
- /* Create list of centres based on list of categories */
+ /* Create list of centers based on list of categories */
for (i = 1; i <= nlines; i++) {
+ int node;
+
ltype = Vect_get_line_type(&Map, i);
if (!(ltype & GV_POINT))
continue;
@@ -274,128 +287,69 @@
if (Vect_cat_in_cat_list(cat, catlist)) {
Vect_net_get_node_cost(&Map, node, &n1cost);
if (n1cost == -1) { /* closed */
- G_warning(_("Centre at closed node (costs = -1) ignored"));
+ G_warning(_("Center at closed node (costs = -1) ignored"));
}
else {
- if (acentres == ncentres) {
- acentres += 1;
+ if (acenters == ncenters) {
+ acenters += 1;
Centers =
(CENTER *) G_realloc(Centers,
- acentres * sizeof(CENTER));
+ acenters * sizeof(CENTER));
}
- Centers[ncentres].cat = cat;
- Centers[ncentres].node = node;
- G_debug(2, "centre = %d node = %d cat = %d", ncentres,
+ Centers[ncenters].cat = cat;
+ Centers[ncenters].node = node;
+ G_debug(2, "center = %d node = %d cat = %d", ncenters,
node, cat);
- ncentres++;
+ ncenters++;
}
}
}
- G_message(_("Number of centres: %d (nlayer %d)"), ncentres, nfield);
+ G_message(_("Number of centers: %d (nlayer %d)"), ncenters, nfield);
- if (ncentres == 0)
- G_warning(_
- ("Not enough centres for selected nlayer. Nothing will be allocated."));
+ if (ncenters == 0)
+ G_warning(_("Not enough centers for selected nlayer. Nothing will be allocated."));
/* alloc and reset space for all nodes */
if (turntable_f->answer) {
/* if turntable is used we are looking for lines as destinations, instead of the intersections (nodes) */
Nodes = (NODE *) G_calloc((nlines * 2 + 2), sizeof(NODE));
for (i = 2; i <= (nlines * 2 + 2); i++) {
- Nodes[i].centre = -1;/* NOTE: first two items of Nodes are not used */
+ Nodes[i].center = -1;/* NOTE: first two items of Nodes are not used */
}
}
else {
Nodes = (NODE *) G_calloc((nnodes + 1), sizeof(NODE));
for (i = 1; i <= nnodes; i++) {
- Nodes[i].centre = -1;
+ Nodes[i].center = -1;
}
}
- apnts1 = 1;
- pnts1 = (ISOPOINT *) G_malloc(apnts1 * sizeof(ISOPOINT));
+ /* Fill Nodes by nearest center and costs from that center */
- apnts2 = 1;
- pnts2 = (ISOPOINT *) G_malloc(apnts2 * sizeof(ISOPOINT));
-
- /* Fill Nodes by nearest centre and costs from that centre */
- for (centre = 0; centre < ncentres; centre++) {
- node1 = Centers[centre].node;
- Vect_net_get_node_cost(&Map, node1, &n1cost);
- G_debug(2, "centre = %d node = %d cat = %d", centre, node1,
- Centers[centre].cat);
- G_message(_("Calculating costs from centre %d..."), centre + 1);
- if (turntable_f->answer)
- for (line = 1; line <= nlines; line++) {
- G_debug(5, " node1 = %d line = %d", node1, line);
- Vect_net_get_node_cost(&Map, line, &n2cost);
- /* closed, left it as not attached */
-
- if (Vect_read_line(&Map, Points, Cats, line) < 0)
- continue;
- if (Vect_get_line_type(&Map, line) != GV_LINE)
- continue;
- if (!Vect_cat_get(Cats, tucfield, &cat))
- continue;
-
- for (j = 0; j < 2; j++) {
- if (j == 1)
- cat *= -1;
-
- ret =
- Vect_net_ttb_shortest_path(&Map, node1, 0, cat, 1,
- tucfield, NULL,
- &cost);
- if (ret == -1) {
- continue;
- } /* node unreachable */
-
- /* We must add centre node costs (not calculated by Vect_net_shortest_path() ), but
- * only if centre and node are not identical, because at the end node cost is add later */
- if (ret != 1)
- cost += n1cost;
-
- G_debug(5,
- "Arc nodes: %d %d cost: %f (x old cent: %d old cost %f",
- node1, line, cost, Nodes[line * 2 + j].centre,
- Nodes[line * 2 + j].cost);
- if (Nodes[line * 2 + j].centre == -1 ||
- cost < Nodes[line * 2 + j].cost) {
- Nodes[line * 2 + j].cost = cost;
- Nodes[line * 2 + j].centre = centre;
- }
- }
- }
- else
- for (node2 = 1; node2 <= nnodes; node2++) {
- G_percent(node2, nnodes, 1);
- G_debug(5, " node1 = %d node2 = %d", node1, node2);
- Vect_net_get_node_cost(&Map, node2, &n2cost);
- if (n2cost == -1) {
- continue;
- } /* closed, left it as not attached */
-
- ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &cost);
- if (ret == -1) {
- continue;
- } /* node unreachable */
-
- /* We must add centre node costs (not calculated by Vect_net_shortest_path() ), but
- * only if centre and node are not identical, because at the end node cost is add later */
- if (node1 != node2)
- cost += n1cost;
- G_debug(5,
- "Arc nodes: %d %d cost: %f (x old cent: %d old cost %f",
- node1, node2, cost, Nodes[node2].centre,
- Nodes[node2].cost);
- if (Nodes[node2].centre == -1 || cost < Nodes[node2].cost) {
- Nodes[node2].cost = cost;
- Nodes[node2].centre = centre;
- }
- }
+ if (turntable_f->answer) {
+ if (from_centers) {
+ G_message(_("Calculating costs from centers ..."));
+ alloc_from_centers_loop_tt(&Map, Nodes, Centers, ncenters,
+ tucfield);
+ }
+ else {
+ G_message(_("Calculating costs to centers ..."));
+ alloc_to_centers_loop_tt(&Map, Nodes, Centers, ncenters,
+ tucfield);
+ }
}
+ else {
+ if (from_centers) {
+ G_message(_("Calculating costs from centers ..."));
+ alloc_from_centers(Vect_net_get_graph(&Map), Nodes, Centers, ncenters);
+ }
+ else {
+ G_message(_("Calculating costs to centers ..."));
+ alloc_to_centers(Vect_net_get_graph(&Map), Nodes, Centers, ncenters);
+ }
+ }
/* Write arcs to new map */
if (Vect_open_new(&Out, output->answer, Vect_is_3d(&Map)) < 0)
@@ -409,7 +363,7 @@
/* create attribute table:
* cat: new category
* ocat: original category in afield
- * centre: nearest centre
+ * center: nearest center
* isonr: iso zone number
* isolbl: iso zone label
*/
@@ -446,8 +400,11 @@
db_begin_transaction(driver);
}
- G_message("Generating isolines...");
- nlines = Vect_get_num_lines(&Map);
+ G_message(_("Generating isolines..."));
+ apnts1 = 1;
+ pnts1 = (ISOPOINT *) G_malloc(apnts1 * sizeof(ISOPOINT));
+ apnts2 = 1;
+ pnts2 = (ISOPOINT *) G_malloc(apnts2 * sizeof(ISOPOINT));
ucat = 1;
for (line = 1; line <= nlines; line++) {
G_percent(line, nlines, 2);
@@ -471,29 +428,39 @@
}
if (turntable_f->answer) {
- centre1 = Nodes[line * 2].centre;
- centre2 = Nodes[line * 2 + 1].centre;
+ center1 = Nodes[line * 2].center;
+ center2 = Nodes[line * 2 + 1].center;
s1cost = Nodes[line * 2].cost;
s2cost = Nodes[line * 2 + 1].cost;
n1cost = n2cost = 0;
}
else {
Vect_get_line_nodes(&Map, line, &node1, &node2);
- centre1 = Nodes[node1].centre;
- centre2 = Nodes[node2].centre;
+ center1 = Nodes[node1].center;
+ center2 = Nodes[node2].center;
s1cost = Nodes[node1].cost;
s2cost = Nodes[node2].cost;
+ if (s1cost > 0)
+ s1cost /= Map.dgraph.cost_multip;
+ if (s2cost > 0)
+ s2cost /= Map.dgraph.cost_multip;
Vect_net_get_node_cost(&Map, node1, &n1cost);
Vect_net_get_node_cost(&Map, node2, &n2cost);
+ }
+ if (from_centers) {
+ Vect_net_get_line_cost(&Map, line, GV_FORWARD, &e1cost);
+ Vect_net_get_line_cost(&Map, line, GV_BACKWARD, &e2cost);
}
+ else {
+ /* from node to center */
+ Vect_net_get_line_cost(&Map, line, GV_FORWARD, &e2cost);
+ Vect_net_get_line_cost(&Map, line, GV_BACKWARD, &e1cost);
+ }
- Vect_net_get_line_cost(&Map, line, GV_FORWARD, &e1cost);
- Vect_net_get_line_cost(&Map, line, GV_BACKWARD, &e2cost);
-
G_debug(3, "Line %d : length = %f", line, l);
- G_debug(3, "Arc centres: %d %d (nodes: %d %d)", centre1, centre2,
+ G_debug(3, "Arc centers: %d %d (nodes: %d %d)", center1, center2,
node1, node2);
G_debug(3, " s1cost = %f n1cost = %f e1cost = %f", s1cost, n1cost,
@@ -503,23 +470,27 @@
/* First check if arc is reachable from at least one side */
- if ((centre1 != -1 && n1cost != -1 && e1cost != -1) ||
- (centre2 != -1 && n2cost != -1 && e2cost != -1)) {
+ if ((center1 != -1 && n1cost != -1 && e1cost != -1) ||
+ (center2 != -1 && n2cost != -1 && e2cost != -1)) {
/* Line is reachable at least from one side */
G_debug(3, " -> arc is reachable");
/* Add costs of node to starting costs */
- s1cost += n1cost;
- s2cost += n2cost;
+ if (s1cost >= 0 && n1cost > 0)
+ s1cost += n1cost;
+ if (s2cost >= 0 && n2cost > 0)
+ s2cost += n2cost;
- e1cost /= l;
- e2cost /= l;
+ if (e1cost > 0)
+ e1cost /= l;
+ if (e2cost > 0)
+ e2cost /= l;
/* Find points on isolines along the line in both directions, add them to array,
* first point is placed at the beginning/end of line */
/* Forward */
npnts1 = 0; /* in case this direction is closed */
- if (centre1 != -1 && n1cost != -1 && e1cost != -1) {
+ if (center1 != -1 && n1cost != -1 && e1cost != -1) {
/* Find iso for beginning of the line */
next_iso = 0;
for (i = niso - 1; i >= 0; i--) {
@@ -531,7 +502,7 @@
/* Add first */
pnts1[0].iso = next_iso;
pnts1[0].distance = 0;
- pnts1[0].centre = centre1;
+ pnts1[0].center = center1;
npnts1++;
next_iso++;
@@ -551,7 +522,7 @@
}
pnts1[npnts1].iso = next_iso;
pnts1[npnts1].distance = l1;
- pnts1[npnts1].centre = centre1;
+ pnts1[npnts1].center = center1;
G_debug(3,
" forward %d : iso %d : distance %f : cost %f",
npnts1, next_iso, l1, iso[next_iso]);
@@ -563,7 +534,7 @@
/* Backward */
npnts2 = 0;
- if (centre2 != -1 && n2cost != -1 && e2cost != -1) {
+ if (center2 != -1 && n2cost != -1 && e2cost != -1) {
/* Find iso for beginning of the line */
next_iso = 0;
for (i = niso - 1; i >= 0; i--) {
@@ -575,7 +546,7 @@
/* Add first */
pnts2[0].iso = next_iso;
pnts2[0].distance = l;
- pnts2[0].centre = centre2;
+ pnts2[0].center = center2;
npnts2++;
next_iso++;
@@ -595,7 +566,7 @@
}
pnts2[npnts2].iso = next_iso;
pnts2[npnts2].distance = l - l1;
- pnts2[npnts2].centre = centre2;
+ pnts2[npnts2].center = center2;
G_debug(3,
" backward %d : iso %d : distance %f : cost %f",
npnts2, next_iso, l - l1, iso[next_iso]);
@@ -648,7 +619,6 @@
npnts2--;
}
else {
-
break;
}
}
@@ -657,7 +627,8 @@
G_debug(3, " npnts2 2. cut = %d", npnts2);
if (npnts1 > 0 && npnts2 > 0) {
- if (pnts1[npnts1 - 1].centre != pnts2[npnts2 - 1].centre) {
+ if (pnts1[npnts1 - 1].center != pnts2[npnts2 - 1].center &&
+ e1cost >= 0 && e2cost >= 0) {
if (npnts1 == apnts1) {
apnts1 += 1;
@@ -665,10 +636,20 @@
(ISOPOINT *) G_realloc(pnts1,
apnts1 * sizeof(ISOPOINT));
}
- pnts1[npnts1].centre = pnts2[npnts2 - 1].centre;
- pnts1[npnts1].iso = pnts2[npnts2 - 1].iso;
- pnts1[npnts1].distance = (pnts1[npnts1 - 1].distance + pnts2[npnts2 - 1].distance) / 2.0;
- npnts1++;
+ if (e1cost + e2cost == 0) {
+ if (s1cost + s2cost == 0)
+ l1 = l / 2.;
+ else
+ l1 = l * s1cost / (s1cost + s2cost);
+ }
+ else
+ l1 = (l * e2cost - s1cost + s2cost) / (e1cost + e2cost);
+ if (l1 != pnts1[npnts1 - 1].distance) {
+ pnts1[npnts1].distance = l1;
+ pnts1[npnts1].iso = pnts2[npnts2 - 1].iso;
+ pnts1[npnts1].center = pnts2[npnts2 - 1].center;
+ npnts1++;
+ }
}
}
@@ -683,7 +664,7 @@
pnts2[npnts2 - 1].iso);
pnts1[0].iso = pnts2[npnts2 - 1].iso; /* use last point iso in reverse direction */
pnts1[0].distance = 0;
- pnts1[0].centre = pnts2[npnts2 - 1].centre;
+ pnts1[0].center = pnts2[npnts2 - 1].center;
npnts1++;
}
for (i = npnts2 - 1; i >= 0; i--) {
@@ -699,14 +680,14 @@
}
pnts1[npnts1].iso = pnts2[i].iso - 1; /* last may be -1, but it is not used */
pnts1[npnts1].distance = pnts2[i].distance;
- pnts1[npnts1].centre = pnts2[i].centre;
+ pnts1[npnts1].center = pnts2[i].center;
npnts1++;
}
/* In case npnts2 == 0 add point at the end */
if (npnts2 == 0) {
pnts1[npnts1].iso = 0; /* not used */
pnts1[npnts1].distance = l;
- pnts1[npnts1].centre = centre1;
+ pnts1[npnts1].center = center1;
npnts1++;
}
@@ -734,7 +715,7 @@
sprintf(buf,
"insert into %s values ( %d, %d, %d, %d, \'%s\')",
- Fi->table, ucat, ocat, Centers[pnts1[i - 1].centre].cat,
+ Fi->table, ucat, ocat, Centers[pnts1[i - 1].center].cat,
pnts1[i - 1].iso + 1, isolbl[pnts1[i - 1].iso]);
db_set_string(&sql, buf);
G_debug(3, "%s", db_get_string(&sql));
Modified: grass/trunk/vector/v.net.iso/v.net.iso.html
===================================================================
--- grass/trunk/vector/v.net.iso/v.net.iso.html 2017-06-23 06:37:41 UTC (rev 71211)
+++ grass/trunk/vector/v.net.iso/v.net.iso.html 2017-06-23 06:55:26 UTC (rev 71212)
@@ -15,6 +15,12 @@
and also different costs for both directions of a vector line.
For areas, costs will be calculated along boundary lines.
<p>
+The input vector needs to be prepared with <em>v.net operation=connect</em>
+in order to connect points representing center nodes to the network.
+<p>
+The nearest center can be determined using either costs from the
+nearest center or costs to the nearest center with option
+<b>method</b>.<p>
By default, the iso band number is used as category value for output
lines. With the <b>-u</b> flag, output lines become unique categories
and an attribute table is created with the fields <em>cat, ocat,
@@ -26,17 +32,15 @@
input <b>arc_layer</b> to layer 2 in the output, together with any
attribute table.
<p>
-Application of flag <b>-t</b> enables a turntable support.
-This flag requires additional parameters <b>turn_layer</b> and <b>turn_cat_layer</b>
-that are otherwise ignored.
- The turntable allows
-to model e.g. traffic code, where some turns may be prohibited.
-This means that the input layer is expanded by
-turntable with costs of every possible turn on any possible node
-(intersection) in both directions.
- Turntable can be created by
- the <em><a href="v.net.html">v.net</a></em> module.
-For more information about turns in the vector network analyses see
+Application of flag <b>-t</b> enables a turntable support. This flag
+requires additional parameters <b>turn_layer</b> and
+<b>turn_cat_layer</b> that are otherwise ignored. The turntable allows
+to model e.g. traffic code, where some turns may be prohibited. This
+means that the input layer is expanded by turntable with costs of every
+possible turn on any possible node (intersection) in both directions.
+Turntable can be created by the <em><a href="v.net.html">v.net</a></em>
+module. For more information about turns in the vector network analyses
+see
<a href="http://grasswiki.osgeo.org/wiki/Turns_in_the_vector_network_analysis">wiki page</a>.
<h2>NOTES</h2>
More information about the grass-commit
mailing list