[GRASS-SVN] r30294 - in grass/trunk/display: . d.thematic.area

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Feb 22 13:14:09 EST 2008


Author: mlennert
Date: 2008-02-22 13:14:09 -0500 (Fri, 22 Feb 2008)
New Revision: 30294

Added:
   grass/trunk/display/d.thematic.area/
   grass/trunk/display/d.thematic.area/Makefile
   grass/trunk/display/d.thematic.area/area.c
   grass/trunk/display/d.thematic.area/description.html
   grass/trunk/display/d.thematic.area/local_proto.h
   grass/trunk/display/d.thematic.area/main.c
   grass/trunk/display/d.thematic.area/plot.h
   grass/trunk/display/d.thematic.area/plot1.c
Log:
First commit of d.thematic.area: module to display cloropleth maps


Added: grass/trunk/display/d.thematic.area/Makefile
===================================================================
--- grass/trunk/display/d.thematic.area/Makefile	                        (rev 0)
+++ grass/trunk/display/d.thematic.area/Makefile	2008-02-22 18:14:09 UTC (rev 30294)
@@ -0,0 +1,13 @@
+
+MODULE_TOPDIR = ../..
+
+PGM = d.thematic.area
+
+LIBES        = $(DISPLAYLIB) $(RASTERLIB) $(VECTLIB) $(DBMILIB) $(GISLIB) $(SYMBLIB)
+DEPENDENCIES = $(DISPLAYDEP) $(RASTERDEP) $(VECTDEP) $(DBMIDEP) $(GISDEP) $(SYMBDEP)
+EXTRA_INC = $(VECT_INC)
+EXTRA_CFLAGS = $(VECT_CFLAGS)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass/trunk/display/d.thematic.area/area.c
===================================================================
--- grass/trunk/display/d.thematic.area/area.c	                        (rev 0)
+++ grass/trunk/display/d.thematic.area/area.c	2008-02-22 18:14:09 UTC (rev 30294)
@@ -0,0 +1,182 @@
+/* Author: Moritz Lennert, based on d.vect from Radim Blazek
+ *
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <grass/gis.h>
+#include <grass/Vect.h>
+#include <grass/display.h>
+#include <grass/raster.h>
+#include <grass/colors.h>
+#include <grass/dbmi.h>
+#include <grass/glocale.h>
+#include "plot.h"
+#include "local_proto.h"
+
+int dareatheme(struct Map_info *Map, struct cat_list *Clist,
+	       dbCatValArray * cvarr, double *breaks, int nbreaks,
+	       const struct color_rgb *colors, const struct color_rgb *bcolor,
+	       int chcat, struct Cell_head *window, int default_width, int *frequencies, int nodraw)
+{
+
+    int num, area, isle, n_isles, n_points;
+    double xl, yl;
+    struct line_pnts *Points, *IPoints;
+    struct line_cats *Cats;
+    int cat, centroid = 0;
+    double breakval = 0.0;
+
+    dbCatVal *cv = NULL;
+
+    G_debug(1, "display areas:");
+    Points = Vect_new_line_struct();
+    IPoints = Vect_new_line_struct();
+    Cats = Vect_new_cats_struct();
+
+
+    num = Vect_get_num_areas(Map);
+    G_debug(2, "n_areas = %d", num);
+   
+
+    for (area = 1; area <= num; area++) {
+	int i;
+	BOUND_BOX box;
+	G_debug(3, "area = %d", area);
+
+	if (!Vect_area_alive(Map, area))
+	    continue;
+
+	/* Check box */
+	Vect_get_area_box(Map, area, &box);
+	if (box.N < window->south || box.S > window->north ||
+	    box.E < window->west || box.W > window->east) {
+
+	    if (window->proj != PROJECTION_LL)
+		continue;
+	    else {		/* out of bounds for -180 to 180, try 0 to 360 as well */
+		if (box.N < window->south || box.S > window->north)
+		    continue;
+		if (box.E + 360 < window->west || box.W + 360 > window->east)
+		    continue;
+	    }
+	}
+
+	if (chcat) {		/* check category: where_opt used */
+	    int found = 0;
+
+	    centroid = Vect_get_area_centroid(Map, area);
+	    G_debug(3, "centroid = %d", centroid);
+	    if (centroid < 1)
+		continue;
+	    Vect_read_line(Map, Points, Cats, centroid);
+
+	    for (i = 0; i < Cats->n_cats; i++) {
+		G_debug(3, "  centroid = %d, field = %d, cat = %d", centroid,
+			Cats->field[i], Cats->cat[i]);
+
+		if (Cats->field[i] == Clist->field &&
+		    Vect_cat_in_cat_list(Cats->cat[i], Clist)) {
+		    found = 1;
+		    break;
+		}
+	    }
+	    if (!found)
+		continue;
+	}			/* end if chcat */
+	else if (Clist->field > 0) {
+	    int found = 0;
+
+	    centroid = Vect_get_area_centroid(Map, area);
+	    G_debug(3, "centroid = %d", centroid);
+	    if (centroid < 1)
+		continue;
+	    Vect_read_line(Map, Points, Cats, centroid);
+
+	    for (i = 0; i < Cats->n_cats; i++) {
+		G_debug(3, "  centroid = %d, field = %d, cat = %d", centroid,
+			Cats->field[i], Cats->cat[i]);
+		if (Cats->field[i] == Clist->field) {
+		    found = 1;
+		    break;
+		}
+	    }
+	    /* lines with no category will be displayed */
+	    if (Cats->n_cats > 0 && !found)
+		continue;
+	}
+
+	G_debug(3, "display area %d", area);
+
+	/* fill */
+	Vect_get_area_points(Map, area, Points);
+	G_debug(3, "n_points = %d", Points->n_points);
+
+	n_points = Points->n_points;
+	xl = Points->x[n_points - 1];
+	yl = Points->y[n_points - 1];
+	n_isles = Vect_get_area_num_isles(Map, area);
+	for (i = 0; i < n_isles; i++) {
+	    isle = Vect_get_area_isle(Map, area, i);
+	    Vect_get_isle_points(Map, isle, IPoints);
+	    Vect_append_points(Points, IPoints, GV_FORWARD);
+	    Vect_append_point(Points, xl, yl, 0.0);	/* ??? */
+	}
+
+	cat = Vect_get_area_cat(Map, area,
+				(Clist->field > 0 ? Clist->field :
+				 (Cats->n_cats > 0 ? Cats->field[0] : 1)));
+
+	if (!Vect_get_area_centroid(Map, area) && cat == -1) {
+	    continue;
+	}
+
+	centroid = Vect_get_area_centroid(Map, area);
+	if (cat >= 0) {
+	    G_debug(3, "display area %d, centroid %d, cat %d", area, centroid,
+		    cat);
+
+	    /* Get value of data for this area */
+	    if (db_CatValArray_get_value(cvarr, cat, &cv) != DB_OK) {
+		G_debug(3, "No value found for cat %i", cat);
+
+	    }
+	    else {
+		breakval =
+		    (cvarr->ctype == DB_C_TYPE_INT ? cv->val.i : cv->val.d);
+	    }
+	}
+
+	/* find out into which class breakval falls */
+	i = 0;
+	while (breakval > breaks[i] && i < nbreaks)
+	    i++;
+	frequencies[i]++;
+
+        if(!nodraw) {
+	/* plot polygon in class color */
+	R_RGB_color(colors[i].r, colors[i].g, colors[i].b);
+	plot_polygon(Points->x, Points->y, Points->n_points);
+
+	/* XXX rewrite boundary */
+	if (bcolor) {
+	    int i;
+	    Vect_get_area_points(Map, area, Points);
+	    R_RGB_color(bcolor->r, bcolor->g, bcolor->b);
+	    /*use different user defined render methods */
+	    plot_polyline(Points->x, Points->y, Points->n_points);
+	    for (i = 0; i < n_isles; i++) {
+		isle = Vect_get_area_isle(Map, area, i);
+		Vect_get_isle_points(Map, isle, Points);
+		/*use different user defined render methods */
+		plot_polyline(Points->x, Points->y, Points->n_points);
+	    }
+	}
+      } /* end if !nodraw */
+    }				/* end for loop over areas */
+
+    Vect_destroy_line_struct(Points);
+    Vect_destroy_line_struct(IPoints);
+    Vect_destroy_cats_struct(Cats);
+
+    return 0;
+}

