[GRASS-SVN] r38558 - in grass-addons/vector/net.analyze: . netalib v.net.allpairs v.net.bridge v.net.centrality v.net.components v.net.connectivity v.net.distance v.net.flow v.net.spanningtree v.net.timetable

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Jul 31 14:20:49 EDT 2009


Author: dano
Date: 2009-07-31 14:20:49 -0400 (Fri, 31 Jul 2009)
New Revision: 38558

Added:
   grass-addons/vector/net.analyze/netalib/timetables.c
   grass-addons/vector/net.analyze/v.net.allpairs/description.html
   grass-addons/vector/net.analyze/v.net.bridge/description.html
   grass-addons/vector/net.analyze/v.net.centrality/description.html
   grass-addons/vector/net.analyze/v.net.components/description.html
   grass-addons/vector/net.analyze/v.net.flow/description.html
   grass-addons/vector/net.analyze/v.net.spanningtree/v.net.spanningtree.tmp.html
   grass-addons/vector/net.analyze/v.net.timetable/
   grass-addons/vector/net.analyze/v.net.timetable/Makefile
   grass-addons/vector/net.analyze/v.net.timetable/main.c
Modified:
   grass-addons/vector/net.analyze/Makefile
   grass-addons/vector/net.analyze/netalib/centrality.c
   grass-addons/vector/net.analyze/netalib/flow.c
   grass-addons/vector/net.analyze/netalib/neta.h
   grass-addons/vector/net.analyze/netalib/path.c
   grass-addons/vector/net.analyze/netalib/utils.c
   grass-addons/vector/net.analyze/v.net.allpairs/main.c
   grass-addons/vector/net.analyze/v.net.bridge/main.c
   grass-addons/vector/net.analyze/v.net.centrality/main.c
   grass-addons/vector/net.analyze/v.net.components/main.c
   grass-addons/vector/net.analyze/v.net.connectivity/main.c
   grass-addons/vector/net.analyze/v.net.distance/main.c
   grass-addons/vector/net.analyze/v.net.flow/main.c
   grass-addons/vector/net.analyze/v.net.spanningtree/main.c
Log:
New module: v.net.timetable, several bux fixes and documentation

Modified: grass-addons/vector/net.analyze/Makefile
===================================================================
--- grass-addons/vector/net.analyze/Makefile	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/Makefile	2009-07-31 18:20:49 UTC (rev 38558)
@@ -8,7 +8,8 @@
         v.net.flow \
         v.net.connectivity \
         v.net.centrality \
-        v.net.distance
+        v.net.distance \
+        v.net.timetable
 
 SUBDIRS = netalib $(SUBDIRS1)
 

Modified: grass-addons/vector/net.analyze/netalib/centrality.c
===================================================================
--- grass-addons/vector/net.analyze/netalib/centrality.c	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/netalib/centrality.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -97,7 +97,7 @@
 int neta_betweenness_closeness(dglGraph_s * graph, double *betweenness,
 			       double *closeness)
 {
-    int i, j, nnodes, stack_size;
+    int i, j, nnodes, stack_size, count;
     dglInt32_t *dst, *node, *stack, *cnt, *delta;
     dglNodeTraverser_s nt;
     dglEdgesetTraverser_s et;
@@ -126,9 +126,11 @@
 	    betweenness[i] = 0;
     }
 
