[GRASS-SVN] r45958 - in grass/branches/releasebranch_6_4: include lib/vector/vedit

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Apr 13 15:22:01 EDT 2011


Author: martinl
Date: 2011-04-13 12:22:01 -0700 (Wed, 13 Apr 2011)
New Revision: 45958

Added:
   grass/branches/releasebranch_6_4/lib/vector/vedit/render.c
Modified:
   grass/branches/releasebranch_6_4/include/vedit.h
Log:
vedit: backport Vedit_render_map() - used by wxGUI digitizer


Modified: grass/branches/releasebranch_6_4/include/vedit.h
===================================================================
--- grass/branches/releasebranch_6_4/include/vedit.h	2011-04-13 19:20:58 UTC (rev 45957)
+++ grass/branches/releasebranch_6_4/include/vedit.h	2011-04-13 19:22:01 UTC (rev 45958)
@@ -12,6 +12,55 @@
 #define QUERY_LENGTH   0	/* select by line length */
 #define QUERY_DANGLE   1	/* select dangles */
 
+/* used by Vedit_render_map() */
+#define TYPE_POINT           0x01
+#define TYPE_LINE	     0x02
+#define TYPE_BOUNDARYNO      0x04
+#define TYPE_BOUNDARYTWO     0x08
+#define TYPE_BOUNDARYONE     0x10
+#define TYPE_CENTROIDIN      0x20
+#define TYPE_CENTROIDOUT     0x40
+#define TYPE_CENTROIDDUP     0x80
+#define TYPE_NODEONE         0x100
+#define TYPE_NODETWO         0x200
+#define TYPE_VERTEX          0x400
+#define TYPE_AREA            0x800
+#define TYPE_ISLE            0x1000
+#define TYPE_DIRECTION       0x2000
+
+#define DRAW_POINT           0x01
+#define DRAW_LINE	     0x02
+#define DRAW_BOUNDARYNO      0x04
+#define DRAW_BOUNDARYTWO     0x08
+#define DRAW_BOUNDARYONE     0x10
+#define DRAW_CENTROIDIN      0x20
+#define DRAW_CENTROIDOUT     0x40
+#define DRAW_CENTROIDDUP     0x80
+#define DRAW_NODEONE         0x100
+#define DRAW_NODETWO         0x200
+#define DRAW_VERTEX          0x400
+#define DRAW_AREA            0x800
+#define DRAW_DIRECTION       0x1000
+
+struct rpoint {
+    /* screen coordinates */
+    int x, y;
+};
+
+struct robject {
+    /* object to be rendered */
+    int            fid;       /* feature id */
+    int            type;
+    int            npoints;
+    struct rpoint *point;     /* list of points */
+};
+
+struct robject_list {
+    /* list of objects to be rendered */
+    int              nitems;
+    struct robject **item;
+};
+
 /* break.c */
 int Vedit_split_lines(struct Map_info *, struct ilist *,
 		      struct line_pnts *, double, struct ilist *);
@@ -45,6 +94,10 @@
 int Vedit_move_lines(struct Map_info *, struct Map_info **, int,
 		     struct ilist *, double, double, double, int, double);
 
+/* render.c */
+struct robject_list *Vedit_render_map(struct Map_info *, struct bound_box *, int,
+				      double, double, int, int, double);
+
 /* select.c */
 int Vedit_select_by_query(struct Map_info *,
 			  int, int, double, int, struct ilist *);

