[GRASS-SVN] r69572 - in grass-addons/grass7/raster3d: . r3.scatterplot

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Sep 24 15:57:14 PDT 2016


Author: wenzeslaus
Date: 2016-09-24 15:57:14 -0700 (Sat, 24 Sep 2016)
New Revision: 69572

Added:
   grass-addons/grass7/raster3d/r3.scatterplot/
   grass-addons/grass7/raster3d/r3.scatterplot/Makefile
   grass-addons/grass7/raster3d/r3.scatterplot/main.c
   grass-addons/grass7/raster3d/r3.scatterplot/r3.scatterplot.html
   grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot.png
   grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables.png
   grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables_3rd_color.png
   grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables_3rd_z.png
   grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables_3rd_z_4th_color.png
   grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables_3rd_z_4th_color2.png
   grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2d.png
   grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_3_variables.png
   grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_3_variables_3_colors.png
   grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_3_variables_3_colors_overlap.png
   grass-addons/grass7/raster3d/r3.scatterplot/vector_mask.c
   grass-addons/grass7/raster3d/r3.scatterplot/vector_mask.h
Modified:
   grass-addons/grass7/raster3d/Makefile
Log:
r3.scatterplot: scatter plot of 3D rasters as vector points

Modified: grass-addons/grass7/raster3d/Makefile
===================================================================
--- grass-addons/grass7/raster3d/Makefile	2016-09-24 20:23:27 UTC (rev 69571)
+++ grass-addons/grass7/raster3d/Makefile	2016-09-24 22:57:14 UTC (rev 69572)
@@ -1,10 +1,10 @@
 MODULE_TOPDIR = ..
 
 SUBDIRS = \
-	r3.profile
+	r3.profile \
+	r3.scatterplot \
 	r3.what
 
 include $(MODULE_TOPDIR)/include/Make/Dir.make
 
 default: subdirs
-

Added: grass-addons/grass7/raster3d/r3.scatterplot/Makefile
===================================================================
--- grass-addons/grass7/raster3d/r3.scatterplot/Makefile	                        (rev 0)
+++ grass-addons/grass7/raster3d/r3.scatterplot/Makefile	2016-09-24 22:57:14 UTC (rev 69572)
@@ -0,0 +1,13 @@
+MODULE_TOPDIR = ../..
+
+PGM = r3.scatterplot
+
+LIBES = $(RASTER3DLIB) $(VECTORLIB) $(GISLIB) $(MATHLIB)
+DEPENDENCIES = $(RASTER3DDEP) $(VECTORDEP) $(GISDEP)
+
+EXTRA_INC = $(VECT_INC)
+EXTRA_CFLAGS = $(VECT_CFLAGS)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/Makefile
___________________________________________________________________
Added: svn:mime-type
   + text/x-makefile
Added: svn:eol-style
   + native

