[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