-
+    count = 0;
+    G_percent_reset();
     dglNode_T_Initialize(&nt, graph);
     for (node = dglNode_T_First(&nt); node; node = dglNode_T_Next(&nt)) {
+	G_percent(count++, nnodes, 1);
 	dglInt32_t s = dglNodeGet_Id(graph, node);
 	dglHeapData_u heap_data;
 	dglHeapNode_s heap_node;

Modified: grass-addons/vector/net.analyze/netalib/flow.c
===================================================================
--- grass-addons/vector/net.analyze/netalib/flow.c	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/netalib/flow.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -65,6 +65,7 @@
 
     for (i = 0; i <= nlines; i++)
 	flow[i] = 0;
+
     total_flow = 0;
     while (1) {
 	dglInt32_t node, edge_id, min_residue;

Modified: grass-addons/vector/net.analyze/netalib/neta.h
===================================================================
--- grass-addons/vector/net.analyze/netalib/neta.h	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/netalib/neta.h	2009-07-31 18:20:49 UTC (rev 38558)
@@ -27,39 +27,89 @@
 #include <grass/glocale.h>
 #include <grass/dgl/graph.h>
 
-/*neta_bridge.c*/
-int neta_compute_bridges(dglGraph_s *graph, struct ilist *bridge_list);
-int neta_articulation_points(dglGraph_s *graph, struct ilist *articulation_list);
+/*bridge.c */
+int neta_compute_bridges(dglGraph_s * graph, struct ilist *bridge_list);
+int neta_articulation_points(dglGraph_s * graph,
+			     struct ilist *articulation_list);
 
-/*neta_components.c*/
-int neta_weakly_connected_components(dglGraph_s *graph, int *component);
-int neta_strongly_connected_components(dglGraph_s *graph, int *component);
+/*components.c */
+int neta_weakly_connected_components(dglGraph_s * graph, int *component);
+int neta_strongly_connected_components(dglGraph_s * graph, int *component);
 
-/*neta_spanningtree.c*/
-int neta_spanning_tree(dglGraph_s *graph, struct ilist *tree_list);
+/*spanningtree.c */
+int neta_spanning_tree(dglGraph_s * graph, struct ilist *tree_list);
 
-/*neta_allpairs.c*/
-int neta_allpairs(dglGraph_s *graph, dglInt32_t **dist);
+/*allpairs.c */
+int neta_allpairs(dglGraph_s * graph, dglInt32_t ** dist);
 
-/*neta_utils.c*/
-void neta_add_point_on_node(struct Map_info *In, struct Map_info *Out, int node, struct line_cats *Cats);
+/*neta_flow.c */
+int neta_flow(dglGraph_s * graph, struct ilist *source_list,
+	      struct ilist *sink_list, int *flow);
+int neta_min_cut(dglGraph_s * graph, struct ilist *source_list,
+		 struct ilist *sink_list, int *flow, struct ilist *cut);
+int neta_split_vertices(dglGraph_s * in, dglGraph_s * out, int *node_costs);
 
-/*neta_flow.c*/
-int neta_flow(dglGraph_s * graph, struct ilist *source_list, struct ilist *sink_list, int *flow);
-int neta_min_cut(dglGraph_s *graph, struct ilist *source_list, struct ilist *sink_list, int *flow, struct ilist *cut);
-int neta_split_vertices(dglGraph_s *in, dglGraph_s *out, int *node_costs);
-
-/*utils.c*/
+/*utils.c */
 void neta_add_point_on_node(struct Map_info *In, struct Map_info *Out, int node,
 			    struct line_cats *Cats);
 void neta_points_to_nodes(struct Map_info *In, struct ilist *point_list);
-int neta_get_node_costs(struct Map_info *In, int layer, char *column, int *node_costs);
-void neta_varray_to_nodes(struct Map_info *map, VARRAY *varray, struct ilist *nodes, int *nodes_to_features);
-/*centrality.c*/
+int neta_get_node_costs(struct Map_info *In, int layer, char *column,
+			int *node_costs);
+void neta_varray_to_nodes(struct Map_info *map, VARRAY * varray,
+			  struct ilist *nodes, int *nodes_to_features);
+int neta_initialise_varray(struct Map_info *In, int layer, int mask_type,
+			   char *where, char *cat, VARRAY ** varray);
+/*centrality.c */
 void neta_degree_centrality(dglGraph_s * graph, double *degree);
-int neta_eigenvector_centrality(dglGraph_s *graph, int iterations, double error, double *eigenvector);
-int neta_betweenness_closeness(dglGraph_s * graph, double *betweenness, double *closeness);
+int neta_eigenvector_centrality(dglGraph_s * graph, int iterations,
+				double error, double *eigenvector);
+int neta_betweenness_closeness(dglGraph_s * graph, double *betweenness,
+			       double *closeness);
 
-/*path.c*/
-int neta_distance_from_points(dglGraph_s *graph, struct ilist *from, int *dst, dglInt32_t **prev);
+/*path.c */
+int neta_distance_from_points(dglGraph_s * graph, struct ilist *from, int *dst,
+			      dglInt32_t ** prev);
+int neta_find_path(dglGraph_s * graph, int from, int to, int *edges,
+		   struct ilist *list);
+
+/*timetables.c */
+
+/*Structure containing all information about a timetable.
+ * Everything in indexed from 0.
+ */
+typedef struct
+{
+    int routes;			/*Number of different routes. Two routes are different even if they differ only in time. */
+    int *route_length;		/*Length of each route, i.e., number of stops */
+    int **route_stops;		/*list of stops on each route in order (time increases) */
+    int **route_times;		/*stop arrival times on overy route. Stops are given in the same order as above */
+    int stops;			/*number of stops */
+    int *stop_length;		/*Number of routes stopping at each stop */
+    int **stop_routes;		/*List of routes for each stop. Routes are in increasing order */
+    int **stop_times;		/*arrival times of routes for each stop. Routes are given in the same order as above */
+    int *walk_length;		/*number of stops with "walking connection" for each stop */
+    int **walk_stops;		/*list of stops within walking distance for each stop */
+    int **walk_times;		/*walking times between stops as given above */
+} neta_timetable;
+
+typedef struct
+{
+    int **dst;
+    int **prev_stop;
+    int **prev_route;
+    int **prev_conn;
+    int rows, routes;
+} neta_timetable_result;
+
+int neta_init_timetable_from_db(struct Map_info *In, int route_layer,
+				int walk_layer, char *route_id, char *times,
+				neta_timetable * timetable, int **route_ids,
+				int **stop_ids);
+int neta_timetable_shortest_path(neta_timetable * timetable, int from_stop,
+				 int to_stop, int start_time, int min_change,
+				 int max_changes, int walking_change,
+				 neta_timetable_result * result);
+int neta_timetable_get_route_time(neta_timetable * timetable, int stop,
+				  int route);
+void neta_timetable_result_release(neta_timetable_result * result);
 #endif

Modified: grass-addons/vector/net.analyze/netalib/path.c
===================================================================
--- grass-addons/vector/net.analyze/netalib/path.c	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/netalib/path.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -85,3 +85,65 @@
 
     return 0;
 }
+
+/*Find a path (minimum number of edges) from 'from' to 'to' using only edges in 'edges'. Precisely, edge with
+ * id I is used iff edges[abs(i)] == 1. List stores the indices of lines on the path. Method return number of
+ * edges or -1 if no path exist */
+int neta_find_path(dglGraph_s * graph, int from, int to, int *edges,
+		   struct ilist *list)
+{
+    dglInt32_t **prev, *queue;
+    dglEdgesetTraverser_s et;
+    char *vis;
+    int begin, end, cur, nnodes;
+
+    nnodes = dglGet_NodeCount(graph);
+    prev = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
+    queue = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
+    vis = (char *)G_calloc(nnodes + 1, sizeof(char));
+    if (!prev || !queue || !vis) {
+	G_fatal_error(_("Out of memory"));
+	return -1;
+    }
+    Vect_reset_list(list);
+
+    begin = 0;
+    end = 1;
+    vis[from] = 'y';
+    queue[0] = from;
+    prev[from] = NULL;
+    while (begin != end) {
+	dglInt32_t vertex = queue[begin++];
+	if (vertex == to)
+	    break;
+	dglInt32_t *edge, *node = dglGetNode(graph, vertex);
+	dglEdgeset_T_Initialize(&et, graph, dglNodeGet_OutEdgeset(graph, node));
+	for (edge = dglEdgeset_T_First(&et); edge;
+	     edge = dglEdgeset_T_Next(&et)) {
+	    dglInt32_t id = abs(dglEdgeGet_Id(graph, edge));
+	    dglInt32_t to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
+	    if (edges[id] && !vis[to]) {
+		vis[to] = 'y';
+		prev[to] = edge;
+		queue[end++] = to;
+	    }
+	}
+	dglEdgeset_T_Release(&et);
+    }
+    G_free(queue);
+    if (!vis[to]) {
+	G_free(prev);
+	G_free(vis);
+	return -1;
+    }
+
+    cur = to;
+    while (prev[cur] != NULL) {
+	Vect_list_append(list, abs(dglEdgeGet_Id(graph, prev[cur])));
+	cur = dglNodeGet_Id(graph, dglEdgeGet_Head(graph, prev[cur]));
+    }
+
+    G_free(prev);
+    G_free(vis);
+    return list->n_values;
+}

Added: grass-addons/vector/net.analyze/netalib/timetables.c
===================================================================
--- grass-addons/vector/net.analyze/netalib/timetables.c	                        (rev 0)
+++ grass-addons/vector/net.analyze/netalib/timetables.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -0,0 +1,473 @@
+
+/****************************************************************
+ *
+ * MODULE:     netalib
+ *
+ * AUTHOR(S):  Daniel Bundala
+ *
+ * PURPOSE:    Shortest path using timetables
+ *      
+ *
+ * COPYRIGHT:  (C) 2002-2005 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.
+ *
+ ****************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <grass/gis.h>
+#include <grass/Vect.h>
+#include <grass/dbmi.h>
+#include <grass/glocale.h>
+#include <grass/dgl/graph.h>
+#include <grass/neta.h>
+
+/*returns -1 on failure and number of distinct elements on success */
+int neta_init_distinct(dbDriver * driver, dbString * sql, int **lengths,
+		       int **ids)
+{
+    int count, last, cur, result, index, more;
+    dbCursor cursor;
+    dbTable *table;
+    dbColumn *column;
+    dbValue *value;
+
+    if (db_open_select_cursor(driver, sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
+	G_warning(_("Unable to open select cursor: %s"), db_get_string(sql));
+	return -1;
+    }
+    /*TODO: check column types */
+
+    count = last = 0;
+    /*count number of distinct routes */
+    table = db_get_cursor_table(&cursor);
+    column = db_get_table_column(table, 0);
+    while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
+	value = db_get_column_value(column);
+	cur = db_get_value_int(value);
+	if (count == 0 || cur != last) {
+	    last = cur;
+	    count++;
+	}
+    }
+    result = count;
+    db_close_cursor(&cursor);
+
+    *lengths = (int *)G_calloc(count, sizeof(int));
+    *ids = (int *)G_calloc(count, sizeof(int));
+    if (!*lengths || !*ids) {
+	G_warning(_("Out of memory"));
+	return -1;
+    }
+    db_open_select_cursor(driver, sql, &cursor, DB_SEQUENTIAL);
+    count = index = 0;
+    /*calculate the lengths of the routes */
+    table = db_get_cursor_table(&cursor);
+    column = db_get_table_column(table, 0);
+    while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
+	value = db_get_column_value(column);
+	cur = db_get_value_int(value);
+	if (count != 0 && cur != last)
+	    index++;
+	if (count == 0 || cur != last)
+	    (*ids)[index] = cur;
+	(*lengths)[index]++;
+	last = cur;
+	count++;
+    }
+    return result;
+}
+
+static int neta_cmp_int(const void *a, const void *b)
+{
+    return *(int *)a - *(int *)b;
+}
+
+/*Initialises timetable from a database. Returns 0 on success */
+int neta_init_timetable_from_db(struct Map_info *In, int route_layer,
+				int walk_layer, char *route_id, char *times,
+				neta_timetable * timetable, int **route_ids,
+				int **stop_ids)
+{
+    int more, i, stop, route, time, *stop_pnt, stop1, stop2;
+    dbString sql;
+    dbCursor cursor;
+    dbTable *table;
+    dbColumn *column1, *column2, *column3;
+    dbValue *value;
+    char buf[2000];
+
+    dbDriver *driver;
+    struct field_info *Fi;
+    Fi = Vect_get_field(In, route_layer);
+    driver = db_start_driver_open_database(Fi->driver, Fi->database);
+    if (driver == NULL)
+	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
+		      Fi->database, Fi->driver);
+
+
+    db_init_string(&sql);
+    sprintf(buf, "select %s from %s order by %s", route_id, Fi->table,
+	    route_id);
+    db_set_string(&sql, buf);
+    timetable->routes =
+	neta_init_distinct(driver, &sql, &(timetable->route_length), route_ids);
+    if (timetable->routes < 0)
+	return 1;
+
+    sprintf(buf, "select %s from %s order by %s", Fi->key, Fi->table, Fi->key);
+    db_set_string(&sql, buf);
+    timetable->stops =
+	neta_init_distinct(driver, &sql, &(timetable->stop_length), stop_ids);
+    if (timetable->stops < 0)
+	return 1;
+
+    timetable->route_stops = (int **)G_calloc(timetable->routes, sizeof(int *));
+    timetable->route_times = (int **)G_calloc(timetable->routes, sizeof(int *));
+    timetable->stop_routes = (int **)G_calloc(timetable->stops, sizeof(int *));
+    timetable->stop_times = (int **)G_calloc(timetable->stops, sizeof(int *));
+    timetable->walk_length = (int *)G_calloc(timetable->stops, sizeof(int));
+    timetable->walk_stops = (int **)G_calloc(timetable->stops, sizeof(int *));
+    timetable->walk_times = (int **)G_calloc(timetable->stops, sizeof(int *));
+    if (!timetable->route_stops || !timetable->route_times ||
+	!timetable->stop_routes || !timetable->stop_times ||
+	!timetable->walk_length) {
+	G_warning(_("Out of memory"));
+	return 2;
+    }
+
+    for (i = 0; i < timetable->routes; i++) {
+	timetable->route_stops[i] =
+	    (int *)G_calloc(timetable->route_length[i], sizeof(int));
+	timetable->route_times[i] =
+	    (int *)G_calloc(timetable->route_length[i], sizeof(int));
+	if (!timetable->route_stops[i] || !timetable->route_times[i]) {
+	    G_warning(_("Out of memory"));
+	    return 2;
+	}
+
+	timetable->route_length[i] = 0;
+    }
+
+    for (i = 0; i < timetable->stops; i++) {
+	timetable->stop_routes[i] =
+	    (int *)G_calloc(timetable->stop_length[i], sizeof(int));
+	timetable->stop_times[i] =
+	    (int *)G_calloc(timetable->stop_length[i], sizeof(int));
+	if (!timetable->stop_routes[i] || !timetable->stop_times[i]) {
+	    G_warning(_("Out of memory"));
+	    return 2;
+	}
+	timetable->walk_length[i] = 0;
+	timetable->stop_length[i] = 0;
+    }
+
+    sprintf(buf, "select %s, %s, %s from %s order by %s", Fi->key, route_id,
+	    times, Fi->table, times);
+    db_set_string(&sql, buf);
+
+    if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
+	G_warning(_("Unable to open select cursor: %s"), db_get_string(&sql));
+	return 1;
+    }
+
+
+    table = db_get_cursor_table(&cursor);
+    column1 = db_get_table_column(table, 0);
+    column2 = db_get_table_column(table, 1);
+    column3 = db_get_table_column(table, 2);
+    while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
+	value = db_get_column_value(column1);
+	stop = db_get_value_int(value);
+	value = db_get_column_value(column2);
+	route = db_get_value_int(value);
+	value = db_get_column_value(column3);
+	time = db_get_value_int(value);
+	stop =
+	    (int *)bsearch(&stop, *stop_ids, timetable->stops, sizeof(int),
+			   neta_cmp_int) - (*stop_ids);
+	route =
+	    (int *)bsearch(&route, *route_ids, timetable->routes, sizeof(int),
+			   neta_cmp_int) - (*route_ids);
+
+	timetable->stop_routes[stop][timetable->stop_length[stop]] = route;
+	timetable->stop_times[stop][timetable->stop_length[stop]++] = time;
+
+	timetable->route_stops[route][timetable->route_length[route]] = stop;
+	timetable->route_times[route][timetable->route_length[route]++] = time;
+    }
+    db_close_cursor(&cursor);
+
+    if (walk_layer != -1) {
+
+	Fi = Vect_get_field(In, walk_layer);
+	sprintf(buf, "select * from %s", Fi->table);
+	db_set_string(&sql, buf);
+
+	if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
+	    DB_OK) {
+	    G_warning(_("Unable to open select cursor: %s"),
+		      db_get_string(&sql));
+	    return 1;
+	}
+
+	table = db_get_cursor_table(&cursor);
+	column1 = db_get_table_column(table, 0);
+	column2 = db_get_table_column(table, 1);
+	while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
+	    value = db_get_column_value(column2);
+	    stop = db_get_value_int(value);
+	    stop_pnt =
+		(int *)bsearch(&stop, *stop_ids, timetable->stops, sizeof(int),
+			       neta_cmp_int);
+	    if (stop_pnt) {
+		value = db_get_column_value(column1);
+		stop = db_get_value_int(value);
+		stop_pnt =
+		    (int *)bsearch(&stop, *stop_ids, timetable->stops,
+				   sizeof(int), neta_cmp_int);
+		if (stop_pnt) {
+		    stop = stop_pnt - (*stop_ids);
+		    timetable->walk_length[stop]++;
+		}
+	    }
+	}
+	db_close_cursor(&cursor);
+
+	for (i = 0; i < timetable->stops; i++) {
+	    timetable->walk_stops[i] =
+		(int *)G_calloc(timetable->walk_length[i], sizeof(int));
+	    timetable->walk_times[i] =
+		(int *)G_calloc(timetable->walk_length[i], sizeof(int));
+	    if (!timetable->walk_stops[i] || !timetable->walk_times[i]) {
+		G_warning(_("Out of memory"));
+		return 2;
+	    }
+	    timetable->walk_length[i] = 0;
+	}
+
+	if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
+	    DB_OK) {
+	    G_warning(_("Unable to open select cursor: %s"),
+		      db_get_string(&sql));
+	    return 1;
+	}
+
+	table = db_get_cursor_table(&cursor);
+	column1 = db_get_table_column(table, 0);
+	column2 = db_get_table_column(table, 1);
+	column3 = db_get_table_column(table, 2);
+	while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
+	    value = db_get_column_value(column2);
+	    stop = db_get_value_int(value);
+	    stop_pnt =
+		(int *)bsearch(&stop, *stop_ids, timetable->stops, sizeof(int),
+			       neta_cmp_int);
+	    if (stop_pnt) {
+		stop2 = stop_pnt - (*stop_ids);
+		value = db_get_column_value(column1);
+		stop = db_get_value_int(value);
+		stop_pnt =
+		    (int *)bsearch(&stop, *stop_ids, timetable->stops,
+				   sizeof(int), neta_cmp_int);
+		if (stop_pnt) {
+		    stop1 = stop_pnt - (*stop_ids);
+		    value = db_get_column_value(column3);
+		    time = db_get_value_int(value);
+		    timetable->walk_stops[stop1][timetable->
+						 walk_length[stop1]] = stop2;
+		    timetable->walk_times[stop1][timetable->
+						 walk_length[stop1]++] = time;
+		}
+	    }
+	}
+	db_close_cursor(&cursor);
+    }
+    db_close_database_shutdown_driver(driver);
+
+    return 0;
+}
+
+typedef struct
+{
+    int v;
+    int conns;
+} neta_heap_data;
+
+neta_heap_data *new_heap_data(int conns, int v)
+{
+    neta_heap_data *d = (neta_heap_data *) G_calloc(1, sizeof(neta_heap_data));
+    d->v = v;
+    d->conns = conns;
+    return d;
+}
+
+void neta_update_dijkstra(int old_conns, int new_conns, int to, int new_dst,
+			  int v, int route, int rows, int update,
+			  neta_timetable_result * result, dglHeap_s * heap)
+{
+    if (result->dst[new_conns][to] == -1 ||
+	result->dst[new_conns][to] > new_dst) {
+	result->dst[new_conns][to] = new_dst;
+	result->prev_stop[new_conns][to] = v;
+	result->prev_route[new_conns][to] = route;
+	result->prev_conn[new_conns][to] = old_conns;
+	if (update) {
+	    dglHeapData_u heap_data;
+	    heap_data.pv = (void *)new_heap_data(new_conns, to);
+	    dglHeapInsertMin(heap, new_dst, ' ', heap_data);
+	}
+    }
+}
+
+/* computes the earliest arrival time to to_stop from from_stop starting at start_time, or -1 if no path exists */
+int neta_timetable_shortest_path(neta_timetable * timetable, int from_stop,
+				 int to_stop, int start_time, int min_change,
+				 int max_changes, int walking_change,
+				 neta_timetable_result * result)
+{
+    int i, j;
+    dglHeap_s heap;
+
+    int opt_conns, rows = 1;
+    if (max_changes != -1)
+	rows = max_changes + 2;
+
+    result->rows = rows;
+    result->dst = (int **)G_calloc(rows, sizeof(int *));
+    result->prev_stop = (int **)G_calloc(rows, sizeof(int *));
+    result->prev_route = (int **)G_calloc(rows, sizeof(int *));
+    result->prev_conn = (int **)G_calloc(rows, sizeof(int *));
+
+    if (!result->dst || !result->prev_stop || !result->prev_route ||
+	!result->prev_conn) {
+	G_warning(_("Out of memory"));
+	return -1;
+    }
+
+    for (i = 0; i < rows; i++) {
+	result->dst[i] = (int *)G_calloc(timetable->stops, sizeof(int));
+	result->prev_stop[i] = (int *)G_calloc(timetable->stops, sizeof(int));
+	result->prev_route[i] = (int *)G_calloc(timetable->stops, sizeof(int));
+	result->prev_conn[i] = (int *)G_calloc(timetable->stops, sizeof(int));
+	if (!result->dst[i] || !result->prev_stop[i] || !result->prev_route[i]
+	    || !result->prev_conn[i]) {
+	    G_warning(_("Out of memory"));
+	    return -1;
+	}
+    }
+
+    if (from_stop == to_stop) {
+	result->dst[0][to_stop] = start_time;
+	result->prev_route[0][to_stop] = result->prev_stop[0][to_stop] = -1;
+	result->routes = 0;
+	return start_time;
+    }
+
+    result->routes = -1;
+    if (walking_change > 1)
+	walking_change = 1;
+    if (walking_change < 0 || max_changes == -1)
+	walking_change = 0;
+    dglHeapInit(&heap);
+
+    for (i = 0; i < rows; i++)
+	for (j = 0; j < timetable->stops; j++)
+	    result->dst[i][j] = result->prev_stop[i][j] =
+		result->prev_route[i][j] = -1;
+
+    result->dst[0][from_stop] = start_time - min_change;
+    result->prev_stop[0][from_stop] = result->prev_route[0][from_stop] = -1;
+    dglHeapData_u heap_data;
+    heap_data.pv = (void *)new_heap_data(0, from_stop);
+    dglHeapInsertMin(&heap, start_time - min_change, ' ', heap_data);
+
+    while (1) {
+	dglInt32_t v, dist, conns;
+	dglHeapNode_s heap_node;
+	int new_conns, walk_conns, update;
+	if (!dglHeapExtractMin(&heap, &heap_node))
+	    break;
+	v = ((neta_heap_data *) (heap_node.value.pv))->v;
+	conns = ((neta_heap_data *) (heap_node.value.pv))->conns;
+	dist = heap_node.key;
+
+	if (dist > result->dst[conns][v])
+	    continue;
+	if (v == to_stop)
+	    break;
+	new_conns = (max_changes == -1) ? 0 : (conns + 1);
+	walk_conns = conns + walking_change;
+
+	/*walking */
+	if (walk_conns < rows) {
+	    /*            update = (max_changes == -1 || walk_conns <= max_changes); */
+	    update = 1;
+	    for (i = 0; i < timetable->walk_length[v]; i++) {
+		int to = timetable->walk_stops[v][i];
+		int new_dst = dist + timetable->walk_times[v][i];
+		neta_update_dijkstra(conns, walk_conns, to, new_dst, v, -2,
+				     rows, update, result, &heap);
+	    }
+	}
+
+	if (new_conns >= rows)
+	    continue;
+	/*process all routes arriving after dist+min_change */
+	for (i = 0; i < timetable->stop_length[v]; i++)
+	    if (timetable->stop_times[v][i] >= dist + min_change) {
+		int route = timetable->stop_routes[v][i];
+		/*find the index of v on the route */
+		for (j = 0; j < timetable->route_length[route]; j++)
+		    if (timetable->route_stops[route][j] == v)
+			break;
+		j++;
+		for (; j < timetable->route_length[route]; j++) {
+		    int to = timetable->route_stops[route][j];
+		    neta_update_dijkstra(conns, new_conns, to,
+					 timetable->route_times[route][j], v,
+					 route, rows, 1, result, &heap);
+		}
+	    }
+    }
+    dglHeapFree(&heap, NULL);
+    opt_conns = -1;
+    for (i = 0; i < rows; i++)
+	if (result->dst[i][to_stop] != -1 &&
+	    (opt_conns == -1 ||
+	     result->dst[opt_conns][to_stop] > result->dst[i][to_stop]))
+	    opt_conns = i;
+    result->routes = opt_conns;
+
+    if (opt_conns != -1)
+	return result->dst[opt_conns][to_stop];
+    return -1;
+}
+
+/*returns the time when route "route" arrives at stop "stop" or -1 */
+int neta_timetable_get_route_time(neta_timetable * timetable, int stop,
+				  int route)
+{
+    int i;
+    for (i = 0; i < timetable->route_length[route]; i++)
+	if (timetable->route_stops[route][i] == stop)
+	    return timetable->route_times[route][i];
+    return -1;
+}
+
+void neta_timetable_result_release(neta_timetable_result * result)
+{
+    int i;
+    for (i = 0; i < result->rows; i++) {
+	G_free(result->dst[i]);
+	G_free(result->prev_stop[i]);
+	G_free(result->prev_route[i]);
+    }
+    G_free(result->dst);
+    G_free(result->prev_stop);
+    G_free(result->prev_route);
+}