Added: grass-addons/grass7/raster3d/r3.scatterplot/main.c
===================================================================
--- grass-addons/grass7/raster3d/r3.scatterplot/main.c	                        (rev 0)
+++ grass-addons/grass7/raster3d/r3.scatterplot/main.c	2016-09-24 22:57:14 UTC (rev 69572)
@@ -0,0 +1,417 @@
+/****************************************************************************
+ *
+ * MODULE:       r3.scatterplot
+ *
+ * AUTHOR(S):    Vaclav Petras <wenzeslaus gmail com>
+ *
+ * PURPOSE:      Creates a scatter plot of two or more 3D maps
+ *
+ * COPYRIGHT:    (C) 2016 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.
+ *
+ *****************************************************************************/
+
+/*
+TODO: attribute table with backlink coordinates
+TODO: store color of the original cell for each raster in attr table
+TODO: additional attributes from additional maps? (may be too much)
+TODO: decimate every nth point
+TODO: set resolution internally to a lower one (resolution option)
+TODO: auto offset flag would benefit from coordinates in attribute table
+TODO: -r for placing into the region: i.e. it needs scale based on rast max, spacing and num of scatter plots
+TODO: flag to set color table so that each layer has separate color (like d.correlate or d.vect layer=-1 -c), good without -f
+TODO: flag or option to output real coordinates - useful for debugging and to see what is sampled
+TODO: layers and cats with RGB as in v.in.lidar ('std layer numbers' conflicting with multiple scatter plots)
+TODO: flag(s) to use depth (-d, always positive?) or z (-z, actual sign) as the 3rd (z) coordinate (to avoid need for r.mapcalc when correlation with z is needed as 3rd dimension)
+TODO: layout: add max num per row so that a row is broken
+TODO: optimize for case z_raster == color_raster or even if one of inputs is z or color
+*/
+
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include <grass/raster3d.h>
+#include <grass/vector.h>
+
+#include "vector_mask.h"
+
+struct ScatterOptions {
+    struct Option *input, *output;
+    struct Option *z_raster, *color_raster;
+    struct Option *xscale, *yscale, *zscale;
+    struct Option *spacing;
+    struct Option *position;
+    struct Option *vector_mask, *vector_mask_field;
+    struct Option *vector_mask_cats, *vector_mask_where;
+};
+
+struct ScatterFlags {
+    struct Flag *auto_offset;
+    struct Flag *one_layer;
+    struct Flag *region_position;
+    struct Flag *invert_mask;
+    struct Flag *notopo;
+};
+
+static void define_parameters(struct ScatterOptions *opt, struct ScatterFlags *flg)
+{
+    struct GModule *module;
+
+    module = G_define_module();
+    G_add_keyword(_("raster3d"));
+    G_add_keyword(_("statistics"));
+    G_add_keyword(_("diagram"));
+    G_add_keyword(_("correlation"));
+    G_add_keyword(_("scatter plot"));
+    G_add_keyword(_("vector"));
+    G_add_keyword(_("voxel"));
+    module->label = _("Creates a scatter plot of 3D raster maps");
+    module->description =
+        _("Creates a scatter plot of two or more 3D raster maps as a vector map");
+
+    opt->input = G_define_standard_option(G_OPT_R3_INPUTS);
+
+    opt->output = G_define_standard_option(G_OPT_V_OUTPUT);
+
+    opt->z_raster = G_define_standard_option(G_OPT_R3_INPUT);
+    opt->z_raster->key = "z_raster";
+    opt->z_raster->description =
+        _("Name of input 3D raster map to define Z coordinates");
+    opt->z_raster->required = NO;
+
+    opt->color_raster = G_define_standard_option(G_OPT_R3_INPUT);
+    opt->color_raster->key = "color_raster";
+    opt->color_raster->description =
+        _("Name of input 3D raster map to define category and color");
+    opt->color_raster->required = NO;
+
+    opt->xscale = G_define_option();
+    opt->xscale->key = "xscale";
+    opt->xscale->type = TYPE_DOUBLE;
+    opt->xscale->required = NO;
+    opt->xscale->answer = "1.0";
+    opt->xscale->description = _("Scale to apply to X axis");
+    opt->xscale->guisection = _("Transform");
+
+    opt->yscale = G_define_option();
+    opt->yscale->key = "yscale";
+    opt->yscale->type = TYPE_DOUBLE;
+    opt->yscale->required = NO;
+    opt->yscale->answer = "1.0";
+    opt->yscale->description = _("Scale to apply to Y axis");
+    opt->yscale->guisection = _("Transform");
+
+    opt->zscale = G_define_option();
+    opt->zscale->key = "zscale";
+    opt->zscale->type = TYPE_DOUBLE;
+    opt->zscale->required = NO;
+    opt->zscale->answer = "1.0";
+    opt->zscale->description = _("Scale to apply to Z axis");
+    opt->zscale->guisection = _("Transform");
+
+    flg->region_position = G_define_flag();
+    flg->region_position->key = 'w';
+    flg->region_position->label =
+        _("Place into the current region south-west corner");
+    flg->region_position->description =
+        _("The output coordinates will not represent the original values");
+    flg->region_position->guisection = _("Layout");
+
+    opt->position = G_define_standard_option(G_OPT_M_COORDS);
+    opt->position->key = "position";
+    opt->position->label =
+        _("Place to the given coordinates");
+    opt->position->description =
+        _("The output coordinates will not represent the original values");
+    opt->position->guisection = _("Layout");
+
+    flg->auto_offset = G_define_flag();
+    flg->auto_offset->key = 'f';
+    flg->auto_offset->label =
+        _("Automatically offset each scatter plot");
+    flg->auto_offset->description =
+        _("The output coordinates will not represent the original values");
+    flg->auto_offset->guisection = _("Layout");
+
+    opt->spacing = G_define_option();
+    opt->spacing->key = "spacing";
+    opt->spacing->type = TYPE_DOUBLE;
+    opt->spacing->required = NO;
+    opt->spacing->label = _("Spacing between scatter plots");
+    opt->spacing->description = _("Applied when automatic offset is used");
+    opt->spacing->guisection = _("Layout");
+
+    flg->one_layer = G_define_flag();
+    flg->one_layer->key = 's';
+    flg->one_layer->label = _("Put points into a single layer");
+    flg->one_layer->description =
+        _("Even with multiple rasters, put all points into a single layer");
+    flg->one_layer->guisection = _("Layout");
+
+    opt->vector_mask = G_define_standard_option(G_OPT_V_INPUT);
+    opt->vector_mask->key = "vector_mask";
+    opt->vector_mask->required = NO;
+    opt->vector_mask->label = _("Areas to use in the scatter plots");
+    opt->vector_mask->description =
+        _("Name of vector map with areas from where the scatter plot should be generated");
+    opt->vector_mask->guisection = _("Mask");
+
+    opt->vector_mask_field = G_define_standard_option(G_OPT_V_FIELD);
+    opt->vector_mask_field->key = "mask_layer";
+    opt->vector_mask_field->label = _("Layer number or name for vector mask");
+    opt->vector_mask_field->guisection = _("Mask");
+
+    opt->vector_mask_cats = G_define_standard_option(G_OPT_V_CATS);
+    opt->vector_mask_cats->key = "mask_cats";
+    opt->vector_mask_cats->label = _("Category values for vector mask");
+    opt->vector_mask_cats->guisection = _("Mask");
+
+    opt->vector_mask_where = G_define_standard_option(G_OPT_DB_WHERE);
+    opt->vector_mask_where->key = "mask_where";
+    opt->vector_mask_where->label = _("WHERE conditions for the vector mask");
+    opt->vector_mask_where->guisection = _("Mask");
+
+    flg->invert_mask = G_define_flag();
+    flg->invert_mask->key = 'u';
+    flg->invert_mask->description = _("Invert mask");
+    flg->invert_mask->guisection = _("Mask");
+
+    flg->notopo = G_define_standard_flag(G_FLG_V_TOPO);
+
+    G_option_requires(opt->spacing, flg->auto_offset, NULL);
+    G_option_exclusive(opt->position, flg->region_position, NULL);
+    G_option_requires(opt->vector_mask_field, opt->vector_mask, NULL);
+    G_option_requires(opt->vector_mask_cats, opt->vector_mask, NULL);
+    G_option_requires(opt->vector_mask_where, opt->vector_mask, NULL);
+    G_option_requires(flg->invert_mask, opt->vector_mask, NULL);
+}
+
+static void option_to_en(struct Option *option, double *easting, double *northing, struct Cell_head *region)
+{
+    if (!G_scan_easting(option->answers[0], easting, region->proj))
+        G_fatal_error(_("Invalid easting: %s"), option->answers[0]);
+    if (!G_scan_northing(option->answers[1], northing, region->proj))
+        G_fatal_error(_("Invalid northing: %s"), option->answers[1]);
+}
+
+static RASTER3D_Map *open_raster3d(char *name, RASTER3D_Region *region)
+{
+    RASTER3D_Map * map;
+
+    map = Rast3d_open_cell_old(name, G_find_raster3d(name, ""), region,
+                         RASTER3D_TILE_SAME_AS_FILE, RASTER3D_USE_CACHE_DEFAULT);
+    if (map == NULL)
+        Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"), name);
+    return map;
+}
+
+int main(int argc, char *argv[])
+{
+    struct ScatterOptions opt;
+    struct ScatterFlags flg;
+
+    G_gisinit(argv[0]);
+
+    define_parameters(&opt, &flg);
+
+    if (G_parser(argc, argv))
+        exit(EXIT_FAILURE);
+
+    double xscale = 1.0;
+    double yscale = 1.0;
+    double zscale = 1.0;
+
+    if (opt.xscale->answer)
+        xscale = atof(opt.xscale->answer);
+    if (opt.yscale->answer)
+        yscale = atof(opt.yscale->answer);
+    if (opt.zscale->answer)
+        zscale = atof(opt.zscale->answer);
+
+    double spacing = 0;
+
+    if (opt.spacing->answer)
+        spacing = atof(opt.spacing->answer);
+
+    double start_x = 0;
+    double start_y = 0;
+    struct Cell_head region_2d;
+
+    G_get_window(&region_2d);
+
+    if (flg.region_position->answer) {
+        start_x = region_2d.west;
+        start_y = region_2d.south;
+    }
+
+    if (opt.position->answer)
+        option_to_en(opt.position, &start_x, &start_y, &region_2d);
+
+    RASTER3D_Region region;
+
+    Rast3d_init_defaults();
+    Rast3d_get_window(&region);
+
+    struct Map_info output;
+    struct line_pnts *points;
+    struct line_cats *cats;
+
+    /* TODO: clean up the following code */
+    /* open output vector */
+    char buf[2000];
+    sprintf(buf, "%s", opt.output->answer);
+    /* strip any @mapset from vector output name */
+    G_find_vector(buf, G_mapset());
+    if (Vect_open_new(&output, opt.output->answer, 1) < 0)
+        G_fatal_error(_("Unable to create vector map <%s>"), opt.output->answer);
+    Vect_hist_command(&output);
+
+    points = Vect_new_line_struct();
+    cats = Vect_new_cats_struct();
+
+    int rows, cols, depths;
+    int col, row, depth;
+    char **name1, **name2;
+    DCELL x, y, z;
+    FCELL fcat;
+    int cat;
+    int layer;
+    /* actual geographical coordinates */
+    double xcoor, ycoor, unused;
+
+    double current_max_x = -HUGE_VAL;
+    double layer_x_offset = start_x;
+    double layer_y_offset = start_y;
+
+    z = 0;
+    cat = 1;
+    layer = 1;
+    rows = region.rows;
+    cols = region.cols;
+    depths = region.depths;
+    G_debug(1, "limits: r=%d c=%d d=%d", rows, cols, depths);
+
+    RASTER3D_Map *z_raster = NULL;
+    RASTER3D_Map *color_raster = NULL;
+
+    int n_inputs = 0;
+
+    for (name1 = opt.input->answers; *name1 != NULL; name1++) {
+        n_inputs++;
+        if (!G_find_raster3d(*name1, ""))
+            Rast3d_fatal_error(_("3D raster map <%s> not found"), *name1);
+    }
+
+    if (opt.color_raster->answer)
+        color_raster = open_raster3d(opt.color_raster->answer, &region);
+    if (opt.z_raster->answer)
+        z_raster = open_raster3d(opt.z_raster->answer, &region);
+
+    struct VectorMask vector_mask;
+    int use_vector_mask = FALSE;
+    if (opt.vector_mask->answer) {
+        VectorMask_init(&vector_mask, opt.vector_mask->answer,
+                        opt.vector_mask_field->answer,
+                        opt.vector_mask_cats->answer, opt.vector_mask_where->answer,
+                        flg.invert_mask->answer);
+        use_vector_mask = TRUE;
+    }
+
+    for (name1 = opt.input->answers; *name1 != NULL; name1++) {
+        for (name2 = opt.input->answers; *name2 != NULL; name2++) {
+            /* same name or used combination */
+            if (name1 >= name2)
+                continue;
+            /* report when relevant */
+            if (n_inputs > 2 && !flg.one_layer->answer)
+                G_message(_("Putting values from <%s> and <%s> into layer %d of <%s>"),
+                          *name1, *name2, layer, opt.output->answer);
+            G_debug(3, "save %s + %s to %d (%s)", *name1, *name2, layer, opt.output->answer);
+            RASTER3D_Map *map1 = open_raster3d(*name1, &region);
+            RASTER3D_Map *map2 = open_raster3d(*name2, &region);
+
+            for (row = 0; row < rows; row++) {
+                G_percent(row, rows, 1);
+                for (col = 0; col < cols; col++) {
+                    /* vector mask is expensive, so we first do 2D loops */
+                    if (use_vector_mask) {
+                            Rast3d_coord2location(&region, row + 0.5, col + 0.5, 0, &ycoor, &xcoor, &unused);
+                            if (!VectorMask_point_in(&vector_mask, xcoor, ycoor))
+                                continue;
+                    }
+                    for (depth = 0; depth < depths; depth++) {
+                        x = Rast3d_get_double(map1, col, row, depth);
+                        if (Rast_is_d_null_value(&x))
+                            continue;
+                        y = Rast3d_get_double(map2, col, row, depth);
+                        if (Rast_is_d_null_value(&y))
+                            continue;
+                        if (z_raster) {
+                            z = Rast3d_get_double(z_raster, col, row, depth);
+                            if (Rast_is_d_null_value(&z))
+                                continue;
+                        }
+                        if (color_raster) {
+                            fcat = Rast3d_get_float(color_raster, col, row, depth);
+                            if (Rast_is_d_null_value(&fcat))
+                                continue;
+                            cat = (int) fcat;
+                            /* TODO: what to do when value cannot be cat */
+                        }
+                        x *= xscale;
+                        y *= yscale;
+                        z *= zscale;
+                        x += layer_x_offset;
+                        y += layer_y_offset;
+                        if (current_max_x < x)
+                            current_max_x = x;
+                        Vect_cat_set(cats, layer, cat);
+                        Vect_append_point(points, x, y, z);
+                        //Vect_append_point(points, xcoor, ycoor, z);
+                        Vect_write_line(&output, GV_POINT, points, cats);
+                        Vect_reset_line(points);
+                        Vect_reset_cats(cats);
+                        /* TODO: we can determine cat == GV_CAT_MAX ahead and tell user what to do */
+                        cat++;
+                    }
+                }
+            }
+            G_percent(1, 1, 1);
+            if (!Rast3d_close(map1))
+                Rast3d_fatal_error(_("Unable to close 3D raster map"));
+            if (!Rast3d_close(map2))
+                Rast3d_fatal_error(_("Unable to close 3D raster map"));
+            if (!flg.one_layer->answer)
+                layer++;
+            if (flg.auto_offset->answer)
+                layer_x_offset = current_max_x + spacing;
+        }
+    }
+
+    Vect_destroy_line_struct(points);
+    Vect_destroy_cats_struct(cats);
+
+    if (color_raster) {
+        struct Colors colors;
+
+        Rast3d_read_colors(opt.color_raster->answer, G_find_raster3d(opt.color_raster->answer, ""), &colors);
+        Vect_write_colors(opt.output->answer, G_mapset(), &colors);
+    }
+
+    if (z_raster && !Rast3d_close(z_raster))
+        Rast3d_fatal_error(_("Unable to close 3D raster map"));
+    if (color_raster && !Rast3d_close(color_raster))
+        Rast3d_fatal_error(_("Unable to close 3D raster map"));
+
+    if (opt.vector_mask->answer) {
+        VectorMask_destroy(&vector_mask);
+    }
+
+    if (!flg.notopo->answer)
+        Vect_build(&output);
+    Vect_close(&output);
+
+    exit(EXIT_SUCCESS);
+}


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/main.c
___________________________________________________________________
Added: svn:mime-type
   + text/x-csrc