Added: grass/trunk/display/d.thematic.area/description.html
===================================================================
--- grass/trunk/display/d.thematic.area/description.html	                        (rev 0)
+++ grass/trunk/display/d.thematic.area/description.html	2008-02-22 18:14:09 UTC (rev 30294)
@@ -0,0 +1,30 @@
+<H2>DESCRIPTION</H2>
+
+<em>d.thematic.area</em> draws thematic coropleth vector maps based on an attribute column or an expression involving several columns. It takes a number of class breaks (excluding the minimum and maximum values) and a list of colors to apply to the classes (has to be the number of class breaks + 1).
+
+The <em>-l</em> flag instructs the module to print legend information (class min | class max | number of observations in class | color) to standard output for futher use in graphical software. When given this flag with the <em>-n</em> flag, the module will only print the legend information without drawing the map.
+
+One can used <em>v.class</em> to supply class breaks for d.thematic.area (see example below);
+
+
+<H2>EXAMPLE</H2>
+
+<div class="code"><pre>
+d.thematic.area -l map=communes3 data=pop breaks=111393.250000,222785.500000,334177.750000 colors=255:0:0,0:255:0,0:0:255,0,0,0
+</pre></div>
+
+The following example uses a calculated attribute (density = pop/area) and v.class to calculate class breaks and feed them directly into d.thematic.area:
+<div class="code"><pre>
+d.thematic.area -l map=communes2 data=pop/area breaks=`v.class -g map=communes2 column=pop/area algo=std nbcla=5` colors=0:0:255,50:100:255,255:100:50,255:0:0,156:0:0
+</pre></div>
+
+<H2>SEE ALSO</H2>
+
+<EM><A HREF="v.class.html">v.class</A></EM>
+<EM><A HREF="d.vect.html">d.vect</A></EM>
+<EM><A HREF="v.univar.html">v.univar</A></EM>
+
+
+<H2>AUTHOR</H2>
+
+Moritz Lennert

Added: grass/trunk/display/d.thematic.area/local_proto.h
===================================================================
--- grass/trunk/display/d.thematic.area/local_proto.h	                        (rev 0)
+++ grass/trunk/display/d.thematic.area/local_proto.h	2008-02-22 18:14:09 UTC (rev 30294)
@@ -0,0 +1,16 @@
+#include <grass/dbmi.h>
+#include <grass/symbol.h>
+#include <grass/colors.h>
+
+FILE *open_vect(char *, char *);
+int close_vect(FILE *);
+int plot1(struct Map_info *, int, int, struct cat_list *,
+	  const struct color_rgb *, const struct color_rgb *, int, SYMBOL *,
+	  int, int, int, int, char *, int, char *, double);
+int dareatheme(struct Map_info *, struct cat_list *, dbCatValArray *, double *, int,
+	  const struct color_rgb *, const struct color_rgb *, int,
+	  struct Cell_head *, int, int *, int);
+void plot_polygon(double *, double *, int);
+void plot_polyline(double *, double *, int);
+
+int dcmp  (const void *, const void *);

