[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