[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