Property changes on: grass-addons/vector/net.analyze/netalib/timetables.c
___________________________________________________________________
Added: svn:executable
   + *

Modified: grass-addons/vector/net.analyze/netalib/utils.c
===================================================================
--- grass-addons/vector/net.analyze/netalib/utils.c	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/netalib/utils.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -121,15 +121,16 @@
 
 /*returns the list of all nodes on features selected by varray.
  * nodes_to_features conains the index of a feature adjecent to each node or -1 if no such feature
- * specified by varray exists */
+ * specified by varray exists. Nodes_to_features might be NULL, in which case it is left unitialised.  */
 void neta_varray_to_nodes(struct Map_info *map, VARRAY * varray,
 			  struct ilist *nodes, int *nodes_to_features)
 {
     int nlines, nnodes, i;
     nlines = Vect_get_num_lines(map);
     nnodes = Vect_get_num_nodes(map);
-    for (i = 1; i <= nnodes; i++)
-	nodes_to_features[i] = -1;
+    if (nodes_to_features)
+	for (i = 1; i <= nnodes; i++)
+	    nodes_to_features[i] = -1;
 
     for (i = 1; i <= nlines; i++)
 	if (varray->c[i]) {
@@ -138,14 +139,52 @@
 		int node;
 		Vect_get_line_nodes(map, i, &node, NULL);
 		Vect_list_append(nodes, node);
-		nodes_to_features[node] = i;
+		if (nodes_to_features)
+		    nodes_to_features[node] = i;
 	    }
 	    else {
 		int node1, node2;
 		Vect_get_line_nodes(map, i, &node1, &node2);
 		Vect_list_append(nodes, node1);
 		Vect_list_append(nodes, node2);
-		nodes_to_features[node1] = nodes_to_features[node2] = i;
+		if (nodes_to_features)
+		    nodes_to_features[node1] = nodes_to_features[node2] = i;
 	    }
 	}
 }
+
+int neta_initialise_varray(struct Map_info *In, int layer, int mask_type,
+			   char *where, char *cat, VARRAY ** varray)
+{
+    /* parse filter option and select appropriate lines */
+    if (where) {
+	if (layer < 1)
+	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "where");
+	if (cat)
+	    G_warning(_
+		      ("'where' and 'cats' parameters were supplied, cat will be ignored"));
+	*varray = Vect_new_varray(Vect_get_num_lines(In));
+	if (Vect_set_varray_from_db
+	    (In, layer, where, mask_type, 1, *varray) == -1) {
+	    G_warning(_("Unable to load data from database"));
+	    return 0;
+	}
+	return 1;
+    }
+    else if (cat) {
+	if (layer < 1)
+	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "cat");
+	*varray = Vect_new_varray(Vect_get_num_lines(In));
+	if (Vect_set_varray_from_cat_string
+	    (In, layer, cat, mask_type, 1, *varray) == -1) {
+	    G_warning(_("Problem loading category values"));
+	    return 0;
+	}
+	return 1;
+    }
+    else {
+	return 2;
+    }
+
+
+}

Added: grass-addons/vector/net.analyze/v.net.allpairs/description.html
===================================================================
--- grass-addons/vector/net.analyze/v.net.allpairs/description.html	                        (rev 0)
+++ grass-addons/vector/net.analyze/v.net.allpairs/description.html	2009-07-31 18:20:49 UTC (rev 38558)
@@ -0,0 +1,33 @@
+<h2>DESCRIPTION</h2>
+
+<em>v.net.allpairs</em> computes the shortest path between each select node and all other nodes. 
+
+<h2>NOTES</h2>
+
+An attribute table is created and linked to <b>layer</b>. The table contains three columns: <em>cat</em>, <em>to_cat</em>, <em>cost</em>. Each entry denotes the cost of the shortest path from <em>cat</em> to <em>to_cat</em>. If the cost is negative then no path exists. If points are specified by <b>cats, layer</b> or <b>where</b> parameters then the table is filled only for the selected points. In other words, <em>cat</em> columns contains only selected points but the distances are computed and updated for <em>all</em> other nodes.<br>
+If flag <b>-a</b> is set then new points are added on nodes without nodes. These points have the largest categorie. Precisely, category of each new point is larger than any of the old categories. If the flag is not set then no new points are created and hence the attribute table stores the costs only between the points already present in the input. Output consists of all points mentioned in either of the columns.<br>
+If <b>abcolumn</b> is not given then then the same costs are used for forward and backward arcs.
+
+<h2>EXAMPLES</h2>
+
+Find shortest path from each intersection with pedestrian crossing to every other point using <em>SHAPE_LEN</em> for the cost of traversing the arcs in both directions.
+<div class="code"><pre>
+v.net.allpairs input=roads output=roads_pairs afcol=SHAPE_LEN where="crossing=1"
+</pre></div>
+<P>
+
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a HREF="v.net.path">v.net.path</a>,
+<a HREF="v.net.distance">v.net.distance</a>
+
+
+<h2>AUTHORS</h2>
+
+Daniel Bundala, Google Summer of Code 2009, Student<br>
+Wolf Bergenheim, Mentor
+
+<p>
+<i>Last changed: $Date: 2009-07-28 21:04:57 +0200 (Tue, 28 July 2009) $</i>


Property changes on: grass-addons/vector/net.analyze/v.net.allpairs/description.html
___________________________________________________________________
Added: svn:executable
   + *

Modified: grass-addons/vector/net.analyze/v.net.allpairs/main.c
===================================================================
--- grass-addons/vector/net.analyze/v.net.allpairs/main.c	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/v.net.allpairs/main.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -40,7 +40,7 @@
     dglGraph_s *graph;
     int i, j, geo, nnodes, nlines, max_cat, *cats;
     dglInt32_t **dist;
-    char buf[2000];
+    char buf[2000], *output;
 
     /* Attribute table */
     dbString sql;
@@ -123,46 +123,23 @@
 
     /* parse filter option and select appropriate lines */
     layer = atoi(field_opt->answer);
-    if (where_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "where");
-	if (cat_opt->answer)
-	    G_warning(_
-		      ("'where' and 'cats' parameters were supplied, cat will be ignored"));
-	chcat = 1;
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	if (Vect_set_varray_from_db
-	    (&In, layer, where_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Unable to load data from database"));
-	}
-    }
-    else if (cat_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "cat");
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	chcat = 1;
-	if (Vect_set_varray_from_cat_string
-	    (&In, layer, cat_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Problem loading category values"));
-	}
-    }
-    else {
-	chcat = 0;
-	varray = NULL;
-    }
+    chcat =
+	(neta_initialise_varray
+	 (&In, layer, GV_POINT, where_opt->answer, cat_opt->answer,
+	  &varray) == 1);
 
     /* Create table */
     Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
     Vect_map_add_dblink(&Out, 1, NULL, Fi->table, "cat", Fi->database,
 			Fi->driver);
-
+    db_init_string(&sql);
     driver = db_start_driver_open_database(Fi->driver, Fi->database);
     if (driver == NULL)
 	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
 		      Fi->database, Fi->driver);
 
     sprintf(buf,
-	    "create table %s ( from_cat integer, to_cat integer, cost double precision)",
+	    "create table %s ( cat integer, to_cat integer, cost double precision)",
 	    Fi->table);
 
     db_set_string(&sql, buf);
@@ -172,10 +149,10 @@
 	db_close_database_shutdown_driver(driver);
 	G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql));
     }
-
-    if (db_create_index2(driver, Fi->table, "cat") != DB_OK)
-	G_warning(_("Cannot create index"));
-
+    /*
+     * if (db_create_index2(driver, Fi->table, "cat") != DB_OK)
+     * G_warning(_("Cannot create index"));
+     */
     if (db_grant_on_table
 	(driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK)
 	G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table);
@@ -189,6 +166,7 @@
     nnodes = dglGet_NodeCount(graph);
     dist = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
     cats = (int *)G_calloc(nnodes + 1, sizeof(int));	/*id of each node. -1 if not used */
+    output = (char *)G_calloc(nnodes + 1, sizeof(char));
 
     if (!dist || !cats)
 	G_fatal_error(_("Out of memory"));
@@ -199,8 +177,10 @@
     }
     neta_allpairs(graph, dist);
 
-    for (i = 1; i <= nnodes; i++)
+    for (i = 1; i <= nnodes; i++) {
 	cats[i] = -1;
+	output[i] = 0;
+    }
 
     nlines = Vect_get_num_lines(&In);
     max_cat = 0;
@@ -213,8 +193,11 @@
 	    int node;
 	    Vect_get_line_nodes(&In, i, &node, NULL);
 	    Vect_cat_get(Cats, layer, &cats[node]);
-	    if (cats[node] != -1)
+	    if (cats[node] != -1) {
 		Vect_write_line(&Out, GV_POINT, Points, Cats);
+		if (!chcat || varray->c[i])
+		    output[node] = 'y';
+	    }
 	}
 
     }
