1 /*!
2    \file vector/neta/utils.c
3 
4    \brief Network Analysis library - utils
5 
6    Utils subroutines.
7 
8    (C) 2009-2010 by Daniel Bundala, and the GRASS Development Team
9 
10    This program is free software under the GNU General Public License
11    (>=v2). Read the file COPYING that comes with GRASS for details.
12 
13    \author Daniel Bundala (Google Summer of Code 2009)
14  */
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <grass/gis.h>
19 #include <grass/vector.h>
20 #include <grass/glocale.h>
21 #include <grass/dbmi.h>
22 #include <grass/neta.h>
23 
24 
25 /*!
26    \brief Writes point
27 
28    Writes GV_POINT to Out at the position of the node in <em>In</em>.
29 
30    \param In pointer to Map_info structure (input vector map)
31    \param[in,out] Out pointer to Map_info structure (output vector map)
32    \param node node id
33    \param Cats pointer to line_cats structures
34  */
NetA_add_point_on_node(struct Map_info * In,struct Map_info * Out,int node,struct line_cats * Cats)35 void NetA_add_point_on_node(struct Map_info *In, struct Map_info *Out,
36 			    int node, struct line_cats *Cats)
37 {
38     static struct line_pnts *Points;
39     double x, y, z;
40 
41     Points = Vect_new_line_struct();
42     Vect_get_node_coor(In, node, &x, &y, &z);
43     Vect_reset_line(Points);
44     Vect_append_point(Points, x, y, z);
45     Vect_write_line(Out, GV_POINT, Points, Cats);
46     Vect_destroy_line_struct(Points);
47 }
48 
49 /* Returns the list of all points with the given category and field */
50 /*void NetA_get_points_by_category(struct Map_info *In, int field, int cat, struct ilist *point_list)
51  * {
52  * int i, nlines;
53  * struct line_cats *Cats;
54  * Cats = Vect_new_cats_struct();
55  * Vect_get_num_lines(In);
56  * for(i=1;i<=nlines;i++){
57  * int type = Vect_read_line(In, NULL, Cats, i);
58  * if(type!=GV_POINT)continue;
59  * }
60  *
61  * Vect_destroy_cats_struct(Cats);
62  * }
63  */
64 
65 /*!
66    \brief Finds node
67 
68    Find the node corresponding to each point in the point_list
69 
70    \param In pointer to Map_info structure
71    \param point_list list of points (their ids)
72  */
NetA_points_to_nodes(struct Map_info * In,struct ilist * point_list)73 void NetA_points_to_nodes(struct Map_info *In, struct ilist *point_list)
74 {
75     int i, node;
76     struct line_pnts *Points = Vect_new_line_struct();
77 
78     for (i = 0; i < point_list->n_values; i++) {
79 	/* Vect_get_line_nodes(In, point_list->value[i], &node, NULL); */
80 	node = Vect_find_node(In, Points->x[0], Points->y[0], Points->z[0], 0, 0);
81 	point_list->value[i] = node;
82     }
83     Vect_destroy_line_struct(Points);
84 }
85 
86 /*!
87    \brief Get node cost
88 
89    For each node in the map, finds the category of the point on it (if
90    there is any) and stores the value associated with this category in
91    the array node_costs. If there is no point with a category,
92    node_costs=0.
93 
94    node_costs are multiplied by the graph's cost multiplier and
95    truncated to integers (as is done in Vect_net_build_graph)
96 
97    \param In pointer to Map_info structure
98    \param layer layer number
99    \param column name of column
100    \param[out] node_costs list of node costs
101 
102    \returns 1 on success
103    \return 0 on failure
104  */
NetA_get_node_costs(struct Map_info * In,int layer,char * column,int * node_costs)105 int NetA_get_node_costs(struct Map_info *In, int layer, char *column,
106 			int *node_costs)
107 {
108     int i, nlines, nnodes;
109     dbCatValArray vals;
110     struct line_cats *Cats;
111     struct line_pnts *Points;
112 
113     dbDriver *driver;
114     struct field_info *Fi;
115 
116     Fi = Vect_get_field(In, layer);
117     driver = db_start_driver_open_database(Fi->driver, Fi->database);
118     if (driver == NULL)
119 	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
120 		      Fi->database, Fi->driver);
121 
122     nlines = Vect_get_num_lines(In);
123     nnodes = Vect_get_num_nodes(In);
124     Cats = Vect_new_cats_struct();
125     Points = Vect_new_line_struct();
126     for (i = 1; i <= nnodes; i++)
127 	node_costs[i] = 0;
128 
129     db_CatValArray_init(&vals);
130 
131     if (db_select_CatValArray(driver, Fi->table, Fi->key, column, NULL, &vals)
132 	== -1)
133 	return 0;
134     for (i = 1; i <= nlines; i++) {
135 	int type = Vect_read_line(In, Points, Cats, i);
136 
137 	if (type == GV_POINT) {
138 	    int node, cat;
139 	    double value;
140 
141 	    if (!Vect_cat_get(Cats, layer, &cat))
142 		continue;
143 	    Vect_get_line_nodes(In, i, &node, NULL);
144 	    if (db_CatValArray_get_value_double(&vals, cat, &value) == DB_OK) {
145 		if (value < 0)
146 		    node_costs[node] = -1;
147 		else
148 		    node_costs[node] = value * In->dgraph.cost_multip;
149 	    }
150 	}
151     }
152 
153     Vect_destroy_cats_struct(Cats);
154     db_CatValArray_free(&vals);
155     db_close_database_shutdown_driver(driver);
156     return 1;
157 }
158 
159 /*!
160    \brief Get list of nodes from varray
161 
162    Returns the list of all nodes on features selected by varray.
163    nodes_to_features contains the index of a feature adjacent to each
164    node or -1 if no such feature specified by varray
165    exists. Nodes_to_features might be NULL, in which case it is left
166    unitialised. Nodes_to_features will be wrong if several lines connect
167    to the same node.
168 
169    \param map pointer to Map_info structure
170    \param varray pointer to varray structure
171    \param[out] nodes list of node ids
172    \param[out] nodes_to_features maps nodes to features
173  */
NetA_varray_to_nodes(struct Map_info * map,struct varray * varray,struct ilist * nodes,int * nodes_to_features)174 void NetA_varray_to_nodes(struct Map_info *map, struct varray *varray,
175 			  struct ilist *nodes, int *nodes_to_features)
176 {
177     int nlines, nnodes, i;
178     struct line_pnts *Points = Vect_new_line_struct();
179 
180     nlines = Vect_get_num_lines(map);
181     nnodes = Vect_get_num_nodes(map);
182     if (nodes_to_features)
183 	for (i = 1; i <= nnodes; i++)
184 	    nodes_to_features[i] = -1;
185 
186     for (i = 1; i <= nlines; i++) {
187 	if (varray->c[i]) {
188 	    int type = Vect_read_line(map, Points, NULL, i);
189 
190 	    if (type == GV_POINT) {
191 		int node;
192 
193 		node = Vect_find_node(map, Points->x[0], Points->y[0], Points->z[0], 0, 0);
194 		if (node) {
195 		    Vect_list_append(nodes, node);
196 		    if (nodes_to_features)
197 			nodes_to_features[node] = i;
198 		}
199 		else
200 		    G_warning(_("Point %d is not connected!"), i);
201 	    }
202 	    else {
203 		int node1, node2;
204 
205 		Vect_get_line_nodes(map, i, &node1, &node2);
206 		Vect_list_append(nodes, node1);
207 		Vect_list_append(nodes, node2);
208 		if (nodes_to_features)
209 		    nodes_to_features[node1] = nodes_to_features[node2] = i;
210 	    }
211 	}
212     }
213     Vect_destroy_line_struct(Points);
214 }
215 
216 /*!
217    \brief Initialize varray
218 
219    \param In pointer to Map_info structure
220    \param layer layer number
221    \param mask_type ?
222    \param where where statement
223    \param cat ?
224    \param[out] pointer to varray structure
225 
226    \return number of items set
227    \return -1 on error
228  */
NetA_initialise_varray(struct Map_info * In,int layer,int mask_type,char * where,char * cat,struct varray ** varray)229 int NetA_initialise_varray(struct Map_info *In, int layer, int mask_type,
230 			   char *where, char *cat, struct varray **varray)
231 {
232     int n, ni;
233 
234     if (layer < 1)
235 	G_fatal_error(_("'%s' must be > 0"), "layer");
236 
237     n = Vect_get_num_lines(In);
238     *varray = Vect_new_varray(n);
239     ni = 0;
240 
241     /* parse filter option and select appropriate lines */
242     if (where) {
243 	if (cat)
244 	    G_warning(_("'where' and 'cats' parameters were supplied, cat will be ignored"));
245 	ni = Vect_set_varray_from_db(In, layer, where, mask_type, 1, *varray);
246 	if (ni == -1) {
247 	    G_warning(_("Unable to load data from database"));
248 	}
249 	return ni;
250     }
251     else if (cat) {
252 	ni = Vect_set_varray_from_cat_string(In, layer, cat, mask_type, 1, *varray);
253 	if (ni == -1) {
254 	    G_warning(_("Problem loading category values"));
255 	}
256 	return ni;
257     }
258     else { /* all features of given layer */
259 	int i, cat;
260 	int ltype;			/* line type */
261 	struct line_cats *Cats;
262 
263 	Cats = Vect_new_cats_struct();
264 
265 	for (i = 1; i <= n; i++) {
266 	    ltype = Vect_read_line(In, NULL, Cats, i);
267 
268 	    if (!(ltype & mask_type))
269 		continue;	/* is not specified type */
270 
271 	    if (Vect_cat_get(Cats, layer, &cat)) {
272 		(*varray)->c[i] = 1;
273 		ni++;
274 	    }
275 	}
276 	Vect_destroy_cats_struct(Cats);
277 
278 	return ni;
279     }
280 }
281