Added: grass/trunk/display/d.thematic.area/main.c
===================================================================
--- grass/trunk/display/d.thematic.area/main.c	                        (rev 0)
+++ grass/trunk/display/d.thematic.area/main.c	2008-02-22 18:14:09 UTC (rev 30294)
@@ -0,0 +1,405 @@
+/*
+ ****************************************************************************
+ *
+ * MODULE:       d.area.thematic
+ * AUTHOR(S):    Moritz Lennert, based on d.vect
+ * PURPOSE:      display a thematic vector area map
+ *               on top of the current image.
+ * COPYRIGHT:    (C) 2007 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.
+ *
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <grass/config.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/display.h>
+#include <grass/Vect.h>
+#include <grass/colors.h>
+#include <grass/dbmi.h>
+#include <grass/glocale.h>
+#include "plot.h"
+#include "local_proto.h"
+
+
+int main(int argc, char **argv)
+{
+    char *mapset;
+    int ret, level;
+    int i, stat = 0;
+    int nclass, nbreaks, *frequencies;
+    int chcat = 0;
+    int r, g, b;
+    int has_color = 0;
+    struct color_rgb *colors, bcolor;
+    int default_width;
+    int verbose = FALSE;
+    char map_name[128];
+    struct GModule *module;
+    struct Option *map_opt;
+    struct Option *column_opt;
+    struct Option *breaks_opt;
+    struct Option *colors_opt;
+    struct Option *bcolor_opt;
+    struct Option *bwidth_opt;
+    struct Option *where_opt;
+    struct Option *field_opt;
+    struct Option *render_opt;
+    struct Flag *legend_flag, *x_flag, *nodraw_flag;
+
+    struct cat_list *Clist;
+    int *cats, ncat, nrec;
+    struct Map_info Map;
+    struct field_info *fi;
+    dbDriver *driver;
+    dbHandle handle;
+    dbCatValArray cvarr;
+    struct Cell_head window;
+    BOUND_BOX box;
+    double overlap, *breakpoints, min, max;
+
+    /* Initialize the GIS calls */
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    module->keywords = _("display");
+    module->description =
+	_("Displays a thematic vector area map in the active"
+	  "frame on the graphics monitor.");
+
+    map_opt = G_define_standard_option(G_OPT_V_MAP);
+
+    column_opt = G_define_option();
+    column_opt->key = "column";
+    column_opt->type = TYPE_STRING;
+    column_opt->required = YES;
+    column_opt->description =
+	_("Data to be classified: column name or expression");
+
+    breaks_opt = G_define_option();
+    breaks_opt->key = "breaks";
+    breaks_opt->type = TYPE_STRING;
+    breaks_opt->required = YES;
+    breaks_opt->multiple = YES;
+    breaks_opt->description = _("Class breaks, without minimum and maximum");
+
+    colors_opt = G_define_option();
+    colors_opt->key = "colors";
+    colors_opt->type = TYPE_STRING;
+    colors_opt->required = YES;
+    colors_opt->multiple = YES;
+    colors_opt->description = _("Colors (one more than class breaks).");
+    colors_opt->gisprompt = GISPROMPT_COLOR;
+
+    field_opt = G_define_standard_option(G_OPT_V_FIELD);
+    field_opt->description =
+	_("Layer number. If -1, all layers are displayed.");
+
+    where_opt = G_define_standard_option(G_OPT_WHERE);
+    where_opt->guisection = _("Query");
+
+    bwidth_opt = G_define_option();
+    bwidth_opt->key = "bwidth";
+    bwidth_opt->type = TYPE_INTEGER;
+    bwidth_opt->answer = "0";
+    bwidth_opt->guisection = _("Boundaries");
+    bwidth_opt->description = _("Boundary width");
+
+    bcolor_opt = G_define_option();
+    bcolor_opt->key = "bcolor";
+    bcolor_opt->type = TYPE_STRING;
+    bcolor_opt->answer = DEFAULT_FG_COLOR;
+    bcolor_opt->description = _("Boundary color");
+    bcolor_opt->guisection = _("Boundaries");
+    bcolor_opt->gisprompt = GISPROMPT_COLOR;
+
+    render_opt = G_define_option();
+    render_opt->key = "render";
+    render_opt->type = TYPE_STRING;
+    render_opt->required = NO;
+    render_opt->multiple = NO;
+    render_opt->answer = "l";
+    render_opt->options = "g,r,d,c,l";
+    render_opt->description = _("Rendering method for filled polygons");
+    render_opt->descriptions =
+	_("g;use the libgis render functions (features: clipping);"
+	  "r;use the raster graphics library functions (features: polylines);"
+	  "d;use the display library basic functions (features: polylines);"
+	  "c;use the display library clipping functions (features: clipping);"
+	  "l;use the display library culling functions (features: culling, polylines)");
+
+
+
+    legend_flag = G_define_flag();
+    legend_flag->key = 'l';
+    legend_flag->description =
+	_("Create legend information and send to stdout");
+
+    nodraw_flag = G_define_flag();
+    nodraw_flag->key = 'n';
+    nodraw_flag->description = _("Do not draw map, only output the legend");
+
+    x_flag = G_define_flag();
+    x_flag->key = 'x';
+    x_flag->description =
+	_("Don't add to list of vectors and commands in monitor "
+	  "(it won't be drawn if the monitor is refreshed)");
+
+    /* Check command line */
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    if (G_strcasecmp(render_opt->answer, "g") == 0)
+	render = RENDER_GPP;
+    else if (G_strcasecmp(render_opt->answer, "r") == 0)
+	render = RENDER_RPA;
+    else if (G_strcasecmp(render_opt->answer, "d") == 0)
+	render = RENDER_DP;
+    else if (G_strcasecmp(render_opt->answer, "c") == 0)
+	render = RENDER_DPC;
+    else if (G_strcasecmp(render_opt->answer, "l") == 0)
+	render = RENDER_DPL;
+    else
+	render = RENDER_GPP;
+
+
+    if (G_verbose() > G_verbose_std())
+	verbose = TRUE;
+
+    G_get_set_window(&window);
+
+    /* Read map options */
+
+    G_strcpy(map_name, map_opt->answer);
+
+
+    /* Make sure map is available */
+    mapset = G_find_vector2(map_name, "");
+
+    if (mapset == NULL)
+	G_fatal_error(_("Vector map <%s> not found"), map_name);
+
+    /* open vector */
+    level = Vect_open_old(&Map, map_name, mapset);
+
+    if (level < 2)
+	G_fatal_error(_
+		      ("%s: You must build topology on vector map. Run v.build."),
+		      map_name);
+
+    /* Check database connection and open it */
+    Clist = Vect_new_cat_list();
+    Clist->field = atoi(field_opt->answer);
+    if (Clist->field < 1)
+	G_fatal_error(_("'layer' must be > 0"));
+    if ((fi = Vect_get_field(&Map, Clist->field)) == NULL)
+	G_fatal_error(_("Database connection not defined"));
+    if (fi != NULL) {
+	driver = db_start_driver(fi->driver);
+	if (driver == NULL)
+	    G_fatal_error(_("Unable to start driver <%s>"), fi->driver);
+
+	db_init_handle(&handle);
+	db_set_handle(&handle, fi->database, NULL);
+	if (db_open_database(driver, &handle) != DB_OK)
+	    G_fatal_error(_("Unable to open database <%s>"), fi->database);
+    }
+
+
+
+    /*Get CatValArray needed for plotting and for legend calculations */
+    db_CatValArray_init(&cvarr);
+    nrec = db_select_CatValArray(driver, fi->table, fi->key,
+				 column_opt->answer, NULL, &cvarr);
+
+
+    G_debug(3, "nrec (%s) = %d", column_opt->answer, nrec);
+
+    if (cvarr.ctype != DB_C_TYPE_INT && cvarr.ctype != DB_C_TYPE_DOUBLE)
+	G_fatal_error(_("Data (%s) not numeric. "
+			"Column must be numeric."), column_opt->answer);
+
+    if (nrec < 0)
+	G_fatal_error(_("Cannot select data (%s) from table"),
+		      column_opt->answer);
+
+    G_debug(2, "\n%d records selected from table", nrec);
+
+    for (i = 0; i < cvarr.n_values; i++) {
+	G_debug(4, "cat = %d  %s = %d", cvarr.value[i].cat, column_opt->answer,
+		(cvarr.ctype == DB_C_TYPE_INT ? cvarr.value[i].val.i :
+		 (int)cvarr.value[i].val.d));
+    }
+
+    /*Get the list of relevant cats if where option is given */
+    if (where_opt->answer) {
+	ncat = db_select_int(driver, fi->table, fi->key, where_opt->answer,
+			     &cats);
+	chcat = 1;
+
+	Vect_array_to_cat_list(cats, ncat, Clist);
+    }
+
+    db_close_database(driver);
+    db_shutdown_driver(driver);
+
+    /*get border line width */
+    default_width = atoi(bwidth_opt->answer);
+    if (default_width < 0)
+	default_width = 0;
+
+    /*get border line color */
+    bcolor = G_standard_color_rgb(WHITE);
+    ret = G_str_to_color(bcolor_opt->answer, &r, &g, &b);
+    if (ret == 1) {
+	has_color = 1;
+	bcolor.r = r;
+	bcolor.g = g;
+	bcolor.b = b;
+    }
+    else if (ret == 2) {	/* none */
+	has_color = 0;
+    }
+    else if (ret == 0) {	/* error */
+	G_fatal_error(_("Unknown color: [%s]"), bcolor_opt->answer);
+    }
+
+    /*Get class breaks */
+    nbreaks = 0;
+    while (breaks_opt->answers[nbreaks] != NULL)
+	nbreaks++;
+    nclass = nbreaks + 1;	/*add one since breaks do not include min and max values */
+    G_debug(3, "nclass = %d", nclass);
+
+    breakpoints = (double *)G_malloc((nbreaks) * sizeof(double));
+    for (i = 0; i < nbreaks; i++)
+	breakpoints[i] = atof(breaks_opt->answers[i]);
+
+    frequencies = (int *)G_malloc((nbreaks + 1) * sizeof(int));
+    for (i = 0; i < nbreaks + 1; i++)
+	    frequencies[i] = 0;
+
+    /* Fill colors */
+    colors = (struct color_rgb *)G_malloc(nclass * sizeof(struct color_rgb));
+
+    if (colors_opt->answers != NULL) {
+	for (i = 0; i < nclass; i++) {
+	    if (colors_opt->answers[i] == NULL)
+		G_fatal_error(_
+			      ("Not enough colors or error in color specifications.\nNeed %i colors."),
+			      nclass);
+
+	    ret = G_str_to_color(colors_opt->answers[i], &r, &g, &b);
+	    if (!ret)
+		G_fatal_error(_("Error interpreting color %s"),
+			      colors_opt->answers[i]);
+	    colors[i].r = r;
+	    colors[i].g = g;
+	    colors[i].b = b;
+
+	}
+    }
+
+
+
+    /* Now's let's prepare the actual plotting */
+	if (R_open_driver() != 0)
+	    G_fatal_error(_("No graphics device selected"));
+
+	D_setup(0);
+
+	G_setup_plot(D_get_d_north(), D_get_d_south(),
+		     D_get_d_west(), D_get_d_east(), D_move_abs, D_cont_abs);
+
+	if (verbose)
+	    G_message(_("Plotting ..."));
+
+	Vect_get_map_box(&Map, &box);
+
+	if (window.north < box.S || window.south > box.N ||
+	    window.east < box.W ||
+	    window.west > G_adjust_easting(box.E, &window)) {
+	    G_message(_
+		      ("The bounding box of the map is outside the current region, "
+		       "nothing drawn."));
+	    stat = 0;
+	}
+	else {
+	    overlap =
+		G_window_percentage_overlap(&window, box.N, box.S, box.E,
+					    box.W);
+	    G_debug(1, "overlap = %f \n", overlap);
+	    if (overlap < 1)
+		Vect_set_constraint_region(&Map, window.north, window.south,
+					   window.east, window.west,
+					   PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX);
+
+	    /* default line width */
+	    D_line_width(default_width);
+
+
+	    stat = dareatheme(&Map, Clist, &cvarr, breakpoints, nbreaks, colors,
+			      has_color ? &bcolor : NULL, chcat, &window,
+			      default_width, frequencies, nodraw_flag->answer);
+
+
+	    /* reset line width: Do we need to get line width from display
+	     * driver (not implemented)?  It will help restore previous line
+	     * width (not just 0) determined by another module (e.g.,
+	     * d.linewidth). */
+	    R_line_width(0);
+
+	}			/* end window check if */
+
+	if (!x_flag->answer) {
+	    D_add_to_list(G_recreate_command());
+
+	    D_set_dig_name(G_fully_qualified_name(map_name, mapset));
+	    D_add_to_dig_list(G_fully_qualified_name(map_name, mapset));
+	}
+
+	R_close_driver();
+
+
+
+    if (legend_flag->answer) {
+
+	ret = db_CatValArray_sort_by_value(&cvarr);
+        if(cvarr.ctype == DB_C_TYPE_INT) {
+	     min=cvarr.value[0].val.i;
+	     max=cvarr.value[cvarr.n_values-1].val.i;
+	} else {
+	     min=cvarr.value[0].val.d;
+	     max=cvarr.value[cvarr.n_values-1].val.d;
+	}
+
+
+	fprintf(stdout, "%f|%f|%i|%d:%d:%d\n",
+		min, breakpoints[0], frequencies[0], colors[0].r, colors[0].g,
+		colors[0].b);
+
+	for (i = 1; i < nbreaks; i++) {
+	    fprintf(stdout, "%f|%f|%i|%d:%d:%d\n",
+		    breakpoints[i - 1], breakpoints[i], frequencies[i],
+		    colors[i].r, colors[i].g, colors[i].b);
+	}
+	fprintf(stdout, "%f|%f|%i|%d:%d:%d\n",
+		breakpoints[nbreaks - 1], max, frequencies[nbreaks],
+		colors[0].r, colors[0].g, colors[0].b);
+    }
+
+    if (verbose)
+	G_done_msg("");
+
+    Vect_close(&Map);
+    Vect_destroy_cat_list(Clist);
+
+    exit(stat);
+}

