GRASS Programmer's Manual  6.4.3(2013)-r
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
vector/vedit/render.c
Go to the documentation of this file.
1 
14 #include <math.h>
15 
16 #include <grass/vedit.h>
17 
18 static struct _region
19 {
20  double center_easting;
21  double center_northing;
22  double map_west;
23  double map_north;
24  int map_width;
25  int map_height;
26  double map_res;
27 } region;
28 
29 static struct _state
30 {
31  int nitems_alloc;
32 
33  int type;
34  struct line_pnts *Points;
35 } state;
36 
37 static struct robject *draw_line(struct Map_info *, int, int);
38 static struct robject *draw_line_vertices();
39 static void draw_line_nodes(struct Map_info *, int, int,
40  struct robject_list *);
41 static int draw_line_dir(struct robject_list *, int);
42 static void list_append(struct robject_list *, struct robject *);
43 static struct robject *robj_alloc(int, int);
44 static void robj_points(struct robject *, const struct line_pnts *);
45 static double dist_in_px(double);
46 static void en_to_xy(double, double, int *, int *);
47 static void draw_arrow(int, int, int, int, double, int, int,
48  struct robject_list *);
49 static void draw_area(struct Map_info *, int, struct robject_list *);
50 
61 struct robject_list *Vedit_render_map(struct Map_info *Map,
62  struct bound_box *box, int draw_flag,
63  double center_easting,
64  double center_northing, int map_width,
65  int map_height, double map_res)
66 {
67  int i, nfeat, fid;
68  struct ilist *list;
69  struct robject_list *list_obj;
70  struct robject *robj;
71 
72  /* define region */
73  region.center_easting = center_easting;
74  region.center_northing = center_northing;
75  region.map_width = map_width;
76  region.map_height = map_height;
77  region.map_res = map_res;
78  region.map_west = center_easting - (map_width / 2.) * map_res;
79  region.map_north = center_northing + (map_height / 2.) * map_res;
80 
81  list = Vect_new_list();
82  list_obj = NULL;
83  state.nitems_alloc = 1000;
84 
85  list_obj = (struct robject_list *)G_malloc(sizeof(struct robject_list));
86  list_obj->nitems = 0;
87  list_obj->item =
88  (struct robject **)G_malloc(state.nitems_alloc *
89  sizeof(struct robject *));
90 
91  /* area */
92  if (draw_flag & DRAW_AREA) {
93  nfeat = Vect_select_areas_by_box(Map, box, list);
94  for (i = 0; i < nfeat; i++) {
95  fid = list->value[i];
96  draw_area(Map, fid, list_obj);
97  }
98  }
99 
100  /* draw lines inside of current display region */
101  nfeat = Vect_select_lines_by_box(Map, box, GV_POINTS | GV_LINES, /* fixme */
102  list);
103  G_debug(1, "Vedit_render_map(): region: w=%f, e=%f, s=%f, n=%f nlines=%d",
104  box->W, box->E, box->S, box->N, nfeat);
105 
106  /* features */
107  for (i = 0; i < list->n_values; i++) {
108  fid = list->value[i];
109  robj = draw_line(Map, fid, draw_flag);
110  if (!robj)
111  continue;
112  list_append(list_obj, robj);
113 
114  if (state.type & GV_LINES) {
115  /* vertices */
116  if (draw_flag & DRAW_VERTEX) {
117  robj = draw_line_vertices();
118  robj->fid = fid;
119  if (robj)
120  list_append(list_obj, robj);
121  }
122  /* nodes */
123  if (draw_flag & (DRAW_NODEONE | DRAW_NODETWO)) {
124  draw_line_nodes(Map, fid, draw_flag, list_obj);
125  }
126  /* direction */
127  if (draw_flag & DRAW_DIRECTION) {
128  draw_line_dir(list_obj, fid);
129  }
130  }
131  }
132 
133  list_obj->item =
134  (struct robject **)G_realloc(list_obj->item,
135  list_obj->nitems *
136  sizeof(struct robject *));
137 
138  Vect_destroy_list(list);
139 
140  return list_obj;
141 }
142 
146 struct robject *draw_line(struct Map_info *Map, int line, int draw_flag)
147 {
148  int draw;
149  struct robject *obj;
150 
151  if (!state.Points)
152  state.Points = Vect_new_line_struct();
153 
154  if (!Vect_line_alive(Map, line))
155  return NULL;
156 
157  state.type = Vect_read_line(Map, state.Points, NULL, line);
158 
159  obj = (struct robject *)G_malloc(sizeof(struct robject));
160  obj->fid = line;
161  draw = FALSE;
162  if (state.type & GV_LINES) {
163  if (state.type == GV_LINE) {
164  obj->type = TYPE_LINE;
165  draw = draw_flag & DRAW_LINE;
166  }
167  else if (state.type == GV_BOUNDARY) {
168  int left, right;
169 
170  Vect_get_line_areas(Map, line, &left, &right);
171  if (left == 0 && right == 0) {
172  obj->type = TYPE_BOUNDARYNO;
173  draw = draw_flag & DRAW_BOUNDARYNO;
174  }
175  else if (left > 0 && right > 0) {
176  obj->type = TYPE_BOUNDARYTWO;
177  draw = draw_flag & DRAW_BOUNDARYTWO;
178  }
179  else {
180  obj->type = TYPE_BOUNDARYONE;
181  draw = draw_flag & DRAW_BOUNDARYONE;
182  }
183  }
184  }
185  else if (state.type & GV_POINTS) {
186  if (state.type == GV_POINT) {
187  obj->type = TYPE_POINT;
188  draw = draw_flag & DRAW_POINT;
189  }
190  else if (state.type == GV_CENTROID) {
191  int cret = Vect_get_centroid_area(Map, line);
192 
193  if (cret > 0) { /* -> area */
194  obj->type = TYPE_CENTROIDIN;
195  draw = draw_flag & DRAW_CENTROIDIN;
196  }
197  else if (cret == 0) {
198  obj->type = TYPE_CENTROIDOUT;
199  draw = draw_flag & DRAW_CENTROIDOUT;
200  }
201  else {
202  obj->type = TYPE_CENTROIDDUP;
203  draw = draw_flag & DRAW_CENTROIDDUP;
204  }
205  }
206  }
207  G_debug(3, " draw_line(): type=%d rtype=%d npoints=%d draw=%d",
208  state.type, obj->type, state.Points->n_points, draw);
209 
210  if (!draw)
211  return NULL;
212 
213  obj->npoints = state.Points->n_points;
214  obj->point =
215  (struct rpoint *)G_malloc(obj->npoints * sizeof(struct rpoint));
216  robj_points(obj, state.Points);
217 
218  return obj;
219 }
220 
224 void en_to_xy(double east, double north, int *x, int *y)
225 {
226  double n, w;
227 
228  w = region.center_easting - (region.map_width / 2) * region.map_res;
229  n = region.center_northing + (region.map_height / 2) * region.map_res;
230 
231  if (x)
232  *x = (east - w) / region.map_res;
233  if (y)
234  *y = (n - north) / region.map_res;
235 
236  return;
237 }
238 
242 void draw_line_nodes(struct Map_info *Map, int line, int draw_flag,
243  struct robject_list *list)
244 {
245  unsigned int i;
246  int type, nodes[2];
247  int x, y;
248  double east, north;
249  struct robject *robj;
250 
251  Vect_get_line_nodes(Map, line, &(nodes[0]), &(nodes[1]));
252 
253  for (i = 0; i < sizeof(nodes) / sizeof(int); i++) {
254  type = 0;
255  if (Vect_get_node_n_lines(Map, nodes[i]) == 1) {
256  if (draw_flag & DRAW_NODEONE) {
257  type = TYPE_NODEONE;
258  }
259  }
260  else {
261  if (draw_flag & DRAW_NODETWO) {
262  type = TYPE_NODETWO;
263  }
264  }
265 
266  if (type == 0)
267  continue;
268 
269  Vect_get_node_coor(Map, nodes[i], &east, &north, NULL);
270 
271  robj = robj_alloc(type, 1);
272  en_to_xy(east, north, &x, &y);
273  robj->fid = line;
274  robj->point->x = x;
275  robj->point->y = y;
276 
277  list_append(list, robj);
278  }
279 }
280 
284 void list_append(struct robject_list *list, struct robject *obj)
285 {
286  if (list->nitems >= state.nitems_alloc) {
287  state.nitems_alloc += 1000;
288  list->item =
289  (struct robject **)G_realloc(list->item,
290  state.nitems_alloc *
291  sizeof(struct robject *));
292  }
293  list->item[list->nitems++] = obj;
294 }
295 
299 struct robject *robj_alloc(int type, int npoints)
300 {
301  struct robject *robj;
302 
303  robj = (struct robject *)G_malloc(sizeof(struct robject));
304  robj->type = type;
305  robj->npoints = npoints;
306  robj->point = (struct rpoint *)G_malloc(npoints * sizeof(struct rpoint));
307 
308  return robj;
309 }
310 
314 struct robject *draw_line_vertices()
315 {
316  int i;
317  int x, y;
318  struct robject *robj;
319 
320  robj = robj_alloc(TYPE_VERTEX, state.Points->n_points - 2); /* ignore nodes */
321 
322  for (i = 1; i < state.Points->n_points - 1; i++) {
323  en_to_xy(state.Points->x[i], state.Points->y[i], &x, &y);
324  robj->point[i - 1].x = x;
325  robj->point[i - 1].y = y;
326  }
327 
328  return robj;
329 }
330 
334 int draw_line_dir(struct robject_list *list, int line)
335 {
336  int narrows;
337  int size; /* arrow length in pixels */
338  int limit; /* segment length limit for drawing symbol (in pixels) */
339  double dist, angle, pos;
340  double e, n;
341  int x0, y0, x1, y1;
342 
343  narrows = 0;
344  size = 5;
345  limit = 5; /* 5px for line segment */
346 
347  dist = Vect_line_length(state.Points);
348  G_debug(5, " draw_line_dir() line=%d", line);
349 
350  if (dist_in_px(dist) >= limit) {
351  while (1) {
352  pos = (narrows + 1) * 8 * limit * region.map_res;
353 
354  if (Vect_point_on_line(state.Points, pos,
355  &e, &n, NULL, NULL, NULL) < 1) {
356  break;
357  }
358 
359  en_to_xy(e, n, &x0, &y0);
360 
362  (state.Points, pos - 3 * size * region.map_res, &e, &n, NULL,
363  &angle, NULL) < 1) {
364  break;
365  }
366 
367  en_to_xy(e, n, &x1, &y1);
368 
369  draw_arrow(x0, y0, x1, y1, angle, size, line, list);
370 
371  if (narrows > 1e2) /* low resolution, break */
372  break;
373 
374  narrows++;
375  }
376 
377  /* draw at least one arrow in the middle of line */
378  if (narrows < 1) {
379  dist /= 2.;
380  if (Vect_point_on_line(state.Points, dist,
381  &e, &n, NULL, NULL, NULL) > 0) {
382 
383  en_to_xy(e, n, &x0, &y0);
384 
386  (state.Points, dist - 3 * size * region.map_res, &e, &n,
387  NULL, &angle, NULL) > 0) {
388 
389  en_to_xy(e, n, &x1, &y1);
390 
391  draw_arrow(x0, y0, x1, y1, angle, size, line, list);
392  }
393  }
394  }
395  }
396 
397  return narrows;
398 }
399 
403 double dist_in_px(double dist)
404 {
405  int x, y;
406 
407  en_to_xy(region.map_west + dist, region.map_north, &x, &y);
408 
409  return sqrt(x * x);
410 }
411 
415 void draw_arrow(int x0, int y0, int x1, int y1, double angle, int size, int line,
416  struct robject_list *list)
417 {
418  double angle_symb;
419  struct robject *robj;
420 
421  robj = robj_alloc(TYPE_DIRECTION, 3);
422  robj->fid = line;
423 
424  angle_symb = angle - M_PI / 2.;
425  robj->point[0].x = (int)x1 + size * cos(angle_symb);
426  robj->point[0].y = (int)y1 - size * sin(angle_symb);
427 
428  robj->point[1].x = x0;
429  robj->point[1].y = y0;
430 
431  angle_symb = M_PI / 2. + angle;
432  robj->point[2].x = (int)x1 + size * cos(angle_symb);
433  robj->point[2].y = (int)y1 - size * sin(angle_symb);
434 
435  list_append(list, robj);
436 }
437 
441 void draw_area(struct Map_info *Map, int area, struct robject_list *list)
442 {
443  int i, centroid, isle;
444  int num_isles;
445  struct line_pnts *ipoints;
446 
447  struct robject *robj;
448 
449  if (!state.Points)
450  state.Points = Vect_new_line_struct();
451 
452  if (!Vect_area_alive(Map, area))
453  return;
454 
455  /* check for other centroids -- only area with one centroid is valid */
456  centroid = Vect_get_area_centroid(Map, area);
457  if (centroid <= 0)
458  return;
459 
460  ipoints = Vect_new_line_struct();
461  /* get area's boundary */
462  Vect_get_area_points(Map, area, state.Points);
463  robj = robj_alloc(TYPE_AREA, state.Points->n_points);
464  robj_points(robj, state.Points);
465  list_append(list, robj);
466 
467  /* check for isles */
468  num_isles = Vect_get_area_num_isles(Map, area);
469  for (i = 0; i < num_isles; i++) {
470  isle = Vect_get_area_isle(Map, area, i);
471  if (!Vect_isle_alive(Map, isle))
472  continue;
473 
474  Vect_get_isle_points(Map, isle, ipoints);
475  robj = robj_alloc(TYPE_ISLE, ipoints->n_points);
476  robj_points(robj, ipoints);
477  list_append(list, robj);
478  }
479 
480  Vect_destroy_line_struct(ipoints);
481 }
482 
486 void robj_points(struct robject *robj, const struct line_pnts *points)
487 {
488  int i;
489  int x, y;
490 
491  for (i = 0; i < points->n_points; i++) {
492  en_to_xy(points->x[i], points->y[i], &x, &y);
493  robj->point[i].x = x;
494  robj->point[i].y = y;
495  }
496 }