Copied: grass/branches/releasebranch_6_4/lib/vector/vedit/render.c (from rev 45911, grass/branches/develbranch_6/lib/vector/vedit/render.c)
===================================================================
--- grass/branches/releasebranch_6_4/lib/vector/vedit/render.c	                        (rev 0)
+++ grass/branches/releasebranch_6_4/lib/vector/vedit/render.c	2011-04-13 19:22:01 UTC (rev 45958)
@@ -0,0 +1,496 @@
+/*!
+   \file lib/vector/vedit/render.c
+
+   \brief Vedit library - render vector features (used by wxGUI digitizer)
+
+   (C) 2010-2011 by the GRASS Development Team
+
+   This program is free software under the GNU General Public License
+   (>=v2). Read the file COPYING that comes with GRASS for details.
+
+   \author Martin Landa <landa.martin gmail.com>
+ */
+
+#include <math.h>
+
+#include <grass/vedit.h>
+
+static struct _region
+{
+    double center_easting;
+    double center_northing;
+    double map_west;
+    double map_north;
+    int map_width;
+    int map_height;
+    double map_res;
+} region;
+
+static struct _state
+{
+    int nitems_alloc;
+
+    int type;
+    struct line_pnts *Points;
+} state;
+
+static struct robject *draw_line(struct Map_info *, int, int);
+static struct robject *draw_line_vertices();
+static void draw_line_nodes(struct Map_info *, int, int,
+			    struct robject_list *);
+static int draw_line_dir(struct robject_list *, int);
+static void list_append(struct robject_list *, struct robject *);
+static struct robject *robj_alloc(int, int);
+static void robj_points(struct robject *, const struct line_pnts *);
+static double dist_in_px(double);
+static void en_to_xy(double, double, int *, int *);
+static void draw_arrow(int, int, int, int, double, int, int,
+		       struct robject_list *);
+static void draw_area(struct Map_info *, int, struct robject_list *);
+
+/*!
+  \brief Render vector features into list
+  
+  \param Map pointer to Map_info structure
+  \param box bounding box of region to be rendered
+  \param draw_flag types of objects to be rendered (see vedit.h)
+  \param center_easing, center_northing, map_width, map_height, map_res values used for conversion en->xy
+  
+  \return pointer to robject_list structure
+*/
+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)
+{
+    int i, nfeat, fid;
+    struct ilist *list;
+    struct robject_list *list_obj;
+    struct robject *robj;
+
+    /* define region */
+    region.center_easting = center_easting;
+    region.center_northing = center_northing;
+    region.map_width = map_width;
+    region.map_height = map_height;
+    region.map_res = map_res;
+    region.map_west = center_easting - (map_width / 2.) * map_res;
+    region.map_north = center_northing + (map_height / 2.) * map_res;
+
+    list = Vect_new_list();
+    list_obj = NULL;
+    state.nitems_alloc = 1000;
+
+    list_obj = (struct robject_list *)G_malloc(sizeof(struct robject_list));
+    list_obj->nitems = 0;
+    list_obj->item =
+	(struct robject **)G_malloc(state.nitems_alloc *
+				    sizeof(struct robject *));
+
+    /* area */
+    if (draw_flag & DRAW_AREA) {
+	nfeat = Vect_select_areas_by_box(Map, box, list);
+	for (i = 0; i < nfeat; i++) {
+	    fid = list->value[i];
+	    draw_area(Map, fid, list_obj);
+	}
+    }
+
+    /* draw lines inside of current display region */
+    nfeat = Vect_select_lines_by_box(Map, box, GV_POINTS | GV_LINES,	// fixme
+				     list);
+    G_debug(1, "Vedit_render_map(): region: w=%f, e=%f, s=%f, n=%f nlines=%d",
+	    box->W, box->E, box->S, box->N, nfeat);
+
+    /* features */
+    for (i = 0; i < list->n_values; i++) {
+	fid = list->value[i];
+	robj = draw_line(Map, fid, draw_flag);
+	if (!robj)
+	    continue;
+	list_append(list_obj, robj);
+
+	if (state.type & GV_LINES) {
+	    /* vertices */
+	    if (draw_flag & DRAW_VERTEX) {
+		robj = draw_line_vertices();
+		robj->fid = fid;
+		if (robj)
+		    list_append(list_obj, robj);
+	    }
+	    /* nodes */
+	    if (draw_flag & (DRAW_NODEONE | DRAW_NODETWO)) {
+		draw_line_nodes(Map, fid, draw_flag, list_obj);
+	    }
+	    /* direction */
+	    if (draw_flag & DRAW_DIRECTION) {
+		draw_line_dir(list_obj, fid);
+	    }
+	}
+    }
+
+    list_obj->item =
+	(struct robject **)G_realloc(list_obj->item,
+				     list_obj->nitems *
+				     sizeof(struct robject *));
+
+    Vect_destroy_list(list);
+
+    return list_obj;
+}
+
+/*!
+   \brief Draw one feature
+ */
+struct robject *draw_line(struct Map_info *Map, int line, int draw_flag)
+{
+    int draw;
+    struct robject *obj;
+
+    if (!state.Points)
+	state.Points = Vect_new_line_struct();
+
+    if (!Vect_line_alive(Map, line))
+	return NULL;
+
+    state.type = Vect_read_line(Map, state.Points, NULL, line);
+
+    obj = (struct robject *)G_malloc(sizeof(struct robject));
+    obj->fid = line;
+    draw = FALSE;
+    if (state.type & GV_LINES) {
+	if (state.type == GV_LINE) {
+	    obj->type = TYPE_LINE;
+	    draw = draw_flag & DRAW_LINE;
+	}
+	else if (state.type == GV_BOUNDARY) {
+	    int left, right;
+
+	    Vect_get_line_areas(Map, line, &left, &right);
+	    if (left == 0 && right == 0) {
+		obj->type = TYPE_BOUNDARYNO;
+		draw = draw_flag & DRAW_BOUNDARYNO;
+	    }
+	    else if (left > 0 && right > 0) {
+		obj->type = TYPE_BOUNDARYTWO;
+		draw = draw_flag & DRAW_BOUNDARYTWO;
+	    }
+	    else {
+		obj->type = TYPE_BOUNDARYONE;
+		draw = draw_flag & DRAW_BOUNDARYONE;
+	    }
+	}
+    }
+    else if (state.type & GV_POINTS) {
+	if (state.type == GV_POINT) {
+	    obj->type = TYPE_POINT;
+	    draw = draw_flag & DRAW_POINT;
+	}
+	else if (state.type == GV_CENTROID) {
+	    int cret = Vect_get_centroid_area(Map, line);
+
+	    if (cret > 0) {	// -> area
+		obj->type = TYPE_CENTROIDIN;
+		draw = draw_flag & DRAW_CENTROIDIN;
+	    }
+	    else if (cret == 0) {
+		obj->type = TYPE_CENTROIDOUT;
+		draw = draw_flag & DRAW_CENTROIDOUT;
+	    }
+	    else {
+		obj->type = TYPE_CENTROIDDUP;
+		draw = draw_flag & DRAW_CENTROIDDUP;
+	    }
+	}
+    }
+    G_debug(3, "  draw_line(): type=%d rtype=%d npoints=%d draw=%d",
+	    state.type, obj->type, state.Points->n_points, draw);
+
+    if (!draw)
+	return NULL;
+
+    obj->npoints = state.Points->n_points;
+    obj->point =
+	(struct rpoint *)G_malloc(obj->npoints * sizeof(struct rpoint));
+    robj_points(obj, state.Points);
+
+    return obj;
+}
+
+/*!
+   \brief Convert geographic coordinates to the screen
+ */
+void en_to_xy(double east, double north, int *x, int *y)
+{
+    double n, w;
+
+    w = region.center_easting - (region.map_width / 2) * region.map_res;
+    n = region.center_northing + (region.map_height / 2) * region.map_res;
+
+    if (x)
+	*x = (east - w) / region.map_res;
+    if (y)
+	*y = (n - north) / region.map_res;
+
+    return;
+}
+
+/*!
+   \brief Draw line nodes
+ */
+void draw_line_nodes(struct Map_info *Map, int line, int draw_flag,
+		     struct robject_list *list)
+{
+    unsigned int i;
+    int type, nodes[2];
+    int x, y;
+    double east, north;
+    struct robject *robj;
+
+    Vect_get_line_nodes(Map, line, &(nodes[0]), &(nodes[1]));
+    
+    for (i = 0; i < sizeof(nodes) / sizeof(int); i++) {
+	type = 0;
+	if (Vect_get_node_n_lines(Map, nodes[i]) == 1) {
+	    if (draw_flag & DRAW_NODEONE) {
+		type = TYPE_NODEONE;
+	    }
+	}
+	else {
+	    if (draw_flag & DRAW_NODETWO) {
+		type = TYPE_NODETWO;
+	    }
+	}
+
+	if (type == 0)
+	    continue;
+
+	Vect_get_node_coor(Map, nodes[i], &east, &north, NULL);
+
+	robj = robj_alloc(type, 1);
+	en_to_xy(east, north, &x, &y);
+	robj->fid = line;
+	robj->point->x = x;
+	robj->point->y = y;
+
+	list_append(list, robj);
+    }
+}
+
+/*!
+   \brief Append object to the list
+ */
+void list_append(struct robject_list *list, struct robject *obj)
+{
+    if (list->nitems >= state.nitems_alloc) {
+	state.nitems_alloc += 1000;
+	list->item =
+	    (struct robject **)G_realloc(list->item,
+					 state.nitems_alloc *
+					 sizeof(struct robject *));
+    }
+    list->item[list->nitems++] = obj;
+}
+
+/*!
+   \brief Allocate robject 
+ */
+struct robject *robj_alloc(int type, int npoints)
+{
+    struct robject *robj;
+
+    robj = (struct robject *)G_malloc(sizeof(struct robject));
+    robj->type = type;
+    robj->npoints = npoints;
+    robj->point = (struct rpoint *)G_malloc(npoints * sizeof(struct rpoint));
+
+    return robj;
+}
+
+/*!
+   \brief Draw line vertices
+ */
+struct robject *draw_line_vertices()
+{
+    int i;
+    int x, y;
+    struct robject *robj;
+
+    robj = robj_alloc(TYPE_VERTEX, state.Points->n_points - 2);	/* ignore nodes */
+
+    for (i = 1; i < state.Points->n_points - 1; i++) {
+	en_to_xy(state.Points->x[i], state.Points->y[i], &x, &y);
+	robj->point[i - 1].x = x;
+	robj->point[i - 1].y = y;
+    }
+
+    return robj;
+}
+
+/*!
+   \brief Draw line dirs
+ */
+int draw_line_dir(struct robject_list *list, int line)
+{
+    int narrows;
+    int size;			/* arrow length in pixels */
+    int limit;			/* segment length limit for drawing symbol (in pixels) */
+    double dist, angle, pos;
+    double e, n;
+    int x0, y0, x1, y1;
+
+    narrows = 0;
+    size = 5;
+    limit = 5;			// 5px for line segment
+
+    dist = Vect_line_length(state.Points);
+    G_debug(5, "  draw_line_dir() line=%d", line);
+						  
+    if (dist_in_px(dist) >= limit) {
+	while (1) {
+	    pos = (narrows + 1) * 8 * limit * region.map_res;
+
+	    if (Vect_point_on_line(state.Points, pos,
+				   &e, &n, NULL, NULL, NULL) < 1) {
+		break;
+	    }
+
+	    en_to_xy(e, n, &x0, &y0);
+
+	    if (Vect_point_on_line
+		(state.Points, pos - 3 * size * region.map_res, &e, &n, NULL,
+		 &angle, NULL) < 1) {
+		break;
+	    }
+
+	    en_to_xy(e, n, &x1, &y1);
+
+	    draw_arrow(x0, y0, x1, y1, angle, size, line, list);
+
+	    if (narrows > 1e2)	// low resolution, break
+		break;
+
+	    narrows++;
+	}
+
+	// draw at least one arrow in the middle of line
+	if (narrows < 1) {
+	    dist /= 2.;
+	    if (Vect_point_on_line(state.Points, dist,
+				   &e, &n, NULL, NULL, NULL) > 0) {
+
+		en_to_xy(e, n, &x0, &y0);
+
+		if (Vect_point_on_line
+		    (state.Points, dist - 3 * size * region.map_res, &e, &n,
+		     NULL, &angle, NULL) > 0) {
+
+		    en_to_xy(e, n, &x1, &y1);
+
+		    draw_arrow(x0, y0, x1, y1, angle, size, line, list);
+		}
+	    }
+	}
+    }
+
+    return narrows;
+}
+
+/*!
+   \brief Calculate distance in pixels (on screen)
+ */
+double dist_in_px(double dist)
+{
+    int x, y;
+
+    en_to_xy(region.map_west + dist, region.map_north, &x, &y);
+
+    return sqrt(x * x);
+}
+
+/*!
+   \brief Draw arrow
+ */
+void draw_arrow(int x0, int y0, int x1, int y1, double angle, int size, int line,
+		struct robject_list *list)
+{
+    double angle_symb;
+    struct robject *robj;
+
+    robj = robj_alloc(TYPE_DIRECTION, 3);
+    robj->fid = line;
+    
+    angle_symb = angle - M_PI / 2.;
+    robj->point[0].x = (int)x1 + size * cos(angle_symb);
+    robj->point[0].y = (int)y1 - size * sin(angle_symb);
+
+    robj->point[1].x = x0;
+    robj->point[1].y = y0;
+
+    angle_symb = M_PI / 2. + angle;
+    robj->point[2].x = (int)x1 + size * cos(angle_symb);
+    robj->point[2].y = (int)y1 - size * sin(angle_symb);
+
+    list_append(list, robj);
+}
+
+/*!
+   \brief Draw area
+ */
+void draw_area(struct Map_info *Map, int area, struct robject_list *list)
+{
+    int i, centroid, isle;
+    int num_isles;
+    struct line_pnts *ipoints;
+
+    struct robject *robj;
+
+    if (!state.Points)
+	state.Points = Vect_new_line_struct();
+
+    if (!Vect_area_alive(Map, area))
+	return;
+
+    /* check for other centroids -- only area with one centroid is valid */
+    centroid = Vect_get_area_centroid(Map, area);
+    if (centroid <= 0)
+	return;
+
+    ipoints = Vect_new_line_struct();
+    /* get area's boundary */
+    Vect_get_area_points(Map, area, state.Points);
+    robj = robj_alloc(TYPE_AREA, state.Points->n_points);
+    robj_points(robj, state.Points);
+    list_append(list, robj);
+
+    /* check for isles */
+    num_isles = Vect_get_area_num_isles(Map, area);
+    for (i = 0; i < num_isles; i++) {
+	isle = Vect_get_area_isle(Map, area, i);
+	if (!Vect_isle_alive(Map, isle))
+	    continue;
+
+	Vect_get_isle_points(Map, isle, ipoints);
+	robj = robj_alloc(TYPE_ISLE, ipoints->n_points);
+	robj_points(robj, ipoints);
+	list_append(list, robj);
+    }
+
+    Vect_destroy_line_struct(ipoints);
+}
+
+/*!
+   \brief convert EN -> XY
+ */
+void robj_points(struct robject *robj, const struct line_pnts *points)
+{
+    int i;
+    int x, y;
+
+    for (i = 0; i < points->n_points; i++) {
+	en_to_xy(points->x[i], points->y[i], &x, &y);
+	robj->point[i].x = x;
+	robj->point[i].y = y;
+    }
+}



More information about the grass-commit mailing list