Added: svn:eol-style
   + native

Added: grass-addons/grass7/raster3d/r3.scatterplot/r3.scatterplot.html
===================================================================
--- grass-addons/grass7/raster3d/r3.scatterplot/r3.scatterplot.html	                        (rev 0)
+++ grass-addons/grass7/raster3d/r3.scatterplot/r3.scatterplot.html	2016-09-24 22:57:14 UTC (rev 69572)
@@ -0,0 +1,201 @@
+<h2>DESCRIPTION</h2>
+
+The <em>r3.scatterplot</em> module takes 3D raster maps and creates
+a scatter plot which is a vector map and where individual points in
+the scatter plot are vector points. As with any scatter plot the X
+coordinates of the points represent values from the first raster map
+and the Y coordinates represent values from the second raster map.
+Consequently, the vector map is placed in the combined value space of
+the original raster maps and its geographic position should be ignored.
+Typically, it is necessary to zoom or to change computational in order
+to view the scatter plot or to perform further computations on the result.
+
+<p>
+With the default settings, the <em>r3.scatterplot</em> output allows
+measuring and querying of the values in the scatter plot. Settings
+such as <b>xscale</b> or <b>position</b> option change the coordinates
+and make some of the measurements wrong.
+
+
+<h3>Multiple variables</h3>
+
+If more than two raster maps are provided to the <b>input</b> option,
+<em>r3.scatterplot</em> creates a scatter plot for each unique pair
+of input maps. For example, if A, B, C, and D are the inputs,
+<em>r3.scatterplot</em> creates scatter plots for A and B, A and C,
+A and D, B and C, B and D, and finally C and D. Each pair is part of
+different vector map layer. <em>r3.scatterplot</em> provides textual
+output which specifies the pairs and associated layers.
+
+<p>
+A 3D scatter plot can be generated when the <b>z_raster</b> option is
+provided. A third variable is added to each scatter plot and each point
+has Z coordinate which represents this third variable.
+
+<p>
+Each point can also have a color based on an additional variable
+based on the values from <b>color_raster</b>. Values from a raster are
+stored as categories, i.e. floating point values are truncated to
+integers, and a color table based on the input raster color table is
+assigned to the vector map.
+
+<p>
+The <b>z_raster</b> and <b>color_raster</b> can be the same. This can help
+with understanding the 3D scatter plot and makes the third variable
+visible in 2D as well.
+When <b>z_raster</b> and <b>color_raster</b> are the same, total of four
+variables are associated with one point.
+
+<center>
+<img src="r3_scatterplot_2_variables.png">
+<img src="r3_scatterplot_2_variables_3rd_color.png">
+<img src="r3_scatterplot_2_variables_3rd_z.png">
+<p><em>
+    Figure: One scatter plot of two variables (left),
+    the same scatter plot but with color showing third variable (middle),
+    again the same scatter plot in 3D where Z represents a third variable (right).
+</em></p>
+</center>
+
+<center>
+<img src="r3_scatterplot_2_variables_3rd_z_4th_color.png">
+<img src="r3_scatterplot_2_variables_3rd_z_4th_color2.png">
+<p><em>
+    Figure: One scatter plot in with one variable as Z coordinate and
+    another variable as color (two rotated views).
+</em></p>
+</center>
+
+
+<h3>Layout</h3>
+
+When working only with variable, X axis represents the first one
+and Y axis the second one. With more than one variable, the individual
+scatter plots for individual pairs of variables are at the same
+place. In this case, the coordinates show the actual values of the
+variables. Each scatter plot is placed into a separate layer of
+the output vector map.
+
+<center>
+<img src="r3_scatterplot_3_variables_3_colors_overlap.png">
+<p><em>
+    Figure: Three overlapping scatter plots of three variables A, B, and C.
+    Individual scatter plots are distinguished by color.
+    The colors can be obtained using <tt>d.vect layer=-1 -c</tt>.
+</em></p>
+</center>
+
+<p>
+If visualization is more important than preserving the actual values,
+the <b>-s</b> flag can be used. This will place the scatter plots next
+to each other separated by values provided using <b>spacing</b> option.
+
+<p>
+The layout options can be still combined with additional variables
+represented as Z coordinate or color. In that case, Z coordinate
+or color is same for all the scatter plots.
+
+<center>
+<img src="r3_scatterplot_3_variables_3_colors.png">
+<p><em>
+    Figure: Three scatter plots of three variables A, B, and C.
+    First one is A and B, second A and C, and third B and C.
+</em></p>
+</center>
+
+<center>
+<img src="r3_scatterplot_3_variables.png">
+<p><em>
+    Figure: Three scatter plots of three variables A, B, and C
+    with color showing a fourth variable D in all scatter plots.
+</em></p>
+</center>
+
+The options <b>xscale</b>, <b>yscale</b> and <b>zscale</b> will cause
+the values to be rescaled before they are stored as point coordinates.
+This is useful for visualization when one of the variables has
+significantly different range than the other or when the scatter plot
+is shown with other data and must fit a certain area.
+
+The <b>position</b> option is used to place the scatter plot to any
+given coordinates. Similarly, <b>-w</b> flag can be used to place it
+to the south-west corner of the computation region.
+
+
+<h2>NOTES</h2>
+
+<p>
+The resulting vector will have as many points as there is 3D raster
+cells in the current computational region. It might be appropriate to
+use coarser resolution for the scatter plot than for the other
+computations. However, note that the some values will be skipped
+which may lead, e.g. to missing some outliers.
+
+<p>
+The <b>color_raster</b> input is expected to be categorical raster
+or have values which won't loose anything when converted from floating
+point to integer. This is because vector categories are used to store
+the <b>color_raster</b> values and carry association with the color.
+
+<p>
+The visualization of the output vector map has potentially the same
+issue as visualization of any vector with many points. The points
+cover each other and above certain density of points, it is not possible
+to compare relative density in the scatter plot. Furthermore, if colors
+are associated with the points, the colors of points rendered last are
+those which are visible, not actually showing the prevailing color
+(value). The modules <em><a href="v.mkgrid.html">v.mkgrid</a></em> and
+<em><a href="v.vect.stats.html">v.vect.stats</a></em> can be used to
+overcome this issue.
+
+<h2>EXAMPLES</h2>
+
+<h3>Example with generated data</h3>
+
+Set the computational region for generating data and subsequent
+analysis:
+
+<div class="code"><pre>
+g.region s=0 n=100 w=0 e=100 b=0 t=50 res=10 res3=10 tbres=1 -p3
+</pre></div>
+
+Generate data using raster algebra:
+
+<div class="code"><pre>
+r3.mapcalc "A = if(depth() < ndepths()/ 2,  row()+col()+depth(), col())" -s
+r3.mapcalc "B = if(row() < nrows()/2, rand(0, nrows()) + col() + depth(), depth() + rand(0, nrows()))" -s
+r3.mapcalc "C = if(col() < ncols()/3, row() + depth(), rand(0, ncols()))" -s
+r3.mapcalc "D = depth()"
+</pre></div>
+
+Create a scatter plot of correlations between A and B.
+Use C for the Z axes (height) and D for the color.
+
+<div class="code"><pre>
+r3.scatterplot input=A,B output=scatterplot z_raster=C color_raster=D
+</pre></div>
+
+<center>
+<img src="r3_scatterplot_2d.png">
+<img src="r3_scatterplot.png">
+<p><em>
+    Figure: 2D scatter plot showing third variable as color
+    and 3D scatter plot showing third variable as color and fourth variable on Z axis
+    which uncovers another group of values not visible from the 2D scatter plot
+</em></p>
+</center>
+
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r3.stats.html">r3.stats</a>,
+<a href="d.correlate.html">d.correlate</a>,
+<a href="v.mkgrid.html">v.mkgrid</a>,
+<a href="v.vect.stats.html">v.vect.stats</a>,
+<a href="g.region.html">g.region</a>
+</em>
+
+<h2>AUTHOR</h2>
+
+Vaclav Petras, <a href="http://geospatial.ncsu.edu/osgeorel/">NCSU GeoForAll Lab</a>


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/r3.scatterplot.html
___________________________________________________________________
Added: svn:mime-type
   + text/html
