GRASS 8 Programmer's Manual 8.6.0dev(2026)-55de52a352
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 SPDX-FileCopyrightText: 2010-2011 GRASS Development Team
7 SPDX-License-Identifier: GPL-2.0-or-later
8
9 \author Martin Landa <landa.martin gmail.com>
10 */
11
12#include <math.h>
13
14#include <grass/vedit.h>
15
16static struct _region {
17 double center_easting;
18 double center_northing;
19 double map_west;
20 double map_north;
21 int map_width;
22 int map_height;
23 double map_res;
24} region;
25
26static struct _state {
27 int nitems_alloc;
28
29 int type;
30 struct line_pnts *Points;
31} state;
32
33static struct robject *draw_line(struct Map_info *, int, int);
34static struct robject *draw_line_vertices(void);
35static void draw_line_nodes(struct Map_info *, int, int, struct robject_list *);
36static int draw_line_dir(struct robject_list *, int);
37static void list_append(struct robject_list *, struct robject *);
38static struct robject *robj_alloc(int, int);
39static void robj_points(struct robject *, const struct line_pnts *);
40static double dist_in_px(double);
41static void en_to_xy(double, double, int *, int *);
42static void draw_arrow(int, int, int, int, double, int, int,
43 struct robject_list *);
44static void draw_area(struct Map_info *, int, struct robject_list *);
45
46/*!
47 \brief Render vector features into list
48
49 \param Map pointer to Map_info structure
50 \param box bounding box of region to be rendered
51 \param draw_flag types of objects to be rendered (see vedit.h)
52 \param center_easing, center_northing, map_width, map_height, map_res values
53 used for conversion en->xy
54
55 \return pointer to robject_list structure
56 */
58 struct bound_box *box, int draw_flag,
59 double center_easting,
60 double center_northing, int map_width,
61 int map_height, double map_res)
62{
63 int i, nfeat, fid;
64 struct boxlist *list;
65 struct robject_list *list_obj;
66 struct robject *robj;
67
68 /* define region */
69 region.center_easting = center_easting;
70 region.center_northing = center_northing;
71 region.map_width = map_width;
72 region.map_height = map_height;
73 region.map_res = map_res;
74 region.map_west = center_easting - (map_width / 2.) * map_res;
75 region.map_north = center_northing + (map_height / 2.) * map_res;
76
78 list_obj = NULL;
79 state.nitems_alloc = 1000;
80
81 list_obj = (struct robject_list *)G_malloc(sizeof(struct robject_list));
82 list_obj->nitems = 0;
83 list_obj->item = (struct robject **)G_malloc(state.nitems_alloc *
84 sizeof(struct robject *));
85
86 /* area */
87 if (draw_flag & DRAW_AREA) {
89 for (i = 0; i < nfeat; i++) {
90 fid = list->id[i];
91 draw_area(Map, fid, list_obj);
92 }
93 }
94
95 /* draw lines inside of current display region */
97 list);
98 G_debug(1, "Vedit_render_map(): region: w=%f, e=%f, s=%f, n=%f nlines=%d",
99 box->W, box->E, box->S, box->N, nfeat);
100
101 /* features */
102 for (i = 0; i < list->n_values; i++) {
103 fid = list->id[i];
104 robj = draw_line(Map, fid, draw_flag);
105 if (!robj)
106 continue;
107 list_append(list_obj, robj);
108
109 if (state.type & GV_LINES) {
110 /* vertices */
111 if (draw_flag & DRAW_VERTEX) {
112 robj = draw_line_vertices();
113 robj->fid = fid;
114 if (robj)
115 list_append(list_obj, robj);
116 }
117 /* nodes */
119 draw_line_nodes(Map, fid, draw_flag, list_obj);
120 }
121 /* direction */
123 draw_line_dir(list_obj, fid);
124 }
125 }
126 }
127
128 list_obj->item = (struct robject **)G_realloc(
129 list_obj->item, list_obj->nitems * sizeof(struct robject *));
130
131 G_debug(1, "Vedit_render_map(): -> nitems = %d", list_obj->nitems);
132
134
135 return list_obj;
136}
137
138/*!
139 \brief Draw one feature
140 */
141struct robject *draw_line(struct Map_info *Map, int line, int draw_flag)
142{
143 int draw;
144 struct robject *obj;
145
146 if (!state.Points)
147 state.Points = Vect_new_line_struct();
148
149 if (!Vect_line_alive(Map, line))
150 return NULL;
151
152 state.type = Vect_read_line(Map, state.Points, NULL, line);
153
154 obj = (struct robject *)G_malloc(sizeof(struct robject));
155 obj->fid = line;
156 draw = FALSE;
157 if (state.type & GV_LINES) {
158 if (state.type == GV_LINE) {
159 obj->type = TYPE_LINE;
161 }
162 else if (state.type == GV_BOUNDARY) {
163 int left, right;
164
165 Vect_get_line_areas(Map, line, &left, &right);
166 if (left == 0 && right == 0) {
167 obj->type = TYPE_BOUNDARYNO;
169 }
170 else if (left > 0 && right > 0) {
171 obj->type = TYPE_BOUNDARYTWO;
173 }
174 else {
175 obj->type = TYPE_BOUNDARYONE;
177 }
178 }
179 }
180 else if (state.type & GV_POINTS) {
181 if (state.type == GV_POINT) {
182 obj->type = TYPE_POINT;
184 }
185 else if (state.type == GV_CENTROID) {
186 int cret = Vect_get_centroid_area(Map, line);
187
188 if (cret > 0) { /* -> area */
189 obj->type = TYPE_CENTROIDIN;
191 }
192 else if (cret == 0) {
193 obj->type = TYPE_CENTROIDOUT;
195 }
196 else {
197 obj->type = TYPE_CENTROIDDUP;
199 }
200 }
201 }
202 G_debug(3, " draw_line(): type=%d rtype=%d npoints=%d draw=%d", state.type,
203 obj->type, state.Points->n_points, draw);
204
205 if (!draw) {
206 G_free(obj);
207 return NULL;
208 }
209
210 obj->npoints = state.Points->n_points;
211 obj->point =
212 (struct rpoint *)G_malloc(obj->npoints * sizeof(struct rpoint));
213 robj_points(obj, state.Points);
214
215 return obj;
216}
217
218/*!
219 \brief Convert geographic coordinates to the screen
220 */
221void en_to_xy(double east, double north, int *x, int *y)
222{
223 double n, w;
224
225 w = region.center_easting - (region.map_width / 2) * region.map_res;
226 n = region.center_northing + (region.map_height / 2) * region.map_res;
227
228 if (x)
229 *x = (east - w) / region.map_res;
230 if (y)
231 *y = (n - north) / region.map_res;
232
233 return;
234}
235
236/*!
237 \brief Draw line nodes
238 */
239void draw_line_nodes(struct Map_info *Map, int line, int draw_flag,
240 struct robject_list *list)
241{
242 unsigned int i;
243 int type, nodes[2];
244 int x, y;
245 double east, north;
246 struct robject *robj;
247
248 if (Vect_get_line_type(Map, line) & GV_POINTS)
249 return;
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) {
258 }
259 }
260 else {
261 if (draw_flag & DRAW_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
281/*!
282 \brief Append object to the list
283 */
284void 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 = (struct robject **)G_realloc(
289 list->item, state.nitems_alloc * sizeof(struct robject *));
290 }
291 list->item[list->nitems++] = obj;
292}
293
294/*!
295 \brief Allocate robject
296 */
297struct robject *robj_alloc(int type, int npoints)
298{
299 struct robject *robj;
300
301 robj = (struct robject *)G_malloc(sizeof(struct robject));
302 robj->type = type;
303 robj->npoints = npoints;
304 robj->point = (struct rpoint *)G_malloc(npoints * sizeof(struct rpoint));
305
306 return robj;
307}
308
309/*!
310 \brief Draw line vertices
311 */
312struct robject *draw_line_vertices(void)
313{
314 int i;
315 int x, y;
316 struct robject *robj;
317
318 robj =
319 robj_alloc(TYPE_VERTEX, state.Points->n_points - 2); /* ignore nodes */
320
321 for (i = 1; i < state.Points->n_points - 1; i++) {
322 en_to_xy(state.Points->x[i], state.Points->y[i], &x, &y);
323 robj->point[i - 1].x = x;
324 robj->point[i - 1].y = y;
325 }
326
327 return robj;
328}
329
330/*!
331 \brief Draw line dirs
332 */
333int draw_line_dir(struct robject_list *list, int line)
334{
335 int narrows;
336 int size; /* arrow length in pixels */
337 int limit; /* segment length limit for drawing symbol (in pixels) */
338 double dist, angle, pos;
339 double e, n;
340 int x0, y0, x1, y1;
341
342 narrows = 0;
343 size = 5;
344 limit = 5; /* 5px for line segment */
345
346 dist = Vect_line_length(state.Points);
347 G_debug(5, " draw_line_dir() line=%d", line);
348
349 if (dist_in_px(dist) >= limit) {
350 while (1) {
351 pos = (narrows + 1) * 8 * limit * region.map_res;
352
353 if (Vect_point_on_line(state.Points, pos, &e, &n, NULL, NULL,
354 NULL) < 1) {
355 break;
356 }
357
358 en_to_xy(e, n, &x0, &y0);
359
360 if (Vect_point_on_line(state.Points,
361 pos - 3 * size * region.map_res, &e, &n,
362 NULL, &angle, NULL) < 1) {
363 break;
364 }
365
366 en_to_xy(e, n, &x1, &y1);
367
368 draw_arrow(x0, y0, x1, y1, angle, size, line, list);
369
370 if (narrows > 1e2) /* low resolution, break */
371 break;
372
373 narrows++;
374 }
375
376 /* draw at least one arrow in the middle of line */
377 if (narrows < 1) {
378 dist /= 2.;
379 if (Vect_point_on_line(state.Points, dist, &e, &n, NULL, NULL,
380 NULL) > 0) {
381
382 en_to_xy(e, n, &x0, &y0);
383
384 if (Vect_point_on_line(state.Points,
385 dist - 3 * size * region.map_res, &e, &n,
386 NULL, &angle, NULL) > 0) {
387
388 en_to_xy(e, n, &x1, &y1);
389
390 draw_arrow(x0, y0, x1, y1, angle, size, line, list);
391 }
392 }
393 }
394 }
395
396 return narrows;
397}
398
399/*!
400 \brief Calculate distance in pixels (on screen)
401 */
402double dist_in_px(double dist)
403{
404 int x, y;
405
406 en_to_xy(region.map_west + dist, region.map_north, &x, &y);
407
408 return sqrt(x * x);
409}
410
411/*!
412 \brief Draw arrow
413 */
414void draw_arrow(int x0, int y0, int x1, int y1, double angle, int size,
415 int line, struct robject_list *list)
416{
417 double angle_symb;
418 struct robject *robj;
419
420 robj = robj_alloc(TYPE_DIRECTION, 3);
421 robj->fid = line;
422
423 angle_symb = angle - M_PI / 2.;
424 robj->point[0].x = (int)x1 + size * cos(angle_symb);
425 robj->point[0].y = (int)y1 - size * sin(angle_symb);
426
427 robj->point[1].x = x0;
428 robj->point[1].y = y0;
429
430 angle_symb = M_PI / 2. + angle;
431 robj->point[2].x = (int)x1 + size * cos(angle_symb);
432 robj->point[2].y = (int)y1 - size * sin(angle_symb);
433
434 list_append(list, robj);
435}
436
437/*!
438 \brief Draw area
439 */
440void draw_area(struct Map_info *Map, int area, struct robject_list *list)
441{
442 int i, centroid, isle;
443 int num_isles;
444 struct line_pnts *ipoints;
445
446 struct robject *robj;
447
448 if (!state.Points)
449 state.Points = Vect_new_line_struct();
450
451 if (!Vect_area_alive(Map, area))
452 return;
453
454 /* check for other centroids -- only area with one centroid is valid */
455 centroid = Vect_get_area_centroid(Map, area);
456 if (centroid <= 0)
457 return;
458
460 /* get area's boundary */
461 Vect_get_area_points(Map, area, state.Points);
462 robj = robj_alloc(TYPE_AREA, state.Points->n_points);
463 robj->fid = area;
464 robj_points(robj, state.Points);
465 list_append(list, robj);
466
467 /* check for isles */
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
475 robj = robj_alloc(TYPE_ISLE, ipoints->n_points);
476 robj->fid = -1;
477 robj_points(robj, ipoints);
478 list_append(list, robj);
479 }
480
482}
483
484/*!
485 \brief convert EN -> XY
486 */
487void robj_points(struct robject *robj, const struct line_pnts *points)
488{
489 int i;
490 int x, y;
491
492 for (i = 0; i < points->n_points; i++) {
493 en_to_xy(points->x[i], points->y[i], &x, &y);
494 robj->point[i].x = x;
495 robj->point[i].y = y;
496 }
497}
#define NULL
Definition ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_realloc(p, n)
Definition defs/gis.h:138
#define G_malloc(n)
Definition defs/gis.h:136
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:75
int Vect_get_line_nodes(struct Map_info *, int, int *, int *)
Get line nodes.
Definition level_two.c:302
int Vect_get_node_coor(struct Map_info *, int, double *, double *, double *)
Get node coordinates.
Definition level_two.c:272
double Vect_line_length(const struct line_pnts *)
Calculate line length, 3D-length in case of 3D vector line.
Definition line.c:573
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:411
int Vect_get_line_type(struct Map_info *, int)
Get line type.
Definition level_two.c:252
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:428
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:119
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:30
int Vect_get_node_n_lines(struct Map_info *, int)
Get number of lines for node.
Definition level_two.c:379
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:345
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:43
#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:79
#define M_PI
Definition gis.h:154
struct state state
Definition parser.c:101
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