@@ -230,11 +213,11 @@
     G_percent_reset();
     for (i = 1; i <= nnodes; i++) {
 	G_percent(i, nnodes, 1);
-	if (cats[i] != -1)
+	if (cats[i] != -1 && output[i])	/*Process only selected nodes */
 	    for (j = 1; j <= nnodes; j++)
 		if (cats[j] != -1) {
 		    sprintf(buf, "insert into %s values (%d, %d, %f)",
-			    Fi->table, i, j,
+			    Fi->table, cats[i], cats[j],
 			    dist[i][j] / (double)In.cost_multip);
 		    db_set_string(&sql, buf);
 		    G_debug(3, db_get_string(&sql));

Added: grass-addons/vector/net.analyze/v.net.bridge/description.html
===================================================================
--- grass-addons/vector/net.analyze/v.net.bridge/description.html	                        (rev 0)
+++ grass-addons/vector/net.analyze/v.net.bridge/description.html	2009-07-31 18:20:49 UTC (rev 38558)
@@ -0,0 +1,34 @@
+<h2>DESCRIPTION</h2>
+
+<em>v.net.bridge</em> finds bridges and articulation points in a network. 
+
+<h2>NOTES</h2>
+Bridge in a network is an edge/line whose removal would disconnect the (sub-)network. A node is an articulation point if its removal would disconnect the (sub-)network. For more information and formal definitions check the wikipedia entries: <a href="http://en.wikipedia.org/wiki/Bridge_%28graph_theory%29">bridge</a> and <a href="http://en.wikipedia.org/wiki/Cut_vertex">articulation point</a>.<br><br>
+The output of the module contains the selected features. If <b>method=bridge</b> then lines corresponding to bridges are copied from the input map to the output map. On the other hand, if <b>method=articulation</b> then point are created on the positions of articulation points.<br><br>
+
+
+<br>In GRASS, <em>line</em> is not always a single line segments. It might be, and often is, a sequence of line segments between two intersections. Also, articulation point is a standard graph theoretic terminology which is slightly  misleading in GRASS. An articulation point in graph theory is an articulation <em>node</em> in GRASS terminology. 
+
+<h2>EXAMPLES</h2>
+
+<div class="code"><pre>
+</pre></div>
+<P>
+
+<div class="code"><pre>
+</pre></div>
+
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a HREF="v.category.html">v.category</a>,
+
+
+<h2>AUTHORS</h2>
+
+Daniel Bundala, Google Summer of Code 2009, Student<br>
+Wolf Bergenheim, Mentor
+
+<p>
+<i>Last changed: $Date: 2009-07-28 21:04:57 +0200 (Tue, 28 July 2009) $</i>


Property changes on: grass-addons/vector/net.analyze/v.net.bridge/description.html
___________________________________________________________________
Added: svn:executable
   + *

Modified: grass-addons/vector/net.analyze/v.net.bridge/main.c
===================================================================
--- grass-addons/vector/net.analyze/v.net.bridge/main.c	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/v.net.bridge/main.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -5,7 +5,7 @@
  *
  * AUTHOR(S):  Daniel Bundala
  *
- * PURPOSE:    Computes bridges in the network
+ * PURPOSE:    Computes bridges and articulation points
  *
  * COPYRIGHT:  (C) 2002-2005 by the GRASS Development Team
  *
@@ -61,7 +61,7 @@
     method_opt->required = YES;
     method_opt->multiple = NO;
     method_opt->options = "bridge,articulation";
-    method_opt->descriptions = _("bridge;Find bridges;"
+    method_opt->descriptions = _("bridge;Finds bridges;"
 				 "articulation;Finds articulation points;");
     method_opt->description = _("Feature type");
 
@@ -96,33 +96,10 @@
 
     /* parse filter option and select appropriate lines */
     layer = atoi(field_opt->answer);
-    if (where_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "where");
-	if (cat_opt->answer)
-	    G_warning(_
-		      ("'where' and 'cats' parameters were supplied, cat will be ignored"));
-	chcat = 1;
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	if (Vect_set_varray_from_db
-	    (&In, layer, where_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Unable to load data from database"));
-	}
-    }
-    else if (cat_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "cat");
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	chcat = 1;
-	if (Vect_set_varray_from_cat_string
-	    (&In, layer, cat_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Problem loading category values"));
-	}
-    }
-    else {
-	chcat = 0;
-	varray = NULL;
-    }
+    chcat =
+	(neta_initialise_varray
+	 (&In, layer, mask_type, where_opt->answer, cat_opt->answer,
+	  &varray) == 1);
 
     Vect_net_build_graph(&In, mask_type, 0, 0, NULL, NULL, NULL, 0, 0);
     graph = &(In.graph);

Added: grass-addons/vector/net.analyze/v.net.centrality/description.html
===================================================================
--- grass-addons/vector/net.analyze/v.net.centrality/description.html	                        (rev 0)
+++ grass-addons/vector/net.analyze/v.net.centrality/description.html	2009-07-31 18:20:49 UTC (rev 38558)
@@ -0,0 +1,33 @@
+<h2>DESCRIPTION</h2>
+
+<em>v.net.centrality</em> computes degree, closeness, betweenness and eigenvector centrality measures. 
+
+<h2>NOTES</h2>
+
+The module computes various centrality measures for each node and stores them in the given columns of an attribute table, which is created and linked to the output map. For the description of these, please check the following <a href="http://en.wikipedia.org/wiki/Centrality">wikipedia article</a>. If the column name is not given for a measure then that measure is not computed. If <b>-a</b> flag is set then points are added on nodes without points. Also, the points for which the output is computed can be specified by <b>cats</b>, <b>layer</b> and <b>where</b> parameters. However, if any of these parameters is present then <b>-a</b> flag is ingored and no new points are added.<br>
+Betwenness measure is not normalised. In order to get the normalised values (between 0 and 1), each number needs to be divided by <em>N choose 2=N*(N-1)/2</em> where N is the number of nodes in the connected component. Computation of eigenvector measure terminates if the given number of iterations is reached or the cummulative <em>squared</em> error between the successive iterations is less than <b>error</b>.
+
+<h2>EXAMPLES</h2>
+Compute closeness and betweenness centrality measures for each node and produce a map containing not only points already present in the input map but a map with point on every node. 
+<div class="code"><pre>
+v.net.centrality input=roads output=roads_cent closeness=close betweenness=betw -a
+</pre></div>
+<P>
+
+<div class="code"><pre>
+</pre></div>
+
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a HREF="v.generalize.html">v.generalize</a>
+
+
+<h2>AUTHORS</h2>
+
+Daniel Bundala, Google Summer of Code 2009, Student<br>
+Wolf Bergenheim, Mentor
+
+<p>
+<i>Last changed: $Date: 2009-07-28 21:04:57 +0200 (Tue, 28 July 2009) $</i>


Property changes on: grass-addons/vector/net.analyze/v.net.centrality/description.html
___________________________________________________________________
Added: svn:executable
   + *

Modified: grass-addons/vector/net.analyze/v.net.centrality/main.c
===================================================================
--- grass-addons/vector/net.analyze/v.net.centrality/main.c	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/v.net.centrality/main.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -24,43 +24,67 @@
 #include <grass/dbmi.h>
 #include <grass/neta.h>
 
-void update_record(dbDriver * driver, dbString * sql, char *table, char *key,
-		   char *column, double value, int cat)
+/*Global variables */
+struct Option *deg_opt, *close_opt, *betw_opt, *eigen_opt;
+double *deg, *close, *betw, *eigen;
+/* Attribute table */
+dbString sql, tmp;
+dbDriver *driver;
+struct field_info *Fi;
+
+void append_string(dbString * string, char *s)
 {
+    db_append_string(string, ", ");
+    db_append_string(string, s);
+    db_append_string(string, " double precision");
+}
+
+void append_double(dbString * string, double d)
+{
+    char buf[50];
+    sprintf(buf, ",%f", d);
+    db_append_string(string, buf);
+}
+
+void process_node(int node, int cat)
+{
     char buf[2000];
-    sprintf(buf, "update %s set %s=%f where %s=%d", table, column, value, key,
-	    cat);
-    db_set_string(sql, buf);
-    G_debug(3, db_get_string(sql));
-    if (db_execute_immediate(driver, sql) != DB_OK) {
+    sprintf(buf, "INSERT INTO %s VALUES(%d", Fi->table, cat);
+    db_set_string(&sql, buf);
+    if (deg_opt->answer)
+	append_double(&sql, deg[node]);
+    if (close_opt->answer)
+	append_double(&sql, close[node]);
+    if (betw_opt->answer)
+	append_double(&sql, betw[node]);
+    if (eigen_opt->answer)
+	append_double(&sql, eigen[node]);
+
+    db_append_string(&sql, ")");
+    if (db_execute_immediate(driver, &sql) != DB_OK) {
 	db_close_database_shutdown_driver(driver);
-	G_fatal_error(_("Cannot insert new record: %s"), db_get_string(sql));
-    };
+	G_fatal_error(_("Cannot insert new record: %s"), db_get_string(&sql));
+    }
 }
 
 int main(int argc, char *argv[])
 {
-    struct Map_info In;
+    struct Map_info In, Out;
+    static struct line_pnts *Points;
     struct line_cats *Cats;
     char *mapset;
     struct GModule *module;	/* GRASS module for parsing arguments */
-    struct Option *map_in;
+    struct Option *map_in, *map_out;
     struct Option *cat_opt, *field_opt, *where_opt, *abcol, *afcol;
-    struct Option *deg_opt, *close_opt, *betw_opt, *eigen_opt;
     struct Option *iter_opt, *error_opt;
-    struct Flag *geo_f;
+    struct Flag *geo_f, *add_f;
     int chcat, with_z;
     int layer, mask_type;
     VARRAY *varray;
     dglGraph_s *graph;
-    int i, geo, nnodes, nlines;
-    double *deg, *close, *betw, *eigen;
+    int i, geo, nnodes, nlines, j, max_cat;
+    char buf[2000], *covered;
 
-    /* Attribute table */
-    dbString sql;
-    dbDriver *driver;
-    struct field_info *Fi;
-
     /* initialize GIS environment */
     G_gisinit(argv[0]);		/* reads grass env, stores program name to G_program_name() */
 
@@ -75,6 +99,7 @@
 
     /* Define the different options as defined in gis.h */
     map_in = G_define_standard_option(G_OPT_V_INPUT);
+    map_out = G_define_standard_option(G_OPT_V_OUTPUT);
 
     field_opt = G_define_standard_option(G_OPT_V_FIELD);
     cat_opt = G_define_standard_option(G_OPT_V_CATS);
@@ -130,7 +155,7 @@
     error_opt->type = TYPE_DOUBLE;
     error_opt->required = NO;
     error_opt->description =
-	_("Cuumulative error tolerance for eigenvector centrality");
+	_("Cummulative error tolerance for eigenvector centrality");
 
 
     geo_f = G_define_flag();
@@ -138,14 +163,22 @@
     geo_f->description =
 	_("Use geodesic calculation for longitude-latitude locations");
 
+    add_f = G_define_flag();
+    add_f->key = 'a';
+    add_f->description = _("Add points on nodes");
+
     /* options and flags parser */
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
     /* TODO: make an option for this */
     mask_type = GV_LINE | GV_BOUNDARY;
 
+    Points = Vect_new_line_struct();
     Cats = Vect_new_cats_struct();
 
+    Vect_check_input_output_name(map_in->answer, map_out->answer,
+				 GV_FATAL_EXIT);
+
     if ((mapset = G_find_vector2(map_in->answer, "")) == NULL)
 	G_fatal_error(_("Vector map <%s> not found"), map_in->answer);
 
@@ -157,6 +190,12 @@
 
     with_z = Vect_is_3d(&In);
 
+    if (0 > Vect_open_new(&Out, map_out->answer, with_z)) {
+	Vect_close(&In);
+	G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer);
+    }
+
+
     if (geo_f->answer) {
 	geo = 1;
 	if (G_projection() != PROJECTION_LL)
@@ -167,43 +206,54 @@
 
     /* parse filter option and select appropriate lines */
     layer = atoi(field_opt->answer);
-    if (where_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "where");
-	if (cat_opt->answer)
-	    G_warning(_
-		      ("'where' and 'cats' parameters were supplied, cat will be ignored"));
-	chcat = 1;
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	if (Vect_set_varray_from_db
-	    (&In, layer, where_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Unable to load data from database"));
-	}
-    }
-    else if (cat_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "cat");
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	chcat = 1;
-	if (Vect_set_varray_from_cat_string
-	    (&In, layer, cat_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Problem loading category values"));
-	}
-    }
-    else {
-	chcat = 0;
-	varray = NULL;
-    }
+    chcat =
+	(neta_initialise_varray
+	 (&In, layer, mask_type, where_opt->answer, cat_opt->answer,
+	  &varray) == 1);
 
-    /* Open database */
-    Fi = Vect_get_field(&In, layer);
+    /* Create table */
+    Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
+    Vect_map_add_dblink(&Out, 1, NULL, Fi->table, "cat", Fi->database,
+			Fi->driver);
+    db_init_string(&sql);
     driver = db_start_driver_open_database(Fi->driver, Fi->database);
     if (driver == NULL)
 	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
 		      Fi->database, Fi->driver);
+
+    db_init_string(&tmp);
+    if (deg_opt->answer)
+	append_string(&tmp, deg_opt->answer);
+    if (close_opt->answer)
+	append_string(&tmp, close_opt->answer);
+    if (betw_opt->answer)
+	append_string(&tmp, betw_opt->answer);
+    if (eigen_opt->answer)
+	append_string(&tmp, eigen_opt->answer);
+    sprintf(buf,
+	    "create table %s(cat integer%s)", Fi->table, db_get_string(&tmp));
+
+    db_set_string(&sql, buf);
+    G_debug(2, db_get_string(&sql));
+
+    if (db_execute_immediate(driver, &sql) != DB_OK) {
+	db_close_database_shutdown_driver(driver);
+	G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql));
+    }
+
+    if (db_create_index2(driver, Fi->table, "cat") != DB_OK)
+	G_warning(_("Cannot create index"));
+
+    if (db_grant_on_table
+	(driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK)
+	G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table);
+
     db_begin_transaction(driver);
-    db_init_string(&sql);
 
+    Vect_copy_head_data(&In, &Out);
+    Vect_hist_copy(&In, &Out);
+    Vect_hist_command(&Out);
+
     Vect_net_build_graph(&In, mask_type, atoi(field_opt->answer), 0,
 			 afcol->answer, abcol->answer, NULL, geo, 0);
     graph = &(In.graph);
@@ -211,6 +261,10 @@
 
     deg = close = betw = eigen = NULL;
 
+    covered = (char *)G_calloc(nnodes + 1, sizeof(char));
+    if (!covered)
+	G_fatal_error(_("Out of memory"));
+
     if (deg_opt->answer) {
 	deg = (double *)G_calloc(nnodes + 1, sizeof(double));
 	if (!deg)
@@ -244,6 +298,9 @@
 	G_message(_
 		  ("Computing betweenness and/or closeness centrality measure"));
 	neta_betweenness_closeness(graph, betw, close);
+	if (close)
+	    for (i = 1; i <= nnodes; i++)
+		close[i] /= (double)In.cost_multip;
     }
     if (eigen_opt->answer) {
 	G_message(_("Computing eigenvector centrality measure"));
@@ -251,37 +308,48 @@
 				    atof(error_opt->answer), eigen);
     }
 
+
     nlines = Vect_get_num_lines(&In);
     G_message(_("Writing data into the table..."));
     G_percent_reset();
     for (i = 1; i <= nlines; i++) {
 	G_percent(i, nlines, 1);
-	//        if(!varray->c[i])continue;
-	int type = Vect_read_line(&In, NULL, Cats, i);
-	if (type == GV_POINT) {
+	int type = Vect_read_line(&In, Points, Cats, i);
+	if (type == GV_POINT && (!chcat || varray->c[i])) {
 	    int cat, node;
 	    if (!Vect_cat_get(Cats, layer, &cat))
 		continue;
+	    Vect_write_line(&Out, type, Points, Cats);
 	    Vect_get_line_nodes(&In, i, &node, NULL);
-	    if (deg_opt->answer)
-		update_record(driver, &sql, Fi->table, Fi->key, deg_opt->answer,
-			      deg[node], cat);
-	    if (close_opt->answer)
-		update_record(driver, &sql, Fi->table, Fi->key,
-			      close_opt->answer, close[node], cat);
-	    if (betw_opt->answer)
-		update_record(driver, &sql, Fi->table, Fi->key,
-			      betw_opt->answer, betw[node], cat);
-	    if (eigen_opt->answer)
-		update_record(driver, &sql, Fi->table, Fi->key,
-			      eigen_opt->answer, eigen[node], cat);
+	    process_node(node, cat);
+	    covered[node] = 1;
 	}
+    }
 
+    if (add_f->answer && !chcat) {
+	max_cat = 0;
+	for (i = 1; i <= nlines; i++) {
+	    Vect_read_line(&In, NULL, Cats, i);
+	    for (j = 0; j < Cats->n_cats; j++)
+		if (Cats->cat[j] > max_cat)
+		    max_cat = Cats->cat[j];
+	}
+	max_cat++;
+	for (i = 1; i <= nnodes; i++)
+	    if (!covered[i]) {
+		Vect_reset_cats(Cats);
+		Vect_cat_set(Cats, 1, max_cat);
+		neta_add_point_on_node(&In, &Out, i, Cats);
+		process_node(i, max_cat);
+		max_cat++;
+	    }
 
     }
+
     db_commit_transaction(driver);
     db_close_database_shutdown_driver(driver);
 
+    G_free(covered);
     if (deg)
 	G_free(deg);
     if (close)
@@ -290,8 +358,10 @@
 	G_free(betw);
     if (eigen)
 	G_free(eigen);
+    Vect_build(&Out);
 
     Vect_close(&In);
+    Vect_close(&Out);
 
     exit(EXIT_SUCCESS);
 }