Added: svn:keywords
   + Author Date Id
Added: svn:eol-style
   + native

Added: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables_3rd_color.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables_3rd_color.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables_3rd_z.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables_3rd_z.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables_3rd_z_4th_color.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables_3rd_z_4th_color.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables_3rd_z_4th_color2.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2_variables_3rd_z_4th_color2.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2d.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_2d.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_3_variables.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_3_variables.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_3_variables_3_colors.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_3_variables_3_colors.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_3_variables_3_colors_overlap.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/raster3d/r3.scatterplot/r3_scatterplot_3_variables_3_colors_overlap.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Copied: grass-addons/grass7/raster3d/r3.scatterplot/vector_mask.c (from rev 69545, grass/trunk/vector/v.in.lidar/vector_mask.c)
===================================================================
--- grass-addons/grass7/raster3d/r3.scatterplot/vector_mask.c	                        (rev 0)
+++ grass-addons/grass7/raster3d/r3.scatterplot/vector_mask.c	2016-09-24 22:57:14 UTC (rev 69572)
@@ -0,0 +1,102 @@
+/*
+ * v.in.lidar vector mask
+ *
+ * Copyright 2016 by Vaclav Petras, and The GRASS Development Team
+ *
+ * This program is free software licensed under the GPL (>=v2).
+ * Read the COPYING file that comes with GRASS for details.
+ *
+ */
+
+#include <grass/vector.h>
+#include <grass/glocale.h>
+
+#include "vector_mask.h"
+
+void VectorMask_init(struct VectorMask *vector_mask, const char *name,
+                     const char *layer, char *cats, char *where,
+                     int invert_mask)
+{
+    vector_mask->map_info = G_malloc(sizeof(struct Map_info));
+    if (Vect_open_old2(vector_mask->map_info, name, "", layer) < 2)
+        G_fatal_error(_("Failed to open vector <%s>"), name);
+    vector_mask->cats = NULL;
+    vector_mask->layer = Vect_get_field_number(vector_mask->map_info, layer);
+    if (vector_mask->layer > 0 && (cats || where))
+        vector_mask->cats = Vect_cats_set_constraint(vector_mask->map_info, vector_mask->layer,
+                                                     where, cats);
+    vector_mask->map_bbox = G_malloc(sizeof(struct bound_box));
+    Vect_get_map_box(vector_mask->map_info, vector_mask->map_bbox);
+    vector_mask->nareas = Vect_get_num_areas(vector_mask->map_info);
+    vector_mask->area_bboxes = G_malloc(vector_mask->nareas * sizeof(struct bound_box));
+    vector_mask->area_cats = G_malloc(vector_mask->nareas * sizeof(struct line_cats *));
+    int i;
+    struct line_cats *area_cats;
+    for (i = 1; i <= vector_mask->nareas; i++) {
+        Vect_get_area_box(vector_mask->map_info, i, &vector_mask->area_bboxes[i - 1]);
+        if (vector_mask->cats) {
+            /* it would be nice to allocate whole list at once
+             * with a library function */
+            area_cats = Vect_new_cats_struct();
+            /* getting the cats ahead of time cuts the time to less
+             * than half for maps with many areas */
+            Vect_get_area_cats(vector_mask->map_info, i, area_cats);
+            vector_mask->area_cats[i - 1] = area_cats;
+        }
+    }
+    G_debug(3, "VectorMask_init(): loaded %d areas", vector_mask->nareas);
+    if (invert_mask)
+        vector_mask->inverted = 1;
+    else
+        vector_mask->inverted = 0;
+}
+
+void VectorMask_destroy(struct VectorMask *vector_mask)
+{
+    if (vector_mask->cats) {
+        int i;
+        for (i = 1; i <= vector_mask->nareas; i++) {
+            Vect_destroy_cats_struct(vector_mask->area_cats[i - 1]);
+        }
+    }
+    G_free(vector_mask->area_cats);
+    G_free(vector_mask->map_bbox);
+    G_free(vector_mask->area_bboxes);
+    Vect_close(vector_mask->map_info);
+    G_free(vector_mask->map_info);
+}
+
+int VectorMask_point_in(struct VectorMask *vector_mask, double x, double y)
+{
+    /* inv in res
+     *   F  T continue
+     *   F  F return F
+     *   T  T continue
+     *   T  F return T
+     */
+    //if (!Vect_point_in_box_2d(x, y, vector_mask->map_bbox))
+    //    return vector_mask->inverted;
+    int is_out = TRUE;
+    int i;
+    for (i = 1; i <= vector_mask->nareas; i++) {
+        if (vector_mask->cats) {
+            /* the same as if the area would not exist */
+            if (!Vect_cats_in_constraint(vector_mask->area_cats[i - 1],
+                                         vector_mask->layer, vector_mask->cats))
+                continue;
+        }
+        if (Vect_point_in_area(x, y, vector_mask->map_info, i, &vector_mask->area_bboxes[i - 1])) {
+            is_out = FALSE;
+            break;
+        }
+    }
+    /* inv out res
+     *  F   T   F
+     *  F   F   T
+     *  T   T   T
+     *  T   F   F
+     */
+    if (vector_mask->inverted ^ is_out)
+        return FALSE;
+    return TRUE;
+}

