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