Added: grass-addons/vector/net.analyze/v.net.components/description.html
===================================================================
--- grass-addons/vector/net.analyze/v.net.components/description.html	                        (rev 0)
+++ grass-addons/vector/net.analyze/v.net.components/description.html	2009-07-31 18:20:49 UTC (rev 38558)
@@ -0,0 +1,35 @@
+<h2>DESCRIPTION</h2>
+
+<em>v.net.components</em> computes the weakly and strongly connected components in a network.
+
+<h2>NOTES</h2>
+Two nodes, <em>u</em> and <em>v</em> are in the same strongly connected component if there are directed paths from <em>u</em> to <em>v</em> and from <em>v</em> to <em>u</em>. The nodes are in the same weakly connected component if, ignoring orientation of the edges, there is a path between them.<br>
+
+The type of components is specified by <b>method</b> parameter. Module creates a table and links it to the given <b>layer</b>. This table contains only two integer columns: <em>cat</em> and <em>comp</em>. If a point or both endpoints of a line belong to the same component then the point/line is written to the output map and appropriate information is stored in the table. If <b>-a</b> flag is set then new points are added on the nodes without points. These points have category numbers larger than any category used in the input map.    
+
+<h2>EXAMPLES</h2>
+
+Any road network should form a single strongly connected components. Otherwise,
+it is impossible to travel between some places.
+<div class="code"><pre>
+v.net.components input=roads output=roads_components method=strong
+</pre></div>
+<P>
+
+<div class="code"><pre>
+</pre></div>
+
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a HREF="v.category.html">v.category</a>,
+
+
+<h2>AUTHORS</h2>
+
+Daniel Bundala, Google Summer of Code 2009, Student<br>
+Wolf Bergenheim, Mentor
+
+<p>
+<i>Last changed: $Date: 2009-07-28 21:04:57 +0200 (Tue, 28 July 2009) $</i>


Property changes on: grass-addons/vector/net.analyze/v.net.components/description.html
___________________________________________________________________
Added: svn:executable
   + *

Modified: grass-addons/vector/net.analyze/v.net.components/main.c
===================================================================
--- grass-addons/vector/net.analyze/v.net.components/main.c	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/v.net.components/main.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -49,6 +49,7 @@
     struct GModule *module;	/* GRASS module for parsing arguments */
     struct Option *map_in, *map_out;
     struct Option *cat_opt, *field_opt, *where_opt, *method_opt;
+    struct Flag *add_f;
     int chcat, with_z;
     int layer, mask_type;
     VARRAY *varray;
@@ -88,6 +89,10 @@
 				 "strong;Strongly connected components;");
     method_opt->description = _("Type of components");
 
+    add_f = G_define_flag();
+    add_f->key = 'a';
+    add_f->description = _("Add points on nodes");
+
     /* options and flags parser */
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
@@ -119,33 +124,10 @@
 
     /* parse filter option and select appropriate lines */
     layer = atoi(field_opt->answer);
-    if (where_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "where");
-	if (cat_opt->answer)
-	    G_warning(_
-		      ("'where' and 'cats' parameters were supplied, cat will be ignored"));
-	chcat = 1;
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	if (Vect_set_varray_from_db
-	    (&In, layer, where_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Unable to load data from database"));
-	}
-    }
-    else if (cat_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "cat");
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	chcat = 1;
-	if (Vect_set_varray_from_cat_string
-	    (&In, layer, cat_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Problem loading category values"));
-	}
-    }
-    else {
-	chcat = 0;
-	varray = NULL;
-    }
+    chcat =
+	(neta_initialise_varray
+	 (&In, layer, mask_type, where_opt->answer, cat_opt->answer,
+	  &varray) == 1);
 
     Vect_net_build_graph(&In, mask_type, 0, 0, NULL, NULL, NULL, 0, 0);
     graph = &(In.graph);
@@ -157,10 +139,10 @@
 	exit(EXIT_FAILURE);
     }
     /* Create table */
-    Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
-    Vect_map_add_dblink(&Out, 1, NULL, Fi->table, "cat", Fi->database,
+    Fi = Vect_default_field_info(&Out, layer, NULL, GV_1TABLE);
+    Vect_map_add_dblink(&Out, layer, NULL, Fi->table, "cat", Fi->database,
 			Fi->driver);
-
+    db_init_string(&sql);
     driver = db_start_driver_open_database(Fi->driver, Fi->database);
     if (driver == NULL)
 	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
@@ -198,8 +180,10 @@
 
     nlines = Vect_get_num_lines(&In);
     for (i = 1; i <= nlines; i++) {
-	int comp;
+	int comp, cat;
 	type = Vect_read_line(&In, Points, Cats, i);
+	if (!Vect_cat_get(Cats, layer, &cat))
+	    continue;
 	if (type == GV_LINE || type == GV_BOUNDARY) {
 	    int node1, node2;
 	    Vect_get_line_nodes(&In, i, &node1, &node2);
@@ -219,31 +203,32 @@
 	else
 	    continue;
 	Vect_write_line(&Out, type, Points, Cats);
-	for (j = 0; j < Cats->n_cats; j++)
-	    insert_new_record(driver, Fi, &sql, Cats->cat[j], comp);
+	insert_new_record(driver, Fi, &sql, cat, comp);
+	/*        for(j=0;j<Cats->n_cats;j++)
+	 * if(Cats->field[j] == layer)
+	 * insert_new_record(driver, Fi, &sql, Cats->cat[j], comp);
+	 */
     };
     /*add points on nodes not covered by any point in the network */
     /*find the maximum cat number */
-    /*TODO: Do we want a flag for this? */
-    max_cat = 0;
-    for (i = 1; i <= nlines; i++) {
-	Vect_read_line(&In, NULL, Cats, i);
-	for (j = 0; j < Cats->n_cats; j++)
-	    if (Cats->cat[j] > max_cat)
-		max_cat = Cats->cat[j];
-    }
-    max_cat++;
-    for (i = 1; i <= nnodes; i++)
-	if (!covered[i]) {
-	    double x, y, z;
-	    Vect_reset_cats(Cats);
-	    Vect_cat_set(Cats, 1, max_cat);
-	    Vect_get_node_coor(&In, i, &x, &y, &z);
-	    Vect_reset_line(Points);
-	    Vect_append_point(Points, x, y, z);
-	    Vect_write_line(&Out, GV_POINT, Points, Cats);
-	    insert_new_record(driver, Fi, &sql, max_cat++, component[i]);
+    if (add_f->answer) {
+	max_cat = 0;
+	for (i = 1; i <= nlines; i++) {
+	    Vect_read_line(&In, NULL, Cats, i);
+	    for (j = 0; j < Cats->n_cats; j++)
+		if (Cats->cat[j] > max_cat)
+		    max_cat = Cats->cat[j];
 	}
+	max_cat++;
+	for (i = 1; i <= nnodes; i++)
+	    if (!covered[i]) {
+		Vect_reset_cats(Cats);
+		Vect_cat_set(Cats, 1, max_cat);
+		neta_add_point_on_node(&In, &Out, i, Cats);
+		insert_new_record(driver, Fi, &sql, max_cat++, component[i]);
+	    }
+    }
+
     db_commit_transaction(driver);
     db_close_database_shutdown_driver(driver);
 

Modified: grass-addons/vector/net.analyze/v.net.connectivity/main.c
===================================================================
--- grass-addons/vector/net.analyze/v.net.connectivity/main.c	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/v.net.connectivity/main.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -33,14 +33,16 @@
     char *mapset;
     struct GModule *module;	/* GRASS module for parsing arguments */
     struct Option *map_in, *map_out;
-    struct Option *cat_opt, *field_opt, *where_opt, *ncol, *set1_opt, *set2_opt;
+    struct Option *cat_opt, *field_opt, *where_opt, *ncol;
+    struct Option *catset1_opt, *fieldset1_opt, *whereset1_opt;
+    struct Option *catset2_opt, *fieldset2_opt, *whereset2_opt;
     int chcat, with_z;
     int layer, mask_type;
     VARRAY *varray;
+    VARRAY *varray_set1, *varray_set2;
     dglGraph_s *graph;
     int i, nnodes, nlines, *flow, total_flow, nedges;
     struct ilist *set1_list, *set2_list, *cut;
-    struct cat_list *set1_cats, *set2_cats;
     int *node_costs;
 
     dglGraph_s vg;
@@ -68,15 +70,27 @@
     ncol->required = NO;
     ncol->description = _("Node capacity column");
 
-    set1_opt = G_define_standard_option(G_OPT_V_CATS);
-    set1_opt->key = "set1";
-    set1_opt->required = YES;
-    set1_opt->description = _("Categories of the first set");
+    fieldset1_opt = G_define_standard_option(G_OPT_V_FIELD);
+    fieldset1_opt->key = "set1_layer";
+    fieldset1_opt->description = _("set1 layer");
+    catset1_opt = G_define_standard_option(G_OPT_V_CATS);
+    catset1_opt->key = "set1_cats";
+    catset1_opt->description = _("set1 category values");
+    whereset1_opt = G_define_standard_option(G_OPT_WHERE);
+    whereset1_opt->key = "set1_where";
+    whereset1_opt->description =
+	_("Set1 WHERE conditions of SQL statement without 'where' keyword");
 
-    set2_opt = G_define_standard_option(G_OPT_V_CATS);
-    set2_opt->key = "set2";
-    set2_opt->required = YES;
-    set2_opt->description = _("Categories of the second set");
+    fieldset2_opt = G_define_standard_option(G_OPT_V_FIELD);
+    fieldset2_opt->key = "set2_layer";
+    fieldset2_opt->description = _("set2 layer");
+    catset2_opt = G_define_standard_option(G_OPT_V_CATS);
+    catset2_opt->key = "set2_cats";
+    catset2_opt->description = _("set2 category values");
+    whereset2_opt = G_define_standard_option(G_OPT_WHERE);
+    whereset2_opt->key = "set2_where";
+    whereset2_opt->description =
+	_("Set2 WHERE conditions of SQL statement without 'where' keyword");
 
     /* options and flags parser */
     if (G_parser(argc, argv))
@@ -108,64 +122,37 @@
 
     /* parse filter option and select appropriate lines */
     layer = atoi(field_opt->answer);
-    if (where_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "where");
-	if (cat_opt->answer)
-	    G_warning(_
-		      ("'where' and 'cats' parameters were supplied, cat will be ignored"));
-	chcat = 1;
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	if (Vect_set_varray_from_db
-	    (&In, layer, where_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Unable to load data from database"));
-	}
-    }
-    else if (cat_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "cat");
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	chcat = 1;
-	if (Vect_set_varray_from_cat_string
-	    (&In, layer, cat_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Problem loading category values"));
-	}
-    }
-    else {
-	chcat = 0;
-	varray = NULL;
-    }
+    chcat =
+	(neta_initialise_varray
+	 (&In, layer, mask_type, where_opt->answer, cat_opt->answer,
+	  &varray) == 1);
 
-    set1_cats = Vect_new_cat_list();
-    set2_cats = Vect_new_cat_list();
-    Vect_str_to_cat_list(set1_opt->answer, set1_cats);
-    Vect_str_to_cat_list(set2_opt->answer, set2_cats);
+    if (neta_initialise_varray
+	(&In, atoi(fieldset1_opt->answer), GV_POINT, whereset1_opt->answer,
+	 catset1_opt->answer, &varray_set1) == 2)
+	G_fatal_error(_("Neither %s nor %s was given"), catset1_opt->key,
+		      whereset1_opt->key);
+    if (neta_initialise_varray
+	(&In, atoi(fieldset2_opt->answer), GV_POINT, whereset2_opt->answer,
+	 catset2_opt->answer, &varray_set2) == 2)
+	G_fatal_error(_("Neither %s nor %s was given"), catset2_opt->key,
+		      whereset2_opt->key);
+
     set1_list = Vect_new_list();
     set2_list = Vect_new_list();
 
+    neta_varray_to_nodes(&In, varray_set1, set1_list, NULL);
+    neta_varray_to_nodes(&In, varray_set2, set2_list, NULL);
+
     nlines = Vect_get_num_lines(&In);
     nnodes = Vect_get_num_nodes(&In);
-    for (i = 1; i <= nlines; i++) {
-	int type, cat;
-	type = Vect_read_line(&In, NULL, Cats, i);
-	if (type != GV_POINT)
-	    continue;
-	Vect_cat_get(Cats, layer, &cat);
-	if (Vect_cat_in_cat_list(cat, set1_cats))
-	    Vect_list_append(set1_list, i);
-	if (Vect_cat_in_cat_list(cat, set2_cats))
-	    Vect_list_append(set2_list, i);
-    }
 
     if (set1_list->n_values == 0)
-	G_fatal_error(_("No points with categories [%s]"), set1_opt->answer);
+	G_fatal_error(_("%s is empty"), "set1");
 
     if (set2_list->n_values == 0)
-	G_fatal_error(_("No points with categories [%s]"), set2_opt->answer);
+	G_fatal_error(_("%s is empty"), "set2");
 
-    neta_points_to_nodes(&In, set1_list);
-    neta_points_to_nodes(&In, set2_list);
-
     Vect_copy_head_data(&In, &Out);
     Vect_hist_copy(&In, &Out);
 

Modified: grass-addons/vector/net.analyze/v.net.distance/main.c
===================================================================
--- grass-addons/vector/net.analyze/v.net.distance/main.c	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/v.net.distance/main.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -25,43 +25,6 @@
 #include <grass/dbmi.h>
 #include <grass/neta.h>
 
-int initiliase_varray(struct Map_info *In, int layer, int mask_type,
-		      char *where, char *cat, VARRAY ** varray)
-{
-    /* parse filter option and select appropriate lines */
-    if (where) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "where");
-	if (cat)
-	    G_warning(_
-		      ("'where' and 'cats' parameters were supplied, cat will be ignored"));
-	*varray = Vect_new_varray(Vect_get_num_lines(In));
-	if (Vect_set_varray_from_db
-	    (In, layer, where, mask_type, 1, *varray) == -1) {
-	    G_warning(_("Unable to load data from database"));
-	    return 0;
-	}
-	return 1;
-    }
-    else if (cat) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "cat");
-	*varray = Vect_new_varray(Vect_get_num_lines(In));
-	if (Vect_set_varray_from_cat_string
-	    (In, layer, cat, mask_type, 1, *varray) == -1) {
-	    G_warning(_("Problem loading category values"));
-	    return 0;
-	}
-	return 1;
-    }
-    else {
-	G_fatal_error(_("Neither 'where' nor 'cat' were specified"));
-	return 0;
-    }
-
-
-}
-
 int main(int argc, char *argv[])
 {
     struct Map_info In, Out;
@@ -72,7 +35,7 @@
     struct Option *map_in, *map_out, *abcol, *afcol;
     struct Option *catf_opt, *fieldf_opt, *wheref_opt;
     struct Option *catt_opt, *fieldt_opt, *wheret_opt;
-    struct Flag *geo_f, *newpoints_f;
+    struct Flag *geo_f;
     int with_z, geo;
     int mask_type;
     VARRAY *varrayf, *varrayt;
@@ -129,7 +92,7 @@
     afcol = G_define_option();
     afcol->key = "afcolumn";
     afcol->type = TYPE_STRING;
-    afcol->required = NO;
+    afcol->required = YES;
     afcol->description = _("Arc forward/both direction(s) cost column");
 
     abcol = G_define_option();
@@ -199,10 +162,10 @@
     /*initialise varrays and nodes list appropriatelly */
     flayer = atoi(fieldf_opt->answer);
     tlayer = atoi(fieldt_opt->answer);
-    initiliase_varray(&In, flayer, GV_POINT, wheref_opt->answer,
-		      catf_opt->answer, &varrayf);
-    initiliase_varray(&In, tlayer, mask_type, wheret_opt->answer,
-		      catt_opt->answer, &varrayt);
+    neta_initialise_varray(&In, flayer, GV_POINT, wheref_opt->answer,
+			   catf_opt->answer, &varrayf);
+    neta_initialise_varray(&In, tlayer, mask_type, wheret_opt->answer,
+			   catt_opt->answer, &varrayt);
 
     nodest = Vect_new_list();
     neta_varray_to_nodes(&In, varrayt, nodest, nodes_to_features);
@@ -216,7 +179,7 @@
     Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
     Vect_map_add_dblink(&Out, 1, NULL, Fi->table, "cat", Fi->database,
 			Fi->driver);
-
+    db_init_string(&sql);
     driver = db_start_driver_open_database(Fi->driver, Fi->database);
     if (driver == NULL)
 	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),

