GRASS 8 Programmer's Manual 8.6.0dev(2026)-ddeab64dbf
Loading...
Searching...
No Matches
vector/vedit/render.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/vedit/render.c
3
4 \brief Vedit library - render vector features (used by wxGUI digitizer)
5
6 (C) 2010-2011 by the GRASS Development Team
7
8 This program is free software under the GNU General Public License
9 (>=v2). Read the file COPYING that comes with GRASS for details.
10
11 \author Martin Landa <landa.martin gmail.com>
12 */
13
14#include <math.h>
15
16#include <grass/vedit.h>
17
18static struct _region {
19 double center_easting;
20 double center_northing;
21 double map_west;
22 double map_north;
23 int map_width;
24 int map_height;
25 double map_res;
26} region;
27
28static struct _state {
29 int nitems_alloc;
30
31 int type;
32 struct line_pnts *Points;
33} state;
34
35static struct robject *draw_line(struct Map_info *, int, int);
36static struct robject *draw_line_vertices(void);
37static void draw_line_nodes(struct Map_info *, int, int, struct robject_list *);
38static int draw_line_dir(struct robject_list *, int);
39static void list_append(struct robject_list *, struct robject *);
40static struct robject *robj_alloc(int, int);
41static void robj_points(struct robject *, const struct line_pnts *);
42static double dist_in_px(double);
43static void en_to_xy(double, double, int *, int *);
44static void draw_arrow(int, int, int, int, double, int, int,
45 struct robject_list *);
46static void draw_area(struct Map_info *, int, struct robject_list *);
47
48/*!
49 \brief Render vector features into list
50
51 \param Map pointer to Map_info structure
52 \param box bounding box of region to be rendered
53 \param draw_flag types of objects to be rendered (see vedit.h)
54 \param center_easing, center_northing, map_width, map_height, map_res values
55 used for conversion en->xy
56
57 \return pointer to robject_list structure
58 */
60 struct bound_box *box, int draw_flag,
61 double center_easting,
62 double center_northing, int map_width,
63 int map_height, double map_res)
64{
65 int i, nfeat, fid;
66 struct boxlist *list;
67 struct robject_list *list_obj;
68 struct robject *robj;
69
70 /* define region */
71 region.center_easting = center_easting;
72 region.center_northing = center_northing;
73 region.map_width = map_width;
74 region.map_height = map_height;
75 region.map_res = map_res;
76 region.map_west = center_easting - (map_width / 2.) * map_res;
77 region.map_north = center_northing + (map_height / 2.) * map_res;
78
80 list_obj = NULL;
81 state.nitems_alloc = 1000;
82
83 list_obj = (struct robject_list *)G_malloc(sizeof(struct robject_list));
84 list_obj->nitems = 0;
85 list_obj->item = (struct robject **)G_malloc(state.nitems_alloc *
86 sizeof(struct robject *));
87
88 /* area */
89 if (draw_flag & DRAW_AREA) {
91 for (i = 0; i < nfeat; i++) {
92 fid = list->id[i];
93 draw_area(Map, fid, list_obj);
94 }
95 }
96
97 /* draw lines inside of current display region */
99 list);
100 G_debug(1, "Vedit_render_map(): region: w=%f, e=%f, s=%f, n=%f nlines=%d",
101 box->W, box->E, box->S, box->N, nfeat);
102
103 /* features */
104 for (i = 0; i < list->n_values; i++) {
105 fid = list->id[i];
106 robj = draw_line(Map, fid, draw_flag);
107 if (!robj)
108 continue;
109 list_append(list_obj, robj);
110
111 if (state.type & GV_LINES) {
112 /* vertices */
113 if (draw_flag & DRAW_VERTEX) {
114 robj = draw_line_vertices();
115 robj->fid = fid;
116 if (robj)
117 list_append(list_obj, robj);
118 }
119 /* nodes */
121 draw_line_nodes(Map, fid, draw_flag, list_obj);
122 }
123 /* direction */
125 draw_line_dir(list_obj, fid);
126 }
127 }
128 }
129
130 list_obj->item = (struct robject **)G_realloc(
131 list_obj->item, list_obj->nitems * sizeof(struct robject *));
132
133 G_debug(1, "Vedit_render_map(): -> nitems = %d", list_obj->nitems);
134
136
137 return list_obj;
138}
139
140/*!
141 \brief Draw one feature
142 */
143struct robject *draw_line(struct Map_info *Map, int line, int draw_flag)
144{
145 int draw;
146 struct robject *obj;
147
148 if (!state.Points)
149 state.Points = Vect_new_line_struct();
150
151 if (!Vect_line_alive(Map, line))
152 return NULL;
153
154 state.type = Vect_read_line(Map, state.Points, NULL, line);
155
156 obj = (struct robject *)G_malloc(sizeof(struct robject));
157 obj->fid = line;
158 draw = FALSE;
159 if (state.type & GV_LINES) {
160 if (state.type == GV_LINE) {
161 obj->type = TYPE_LINE;
163 }
164 else if (state.type == GV_BOUNDARY) {
165 int left, right;
166
167 Vect_get_line_areas(Map, line, &left, &right);
168 if (left == 0 && right == 0) {
169 obj->type = TYPE_BOUNDARYNO;
171 }
172 else if (left > 0 && right > 0) {
173 obj->type = TYPE_BOUNDARYTWO;
175 }
176 else {
177 obj->type = TYPE_BOUNDARYONE;
179 }
180 }
181 }
182 else if (state.type & GV_POINTS) {
183 if (state.type == GV_POINT) {
184 obj->type = TYPE_POINT;
186 }
187 else if (state.type == GV_CENTROID) {
188 int cret = Vect_get_centroid_area(Map, line);
189
190 if (cret > 0) { /* -> area */
191 obj->type = TYPE_CENTROIDIN;
193 }
194 else if (cret == 0) {
195 obj->type = TYPE_CENTROIDOUT;
197 }
198 else {
199 obj->type = TYPE_CENTROIDDUP;
201 }
202 }
203 }
204 G_debug(3, " draw_line(): type=%d rtype=%d npoints=%d draw=%d", state.type,
205 obj->type, state.Points->n_points, draw);
206
207 if (!draw) {
208 G_free(obj);
209 return NULL;
210 }
211
212 obj->npoints = state.Points->n_points;
213 obj->point =
214 (struct rpoint *)G_malloc(obj->npoints * sizeof(struct rpoint));
215 robj_points(obj, state.Points);
216
217 return obj;
218}
219
220/*!
221 \brief Convert geographic coordinates to the screen
222 */
223void en_to_xy(double east, double north, int *x, int *y)
224{
225 double n, w;
226
227 w = region.center_easting - (region.map_width / 2) * region.map_res;
228 n = region.center_northing + (region.map_height / 2) * region.map_res;
229
230 if (x)
231 *x = (east - w) / region.map_res;
232 if (y)
233 *y = (n - north) / region.map_res;
234
235 return;
236}
237
238/*!
239 \brief Draw line nodes
240 */
241void draw_line_nodes(struct Map_info *Map, int line, int draw_flag,
242 struct robject_list *list)
243{
244 unsigned int i;
245 int type, nodes[2];
246 int x, y;
247 double east, north;
248 struct robject *robj;
249
250 if (Vect_get_line_type(Map, line) & GV_POINTS)
251 return;
252
253 Vect_get_line_nodes(Map, line, &(nodes[0]), &(nodes[1]));
254
255 for (i = 0; i < sizeof(nodes) / sizeof(int); i++) {
256 type = 0;
257 if (Vect_get_node_n_lines(Map, nodes[i]) == 1) {
258 if (draw_flag & DRAW_NODEONE) {
260 }
261 }
262 else {
263 if (draw_flag & DRAW_NODETWO) {
265 }
266 }
267
268 if (type == 0)
269 continue;
270
271 Vect_get_node_coor(Map, nodes[i], &east, &north, NULL);
272
273 robj = robj_alloc(type, 1);
274 en_to_xy(east, north, &x, &y);
275 robj->fid = line;
276 robj->point->x = x;
277 robj->point->y = y;
278
279 list_append(list, robj);
280 }
281}
282
283/*!
284 \brief Append object to the list
285 */
286void list_append(struct robject_list *list, struct robject *obj)
287{
288 if (list->nitems >= state.nitems_alloc) {
289 state.nitems_alloc += 1000;
290 list->item = (struct robject **)G_realloc(
291 list->item, state.nitems_alloc * sizeof(struct robject *));
292 }
293 list->item[list->nitems++] = obj;
294}
295
296/*!
297 \brief Allocate robject
298 */
299struct 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
311/*!
312 \brief Draw line vertices
313 */
314struct robject *draw_line_vertices(void)
315{
316 int i;
317 int x, y;
318 struct robject *robj;
319
320 robj =
321 robj_alloc(TYPE_VERTEX, state.Points->n_points - 2); /* ignore nodes */
322
323 for (i = 1; i < state.Points->n_points - 1; i++) {
324 en_to_xy(state.Points->x[i], state.Points->y[i], &x, &y);
325 robj->point[i - 1].x = x;
326 robj->point[i - 1].y = y;
327 }
328
329 return robj;
330}
331
332/*!
333 \brief Draw line dirs
334 */
335int draw_line_dir(struct robject_list *list, int line)
336{
337 int narrows;
338 int size; /* arrow length in pixels */
339 int limit; /* segment length limit for drawing symbol (in pixels) */
340 double dist, angle, pos;
341 double e, n;
342 int x0, y0, x1, y1;
343
344 narrows = 0;
345 size = 5;
346 limit = 5; /* 5px for line segment */
347
348 dist = Vect_line_length(state.Points);
349 G_debug(5, " draw_line_dir() line=%d", line);
350
351 if (dist_in_px(dist) >= limit) {
352 while (1) {
353 pos = (narrows + 1) * 8 * limit * region.map_res;
354
355 if (Vect_point_on_line(state.Points, pos, &e, &n, NULL, NULL,
356 NULL) < 1) {
357 break;
358 }
359
360 en_to_xy(e, n, &x0, &y0);
361
362 if (Vect_point_on_line(state.Points,
363 pos - 3 * size * region.map_res, &e, &n,
364 NULL, &angle, NULL) < 1) {
365 break;
366 }
367
368 en_to_xy(e, n, &x1, &y1);
369
370 draw_arrow(x0, y0, x1, y1, angle, size, line, list);
371
372 if (narrows > 1e2) /* low resolution, break */
373 break;
374
375 narrows++;
376 }
377
378 /* draw at least one arrow in the middle of line */
379 if (narrows < 1) {
380 dist /= 2.;
381 if (Vect_point_on_line(state.Points, dist, &e, &n, NULL, NULL,
382 NULL) > 0) {
383
384 en_to_xy(e, n, &x0, &y0);
385
386 if (Vect_point_on_line(state.Points,
387 dist - 3 * size * region.map_res, &e, &n,
388 NULL, &angle, NULL) > 0) {
389
390 en_to_xy(e, n, &x1, &y1);
391
392 draw_arrow(x0, y0, x1, y1, angle, size, line, list);
393 }
394 }
395 }
396 }
397
398 return narrows;
399}
400
401/*!
402 \brief Calculate distance in pixels (on screen)
403 */
404double dist_in_px(double dist)
405{
406 int x, y;
407
408 en_to_xy(region.map_west + dist, region.map_north, &x, &y);
409
410 return sqrt(x * x);
411}
412
413/*!
414 \brief Draw arrow
415 */
416void draw_arrow(int x0, int y0, int x1, int y1, double angle, int size,
417 int line, struct robject_list *list)
418{
419 double angle_symb;
420 struct robject *robj;
421
422 robj = robj_alloc(TYPE_DIRECTION, 3);
423 robj->fid = line;
424
425 angle_symb = angle - M_PI / 2.;
426 robj->point[0].x = (int)x1 + size * cos(angle_symb);
427 robj->point[0].y = (int)y1 - size * sin(angle_symb);
428
429 robj->point[1].x = x0;
430 robj->point[1].y = y0;
431
432 angle_symb = M_PI / 2. + angle;
433 robj->point[2].x = (int)x1 + size * cos(angle_symb);
434 robj->point[2].y = (int)y1 - size * sin(angle_symb);
435
436 list_append(list, robj);
437}
438
439/*!
440 \brief Draw area
441 */
442void draw_area(struct Map_info *Map, int area, struct robject_list *list)
443{
444 int i, centroid, isle;
445 int num_isles;
446 struct line_pnts *ipoints;
447
448 struct robject *robj;
449
450 if (!state.Points)
451 state.Points = Vect_new_line_struct();
452
453 if (!Vect_area_alive(Map, area))
454 return;
455
456 /* check for other centroids -- only area with one centroid is valid */
457 centroid = Vect_get_area_centroid(Map, area);
458 if (centroid <= 0)
459 return;
460
462 /* get area's boundary */
463 Vect_get_area_points(Map, area, state.Points);
464 robj = robj_alloc(TYPE_AREA, state.Points->n_points);
465 robj->fid = area;
466 robj_points(robj, state.Points);
467 list_append(list, robj);
468
469 /* check for isles */
471 for (i = 0; i < num_isles; i++) {
472 isle = Vect_get_area_isle(Map, area, i);
473 if (!Vect_isle_alive(Map, isle))
474 continue;
475
477 robj = robj_alloc(TYPE_ISLE, ipoints->n_points);
478 robj->fid = -1;
479 robj_points(robj, ipoints);
480 list_append(list, robj);
481 }
482
484}
485
486/*!
487 \brief convert EN -> XY
488 */
489void robj_points(struct robject *robj, const struct line_pnts *points)
490{
491 int i;
492 int x, y;
493
494 for (i = 0; i < points->n_points; i++) {
495 en_to_xy(points->x[i], points->y[i], &x, &y);
496 robj->point[i].x = x;
497 robj->point[i].y = y;
498 }
499}
#define NULL
Definition ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:147
#define G_realloc(p, n)
Definition defs/gis.h:141
#define G_malloc(n)
Definition defs/gis.h:139
int G_debug(int, const char *,...) __attribute__((format(printf
void Vect_destroy_line_struct(struct line_pnts *)
Frees all memory associated with a line_pnts structure, including the structure itself.
Definition line.c:77
int Vect_get_line_nodes(struct Map_info *, int, int *, int *)
Get line nodes.
Definition level_two.c:304
int Vect_get_node_coor(struct Map_info *, int, double *, double *, double *)
Get node coordinates.
Definition level_two.c:274
double Vect_line_length(const struct line_pnts *)
Calculate line length, 3D-length in case of 3D vector line.
Definition line.c:575
int Vect_area_alive(struct Map_info *, int)
Check if area is alive or dead (topological level required)
int Vect_point_on_line(const struct line_pnts *, double, double *, double *, double *, double *, double *)
Find point on line in the specified distance.
Definition line.c:413
int Vect_get_line_type(struct Map_info *, int)
Get line type.
Definition level_two.c:254
struct boxlist * Vect_new_boxlist(int)
Creates and initializes a struct boxlist.
void Vect_destroy_boxlist(struct boxlist *)
Frees all memory associated with a struct boxlist, including the struct itself.
int Vect_get_isle_points(struct Map_info *, int, struct line_pnts *)
Returns polygon array of points for given isle.
int Vect_get_area_points(struct Map_info *, int, struct line_pnts *)
Returns polygon array of points (outer ring) of given area.
int Vect_get_centroid_area(struct Map_info *, int)
Get area id the centroid is within.
Definition level_two.c:430
int Vect_isle_alive(struct Map_info *, int)
Check if isle is alive or dead (topological level required)
int Vect_get_area_isle(struct Map_info *, int, int)
Returns isle id for area.
int Vect_read_line(struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (topological level required)
int Vect_get_area_num_isles(struct Map_info *, int)
Returns number of isles for given area.
int Vect_line_alive(struct Map_info *, int)
Check if feature is alive or dead (topological level required)
int Vect_select_areas_by_box(struct Map_info *, const struct bound_box *, struct boxlist *)
Select areas with bounding boxes by box.
Definition sindex.c:121
int Vect_select_lines_by_box(struct Map_info *, const struct bound_box *, int, struct boxlist *)
Select lines with bounding boxes by box.
Definition sindex.c:32
int Vect_get_node_n_lines(struct Map_info *, int)
Get number of lines for node.
Definition level_two.c:381
int Vect_get_area_centroid(struct Map_info *, int)
Returns centroid id for given area.
int Vect_get_line_areas(struct Map_info *, int, int *, int *)
Get area id on the left and right side of the boundary.
Definition level_two.c:347
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:45
#define GV_CENTROID
#define GV_LINE
#define GV_POINT
Feature types used in memory on run time (may change)
#define GV_LINES
#define GV_BOUNDARY
#define GV_POINTS
#define FALSE
Definition gis.h:82
#define M_PI
Definition gis.h:157
struct state state
Definition parser.c:103
Vector map info.
Bounding box.
Definition dig_structs.h:62
double W
West.
Definition dig_structs.h:78
double S
South.
Definition dig_structs.h:70
double N
North.
Definition dig_structs.h:66
double E
East.
Definition dig_structs.h:74
List of bounding boxes with id.
Feature geometry info - coordinates.
double * y
Array of Y coordinates.
double * x
Array of X coordinates.
int n_points
Number of points.
Definition manage.h:4
int npoints
Definition vedit.h:54
int fid
Definition vedit.h:52
int type
Definition vedit.h:53
Definition vedit.h:45
int x
Definition vedit.h:47
int y
Definition vedit.h:47
struct robject_list * Vedit_render_map(struct Map_info *Map, struct bound_box *box, int draw_flag, double center_easting, double center_northing, int map_width, int map_height, double map_res)
Render vector features into list.
#define DRAW_NODETWO
Definition vedit.h:40
#define DRAW_BOUNDARYNO
Definition vedit.h:33
#define TYPE_VERTEX
Definition vedit.h:26
#define TYPE_BOUNDARYTWO
Definition vedit.h:19
#define DRAW_VERTEX
Definition vedit.h:41
#define TYPE_ISLE
Definition vedit.h:28
#define DRAW_CENTROIDDUP
Definition vedit.h:38
#define DRAW_NODEONE
Definition vedit.h:39
#define TYPE_DIRECTION
Definition vedit.h:29
#define TYPE_CENTROIDDUP
Definition vedit.h:23
#define TYPE_AREA
Definition vedit.h:27
#define DRAW_CENTROIDOUT
Definition vedit.h:37
#define DRAW_POINT
Definition vedit.h:31
#define DRAW_LINE
Definition vedit.h:32
#define DRAW_AREA
Definition vedit.h:42
#define DRAW_DIRECTION
Definition vedit.h:43
#define TYPE_CENTROIDIN
Definition vedit.h:21
#define TYPE_CENTROIDOUT
Definition vedit.h:22
#define TYPE_LINE
Definition vedit.h:17
#define DRAW_CENTROIDIN
Definition vedit.h:36
#define TYPE_POINT
Definition vedit.h:16
#define TYPE_BOUNDARYONE
Definition vedit.h:20
#define TYPE_BOUNDARYNO
Definition vedit.h:18
#define DRAW_BOUNDARYONE
Definition vedit.h:35
#define TYPE_NODETWO
Definition vedit.h:25
#define DRAW_BOUNDARYTWO
Definition vedit.h:34
#define TYPE_NODEONE
Definition vedit.h:24
#define x