Copied: grass-addons/grass7/raster3d/r3.scatterplot/vector_mask.h (from rev 69545, grass/trunk/vector/v.in.lidar/vector_mask.h)
===================================================================
--- grass-addons/grass7/raster3d/r3.scatterplot/vector_mask.h	                        (rev 0)
+++ grass-addons/grass7/raster3d/r3.scatterplot/vector_mask.h	2016-09-24 22:57:14 UTC (rev 69572)
@@ -0,0 +1,39 @@
+
+/****************************************************************************
+ *
+ * MODULE:       v.in.lidar
+ * AUTHOR(S):    Vaclav Petras
+ * PURPOSE:      vector mask
+ * COPYRIGHT:    (C) 2015 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the COPYING file that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
+
+
+#ifndef VECTOR_MASK_H
+#define VECTOR_MASK_H
+
+struct Map_info;
+struct bound_box;
+
+struct VectorMask {
+    struct Map_info *map_info;
+    struct cat_list *cats;
+    struct line_cats **area_cats;
+    int layer;
+    struct bound_box *map_bbox;
+    struct bound_box *area_bboxes;
+    int nareas;
+    int inverted;
+};
+
+void VectorMask_init(struct VectorMask *vector_mask, const char *name,
+                     const char *layer, char *cats, char *where,
+                     int invert_mask);
+void VectorMask_destroy(struct VectorMask *vector_mask);
+int VectorMask_point_in(struct VectorMask *vector_mask, double x, double y);
+
+#endif /* VECTOR_MASK_H */



More information about the grass-commit mailing list