Added: grass-addons/vector/net.analyze/v.net.flow/description.html
===================================================================
--- grass-addons/vector/net.analyze/v.net.flow/description.html	                        (rev 0)
+++ grass-addons/vector/net.analyze/v.net.flow/description.html	2009-07-31 18:20:49 UTC (rev 38558)
@@ -0,0 +1,36 @@
+<h2>DESCRIPTION</h2>
+
+<em>v.net.flow</em> computes the maximum flow and minimum cut between two sets of nodes.
+
+<h2>NOTES</h2>
+The two sets of nodes are called <em>sources</em> and <em>sink</em> and <em>v.net.flow</em> finds the maximimum flow from the former to the latter ones. Edge capacities can be specified by <b>afcolumn</b> for forward direction and <b>abcolumn</b> for backward direction. If the latter parameter is ommited then the same capacity is used in either direction. The sets are given by the respective <b>cats</b>, <b>layer</b> and <b>where</b> parameters. Maximum flow corresponds to the maximum amount of water possibly flowing through the network preserving the capacity constraints and minimum cut to set of edges of minimum total capacity completely separating sources from sinks. The cut produced by this module corresponds to the first fully saturated edges from sources to sinks. An attribute table containing the flow information is linked to the <b>output</b> map. The table consists of two columns: <em>cat</em> and <em>flow</em> and stores the flow along each line. Negative flow means that "water" is flowing in the backward direction. <b>Cut</b> map contains the edges in the minimum cut. <br>
+A famous <a href="http://en.wikipedia.org/wiki/Max-flow_min-cut_theorem">result</a> says that the total amount of water flowing is equal to the minimum cut.
+ 
+
+<h2>EXAMPLES</h2>
+
+Find maximum flow from factories to stores using SPEED for the capacities.
+<div class="code"><pre>
+v.net.flow input=roads output=roads_flow cut=roads_cut afcolumn=SPEED source_where="type=factory" sink_where="type=store"
+</pre></div>
+<P>
+
+If all the capacties are one then the minimum cut corresponds to the minimum number of edges separating sources from sinks. 
+<div class="code"><pre>
+v.net.flow input=network output=flow cut=cut afcolumn=ones source_cats=1-10 sink_cats=100-100
+</pre></div>
+
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a HREF="v.net.connectivity.html">v.net.connectivity</a>
+
+
+<h2>AUTHORS</h2>
+
+Daniel Bundala, Google Summer of Code 2009, Student<br>
+Wolf Bergenheim, Mentor
+
+<p>
+<i>Last changed: $Date: 2009-07-28 21:04:57 +0200 (Tue, 28 July 2009) $</i>


Property changes on: grass-addons/vector/net.analyze/v.net.flow/description.html
___________________________________________________________________
Added: svn:executable
   + *

Modified: grass-addons/vector/net.analyze/v.net.flow/main.c
===================================================================
--- grass-addons/vector/net.analyze/v.net.flow/main.c	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/v.net.flow/main.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -33,15 +33,16 @@
     char *mapset;
     struct GModule *module;	/* GRASS module for parsing arguments */
     struct Option *map_in, *map_out, *cut_out;
-    struct Option *cat_opt, *field_opt, *where_opt, *abcol, *afcol, *source_opt,
-	*sink_opt;
+    struct Option *cat_opt, *field_opt, *where_opt, *abcol, *afcol;
+    struct Option *catsource_opt, *fieldsource_opt, *wheresource_opt;
+    struct Option *catsink_opt, *fieldsink_opt, *wheresink_opt;
     int chcat, with_z;
     int layer, mask_type;
     VARRAY *varray;
+    VARRAY *varray_source, *varray_sink;
     dglGraph_s *graph;
     int i, nlines, *flow, total_flow;
     struct ilist *source_list, *sink_list, *cut;
-    struct cat_list *source_cats, *sink_cats;
     int find_cut;
 
     char buf[2000];
@@ -86,16 +87,30 @@
     abcol->required = NO;
     abcol->description = _("Arc backward direction capacity column");
 
-    source_opt = G_define_standard_option(G_OPT_V_CATS);
-    source_opt->key = "source";
-    source_opt->required = YES;
-    source_opt->description = _("Categories of source(s)");
+    fieldsource_opt = G_define_standard_option(G_OPT_V_FIELD);
+    fieldsource_opt->key = "source_layer";
+    fieldsource_opt->description = _("Source layer");
+    catsource_opt = G_define_standard_option(G_OPT_V_CATS);
+    catsource_opt->key = "source_cats";
+    catsource_opt->description = _("Source category values");
+    wheresource_opt = G_define_standard_option(G_OPT_WHERE);
+    wheresource_opt->key = "source_where";
+    wheresource_opt->description =
+	_("Source WHERE conditions of SQL statement without 'where' keyword");
 
-    sink_opt = G_define_standard_option(G_OPT_V_CATS);
-    sink_opt->key = "sink";
-    sink_opt->required = YES;
-    sink_opt->description = _("Categories of sink(s)");
+    fieldsink_opt = G_define_standard_option(G_OPT_V_FIELD);
+    fieldsink_opt->key = "sink_layer";
+    fieldsink_opt->description = _("Sink layer");
+    catsink_opt = G_define_standard_option(G_OPT_V_CATS);
+    catsink_opt->key = "sink_cats";
+    catsink_opt->description = _("Sink category values");
+    wheresink_opt = G_define_standard_option(G_OPT_WHERE);
+    wheresink_opt->key = "sink_where";
+    wheresink_opt->description =
+	_("Sink WHERE conditions of SQL statement without 'where' keyword");
 
+
+
     /* options and flags parser */
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
@@ -133,45 +148,23 @@
 
     /* parse filter option and select appropriate lines */
     layer = atoi(field_opt->answer);
-    if (where_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "where");
-	if (cat_opt->answer)
-	    G_warning(_
-		      ("'where' and 'cats' parameters were supplied, cat will be ignored"));
-	chcat = 1;
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	if (Vect_set_varray_from_db
-	    (&In, layer, where_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Unable to load data from database"));
-	}
-    }
-    else if (cat_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "cat");
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	chcat = 1;
-	if (Vect_set_varray_from_cat_string
-	    (&In, layer, cat_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Problem loading category values"));
-	}
-    }
-    else {
-	chcat = 0;
-	varray = NULL;
-    }
+    chcat =
+	(neta_initialise_varray
+	 (&In, layer, mask_type, where_opt->answer, cat_opt->answer,
+	  &varray) == 1);
 
     /* Create table */
     Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
     Vect_map_add_dblink(&Out, 1, NULL, Fi->table, "cat", Fi->database,
 			Fi->driver);
-
+    db_init_string(&sql);
     driver = db_start_driver_open_database(Fi->driver, Fi->database);
     if (driver == NULL)
 	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
 		      Fi->database, Fi->driver);
 
-    sprintf(buf, "create table %s (cat integer, flow integer)", Fi->table);
+    sprintf(buf, "create table %s (cat integer, flow double precision)",
+	    Fi->table);
 
     db_set_string(&sql, buf);
     G_debug(2, db_get_string(&sql));
@@ -190,35 +183,30 @@
 
     db_begin_transaction(driver);
 
-    source_cats = Vect_new_cat_list();
-    sink_cats = Vect_new_cat_list();
-    Vect_str_to_cat_list(source_opt->answer, source_cats);
-    Vect_str_to_cat_list(sink_opt->answer, sink_cats);
     source_list = Vect_new_list();
     sink_list = Vect_new_list();
 
-    nlines = Vect_get_num_lines(&In);
-    for (i = 1; i <= nlines; i++) {
-	int type, cat;
-	type = Vect_read_line(&In, NULL, Cats, i);
-	if (type != GV_POINT)
-	    continue;
-	Vect_cat_get(Cats, layer, &cat);
-	if (Vect_cat_in_cat_list(cat, source_cats))
-	    Vect_list_append(source_list, i);
-	if (Vect_cat_in_cat_list(cat, sink_cats))
-	    Vect_list_append(sink_list, i);
-    }
+    if (neta_initialise_varray
+	(&In, atoi(fieldsource_opt->answer), GV_POINT, wheresource_opt->answer,
+	 catsource_opt->answer, &varray_source) == 2)
+	G_fatal_error(_("Neither %s nor %s was given"), catsource_opt->key,
+		      wheresource_opt->key);
+    if (neta_initialise_varray
+	(&In, atoi(fieldsink_opt->answer), GV_POINT, wheresink_opt->answer,
+	 catsink_opt->answer, &varray_sink) == 2)
+	G_fatal_error(_("Neither %s nor %s was given"), catsink_opt->key,
+		      wheresink_opt->key);
 
+
+    neta_varray_to_nodes(&In, varray_source, source_list, NULL);
+    neta_varray_to_nodes(&In, varray_sink, sink_list, NULL);
+
     if (source_list->n_values == 0)
-	G_fatal_error(_("No points with categories [%s]"), source_opt->answer);
+	G_fatal_error(_("No sources"));
 
     if (sink_list->n_values == 0)
-	G_fatal_error(_("No points with categories [%s]"), sink_opt->answer);
+	G_fatal_error(_("No sinks"));
 
-    neta_points_to_nodes(&In, source_list);
-    neta_points_to_nodes(&In, sink_list);
-
     Vect_copy_head_data(&In, &Out);
     Vect_hist_copy(&In, &Out);
 
@@ -227,7 +215,7 @@
     Vect_net_build_graph(&In, mask_type, atoi(field_opt->answer), 0,
 			 afcol->answer, abcol->answer, NULL, 0, 0);
     graph = &(In.graph);
-
+    nlines = Vect_get_num_lines(&In);
     flow = (int *)G_calloc(nlines + 1, sizeof(int));
     if (!flow)
 	G_fatal_error(_("Out of memory"));
@@ -251,8 +239,8 @@
 	    Vect_cat_get(Cats, layer, &cat);
 	    if (cat == -1)
 		continue;	/*TODO: warning? */
-	    sprintf(buf, "insert into %s values (%d, %d)", Fi->table, cat,
-		    flow[i] / In.cost_multip);
+	    sprintf(buf, "insert into %s values (%d, %f)", Fi->table, cat,
+		    flow[i] / (double)In.cost_multip);
 	    db_set_string(&sql, buf);
 	    G_debug(3, db_get_string(&sql));
 

