1 /*!
2    \file vector.c
3 
4    \brief Vector subroutines
5 
6    (C) 2008-2013 by the GRASS Development Team
7 
8    This program is free software under the GNU General Public
9    License (>=v2). Read the file COPYING that comes with GRASS
10    for details.
11 
12    \author Martin Landa <landa.martin gmail.com> (Google SoC 2008/2010)
13  */
14 
15 #include <stdlib.h>
16 #include <string.h>
17 
18 #include <grass/vector.h>
19 #include <grass/dbmi.h>
20 #include <grass/glocale.h>
21 
22 #include "local_proto.h"
23 
24 static int load_vectors(const struct Option *, const struct Option *,
25 			const struct Option *, const struct Option *, int,
26 			nv_data *);
27 
28 /*!
29    \brief Load vector maps (lines)
30 
31    \param params module parameters
32    \param data nviz data
33 
34    \return number of loaded vectors
35  */
load_vlines(const struct GParams * params,nv_data * data)36 int load_vlines(const struct GParams *params, nv_data * data)
37 {
38     return load_vectors(params->elev_map, params->elev_const,
39 			params->vlines, params->vline_pos,
40 			MAP_OBJ_VECT, data);
41 }
42 
43 /*!
44    \brief Load vector maps (points)
45 
46    \param params module parameters
47    \param data nviz data
48 
49    \return number of loaded vectors
50  */
load_vpoints(const struct GParams * params,nv_data * data)51 int load_vpoints(const struct GParams *params, nv_data * data)
52 {
53     return load_vectors(params->elev_map, params->elev_const,
54 			params->vpoints, params->vpoint_pos,
55 			MAP_OBJ_SITE, data);
56 }
57 
load_vectors(const struct Option * elev_map,const struct Option * elev_const,const struct Option * vect,const struct Option * position,int map_obj_type,nv_data * data)58 int load_vectors(const struct Option *elev_map,
59 		 const struct Option *elev_const, const struct Option *vect,
60 		 const struct Option *position,
61 		 int map_obj_type, nv_data * data)
62 {
63     int i, id;
64     int nvects;
65 
66     const char *mapset;
67 
68     double x, y, z;
69 
70     if ((!elev_map->answer || elev_const->answer) && GS_num_surfs() == 0) {	/* load base surface if no loaded */
71 	int *surf_list, nsurf;
72 
73 	Nviz_new_map_obj(MAP_OBJ_SURF, NULL, 0.0, data);
74 
75 	surf_list = GS_get_surf_list(&nsurf);
76 	GS_set_att_const(surf_list[0], ATT_TRANSP, 255);
77     }
78 
79     nvects = 0;
80 
81     for (i = 0; vect->answers[i]; i++) {
82 	mapset = G_find_vector2(vect->answers[i], "");
83 	if (mapset == NULL) {
84 	    G_fatal_error(_("Vector map <%s> not found"), vect->answers[i]);
85 	}
86 	id = Nviz_new_map_obj(map_obj_type,
87 			      G_fully_qualified_name(vect->answers[i],
88 						     mapset), 0.0, data);
89 
90 	/* set position */
91 	x = atof(position->answers[i * 3 + 0]);
92 	y = atof(position->answers[i * 3 + 1]);
93 	z = atof(position->answers[i * 3 + 2]);
94 
95 	if (map_obj_type == MAP_OBJ_VECT)
96 	    GV_set_trans(id, x, y, z);
97 	else
98 	    GP_set_trans(id, x, y, z);
99 
100 	nvects++;
101     }
102 
103     return nvects;
104 }
105 
106 /*!
107    \brief Set vector lines mode
108 
109    \param params parameters
110 
111    \return 1 on success
112    \return 0 on failure
113  */
vlines_set_attrb(const struct GParams * params)114 int vlines_set_attrb(const struct GParams *params)
115 {
116     int i, layer, color, width, flat, height;
117     int *vect_list, nvects;
118     int have_colors;
119 
120     char *color_column, *width_column;
121     struct Colors colors;
122 
123     vect_list = GV_get_vect_list(&nvects);
124 
125     for (i = 0; i < nvects; i++) {
126 	check_map(params, i, TRUE, &layer, NULL);
127 
128 	color = Nviz_color_from_str(params->vline_color->answers[i]);
129 	color_column = params->vline_color_column->answers ?
130 	    params->vline_color_column->answers[i] : NULL;
131 	width = atoi(params->vline_width->answers[i]);
132 	width_column = params->vline_width_column->answers ?
133 	    params->vline_width_column->answers[i] : NULL;
134 
135 	if (strcmp(params->vline_mode->answers[i], "flat") == 0)
136 	    flat = 1;
137 	else
138 	    flat = 0;
139 
140 	/* style (mode -- use memory by default) */
141 	if (GV_set_style(vect_list[i], TRUE, color, width, flat) < 0)
142 	    return 0;
143 
144 	/* check for vector color table */
145 	have_colors = Vect_read_colors(params->vlines->answers[i], "",
146 				       &colors);
147 
148 	if (have_colors || color_column || width_column)
149 	    if (GV_set_style_thematic(vect_list[i], layer, color_column,
150 				      width_column,
151 				      have_colors ? &colors : NULL) < 0)
152 		return 0;
153 
154 	/* height */
155 	height = atoi(params->vline_height->answers[i]);
156 	if (height > 0)
157 	    GV_set_trans(vect_list[i], 0.0, 0.0, height);
158     }
159 
160     return 1;
161 }
162 
163 /*!
164    \brief Set vector points style
165 
166    \param params parameters
167 
168    \return 1 on success
169    \return 0 on failure
170  */
vpoints_set_attrb(const struct GParams * params)171 int vpoints_set_attrb(const struct GParams *params)
172 {
173     int i, layer, have_colors, with_z;
174     int *site_list, nsites;
175     int marker, color, width;
176     float size;
177     char *marker_str, *color_column, *size_column, *width_column,
178 	*marker_column;
179 
180     struct Colors colors;
181 
182     site_list = GP_get_site_list(&nsites);
183 
184     for (i = 0; i < nsites; i++) {
185 	check_map(params, i, FALSE, &layer, &with_z);
186 
187 	color = Nviz_color_from_str(params->vpoint_color->answers[i]);
188 	color_column = params->vpoint_color_column->answers ?
189 	    params->vpoint_color_column->answers[i] : NULL;
190 	size = atof(params->vpoint_size->answers[i]);
191 	size_column = params->vpoint_size_column->answers ?
192 	    params->vpoint_size_column->answers[i] : NULL;
193 	width = atoi(params->vpoint_width->answers[i]);
194 	width_column = params->vpoint_width_column->answers ?
195 	    params->vpoint_width_column->answers[i] : NULL;
196 	marker_str = params->vpoint_marker->answers[i];
197 	marker_column = params->vpoint_marker_column->answers ?
198 	    params->vpoint_marker_column->answers[i] : NULL;
199 	marker = GP_str_to_marker(marker_str);
200 
201 	if (with_z) {
202 	    if (strcmp(params->vpoint_mode->answers[i], "surface") == 0)
203 		GP_set_zmode(site_list[i], FALSE);
204 	    else
205 		GP_set_zmode(site_list[i], TRUE);
206 	}
207 
208 	if (GP_set_style(site_list[i], color, width, size, marker) < 0)
209 	    return 0;
210 
211 	/* check for vector color table */
212 	have_colors = Vect_read_colors(params->vpoints->answers[i], "",
213 				       &colors);
214 
215 	if (have_colors || color_column || width_column ||
216 	    size_column || marker_column) {
217 	    if (GP_set_style_thematic(site_list[i], layer, color_column,
218 				      width_column, size_column,
219 				      marker_column,
220 				      have_colors ? &colors : NULL) < 0)
221 		return 0;
222 	}
223     }
224 
225     return 1;
226 }
227 
228 /*!
229    \brief Check vector map
230 
231    \param params parameters
232    \param index answers array index
233    \param vlines TRUE for lines otherwise points
234    \param[out] field number
235    \param[out] WITH_Z for 3D maps
236 
237    \return 0 on success otherwise 1
238  */
check_map(const struct GParams * params,int index,int vlines,int * field,int * with_z)239 int check_map(const struct GParams *params, int index, int vlines,
240 	      int *field, int *with_z)
241 {
242     int type;
243     struct Map_info Map;
244     const char *map, *layer, *color, *size, *width, *marker;
245     struct field_info *Fi;
246 
247     dbDriver *driver;
248     dbColumn *column;
249 
250     Fi = NULL;
251     driver = NULL;
252 
253     if (vlines) {
254 	map = params->vlines->answers[index];
255 	layer = params->vline_layer->answers[index];
256 	color = params->vline_color_column->answers ?
257 	    params->vline_color_column->answers[index] : NULL;
258 	size = NULL;
259 	width = params->vline_width_column->answers ?
260 	    params->vline_width_column->answers[index] : NULL;
261 	marker = NULL;
262     }
263     else {
264 	map = params->vpoints->answers[index];
265 	layer = params->vpoint_layer->answers[index];
266 	color = params->vpoint_color_column->answers ?
267 	    params->vpoint_color_column->answers[index] : NULL;
268 	size = params->vpoint_size_column->answers ?
269 	    params->vpoint_size_column->answers[index] : NULL;
270 	width = params->vpoint_width_column->answers ?
271 	    params->vpoint_width_column->answers[index] : NULL;
272 	marker = params->vpoint_marker_column->answers ?
273 	    params->vpoint_marker_column->answers[index] : NULL;
274     }
275 
276     if (!map)
277 	return 1;
278 
279     if (1 > Vect_open_old(&Map, map, ""))
280 	G_fatal_error(_("Unable to open vector map <%s>"), map);
281     Vect_set_error_handler_io(&Map, NULL);
282 
283     if (with_z)
284 	*with_z = Vect_is_3d(&Map);
285 
286     *field = -1;
287     Fi = Vect_get_field2(&Map, layer);
288     if (Fi) {
289 	*field = Fi->number;
290 
291 	driver = db_start_driver_open_database(Fi->driver, Fi->database);
292 	if (!driver)
293 	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
294 			  Fi->database, Fi->driver);
295         db_set_error_handler_driver(driver);
296 
297 	if (color) {
298 	    db_get_column(driver, Fi->table, color, &column);
299 	    if (!column)
300 		G_fatal_error(_("Column <%s> in table <%s> not found"),
301 			      color, Fi->table);
302 
303 	    if (db_column_Ctype(driver, Fi->table, color) != DB_C_TYPE_STRING)
304 		G_fatal_error(_("Data type of color column must be character"));
305 	}
306 	if (size) {
307 	    db_get_column(driver, Fi->table, size, &column);
308 	    if (!column)
309 		G_fatal_error(_("Column <%s> in table <%s> not found"),
310 			      size, Fi->table);
311 
312 	    type = db_column_Ctype(driver, Fi->table, size);
313 	    if (type != DB_C_TYPE_INT && type != DB_C_TYPE_DOUBLE)
314 		G_fatal_error(_("Data type of size column must be numeric"));
315 	}
316 	if (width) {
317 	    db_get_column(driver, Fi->table, width, &column);
318 	    if (!column)
319 		G_fatal_error(_("Column <%s> in table <%s> not found"),
320 			      width, Fi->table);
321 
322 	    type = db_column_Ctype(driver, Fi->table, width);
323 	    if (type != DB_C_TYPE_INT && type != DB_C_TYPE_DOUBLE)
324 		G_fatal_error(_("Data type of width column must be numeric"));
325 	}
326 	if (marker) {
327 	    db_get_column(driver, Fi->table, marker, &column);
328 	    if (!column)
329 		G_fatal_error(_("Column <%s> in table <%s> not found"),
330 			      marker, Fi->table);
331 
332 	    type = db_column_Ctype(driver, Fi->table, marker);
333 	    if (db_column_Ctype(driver, Fi->table, marker) !=
334 		DB_C_TYPE_STRING)
335 		G_fatal_error(_("Data type of marker column must be character"));
336 	}
337 
338 	db_close_database_shutdown_driver(driver);
339     }
340 
341     Vect_close(&Map);
342 
343     return 0;
344 }
345