Added: grass/trunk/display/d.thematic.area/plot.h
===================================================================
--- grass/trunk/display/d.thematic.area/plot.h	                        (rev 0)
+++ grass/trunk/display/d.thematic.area/plot.h	2008-02-22 18:14:09 UTC (rev 30294)
@@ -0,0 +1,23 @@
+/* TODO: should use 24bit instead of 16 colors, maybe implement
+   predefined color tables? */
+struct rgb_color {
+        unsigned char R, G, B;
+       };
+
+extern int palette_ncolors;
+extern struct rgb_color palette[16];
+
+#define DISP_SHAPE 0x01
+#define DISP_CAT   0x02
+#define DISP_TOPO  0x04
+#define DISP_DIR   0x08
+#define DISP_ATTR  0x10
+#define DISP_ZCOOR 0x20
+
+#define RENDER_GPP	0
+#define RENDER_RPA	1
+#define RENDER_DP	2
+#define RENDER_DPC	3
+#define RENDER_DPL	4
+
+extern int render;

Added: grass/trunk/display/d.thematic.area/plot1.c
===================================================================
--- grass/trunk/display/d.thematic.area/plot1.c	                        (rev 0)
+++ grass/trunk/display/d.thematic.area/plot1.c	2008-02-22 18:14:09 UTC (rev 30294)
@@ -0,0 +1,505 @@
+/* plot1() - Level One vector reading */
+
+#include <string.h>
+#include <grass/gis.h>
+#include <grass/Vect.h>
+#include <grass/display.h>
+#include <grass/raster.h>
+#include "plot.h"
+#include "local_proto.h"
+#include <grass/symbol.h>
+#include <grass/glocale.h>
+#include <grass/dbmi.h>
+
+#define RENDER_POLYLINE 0
+#define RENDER_POLYGON  1
+
+int palette_ncolors = 16;
+
+struct rgb_color palette[16] = {
+    {198, 198, 198},		/*  1: light gray */
+    {127, 127, 127},		/*  2: medium/dark gray */
+    {255, 0, 0},		/*  3: bright red */
+    {139, 0, 0},		/*  4: dark red */
+    {0, 255, 0},		/*  5: bright green */
+    {0, 139, 0},		/*  6: dark green */
+    {0, 0, 255},		/*  7: bright blue */
+    {0, 0, 139},		/*  8: dark blue   */
+    {255, 255, 0},		/*  9: yellow */
+    {139, 126, 10},		/* 10: olivey brown */
+    {255, 165, 0},		/* 11: orange */
+    {255, 192, 203},		/* 12: pink   */
+    {255, 0, 255},		/* 13: magenta */
+    {139, 0, 139},		/* 14: dark magenta */
+    {0, 255, 255},		/* 15: cyan */
+    {0, 139, 139}		/* 16: dark cyan */
+};
+
+/*local functions */
+static void local_plot_poly(double *xf, double *yf, int n, int type);
+
+/*global render switch */
+int render;
+
+/* *************************************************************** */
+/* function to plot polygons and polylines       ***************** */
+/* the parameter type switches render mode       ***************** */
+/* *************************************************************** */
+static void local_plot_poly(double *xf, double *yf, int n, int type)
+{
+    static int *xi, *yi;
+    static int nalloc;
+    int i;
+
+    if (nalloc < n) {
+	nalloc = n;
+	xi = G_realloc(xi, nalloc * sizeof(int));
+	yi = G_realloc(yi, nalloc * sizeof(int));
+    }
+
+    for (i = 0; i < n; i++) {
+	xi[i] = (int)floor(0.5 + D_u_to_d_col(xf[i]));
+	yi[i] = (int)floor(0.5 + D_u_to_d_row(yf[i]));
+    }
+
+    if (type == RENDER_POLYGON)
+	R_polygon_abs(xi, yi, n);
+    else
+	R_polyline_abs(xi, yi, n);
+}
+
+/* *************************************************************** */
+/* function to use different render methods for polylines ******** */
+/* *************************************************************** */
+void plot_polyline(double *xf, double *yf, int n)
+{
+    int i;
+
+    switch (render) {
+    case RENDER_DP:
+	D_polyline(xf, yf, n);
+	break;
+    case RENDER_DPC:
+	D_polyline_clip(xf, yf, n);
+	break;
+    case RENDER_DPL:
+	D_polyline_cull(xf, yf, n);
+	break;
+    case RENDER_RPA:
+	local_plot_poly(xf, yf, n, RENDER_POLYLINE);
+	break;
+    case RENDER_GPP:
+    default:
+	for (i = 1; i < n; i++)
+	    G_plot_line(xf[i - 1], yf[i - 1], xf[i], yf[i]);
+	break;
+    }
+}
+
+/* *************************************************************** */
+/* function to use different render methods for polygons  ******** */
+/* *************************************************************** */
+void plot_polygon(double *xf, double *yf, int n)
+{
+    switch (render) {
+    case RENDER_GPP:
+	G_plot_polygon(xf, yf, n);
+	break;
+    case RENDER_DP:
+	D_polygon(xf, yf, n);
+	break;
+    case RENDER_DPC:
+	D_polygon_clip(xf, yf, n);
+	break;
+    case RENDER_DPL:
+	D_polygon_cull(xf, yf, n);
+	break;
+    case RENDER_RPA:
+	local_plot_poly(xf, yf, n, RENDER_POLYGON);
+	break;
+    default:
+	G_plot_polygon(xf, yf, n);
+	break;
+    }
+}
+
+/* *************************************************************** */
+/* *************************************************************** */
+/* *************************************************************** */
+int plot1(struct Map_info *Map, int type, int area, struct cat_list *Clist,
+	  const struct color_rgb *color, const struct color_rgb *fcolor,
+	  int chcat, SYMBOL * Symb, int size, int id_flag,
+	  int table_colors_flag, int cats_color_flag, char *rgb_column,
+	  int default_width, char *width_column, double width_scale)
+{
+    int i, ltype, nlines = 0, line, cat = -1;
+    double *x, *y;
+    struct line_pnts *Points, *PPoints;
+    struct line_cats *Cats;
+    double msize;
+    int x0, y0;
+
+    struct field_info *fi = NULL;
+    dbDriver *driver = NULL;
+    dbCatValArray cvarr_rgb, cvarr_width;
+    dbCatVal *cv_rgb = NULL, *cv_width = NULL;
+    int nrec_rgb = 0, nrec_width = 0;
+
+    int open_db;
+    int custom_rgb = FALSE;
+    char colorstring[12];	/* RRR:GGG:BBB */
+    int red, grn, blu;
+    RGBA_Color *line_color, *fill_color, *primary_color;
+    unsigned char which;
+    int width;
+
+    line_color = G_malloc(sizeof(RGBA_Color));
+    fill_color = G_malloc(sizeof(RGBA_Color));
+    primary_color = G_malloc(sizeof(RGBA_Color));
+
+    primary_color->a = RGBA_COLOR_OPAQUE;
+
+    /* change function prototype to pass RGBA_Color instead of color_rgb? */
+    if (color) {
+	line_color->r = color->r;
+	line_color->g = color->g;
+	line_color->b = color->b;
+	line_color->a = RGBA_COLOR_OPAQUE;
+    }
+    else
+	line_color->a = RGBA_COLOR_NONE;
+
+    if (fcolor) {
+	fill_color->r = fcolor->r;
+	fill_color->g = fcolor->g;
+	fill_color->b = fcolor->b;
+	fill_color->a = RGBA_COLOR_OPAQUE;
+    }
+    else
+	fill_color->a = RGBA_COLOR_NONE;
+
+
+    msize = size * (D_d_to_u_col(2.0) - D_d_to_u_col(1.0));	/* do it better */
+
+    Points = Vect_new_line_struct();
+    PPoints = Vect_new_line_struct();
+    Cats = Vect_new_cats_struct();
+
+    open_db = table_colors_flag || width_column;
+
+    if (open_db) {
+	fi = Vect_get_field(Map, (Clist->field > 0 ? Clist->field : 1));
+	if (fi == NULL) {
+	    G_fatal_error(_("Cannot read field info"));
+	}
+
+	driver = db_start_driver_open_database(fi->driver, fi->database);
+	if (driver == NULL)
+	    G_fatal_error(_("Cannot open database %s by driver %s"),
+			  fi->database, fi->driver);
+    }
+
+    if (table_colors_flag) {
+	/* for reading RRR:GGG:BBB color strings from table */
+
+	if (rgb_column == NULL || *rgb_column == '\0')
+	    G_fatal_error(_("Color definition column not specified."));
+
+	db_CatValArray_init(&cvarr_rgb);
+
+	nrec_rgb = db_select_CatValArray(driver, fi->table, fi->key,
+					 rgb_column, NULL, &cvarr_rgb);
+
+	G_debug(3, "nrec_rgb (%s) = %d", rgb_column, nrec_rgb);
+
+	if (cvarr_rgb.ctype != DB_C_TYPE_STRING)
+	    G_fatal_error(_("Color definition column (%s) not a string. "
+			    "Column must be of form RRR:GGG:BBB where RGB values range 0-255."),
+			  rgb_column);
+
+	if (nrec_rgb < 0)
+	    G_fatal_error(_("Cannot select data (%s) from table"), rgb_column);
+
+	G_debug(2, "\n%d records selected from table", nrec_rgb);
+
+	for (i = 0; i < cvarr_rgb.n_values; i++) {
+	    G_debug(4, "cat = %d  %s = %s", cvarr_rgb.value[i].cat, rgb_column,
+		    db_get_string(cvarr_rgb.value[i].val.s));
+	}
+    }
+
+    if (width_column) {
+	if (*width_column == '\0')
+	    G_fatal_error(_("Line width column not specified."));
+
+	db_CatValArray_init(&cvarr_width);
+
+	nrec_width = db_select_CatValArray(driver, fi->table, fi->key,
+					   width_column, NULL, &cvarr_width);
+
+	G_debug(3, "nrec_width (%s) = %d", width_column, nrec_width);
+
+	if (cvarr_width.ctype != DB_C_TYPE_INT &&
+	    cvarr_width.ctype != DB_C_TYPE_DOUBLE)
+	    G_fatal_error(_("Line width column (%s) not a number."),
+			  width_column);
+
+	if (nrec_width < 0)
+	    G_fatal_error(_("Cannot select data (%s) from table"),
+			  width_column);
+
+	G_debug(2, "\n%d records selected from table", nrec_width);
+
+	for (i = 0; i < cvarr_width.n_values; i++) {
+	    G_debug(4, "cat = %d  %s = %d", cvarr_width.value[i].cat,
+		    width_column,
+		    (cvarr_width.ctype ==
+		     DB_C_TYPE_INT ? cvarr_width.value[i].val.
+		     i : (int)cvarr_width.value[i].val.d));
+	}
+    }
+
+    if (open_db)
+	db_close_database_shutdown_driver(driver);
+
+    Vect_rewind(Map);
+
+    /* Is it necessary to reset line/label color in each loop ? */
+
+    if (color && !table_colors_flag && !cats_color_flag)
+	R_RGB_color(color->r, color->g, color->b);
+
+    if (Vect_level(Map) >= 2)
+	nlines = Vect_get_num_lines(Map);
+
+    line = 0;
+    while (1) {
+	if (Vect_level(Map) >= 2) {
+	    line++;
+	    if (line > nlines)
+		return 0;
+	    if (!Vect_line_alive(Map, line))
+		continue;
+	    ltype = Vect_read_line(Map, Points, Cats, line);
+	}
+	else {
+	    ltype = Vect_read_next_line(Map, Points, Cats);
+	    switch (ltype) {
+	    case -1:
+		fprintf(stderr, _("\nERROR: vector map - can't read\n"));
+		return -1;
+	    case -2:		/* EOF */
+		return 0;
+	    }
+	}
+
+	if (!(type & ltype))
+	    continue;
+
+	if (chcat) {
+	    int found = 0;
+
+	    if (id_flag) {	/* use line id */
+		if (!(Vect_cat_in_cat_list(line, Clist)))
+		    continue;
+	    }
+	    else {
+		for (i = 0; i < Cats->n_cats; i++) {
+		    if (Cats->field[i] == Clist->field &&
+			Vect_cat_in_cat_list(Cats->cat[i], Clist)) {
+			found = 1;
+			break;
+		    }
+		}
+		if (!found)
+		    continue;
+	    }
+	}
+	else if (Clist->field > 0) {
+	    int found = 0;
+
+	    for (i = 0; i < Cats->n_cats; i++) {
+		if (Cats->field[i] == Clist->field) {
+		    found = 1;
+		    break;
+		}
+	    }
+	    /* lines with no category will be displayed */
+	    if (Cats->n_cats > 0 && !found)
+		continue;
+	}
+
+
+	if (table_colors_flag) {
+
+	    /* only first category */
+	    cat = Vect_get_line_cat(Map, line,
+				    (Clist->field > 0 ? Clist->field :
+				     (Cats->n_cats > 0 ? Cats->field[0] : 1)));
+
+	    if (cat >= 0) {
+		G_debug(3, "display element %d, cat %d", line, cat);
+
+		/* Read RGB colors from db for current area # */
+		if (db_CatValArray_get_value(&cvarr_rgb, cat, &cv_rgb) != DB_OK) {
+		    custom_rgb = FALSE;
+		}
+		else {
+		    sprintf(colorstring, "%s", db_get_string(cv_rgb->val.s));
+
+		    if (*colorstring != '\0') {
+			G_debug(3, "element %d: colorstring: %s", line,
+				colorstring);
+
+			if (G_str_to_color(colorstring, &red, &grn, &blu) == 1) {
+			    custom_rgb = TRUE;
+			    G_debug(3, "element:%d  cat %d r:%d g:%d b:%d",
+				    line, cat, red, grn, blu);
+			}
+			else {
+			    custom_rgb = FALSE;
+			    G_warning(_
+				      ("Error in color definition column (%s), element %d "
+				       "with cat %d: colorstring [%s]"),
+				      rgb_column, line, cat, colorstring);
+			}
+		    }
+		    else {
+			custom_rgb = FALSE;
+			G_warning(_
+				  ("Error in color definition column (%s), element %d with cat %d"),
+				  rgb_column, line, cat);
+		    }
+		}
+	    }			/* end if cat */
+	    else {
+		custom_rgb = FALSE;
+	    }
+	}			/* end if table_colors_flag */
+
+
+	/* random colors */
+	if (cats_color_flag) {
+	    custom_rgb = FALSE;
+	    if (Clist->field > 0) {
+		cat = Vect_get_line_cat(Map, line, Clist->field);
+		if (cat >= 0) {
+		    G_debug(3, "display element %d, cat %d", line, cat);
+		    /* fetch color number from category */
+		    which = (cat % palette_ncolors);
+		    G_debug(3, "cat:%d which color:%d r:%d g:%d b:%d", cat,
+			    which, palette[which].R, palette[which].G,
+			    palette[which].B);
+
+		    custom_rgb = TRUE;
+		    red = palette[which].R;
+		    grn = palette[which].G;
+		    blu = palette[which].B;
+		}
+	    }
+	    else if (Cats->n_cats > 0) {
+		/* fetch color number from layer */
+		which = (Cats->field[0] % palette_ncolors);
+		G_debug(3, "layer:%d which color:%d r:%d g:%d b:%d",
+			Cats->field[0], which, palette[which].R,
+			palette[which].G, palette[which].B);
+
+		custom_rgb = TRUE;
+		red = palette[which].R;
+		grn = palette[which].G;
+		blu = palette[which].B;
+	    }
+	}
+
+
+	if (nrec_width) {
+
+	    /* only first category */
+	    cat = Vect_get_line_cat(Map, line,
+				    (Clist->field > 0 ? Clist->field :
+				     (Cats->n_cats > 0 ? Cats->field[0] : 1)));
+
+	    if (cat >= 0) {
+		G_debug(3, "display element %d, cat %d", line, cat);
+
+		/* Read line width from db for current area # */
+
+		if (db_CatValArray_get_value(&cvarr_width, cat, &cv_width) !=
+		    DB_OK) {
+		    width = default_width;
+		}
+		else {
+		    width = width_scale * (cvarr_width.ctype == DB_C_TYPE_INT ?
+					   cv_width->val.i : (int)cv_width->val.
+					   d);
+		    if (width < 0) {
+			G_warning(_
+				  ("Error in line width column (%s), element %d "
+				   "with cat %d: line width [%d]"),
+				  width_column, line, cat, width);
+			width = default_width;
+		    }
+		}
+	    }			/* end if cat */
+	    else {
+		width = default_width;
+	    }
+
+	    D_line_width(width);
+	}			/* end if nrec_width */
+
+
+	/* enough of the prep work, lets start plotting stuff */
+	x = Points->x;
+	y = Points->y;
+
+	if ((ltype & GV_POINTS) && Symb != NULL) {
+	    if (!(color || fcolor || custom_rgb))
+		continue;
+
+	    G_plot_where_xy(x[0], y[0], &x0, &y0);
+
+	    /* skip if the point is outside of the display window */
+	    /*      xy<0 tests make it go ever-so-slightly faster */
+	    if (x0 < 0 || y0 < 0 ||
+		x0 > D_get_d_east() || x0 < D_get_d_west() ||
+		y0 > D_get_d_south() || y0 < D_get_d_north())
+		continue;
+
+	    /* use random or RGB column color if given, otherwise reset */
+	    /* centroids always use default color to stand out from underlying area */
+	    if (custom_rgb && (ltype != GV_CENTROID)) {
+		primary_color->r = (unsigned char)red;
+		primary_color->g = (unsigned char)grn;
+		primary_color->b = (unsigned char)blu;
+		D_symbol2(Symb, x0, y0, primary_color, line_color);
+	    }
+	    else
+		D_symbol(Symb, x0, y0, line_color, fill_color);
+
+
+	}
+	else if (color || custom_rgb) {
+	    if (!table_colors_flag && !cats_color_flag)
+		R_RGB_color(color->r, color->g, color->b);
+	    else {
+		if (custom_rgb)
+		    R_RGB_color((unsigned char)red, (unsigned char)grn,
+				(unsigned char)blu);
+		else
+		    R_RGB_color(color->r, color->g, color->b);
+	    }
+
+	    /* Plot the lines */
+	    if (Points->n_points == 1)	/* line with one coor */
+		D_polydots_clip(x, y, Points->n_points);
+	    else		/*use different user defined render methods */
+		plot_polyline(x, y, Points->n_points);
+	}
+    }
+
+    Vect_destroy_line_struct(Points);
+    Vect_destroy_cats_struct(Cats);
+
+    return 0;			/* not reached */
+}



More information about the grass-commit mailing list