Modified: grass-addons/vector/net.analyze/v.net.spanningtree/main.c
===================================================================
--- grass-addons/vector/net.analyze/v.net.spanningtree/main.c	2009-07-31 16:26:21 UTC (rev 38557)
+++ grass-addons/vector/net.analyze/v.net.spanningtree/main.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -46,7 +46,7 @@
     /* initialize module */
     module = G_define_module();
     module->keywords = _("network, spanning tree");
-    module->description = _("Computes spanning.");
+    module->description = _("Computes minimum spanning tree.");
 
     /* Define the different options as defined in gis.h */
     map_in = G_define_standard_option(G_OPT_V_INPUT);
@@ -105,33 +105,10 @@
 
     /* parse filter option and select appropriate lines */
     layer = atoi(field_opt->answer);
-    if (where_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "where");
-	if (cat_opt->answer)
-	    G_warning(_
-		      ("'where' and 'cats' parameters were supplied, cat will be ignored"));
-	chcat = 1;
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	if (Vect_set_varray_from_db
-	    (&In, layer, where_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Unable to load data from database"));
-	}
-    }
-    else if (cat_opt->answer) {
-	if (layer < 1)
-	    G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "cat");
-	varray = Vect_new_varray(Vect_get_num_lines(&In));
-	chcat = 1;
-	if (Vect_set_varray_from_cat_string
-	    (&In, layer, cat_opt->answer, mask_type, 1, varray) == -1) {
-	    G_warning(_("Problem loading category values"));
-	}
-    }
-    else {
-	chcat = 0;
-	varray = NULL;
-    }
+    chcat =
+	(neta_initialise_varray
+	 (&In, layer, mask_type, where_opt->answer, cat_opt->answer,
+	  &varray) == 1);
 
     Vect_net_build_graph(&In, mask_type, atoi(field_opt->answer), 0,
 			 accol->answer, NULL, NULL, geo, 0);
@@ -143,7 +120,7 @@
 
     tree_list = Vect_new_list();
     edges = neta_spanning_tree(graph, tree_list);
-    G_debug(3, "Edges: %d\n", edges);
+    G_debug(3, "Edges: %d", edges);
     for (i = 0; i < edges; i++) {
 	int type = Vect_read_line(&In, Points, Cats, abs(tree_list->value[i]));
 	Vect_write_line(&Out, type, Points, Cats);

Added: grass-addons/vector/net.analyze/v.net.spanningtree/v.net.spanningtree.tmp.html
===================================================================
--- grass-addons/vector/net.analyze/v.net.spanningtree/v.net.spanningtree.tmp.html	                        (rev 0)
+++ grass-addons/vector/net.analyze/v.net.spanningtree/v.net.spanningtree.tmp.html	2009-07-31 18:20:49 UTC (rev 38558)
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>GRASS GIS manual: v.net.spanningtree</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<link rel="stylesheet" href="grassdocs.css" type="text/css">
+</head>
+<body bgcolor="white">
+
+<img src="grass_logo.png" alt="GRASS logo"><hr align=center size=6 noshade>
+
+<h2>NAME</h2>
+<em><b>v.net.spanningtree</b></em>  - Computes minimum spanning tree.
+<h2>KEYWORDS</h2>
+network, spanning tree
+<h2>SYNOPSIS</h2>
+<b>v.net.spanningtree</b><br>
+<b>v.net.spanningtree help</b><br>
+<b>v.net.spanningtree</b> [-<b>g</b>] <b>input</b>=<em>name</em> <b>output</b>=<em>name</em>  [<b>layer</b>=<em>integer</em>]   [<b>cats</b>=<em>range</em>]   [<b>where</b>=<em>sql_query</em>]   [<b>accol</b>=<em>string</em>]   [--<b>overwrite</b>]  [--<b>verbose</b>]  [--<b>quiet</b>] 
+
+<h3>Flags:</h3>
+<DL>
+<DT><b>-g</b></DT>
+<DD>Use geodesic calculation for longitude-latitude locations</DD>
+
+<DT><b>--overwrite</b></DT>
+<DD>Allow output files to overwrite existing files</DD>
+<DT><b>--verbose</b></DT>
+<DD>Verbose module output</DD>
+<DT><b>--quiet</b></DT>
+<DD>Quiet module output</DD>
+</DL>
+
+<h3>Parameters:</h3>
+<DL>
+<DT><b>input</b>=<em>name</em></DT>
+<DD>Name of input vector map</DD>
+
+<DT><b>output</b>=<em>name</em></DT>
+<DD>Name for output vector map</DD>
+
+<DT><b>layer</b>=<em>integer</em></DT>
+<DD>Layer number</DD>
+<DD>A single vector map can be connected to multiple database tables. This number determines which table to use.</DD>
+<DD>Default: <em>1</em></DD>
+
+<DT><b>cats</b>=<em>range</em></DT>
+<DD>Category values</DD>
+<DD>Example: 1,3,7-9,13</DD>
+
+<DT><b>where</b>=<em>sql_query</em></DT>
+<DD>WHERE conditions of SQL statement without 'where' keyword</DD>
+<DD>Example: income &lt; 1000 and inhab &gt;= 10000</DD>
+
+<DT><b>accol</b>=<em>string</em></DT>
+<DD>Arc cost column</DD>
+
+</DL>
+<h2>DESCRIPTION</h2>
+
+<em>v.net.spanningtree</em> find the minimum spanning tree in a network. 
+
+<h2>NOTES</h2>
+Spanning tree is a minimum cost subnetwork connecting all nodes in a network. Or, if a network is disconnected then the module computes the minimum spanning tree for each (weakly) connected component. So, srictly speaking, module dos not compute spanning tree but a spanning forest. As the name suggests spanning tree is a tree. That is, it contains no cycles and if a component has N nodes that the tree has N-1 edges and connected all nodes. <b>Accol</b> is used to specify the costs of the edges. The <b>output</b> consists of the edges in the spanning tree.  
+
+<h2>EXAMPLES</h2>
+
+Find cheapest set of pipelines connecting all nodes.
+<div class="code"><pre>
+v.net.spanningtree input=projected_pipelines output=spanningtree accol=cost 
+</pre></div>
+<P>
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a HREF="v.net.steiner.html">v.net.steiner</a>
+
+
+<h2>AUTHORS</h2>
+
+Daniel Bundala, Google Summer of Code 2009, Student<br>
+Wolf Bergenheim, Mentor
+
+<p>
+<i>Last changed: $Date: 2009-07-28 21:04:57 +0200 (Tue, 28 July 2009) $</i>
+<HR>
+<P><a href="index.html">Main index</a> - <a href="vector.html">vector index</a> - <a href="full_index.html">Full index</a></P>
+<P>&copy; 2003-2009 <a href="http://grass.osgeo.org">GRASS Development Team</a></p>
+</body>
+</html>


Property changes on: grass-addons/vector/net.analyze/v.net.spanningtree/v.net.spanningtree.tmp.html
___________________________________________________________________
Added: svn:executable
   + *

Added: grass-addons/vector/net.analyze/v.net.timetable/Makefile
===================================================================
--- grass-addons/vector/net.analyze/v.net.timetable/Makefile	                        (rev 0)
+++ grass-addons/vector/net.analyze/v.net.timetable/Makefile	2009-07-31 18:20:49 UTC (rev 38558)
@@ -0,0 +1,15 @@
+MODULE_TOPDIR = ../../..
+
+PGM=v.net.timetable
+
+include ../Netalib.make
+
+LIBES     = $(NETALIB) $(VECTLIB) $(VECTLIB_REAL) $(DBMILIB) $(GISLIB)
+DEPENDENCIES = $(NETADEP) $(VECTDEP) $(DBMIDEP) $(GISDEP)
+EXTRA_INC = $(VECT_INC)
+EXTRA_CFLAGS = $(VECT_CFLAGS)
+ 
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd	
+


Property changes on: grass-addons/vector/net.analyze/v.net.timetable/Makefile
___________________________________________________________________
Added: svn:executable
   + *

Added: grass-addons/vector/net.analyze/v.net.timetable/main.c
===================================================================
--- grass-addons/vector/net.analyze/v.net.timetable/main.c	                        (rev 0)
+++ grass-addons/vector/net.analyze/v.net.timetable/main.c	2009-07-31 18:20:49 UTC (rev 38558)
@@ -0,0 +1,534 @@
+
+/****************************************************************
+ *
+ * MODULE:     v.net.timetable
+ *
+ * AUTHOR(S):  Daniel Bundala
+ *
+ * PURPOSE:    Routing with timetables
+ *
+ * COPYRIGHT:  (C) 2002-2005 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.
+ *
+ ****************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <grass/gis.h>
+#include <grass/Vect.h>
+#include <grass/glocale.h>
+#include <grass/neta.h>
+
+struct Map_info In, Out;
+neta_timetable_result result;
+neta_timetable timetable;
+
+struct segment
+{
+    int from_stop, to_stop;
+    int from_time, to_time;
+    int route;
+    struct segment *next;
+} head;
+
+double *stop_x, *stop_y, *stop_z;
+int *stop_ids, *route_ids;
+int *found, *stop_node, *edges, nnodes;
+struct ilist **lines;
+dglGraph_s *graph;
+
+void init_route(int connection, int stop)
+{
+    if (result.prev_stop[connection][stop] == -1)
+	return;
+    struct segment *seg = (struct segment *)G_calloc(1, sizeof(struct segment));
+    int prev_conn = result.prev_conn[connection][stop];
+    seg->next = head.next;
+    head.next = seg;
+    seg->route = result.prev_route[connection][stop];
+    seg->from_stop = result.prev_stop[connection][stop];
+    seg->to_stop = stop;
+    if (seg->route == -2)
+	seg->from_time = result.dst[prev_conn][seg->from_stop];
+    else
+	seg->from_time =
+	    neta_timetable_get_route_time(&timetable, seg->from_stop,
+					  seg->route);
+    seg->to_time = result.dst[connection][stop];
+    init_route(prev_conn, seg->from_stop);
+}
+
+void release_route(struct segment *seg)
+{
+    if (!seg)
+	return;
+    release_route(seg->next);
+    G_free(seg->next);
+}
+
+static int int_cmp(const void *a, const void *b)
+{
+    return *(int *)a - *(int *)b;
+}
+
+void init_database(struct Map_info *Out, dbDriver ** driver,
+		   struct field_info **Fi, int layer, char *columns)
+{
+    dbString sql;
+    char buf[2000];
+    /* Create table */
+    *Fi = Vect_default_field_info(Out, layer, NULL, GV_MTABLE);
+    Vect_map_add_dblink(Out, layer, NULL, (*Fi)->table, "cat", (*Fi)->database,
+			(*Fi)->driver);
+    db_init_string(&sql);
+    *driver = db_start_driver_open_database((*Fi)->driver, (*Fi)->database);
+    if (*driver == NULL)
+	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
+		      (*Fi)->database, (*Fi)->driver);
+
+    sprintf(buf, "create table %s (%s)", (*Fi)->table, columns);
+
+    db_set_string(&sql, buf);
+    G_debug(2, db_get_string(&sql));
+
+    if (db_execute_immediate(*driver, &sql) != DB_OK) {
+	db_close_database_shutdown_driver(*driver);
+	G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql));
+    }
+
+    if (db_create_index2(*driver, (*Fi)->table, "cat") != DB_OK)
+	G_warning(_("Cannot create index"));
+
+    if (db_grant_on_table
+	(*driver, (*Fi)->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK)
+	G_fatal_error(_("Cannot grant privileges on table <%s>"), (*Fi)->table);
+
+    db_free_string(&sql);
+    db_begin_transaction(*driver);
+}
+
+void insert_point(dbDriver * driver, char *table, int cat, int path,
+		  int stop_id, int index, int arrival_time, int departure_time)
+{
+    char buf[2000];
+    dbString sql;
+    db_init_string(&sql);
+
+    sprintf(buf, "insert into %s values (%d, %d, %d, %d, %d, %d)", table, cat,
+	    path, stop_id, index, arrival_time, departure_time);
+    db_set_string(&sql, buf);
+    G_debug(3, db_get_string(&sql));
+    if (db_execute_immediate(driver, &sql) != DB_OK) {
+	db_close_database_shutdown_driver(driver);
+	G_fatal_error(_("Cannot insert new record: %s"), db_get_string(&sql));
+    };
+
+    db_free_string(&sql);
+}
+
+void insert_line(dbDriver * driver, char *table, int cat, int path, int from_id,
+		 int to_id, int route_id, int index, int from_time, int to_time)
+{
+    char buf[2000];
+    dbString sql;
+    db_init_string(&sql);
+
+    sprintf(buf, "insert into %s values (%d, %d, %d, %d, %d, %d, %d, %d)",
+	    table, cat, path, from_id, to_id, route_id, index, from_time,
+	    to_time);
+    db_set_string(&sql, buf);
+    G_debug(3, db_get_string(&sql));
+    if (db_execute_immediate(driver, &sql) != DB_OK) {
+	db_close_database_shutdown_driver(driver);
+	G_fatal_error(_("Cannot insert new record: %s"), db_get_string(&sql));
+    };
+
+    db_free_string(&sql);
+}
+
+int get_nearest_stop(double x, double y, double z, int with_z)
+{
+    int i, mini = -1;
+    double mind, d;
+    for (i = 0; i < timetable.stops; i++) {
+	if (!found[i])
+	    continue;
+	d = Vect_points_distance(x, y, z, stop_x[i], stop_y[i], stop_z[i],
+				 with_z);
+	if (mini == -1 || d < mind) {
+	    mind = d;
+	    mini = i;
+	}
+    }
+    return mini;
+}
+
+void write_subroute(struct segment *seg, struct line_pnts *line, int line_id)
+{
+    int i, j, r;
+    struct line_pnts *Points;
+    struct line_cats *Cats;
+    struct ilist *list;
+    Points = Vect_new_line_struct();
+    Cats = Vect_new_cats_struct();
+    list = Vect_new_list();
+    r = seg->route;
+
+    Vect_cat_set(Cats, 2, line_id);
+
+    if (r < 0) {
+	Vect_write_line(&Out, GV_LINE, line, Cats);
+	return;
+    }
+
+    for (i = 0; i < nnodes; i++)
+	edges[i] = 0;
+    for (i = 0; i < lines[r]->n_values; i++)
+	edges[lines[r]->value[i]] = 1;
+
+    for (i = 0; i < timetable.route_length[r]; i++)
+	if (timetable.route_stops[r][i] == seg->from_stop)
+	    break;
+    for (; timetable.route_stops[r][i] != seg->to_stop; i++)
+	if (neta_find_path
+	    (graph, stop_node[timetable.route_stops[r][i]],
+	     stop_node[timetable.route_stops[r][i + 1]], edges, list) != -1) {
+	    for (j = 0; j < list->n_values; j++) {
+		int type = Vect_read_line(&In, Points, NULL, list->value[j]);
+		Vect_write_line(&Out, type, Points, Cats);
+	    }
+	}
+	else {
+	    G_warning(_("Could not find a path between stops %d and %d"),
+		      stop_ids[timetable.route_stops[r][i]],
+		      stop_ids[timetable.route_stops[r][i + 1]]);
+	}
+
+    Vect_destroy_list(list);
+    Vect_destroy_cats_struct(Cats);
+    Vect_destroy_line_struct(Points);
+}
+
+int main(int argc, char *argv[])
+{
+    static struct line_pnts *Points, *Cur, *Prev;
+    struct line_cats *Counter_Cats, *Cats;
+    char *mapset;
+    struct GModule *module;	/* GRASS module for parsing arguments */
+    struct Option *map_in, *map_out;
+    struct Option *cat_opt, *field_opt, *where_opt, *walk_layer_opt,
+	*path_layer_opt;
+    int chcat, with_z;
+    int layer, mask_type, path_layer;
+    VARRAY *varray;
+    int from_stop, to_stop, start_time, min_change, max_changes, walking_change,
+	ret;
+    int *stop_pnt, i, nlines, point_counter, *route_pnt;
+    int line_counter, index, j;
+    struct segment *cur;
+    char buf[2000];
+
+    /* Attribute table */
+    dbDriver *point_driver, *line_driver;
+    struct field_info *point_Fi, *line_Fi;
+
+    /* initialize GIS environment */
+    G_gisinit(argv[0]);		/* reads grass env, stores program name to G_program_name() */
+
+    /* initialize module */
+    module = G_define_module();
+    module->keywords = _("network, routing, shortest path, timetable");
+    module->description = _("Finds shortest path using timetables.");
+
+    /* Define the different options as defined in gis.h */
+    map_in = G_define_standard_option(G_OPT_V_INPUT);
+    map_out = G_define_standard_option(G_OPT_V_OUTPUT);
+
+    field_opt = G_define_standard_option(G_OPT_V_FIELD);
+    cat_opt = G_define_standard_option(G_OPT_V_CATS);
+    where_opt = G_define_standard_option(G_OPT_WHERE);
+
+    walk_layer_opt = G_define_standard_option(G_OPT_V_FIELD);
+    walk_layer_opt->key = "walking";
+    walk_layer_opt->answer = "-1";
+    walk_layer_opt->description = _("Layer with walking connections or -1");
+
+    path_layer_opt = G_define_standard_option(G_OPT_V_FIELD);
+    path_layer_opt->key = "paths";
+    path_layer_opt->answer = "-1";
+    path_layer_opt->description = _("Layer with route paths or -1");
+
+
+    /* options and flags parser */
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+    /* TODO: make an option for this */
+    mask_type = GV_LINE | GV_BOUNDARY;
+
+    Points = Vect_new_line_struct();
+    Cats = Vect_new_cats_struct();
+    Counter_Cats = Vect_new_cats_struct();
+    Cur = Vect_new_line_struct();
+    Prev = Vect_new_line_struct();
+
+    Vect_check_input_output_name(map_in->answer, map_out->answer,
+				 GV_FATAL_EXIT);
+
+    if ((mapset = G_find_vector2(map_in->answer, "")) == NULL)
+	G_fatal_error(_("Vector map <%s> not found"), map_in->answer);
+
+    Vect_set_open_level(2);
+
+    if (1 > Vect_open_old(&In, map_in->answer, mapset))
+	G_fatal_error(_("Unable to open vector map <%s>"),
+		      G_fully_qualified_name(map_in->answer, mapset));
+
+    with_z = Vect_is_3d(&In);
+
+    if (0 > Vect_open_new(&Out, map_out->answer, with_z)) {
+	Vect_close(&In);
+	G_fatal_error(_("Unable to create vector map <%s>"), map_out->answer);
+    }
+
+
+    /* parse filter option and select appropriate lines */
+    layer = atoi(field_opt->answer);
+    chcat =
+	(neta_initialise_varray
+	 (&In, layer, mask_type, where_opt->answer, cat_opt->answer,
+	  &varray) == 1);
+    path_layer = atoi(path_layer_opt->answer);
+
+
+    init_database(&Out, &point_driver, &point_Fi, 1,
+		  "cat integer, path_id integer, stop_id integer, index integer, arr_time integer, dep_time integer");
+    init_database(&Out, &line_driver, &line_Fi, 2,
+		  "cat integer, path_id integer, from_id integer, to_id integer, route_id integer, index integer, from_time integer, to_time integer");
+
+    Vect_copy_head_data(&In, &Out);
+    Vect_hist_copy(&In, &Out);
+    Vect_hist_command(&Out);
+
+    if (neta_init_timetable_from_db
+	(&In, layer, atoi(walk_layer_opt->answer), "route_id", "stop",
+	 &timetable, &route_ids, &stop_ids) != 0)
+	G_fatal_error(_("Could not initialize the timetables"));
+
+    stop_x = (double *)G_calloc(timetable.stops, sizeof(double));
+    stop_y = (double *)G_calloc(timetable.stops, sizeof(double));
+    stop_z = (double *)G_calloc(timetable.stops, sizeof(double));
+    found = (int *)G_calloc(timetable.stops, sizeof(int));
+
+    if (!stop_x || !stop_y || !stop_z || !found)
+	G_fatal_error(_("Out of memory"));
+
+    if (path_layer > 0) {
+	nnodes = Vect_get_num_nodes(&In);
+	stop_node = (int *)G_calloc(timetable.stops, sizeof(int));
+	lines =
+	    (struct ilist **)G_calloc(timetable.routes, sizeof(struct ilist *));
+	edges = (int *)G_calloc(nnodes + 1, sizeof(int));
+	if (!edges || !stop_node || !lines)
+	    G_fatal_error(_("Out of memory"));
+	for (i = 0; i < timetable.routes; i++)
+	    lines[i] = Vect_new_list();
+
+	Vect_net_build_graph(&In, mask_type, path_layer, 0, NULL, NULL, NULL, 0,
+			     0);
+	graph = &(In.graph);
+    }
+
+
+    nlines = Vect_get_num_lines(&In);
+    for (i = 1; i <= nlines; i++) {
+	int type = Vect_read_line(&In, Points, Cats, i);
+	if (type == GV_POINT) {
+	    int cat, stop, node;
+	    for (j = 0; j < Cats->n_cats; j++) {
+		if (Cats->field[j] != layer)
+		    continue;
+		cat = Cats->cat[j];
+		stop_pnt =
+		    (int *)bsearch(&cat, stop_ids, timetable.stops, sizeof(int),
+				   int_cmp);
+		if (!stop_pnt)
+		    continue;
+
+		stop = stop_pnt - stop_ids;
+		stop_x[stop] = Points->x[0];
+		stop_y[stop] = Points->y[0];
+		stop_z[stop] = Points->z[0];
+		if (path_layer > 0) {
+		    Vect_get_line_nodes(&In, i, &node, NULL);
+		    if (!stop_node[stop])
+			stop_node[stop] = node;
+		}
+		found[stop] = 1;
+	    }
+	}
+	else if (type == GV_LINE && path_layer > 0) {
+	    int cat;
+	    for (j = 0; j < Cats->n_cats; j++) {
+		if (Cats->field[j] != path_layer)
+		    continue;
+		cat = Cats->cat[j];
+		route_pnt =
+		    (int *)bsearch(&cat, route_ids, timetable.routes,
+				   sizeof(int), int_cmp);
+		if (!route_pnt)
+		    continue;
+		Vect_list_append(lines[route_pnt - route_ids], i);
+	    }
+	}
+    }
+
+    for (i = 0; i < timetable.stops; i++)
+	if (!found[i])
+	    G_warning(_("No stop with category: %d"), stop_ids[i]);
+
+    point_counter = line_counter = 1;
+    while (1) {
+	double fx, fy, tx, ty;
+	int path_id;
+	if (fgets(buf, sizeof(buf), stdin) == NULL)
+	    break;
+	ret =
+	    sscanf(buf, "%d %lf %lf %lf %lf %d %d %d %d", &path_id, &fx, &fy,
+		   &tx, &ty, &start_time, &min_change, &max_changes,
+		   &walking_change);
+	if (ret == 9) {
+	    from_stop = get_nearest_stop(fx, fy, 0, with_z);
+	    to_stop = get_nearest_stop(tx, ty, 0, with_z);
+	}
+	else {
+	    ret =
+		sscanf(buf, "%d %d %d %d %d %d %d", &path_id, &from_stop,
+		       &to_stop, &start_time, &min_change, &max_changes,
+		       &walking_change);
+	    if (ret < 7) {
+		G_warning(_("Wrong input format: %s"), buf);
+		continue;
+	    }
+
+	    stop_pnt =
+		(int *)bsearch(&from_stop, stop_ids, timetable.stops,
+			       sizeof(int), int_cmp);
+	    if (!stop_pnt) {
+		G_warning(_("No stop with category: %d"), from_stop);
+		continue;
+	    }
+	    from_stop = stop_pnt - stop_ids;
+	    stop_pnt =
+		(int *)bsearch(&to_stop, stop_ids, timetable.stops, sizeof(int),
+			       int_cmp);
+	    if (!stop_pnt) {
+		G_warning(_("No stop with category: %d"), to_stop);
+		continue;
+	    }
+	    to_stop = stop_pnt - stop_ids;
+	}
+
+	if (from_stop == to_stop) {
+	    G_warning(_("'From' and 'To' stops are the same"));
+	    continue;
+	}
+
+	ret =
+	    neta_timetable_shortest_path(&timetable, from_stop, to_stop,
+					 start_time, min_change, max_changes,
+					 walking_change, &result);
+	if (ret == -1) {
+	    G_warning(_("No path between the stops"));
+	    continue;
+	}
+	head.next = NULL;
+	init_route(result.routes, to_stop);
+	neta_timetable_result_release(&result);
+
+	Vect_reset_line(Points);
+	Vect_reset_line(Cur);
+	Vect_reset_line(Prev);
+	Vect_append_point(Cur, stop_x[from_stop], stop_y[from_stop],
+			  stop_z[from_stop]);
+
+	Vect_reset_cats(Cats);
+	Vect_cat_set(Cats, 1, point_counter);
+	Vect_write_line(&Out, GV_POINT, Cur, Cats);
+	insert_point(point_driver, point_Fi->table, point_counter, path_id,
+		     stop_ids[from_stop], 1, start_time, head.next->from_time);
+	point_counter++;
+	Vect_append_points(Prev, Cur, GV_FORWARD);
+	index = 1;
+	for (cur = head.next; cur; cur = cur->next) {
+	    int dept_time, route_id;
+	    if (cur->route == -2) {
+		printf("Walk ");
+		route_id = -1;
+	    }
+	    else {
+		printf("Route %d, ", route_ids[cur->route]);
+		route_id = route_ids[cur->route];
+	    }
+	    printf("from %d leaving at %d arriving to %d at %d\n",
+		   stop_ids[cur->from_stop], cur->from_time,
+		   stop_ids[cur->to_stop], cur->to_time);
+
+	    Vect_reset_line(Cur);
+	    Vect_reset_line(Points);
+	    Vect_reset_cats(Cats);
+
+	    Vect_append_point(Cur, stop_x[cur->to_stop], stop_y[cur->to_stop],
+			      stop_z[cur->to_stop]);
+
+	    Vect_cat_set(Cats, 1, point_counter);
+	    Vect_write_line(&Out, GV_POINT, Cur, Cats);
+	    if (cur->next)
+		dept_time = cur->next->from_time;
+	    else
+		dept_time = cur->to_time;
+	    insert_point(point_driver, point_Fi->table, point_counter,
+			 path_id, stop_ids[cur->to_stop], index + 1,
+			 cur->to_time, dept_time);
+
+	    Vect_append_points(Points, Prev, GV_FORWARD);
+	    Vect_append_points(Points, Cur, GV_FORWARD);
+	    Vect_reset_cats(Cats);
+	    Vect_cat_set(Cats, 2, line_counter);
+	    if (path_layer <= 0)
+		Vect_write_line(&Out, GV_LINE, Points, Cats);
+	    else
+		write_subroute(cur, Points, line_counter);
+	    insert_line(line_driver, line_Fi->table, line_counter, path_id,
+			stop_ids[cur->from_stop], stop_ids[cur->to_stop],
+			route_id, index, cur->from_time, cur->to_time);
+
+	    Vect_reset_line(Prev);
+	    Vect_append_points(Prev, Cur, GV_FORWARD);
+
+	    point_counter++;
+	    line_counter++;
+	    index++;
+	}
+	release_route(&head);
+    }
+    db_commit_transaction(line_driver);
+    db_commit_transaction(point_driver);
+    db_close_database_shutdown_driver(line_driver);
+    db_close_database_shutdown_driver(point_driver);
+
+    Vect_build(&Out);
+
+    Vect_close(&In);
+    Vect_close(&Out);
+
+    G_free(stop_x);
+    G_free(stop_y);
+    G_free(stop_z);
+    G_free(stop_node);
+
+    exit(EXIT_SUCCESS);
+}


Property changes on: grass-addons/vector/net.analyze/v.net.timetable/main.c
___________________________________________________________________
Added: svn:executable
   + *



More information about the grass-commit mailing list