[GRASS-SVN] r57645 - sandbox/turek/scatter_plot
svn_grass at osgeo.org
svn_grass at osgeo.org
Thu Sep 12 03:44:50 PDT 2013
Author: turek
Date: 2013-09-12 03:44:50 -0700 (Thu, 12 Sep 2013)
New Revision: 57645
Modified:
sandbox/turek/scatter_plot/testing_patch.diff
Log:
bugs fixing
Modified: sandbox/turek/scatter_plot/testing_patch.diff
===================================================================
--- sandbox/turek/scatter_plot/testing_patch.diff 2013-09-12 07:27:23 UTC (rev 57644)
+++ sandbox/turek/scatter_plot/testing_patch.diff 2013-09-12 10:44:50 UTC (rev 57645)
@@ -1,428 +1,3 @@
-Index: lib/vector/Vlib/open.c
-===================================================================
---- lib/vector/Vlib/open.c (revision 57633)
-+++ lib/vector/Vlib/open.c (working copy)
-@@ -240,7 +240,9 @@
- }
- else {
- char file_path[GPATH_MAX];
--
-+ /* reduce to current mapset if search path was set */
-+ if(strcmp(Map->mapset, "") == 0)
-+ Map->mapset = G_store(G_mapset());
- /* temporary map: reduce to current mapset if search path
- * was set */
- if (strcmp(Map->mapset, "") == 0)
-Index: lib/imagery/scatt_sccats.c
-===================================================================
---- lib/imagery/scatt_sccats.c (revision 0)
-+++ lib/imagery/scatt_sccats.c (working copy)
-@@ -0,0 +1,405 @@
-+/*!
-+ \file lib/imagery/scatt_cat_rast.c
-+
-+ \brief Imagery library - functions for manipulation with scatter plot structs.
-+
-+ Copyright (C) 2013 by the GRASS Development Team
-+
-+ This program is free software under the GNU General Public License
-+ (>=v2). Read the file COPYING that comes with GRASS for details.
-+
-+ \author Stepan Turek <stepan.turek at seznam.cz> (Mentor: Martin Landa)
-+ */
-+
-+#include <grass/raster.h>
-+#include <grass/imagery.h>
-+#include <grass/gis.h>
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <math.h>
-+#include <string.h>
-+
-+/*!
-+ \brief Compute band ids from scatter plot id.
-+
-+ Scatter plot id describes which bands defines the scatter plot.
-+
-+ Let say we have 3 bands, their ids are 0, 1 and 2.
-+ Scatter plot with id 0 consists of band 1 (b_1_id) 0 and band 2 (b_2_id) 1.
-+ All scatter plots:
-+ scatt_id b_1_id b_2_id
-+ 0 0 1
-+ 1 0 2
-+ 2 1 2
-+
-+ \param scatt_id scatter plot id
-+ \param n_bands number of bands
-+ \param [out] b_1_id id of band1
-+ \param[out] b_2_id id of band2
-+
-+ \return 0
-+ */
-+int I_id_scatt_to_bands(const int scatt_id, const int n_bands, int * b_1_id, int * b_2_id)
-+{
-+ int n_b1 = n_bands - 1;
-+
-+ * b_1_id = (int) ((2 * n_b1 + 1 - sqrt((double)((2 * n_b1 + 1) * (2 * n_b1 + 1) - 8 * scatt_id))) / 2);
-+
-+ * b_2_id = scatt_id - ((* b_1_id) * (2 * n_b1 + 1) - (* b_1_id) * (* b_1_id)) / 2 + (* b_1_id) + 1;
-+
-+ return 0;
-+}
-+
-+
-+/*!
-+ \brief Compute scatter plot id from band ids.
-+
-+ See also I_id_scatt_to_bands().
-+
-+ \param n_bands number of bands
-+ \param b_1_id id of band1
-+ \param b_1_id id of band2
-+ \param [out] scatt_id scatter plot id
-+
-+ \return 0
-+ */
-+int I_bands_to_id_scatt(const int b_1_id, const int b_2_id, const int n_bands, int * scatt_id)
-+{
-+ int n_b1 = n_bands - 1;
-+
-+ * scatt_id = (b_1_id * (2 * n_b1 + 1) - b_1_id * b_1_id) / 2 + b_2_id - b_1_id - 1;
-+
-+ return 0;
-+}
-+
-+/*!
-+ \brief Initialize structure for storing scatter plots data.
-+
-+ \param cats pointer to scCats struct
-+ \param n_bands number of bands
-+ \param type SC_SCATT_DATA - stores scatter plots
-+ \param type SC_SCATT_CONDITIONS - stores selected areas in scatter plots
-+ */
-+void I_sc_init_cats(struct scCats * cats, int n_bands, int type)
-+{
-+ int i_cat;
-+
-+ cats->type = type;
-+
-+ cats->n_cats = 100;
-+ cats->n_a_cats = 0;
-+
-+ cats->n_bands = n_bands;
-+ cats->n_scatts = (n_bands - 1) * n_bands / 2;
-+
-+ cats->cats_arr = (struct scScatts **) G_malloc(cats->n_cats * sizeof(struct scScatts *));
-+ memset(cats->cats_arr, 0, cats-> n_cats * sizeof(struct scScatts *));
-+
-+ cats->cats_ids = (int *) G_malloc(cats->n_cats * sizeof(int));
-+ cats->cats_idxs =(int *) G_malloc(cats->n_cats * sizeof(int));
-+
-+ for(i_cat = 0; i_cat < cats->n_cats; i_cat++)
-+ cats->cats_idxs[i_cat] = -1;
-+
-+ return;
-+}
-+
-+/*!
-+ \brief Free data of struct scCats, the structure itself remains alocated.
-+
-+ \param cats pointer to existing scCats struct
-+ */
-+void I_sc_free_cats(struct scCats * cats)
-+{
-+ int i_cat;
-+
-+ for(i_cat = 0; i_cat < cats->n_a_cats; i_cat++)
-+ {
-+ if(cats->cats_arr[i_cat])
-+ {
-+ G_free(cats->cats_arr[i_cat]->scatt_idxs);
-+ G_free(cats->cats_arr[i_cat]->scatts_bands);
-+ G_free(cats->cats_arr[i_cat]->scatts_arr);
-+ G_free(cats->cats_arr[i_cat]);
-+ }
-+ }
-+
-+ G_free(cats->cats_ids);
-+ G_free(cats->cats_idxs);
-+ G_free(cats->cats_arr);
-+
-+ cats->n_cats = 0;
-+ cats->n_a_cats = 0;
-+ cats->n_bands = 0;
-+ cats->n_scatts = 0;
-+ cats->type = -1;
-+
-+ return;
-+}
-+
-+#if 0
-+void I_sc_get_active_categories(int * a_cats_ids, int * n_a_cats, struct scCats * cats)
-+{
-+ a_cats_ids = cats->cats_ids;
-+ * n_a_cats = cats->n_a_cats;
-+}
-+#endif
-+
-+/*!
-+ \brief Add category.
-+
-+ Category represents group of scatter plots.
-+
-+ \param cats pointer to scCats struct
-+
-+ \return assigned category id (starts with 0)
-+ \return -1 if maximum nuber of categories was reached
-+ */
-+int I_sc_add_cat(struct scCats * cats)
-+{
-+ int i_scatt, i_cat_id, cat_id;
-+ int n_a_cats = cats->n_a_cats;
-+
-+ if(cats->n_a_cats >= cats->n_cats)
-+ return -1;
-+
-+ for(i_cat_id = 0; i_cat_id < cats->n_cats; i_cat_id++)
-+ if(cats->cats_idxs[i_cat_id] < 0) {
-+ cat_id = i_cat_id;
-+ break;
-+ }
-+
-+ cats->cats_ids[n_a_cats] = cat_id;
-+ cats->cats_idxs[cat_id] = n_a_cats;
-+
-+ cats->cats_arr[n_a_cats] = (struct scScatts *) G_malloc(sizeof(struct scScatts));
-+
-+ cats->cats_arr[n_a_cats]->scatts_arr = (struct scdScattData **) G_malloc(cats->n_scatts * sizeof(struct scdScattData *));
-+ memset((cats->cats_arr[n_a_cats]->scatts_arr), 0, cats->n_scatts * sizeof(struct scdScattData *));
-+
-+ cats->cats_arr[n_a_cats]->n_a_scatts = 0;
-+
-+ cats->cats_arr[n_a_cats]->scatts_bands = (int *) G_malloc(cats->n_scatts * 2 * sizeof(int));
-+
-+ cats->cats_arr[n_a_cats]->scatt_idxs = (int *) G_malloc(cats->n_scatts * sizeof(int));
-+ for(i_scatt = 0; i_scatt < cats->n_scatts; i_scatt++)
-+ cats->cats_arr[n_a_cats]->scatt_idxs[i_scatt] = -1;
-+
-+ ++cats->n_a_cats;
-+
-+ return cat_id;
-+}
-+
-+#if 0
-+int I_sc_delete_cat(struct scCats * cats, int cat_id)
-+{
-+ int cat_idx, i_cat;
-+
-+ if(cat_id < 0 || cat_id >= cats->n_cats)
-+ return -1;
-+
-+ cat_idx = cats->cats_idxs[cat_id];
-+ if(cat_idx < 0)
-+ return -1;
-+
-+ G_free(cats->cats_arr[cat_idx]->scatt_idxs);
-+ G_free(cats->cats_arr[cat_idx]->scatts_bands);
-+ G_free(cats->cats_arr[cat_idx]->scatts_arr);
-+ G_free(cats->cats_arr[cat_idx]);
-+
-+ for(i_cat = cat_idx; i_cat < cats->n_a_cats - 1; i_cat++)
-+ {
-+ cats->cats_arr[i_cat] = cats->cats_arr[i_cat + 1];
-+ cats->cats_ids[i_cat] = cats->cats_ids[i_cat + 1];
-+ }
-+ cats->cats_idxs[cat_id] = -1;
-+
-+ --cats->n_a_cats;
-+
-+ return 0;
-+}
-+#endif
-+
-+/*!
-+ \brief Insert scatter plot data .
-+ Inserted scatt_data struct must have same type as cats struct (SC_SCATT_DATA or SC_SCATT_CONDITIONS).
-+
-+ \param cats pointer to scCats struct
-+ \param cat_id id number of category.
-+ \param scatt_id id number of scatter plot.
-+
-+ \return 0 on success
-+ \return -1 on failure
-+ */
-+int I_sc_insert_scatt_data(struct scCats * cats, struct scdScattData * scatt_data, int cat_id, int scatt_id)
-+{
-+ int band_1, band_2, cat_idx, n_a_scatts;
-+ struct scScatts * scatts;
-+
-+ if(cat_id < 0 || cat_id >= cats->n_cats)
-+ return -1;
-+
-+ cat_idx = cats->cats_idxs[cat_id];
-+ if(cat_idx < 0)
-+ return -1;
-+
-+ if(scatt_id < 0 && scatt_id >= cats->n_scatts)
-+ return -1;
-+
-+ scatts = cats->cats_arr[cat_idx];
-+ if(scatts->scatt_idxs[scatt_id] >= 0)
-+ return -1;
-+
-+ if(!scatt_data->b_conds_arr && cats->type == SC_SCATT_CONDITIONS)
-+ return -1;
-+
-+ if(!scatt_data->scatt_vals_arr && cats->type == SC_SCATT_DATA)
-+ return -1;
-+
-+ n_a_scatts = scatts->n_a_scatts;
-+
-+ scatts->scatt_idxs[scatt_id] = n_a_scatts;
-+
-+ I_id_scatt_to_bands(scatt_id, cats->n_bands, &band_1, &band_2);
-+
-+ scatts->scatts_bands[n_a_scatts * 2] = band_1;
-+ scatts->scatts_bands[n_a_scatts * 2 + 1] = band_2;
-+
-+ scatts->scatts_arr[n_a_scatts] = scatt_data;
-+ ++scatts->n_a_scatts;
-+
-+ return 0;
-+}
-+
-+#if 0
-+int I_sc_remove_scatt_data(struct scCats * cats, struct scdScattData * scatt_data, int cat_id, int scatt_id)
-+{
-+ int cat_idx, scatt_idx, n_init_scatts, i_scatt;
-+ struct scScatts * scatts;
-+
-+ if(cat_id < 0 && cat_id >= cats->n_cats)
-+ return -1;
-+
-+ cat_idx = cats->cats_idxs[cat_id];
-+ if(cat_idx < 0)
-+ return -1;
-+
-+ if(scatt_id < 0 || scatt_id >= cats->n_scatts)
-+ return -1;
-+
-+ scatts = cats->cats_arr[cat_idx];
-+ if(scatts->scatt_idxs[scatt_id] < 0)
-+ return -1;
-+
-+ scatt_data = scatts->scatts_arr[scatt_idx];
-+
-+ for(i_scatt = scatt_idx; i_scatt < scatts->n_a_scatts - 1; i_scatt++)
-+ {
-+ scatts->scatts_arr[i_scatt] = scatts->scatts_arr[i_scatt + 1];
-+ scatts->scatts_bands[i_scatt * 2] = scatts->scatts_bands[(i_scatt + 1)* 2];
-+ scatts->scatts_bands[i_scatt * 2 + 1] = scatts->scatts_bands[(i_scatt + 1) * 2 + 1];
-+ }
-+ scatts->scatts_arr[scatts->n_a_scatts] = NULL;
-+
-+ scatts->scatt_idxs[scatt_id] = -1;
-+
-+ scatt_data = scatts->scatts_arr[scatt_id];
-+ scatts->n_a_scatts--;
-+
-+ return 0;
-+}
-+
-+int I_sc_set_value(struct scCats * cats, int cat_id, int scatt_id, int value_idx, int value)
-+{
-+ int n_a_scatts = cats->cats_arr[cat_id]->n_a_scatts;
-+ int cat_idx, scatt_idx, ret;
-+
-+ cat_idx = cats->cats_idxs[cat_id];
-+ if(cat_idx < 0)
-+ return -1;
-+
-+ if(cats->cats_arr[cat_idx]->scatt_idxs[scatt_id] < 0)
-+ return -1;
-+
-+ cat_idx = cats->cats_idxs[cat_id];
-+ scatt_idx = cats->cats_arr[cat_idx]->scatt_idxs[scatt_id];
-+
-+ I_scd_set_value(cats->cats_arr[cat_idx]->scatts_arr[scatt_idx], value_idx, value);
-+
-+ return 0;
-+}
-+#endif
-+
-+/*!
-+ \brief Insert scatter plot data.
-+
-+ \param scatt_data pointer to existing struct scdScattData
-+ \param type SC_SCATT_DATA for scatter plots or SC_SCATT_CONDITIONS for selected areas in scatter plot
-+ \param n_vals number of data values
-+ \param data array of values (unsigned char for SC_SCATT_CONDITIONS, unsigned int for SC_SCATT_DATA)
-+ */
-+void I_scd_init_scatt_data(struct scdScattData * scatt_data, int type, int n_vals, void * data)
-+{
-+ scatt_data->n_vals = n_vals;
-+
-+ if(type == SC_SCATT_DATA)
-+ {
-+ if(data)
-+ scatt_data->scatt_vals_arr = (unsigned int *) data;
-+ else {
-+ scatt_data->scatt_vals_arr = (unsigned int *) G_malloc(n_vals * sizeof(unsigned int));
-+ memset(scatt_data->scatt_vals_arr, 0, n_vals * sizeof(unsigned int));
-+ }
-+ scatt_data->b_conds_arr = NULL;
-+ }
-+ else if(type == SC_SCATT_CONDITIONS)
-+ {
-+ if(data)
-+ scatt_data->b_conds_arr = (unsigned char *) data;
-+ else {
-+ scatt_data->b_conds_arr = (unsigned char *) G_malloc(n_vals * sizeof(unsigned char));
-+ memset(scatt_data->b_conds_arr, 0, n_vals * sizeof(unsigned char));
-+ }
-+ scatt_data->scatt_vals_arr = NULL;
-+ }
-+
-+ return;
-+}
-+
-+
-+#if 0
-+void I_scd_get_range_min_max(struct scdScattData * scatt_data, CELL * band_1_min, CELL * band_1_max, CELL * band_2_min, CELL * band_2_max)
-+{
-+
-+ Rast_get_range_min_max(&(scatt_data->band_1_range), band_1_min, band_2_min);
-+ Rast_get_range_min_max(&(scatt_data->band_2_range), band_2_min, band_2_max);
-+
-+ return;
-+}
-+s
-+void * I_scd_get_data_ptr(struct scdScattData * scatt_data)
-+{
-+ if(!scatt_data->b_conds_arr)
-+ return scatt_data->b_conds_arr;
-+ else if(!scatt_data->scatt_vals_arr)
-+ return scatt_data->scatt_vals_arr;
-+
-+ return NULL;
-+}
-+
-+int I_scd_set_value(struct scdScattData * scatt_data, unsigned int val_idx, unsigned int val)
-+{
-+ if(val_idx < 0 && val_idx > scatt_data->n_vals)
-+ return -1;
-+
-+ if(scatt_data->b_conds_arr)
-+ scatt_data->b_conds_arr[val_idx] = val;
-+ else if(scatt_data->scatt_vals_arr)
-+ scatt_data->scatt_vals_arr[val_idx] = val;
-+ else
-+ return -1;
-+
-+ return 0;
-+}
-+#endif
Index: lib/imagery/scatt.c
===================================================================
--- lib/imagery/scatt.c (revision 0)
@@ -1227,70 +802,434 @@
+ }
+ return 0;
+}
-Index: include/imagery.h
+Index: lib/imagery/scatt_sccats.c
===================================================================
---- include/imagery.h (revision 57633)
-+++ include/imagery.h (working copy)
-@@ -135,6 +135,56 @@
-
- } IClass_statistics;
-
-+/* Scatter Plot backend */
+--- lib/imagery/scatt_sccats.c (revision 0)
++++ lib/imagery/scatt_sccats.c (working copy)
+@@ -0,0 +1,405 @@
++/*!
++ \file lib/imagery/scatt_cat_rast.c
+
-+#define SC_SCATT_DATA 0
-+#define SC_SCATT_CONDITIONS 1
++ \brief Imagery library - functions for manipulation with scatter plot structs.
+
++ Copyright (C) 2013 by the GRASS Development Team
+
-+/*! Holds list of all catagories.
-+ It can contain selected areas for scatter plots (SC_SCATT_CONDITIONS type) or computed scatter plots (SC_SCATT_DATA type).
-+*/
-+struct scCats
++ This program is free software under the GNU General Public License
++ (>=v2). Read the file COPYING that comes with GRASS for details.
++
++ \author Stepan Turek <stepan.turek at seznam.cz> (Mentor: Martin Landa)
++ */
++
++#include <grass/raster.h>
++#include <grass/imagery.h>
++#include <grass/gis.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <math.h>
++#include <string.h>
++
++/*!
++ \brief Compute band ids from scatter plot id.
++
++ Scatter plot id describes which bands defines the scatter plot.
++
++ Let say we have 3 bands, their ids are 0, 1 and 2.
++ Scatter plot with id 0 consists of band 1 (b_1_id) 0 and band 2 (b_2_id) 1.
++ All scatter plots:
++ scatt_id b_1_id b_2_id
++ 0 0 1
++ 1 0 2
++ 2 1 2
++
++ \param scatt_id scatter plot id
++ \param n_bands number of bands
++ \param [out] b_1_id id of band1
++ \param[out] b_2_id id of band2
++
++ \return 0
++ */
++int I_id_scatt_to_bands(const int scatt_id, const int n_bands, int * b_1_id, int * b_2_id)
++{
++ int n_b1 = n_bands - 1;
++
++ * b_1_id = (int) ((2 * n_b1 + 1 - sqrt((double)((2 * n_b1 + 1) * (2 * n_b1 + 1) - 8 * scatt_id))) / 2);
++
++ * b_2_id = scatt_id - ((* b_1_id) * (2 * n_b1 + 1) - (* b_1_id) * (* b_1_id)) / 2 + (* b_1_id) + 1;
++
++ return 0;
++}
++
++
++/*!
++ \brief Compute scatter plot id from band ids.
++
++ See also I_id_scatt_to_bands().
++
++ \param n_bands number of bands
++ \param b_1_id id of band1
++ \param b_1_id id of band2
++ \param [out] scatt_id scatter plot id
++
++ \return 0
++ */
++int I_bands_to_id_scatt(const int b_1_id, const int b_2_id, const int n_bands, int * scatt_id)
++{
++ int n_b1 = n_bands - 1;
++
++ * scatt_id = (b_1_id * (2 * n_b1 + 1) - b_1_id * b_1_id) / 2 + b_2_id - b_1_id - 1;
++
++ return 0;
++}
++
++/*!
++ \brief Initialize structure for storing scatter plots data.
++
++ \param cats pointer to scCats struct
++ \param n_bands number of bands
++ \param type SC_SCATT_DATA - stores scatter plots
++ \param type SC_SCATT_CONDITIONS - stores selected areas in scatter plots
++ */
++void I_sc_init_cats(struct scCats * cats, int n_bands, int type)
+{
-+ int type; /*!< SC_SCATT_DATA -> computed scatter plots, SC_SCATT_CONDITIONS -> set conditions for scatter plots to be computed*/
++ int i_cat;
+
-+ int n_cats; /*!< number of alocated categories */
++ cats->type = type;
++
++ cats->n_cats = 100;
++ cats->n_a_cats = 0;
++
++ cats->n_bands = n_bands;
++ cats->n_scatts = (n_bands - 1) * n_bands / 2;
++
++ cats->cats_arr = (struct scScatts **) G_malloc(cats->n_cats * sizeof(struct scScatts *));
++ memset(cats->cats_arr, 0, cats-> n_cats * sizeof(struct scScatts *));
++
++ cats->cats_ids = (int *) G_malloc(cats->n_cats * sizeof(int));
++ cats->cats_idxs =(int *) G_malloc(cats->n_cats * sizeof(int));
++
++ for(i_cat = 0; i_cat < cats->n_cats; i_cat++)
++ cats->cats_idxs[i_cat] = -1;
++
++ return;
++}
++
++/*!
++ \brief Free data of struct scCats, the structure itself remains alocated.
++
++ \param cats pointer to existing scCats struct
++ */
++void I_sc_free_cats(struct scCats * cats)
++{
++ int i_cat;
++
++ for(i_cat = 0; i_cat < cats->n_a_cats; i_cat++)
++ {
++ if(cats->cats_arr[i_cat])
++ {
++ G_free(cats->cats_arr[i_cat]->scatt_idxs);
++ G_free(cats->cats_arr[i_cat]->scatts_bands);
++ G_free(cats->cats_arr[i_cat]->scatts_arr);
++ G_free(cats->cats_arr[i_cat]);
++ }
++ }
++
++ G_free(cats->cats_ids);
++ G_free(cats->cats_idxs);
++ G_free(cats->cats_arr);
++
++ cats->n_cats = 0;
++ cats->n_a_cats = 0;
++ cats->n_bands = 0;
++ cats->n_scatts = 0;
++ cats->type = -1;
++
++ return;
++}
++
++#if 0
++void I_sc_get_active_categories(int * a_cats_ids, int * n_a_cats, struct scCats * cats)
++{
++ a_cats_ids = cats->cats_ids;
++ * n_a_cats = cats->n_a_cats;
++}
++#endif
++
++/*!
++ \brief Add category.
+
-+ int n_bands; /*!< number of analyzed bands */
-+ int n_scatts; /*!< number of possible scattter plot which can be created from bands */
++ Category represents group of scatter plots.
+
-+ int n_a_cats; /*!< number of used/active categories */
-+ int * cats_ids; /*!< (cat_idx->cat_id) array index is internal idx (position in cats_arr) and id is saved in it's position*/
-+ int * cats_idxs; /*!< (cat_id->cat_idx) array index is id and internal idx is saved in it's position*/
++ \param cats pointer to scCats struct
+
-+ struct scScatts ** cats_arr; /*!< array of pointers to struct scScatts */
-+};
++ \return assigned category id (starts with 0)
++ \return -1 if maximum nuber of categories was reached
++ */
++int I_sc_add_cat(struct scCats * cats)
++{
++ int i_scatt, i_cat_id, cat_id;
++ int n_a_cats = cats->n_a_cats;
+
++ if(cats->n_a_cats >= cats->n_cats)
++ return -1;
+
-+/*! Holds list of all scatter plots, which belongs to category.
-+*/
-+struct scScatts
++ for(i_cat_id = 0; i_cat_id < cats->n_cats; i_cat_id++)
++ if(cats->cats_idxs[i_cat_id] < 0) {
++ cat_id = i_cat_id;
++ break;
++ }
++
++ cats->cats_ids[n_a_cats] = cat_id;
++ cats->cats_idxs[cat_id] = n_a_cats;
++
++ cats->cats_arr[n_a_cats] = (struct scScatts *) G_malloc(sizeof(struct scScatts));
++
++ cats->cats_arr[n_a_cats]->scatts_arr = (struct scdScattData **) G_malloc(cats->n_scatts * sizeof(struct scdScattData *));
++ memset((cats->cats_arr[n_a_cats]->scatts_arr), 0, cats->n_scatts * sizeof(struct scdScattData *));
++
++ cats->cats_arr[n_a_cats]->n_a_scatts = 0;
++
++ cats->cats_arr[n_a_cats]->scatts_bands = (int *) G_malloc(cats->n_scatts * 2 * sizeof(int));
++
++ cats->cats_arr[n_a_cats]->scatt_idxs = (int *) G_malloc(cats->n_scatts * sizeof(int));
++ for(i_scatt = 0; i_scatt < cats->n_scatts; i_scatt++)
++ cats->cats_arr[n_a_cats]->scatt_idxs[i_scatt] = -1;
++
++ ++cats->n_a_cats;
++
++ return cat_id;
++}
++
++#if 0
++int I_sc_delete_cat(struct scCats * cats, int cat_id)
+{
-+ int n_a_scatts; /*!< number of used/active scatter plots*/
++ int cat_idx, i_cat;
++
++ if(cat_id < 0 || cat_id >= cats->n_cats)
++ return -1;
++
++ cat_idx = cats->cats_idxs[cat_id];
++ if(cat_idx < 0)
++ return -1;
++
++ G_free(cats->cats_arr[cat_idx]->scatt_idxs);
++ G_free(cats->cats_arr[cat_idx]->scatts_bands);
++ G_free(cats->cats_arr[cat_idx]->scatts_arr);
++ G_free(cats->cats_arr[cat_idx]);
++
++ for(i_cat = cat_idx; i_cat < cats->n_a_cats - 1; i_cat++)
++ {
++ cats->cats_arr[i_cat] = cats->cats_arr[i_cat + 1];
++ cats->cats_ids[i_cat] = cats->cats_ids[i_cat + 1];
++ }
++ cats->cats_idxs[cat_id] = -1;
++
++ --cats->n_a_cats;
+
-+ int * scatts_bands; /*!< array of bands for which represents the scatter plots,
-+ every scatter plot has assigned two bads (size of array is n_a_scatts * 2)*/
-+ int * scatt_idxs; /*!< (scatt_id->scatt_idx) internal idx of the scatter plot (position in scatts_arr)*/
++ return 0;
++}
++#endif
+
-+ struct scdScattData ** scatts_arr; /*!< array of pointers to scdScattData */
-+};
++/*!
++ \brief Insert scatter plot data .
++ Inserted scatt_data struct must have same type as cats struct (SC_SCATT_DATA or SC_SCATT_CONDITIONS).
+
-+/*! Holds scatter plot data.
-+*/
-+struct scdScattData
++ \param cats pointer to scCats struct
++ \param cat_id id number of category.
++ \param scatt_id id number of scatter plot.
++
++ \return 0 on success
++ \return -1 on failure
++ */
++int I_sc_insert_scatt_data(struct scCats * cats, struct scdScattData * scatt_data, int cat_id, int scatt_id)
+{
-+ int n_vals; /*!< Number of values in scatter plot. */
++ int band_1, band_2, cat_idx, n_a_scatts;
++ struct scScatts * scatts;
+
-+ unsigned char * b_conds_arr; /*!< array of selected areas (used for SC_SCATT_CONDITIONS type) otherwise NULL */
-+ unsigned int * scatt_vals_arr; /*!< array of computed areas (used for SC_SCATT_DATA type) otherwise NULL */
-+};
++ if(cat_id < 0 || cat_id >= cats->n_cats)
++ return -1;
+
++ cat_idx = cats->cats_idxs[cat_id];
++ if(cat_idx < 0)
++ return -1;
+
- #define SIGNATURE_TYPE_MIXED 1
-
- #define GROUPFILE "CURGROUP"
++ if(scatt_id < 0 && scatt_id >= cats->n_scatts)
++ return -1;
++
++ scatts = cats->cats_arr[cat_idx];
++ if(scatts->scatt_idxs[scatt_id] >= 0)
++ return -1;
++
++ if(!scatt_data->b_conds_arr && cats->type == SC_SCATT_CONDITIONS)
++ return -1;
++
++ if(!scatt_data->scatt_vals_arr && cats->type == SC_SCATT_DATA)
++ return -1;
++
++ n_a_scatts = scatts->n_a_scatts;
++
++ scatts->scatt_idxs[scatt_id] = n_a_scatts;
++
++ I_id_scatt_to_bands(scatt_id, cats->n_bands, &band_1, &band_2);
++
++ scatts->scatts_bands[n_a_scatts * 2] = band_1;
++ scatts->scatts_bands[n_a_scatts * 2 + 1] = band_2;
++
++ scatts->scatts_arr[n_a_scatts] = scatt_data;
++ ++scatts->n_a_scatts;
++
++ return 0;
++}
++
++#if 0
++int I_sc_remove_scatt_data(struct scCats * cats, struct scdScattData * scatt_data, int cat_id, int scatt_id)
++{
++ int cat_idx, scatt_idx, n_init_scatts, i_scatt;
++ struct scScatts * scatts;
++
++ if(cat_id < 0 && cat_id >= cats->n_cats)
++ return -1;
++
++ cat_idx = cats->cats_idxs[cat_id];
++ if(cat_idx < 0)
++ return -1;
++
++ if(scatt_id < 0 || scatt_id >= cats->n_scatts)
++ return -1;
++
++ scatts = cats->cats_arr[cat_idx];
++ if(scatts->scatt_idxs[scatt_id] < 0)
++ return -1;
++
++ scatt_data = scatts->scatts_arr[scatt_idx];
++
++ for(i_scatt = scatt_idx; i_scatt < scatts->n_a_scatts - 1; i_scatt++)
++ {
++ scatts->scatts_arr[i_scatt] = scatts->scatts_arr[i_scatt + 1];
++ scatts->scatts_bands[i_scatt * 2] = scatts->scatts_bands[(i_scatt + 1)* 2];
++ scatts->scatts_bands[i_scatt * 2 + 1] = scatts->scatts_bands[(i_scatt + 1) * 2 + 1];
++ }
++ scatts->scatts_arr[scatts->n_a_scatts] = NULL;
++
++ scatts->scatt_idxs[scatt_id] = -1;
++
++ scatt_data = scatts->scatts_arr[scatt_id];
++ scatts->n_a_scatts--;
++
++ return 0;
++}
++
++int I_sc_set_value(struct scCats * cats, int cat_id, int scatt_id, int value_idx, int value)
++{
++ int n_a_scatts = cats->cats_arr[cat_id]->n_a_scatts;
++ int cat_idx, scatt_idx, ret;
++
++ cat_idx = cats->cats_idxs[cat_id];
++ if(cat_idx < 0)
++ return -1;
++
++ if(cats->cats_arr[cat_idx]->scatt_idxs[scatt_id] < 0)
++ return -1;
++
++ cat_idx = cats->cats_idxs[cat_id];
++ scatt_idx = cats->cats_arr[cat_idx]->scatt_idxs[scatt_id];
++
++ I_scd_set_value(cats->cats_arr[cat_idx]->scatts_arr[scatt_idx], value_idx, value);
++
++ return 0;
++}
++#endif
++
++/*!
++ \brief Insert scatter plot data.
++
++ \param scatt_data pointer to existing struct scdScattData
++ \param type SC_SCATT_DATA for scatter plots or SC_SCATT_CONDITIONS for selected areas in scatter plot
++ \param n_vals number of data values
++ \param data array of values (unsigned char for SC_SCATT_CONDITIONS, unsigned int for SC_SCATT_DATA)
++ */
++void I_scd_init_scatt_data(struct scdScattData * scatt_data, int type, int n_vals, void * data)
++{
++ scatt_data->n_vals = n_vals;
++
++ if(type == SC_SCATT_DATA)
++ {
++ if(data)
++ scatt_data->scatt_vals_arr = (unsigned int *) data;
++ else {
++ scatt_data->scatt_vals_arr = (unsigned int *) G_malloc(n_vals * sizeof(unsigned int));
++ memset(scatt_data->scatt_vals_arr, 0, n_vals * sizeof(unsigned int));
++ }
++ scatt_data->b_conds_arr = NULL;
++ }
++ else if(type == SC_SCATT_CONDITIONS)
++ {
++ if(data)
++ scatt_data->b_conds_arr = (unsigned char *) data;
++ else {
++ scatt_data->b_conds_arr = (unsigned char *) G_malloc(n_vals * sizeof(unsigned char));
++ memset(scatt_data->b_conds_arr, 0, n_vals * sizeof(unsigned char));
++ }
++ scatt_data->scatt_vals_arr = NULL;
++ }
++
++ return;
++}
++
++
++#if 0
++void I_scd_get_range_min_max(struct scdScattData * scatt_data, CELL * band_1_min, CELL * band_1_max, CELL * band_2_min, CELL * band_2_max)
++{
++
++ Rast_get_range_min_max(&(scatt_data->band_1_range), band_1_min, band_2_min);
++ Rast_get_range_min_max(&(scatt_data->band_2_range), band_2_min, band_2_max);
++
++ return;
++}
++s
++void * I_scd_get_data_ptr(struct scdScattData * scatt_data)
++{
++ if(!scatt_data->b_conds_arr)
++ return scatt_data->b_conds_arr;
++ else if(!scatt_data->scatt_vals_arr)
++ return scatt_data->scatt_vals_arr;
++
++ return NULL;
++}
++
++int I_scd_set_value(struct scdScattData * scatt_data, unsigned int val_idx, unsigned int val)
++{
++ if(val_idx < 0 && val_idx > scatt_data->n_vals)
++ return -1;
++
++ if(scatt_data->b_conds_arr)
++ scatt_data->b_conds_arr[val_idx] = val;
++ else if(scatt_data->scatt_vals_arr)
++ scatt_data->scatt_vals_arr[val_idx] = val;
++ else
++ return -1;
++
++ return 0;
++}
++#endif
+Index: lib/vector/Vlib/open.c
+===================================================================
+--- lib/vector/Vlib/open.c (revision 57644)
++++ lib/vector/Vlib/open.c (working copy)
+@@ -240,7 +240,9 @@
+ }
+ else {
+ char file_path[GPATH_MAX];
+-
++ /* reduce to current mapset if search path was set */
++ if(strcmp(Map->mapset, "") == 0)
++ Map->mapset = G_store(G_mapset());
+ /* temporary map: reduce to current mapset if search path
+ * was set */
+ if (strcmp(Map->mapset, "") == 0)
Index: include/defs/vedit.h
===================================================================
---- include/defs/vedit.h (revision 57633)
+--- include/defs/vedit.h (revision 57644)
+++ include/defs/vedit.h (working copy)
@@ -33,6 +33,8 @@
int Vedit_merge_lines(struct Map_info *, struct ilist *);
@@ -1303,7 +1242,7 @@
Index: include/defs/imagery.h
===================================================================
---- include/defs/imagery.h (revision 57633)
+--- include/defs/imagery.h (revision 57644)
+++ include/defs/imagery.h (working copy)
@@ -110,6 +110,26 @@
FILE *I_fopen_subgroup_ref_new(const char *, const char *);
@@ -1332,13 +1271,74 @@
/* sig.c */
int I_init_signatures(struct Signature *, int);
int I_new_signature(struct Signature *);
+Index: include/imagery.h
+===================================================================
+--- include/imagery.h (revision 57644)
++++ include/imagery.h (working copy)
+@@ -135,6 +135,56 @@
+
+ } IClass_statistics;
+
++/* Scatter Plot backend */
++
++#define SC_SCATT_DATA 0
++#define SC_SCATT_CONDITIONS 1
++
++
++/*! Holds list of all catagories.
++ It can contain selected areas for scatter plots (SC_SCATT_CONDITIONS type) or computed scatter plots (SC_SCATT_DATA type).
++*/
++struct scCats
++{
++ int type; /*!< SC_SCATT_DATA -> computed scatter plots, SC_SCATT_CONDITIONS -> set conditions for scatter plots to be computed*/
++
++ int n_cats; /*!< number of alocated categories */
++
++ int n_bands; /*!< number of analyzed bands */
++ int n_scatts; /*!< number of possible scattter plot which can be created from bands */
++
++ int n_a_cats; /*!< number of used/active categories */
++ int * cats_ids; /*!< (cat_idx->cat_id) array index is internal idx (position in cats_arr) and id is saved in it's position*/
++ int * cats_idxs; /*!< (cat_id->cat_idx) array index is id and internal idx is saved in it's position*/
++
++ struct scScatts ** cats_arr; /*!< array of pointers to struct scScatts */
++};
++
++
++/*! Holds list of all scatter plots, which belongs to category.
++*/
++struct scScatts
++{
++ int n_a_scatts; /*!< number of used/active scatter plots*/
++
++ int * scatts_bands; /*!< array of bands for which represents the scatter plots,
++ every scatter plot has assigned two bads (size of array is n_a_scatts * 2)*/
++ int * scatt_idxs; /*!< (scatt_id->scatt_idx) internal idx of the scatter plot (position in scatts_arr)*/
++
++ struct scdScattData ** scatts_arr; /*!< array of pointers to scdScattData */
++};
++
++/*! Holds scatter plot data.
++*/
++struct scdScattData
++{
++ int n_vals; /*!< Number of values in scatter plot. */
++
++ unsigned char * b_conds_arr; /*!< array of selected areas (used for SC_SCATT_CONDITIONS type) otherwise NULL */
++ unsigned int * scatt_vals_arr; /*!< array of computed areas (used for SC_SCATT_DATA type) otherwise NULL */
++};
++
++
+ #define SIGNATURE_TYPE_MIXED 1
+
+ #define GROUPFILE "CURGROUP"
Index: gui/icons/grass/polygon.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: gui/icons/grass/polygon.png
===================================================================
---- gui/icons/grass/polygon.png (revision 57633)
+--- gui/icons/grass/polygon.png (revision 57644)
+++ gui/icons/grass/polygon.png (working copy)
Property changes on: gui/icons/grass/polygon.png
@@ -1347,158 +1347,558 @@
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
-Index: gui/wxpython/iclass/plots.py
+Index: gui/wxpython/vdigit/wxdigit.py
===================================================================
---- gui/wxpython/iclass/plots.py (revision 57633)
-+++ gui/wxpython/iclass/plots.py (working copy)
-@@ -19,6 +19,7 @@
- import wx.lib.plot as plot
- import wx.lib.scrolledpanel as scrolled
- from core.utils import _
-+from core.gcmd import GError
+--- gui/wxpython/vdigit/wxdigit.py (revision 57644)
++++ gui/wxpython/vdigit/wxdigit.py (working copy)
+@@ -17,7 +17,7 @@
+ (and NumPy would be an excellent candidate for acceleration via
+ e.g. OpenCL or CUDA; I'm surprised it hasn't happened already).
- class PlotPanel(scrolled.ScrolledPanel):
- """!Panel for drawing multiple plots.
-@@ -28,7 +29,7 @@
- for each band and for one category. Coincidence plots show min max range
- of classes for each band.
- """
-- def __init__(self, parent, stats_data):
-+ def __init__(self, parent, giface, stats_data):
- scrolled.ScrolledPanel.__init__(self, parent)
-
- self.SetupScrolling(scroll_x = False, scroll_y = True)
-@@ -38,26 +39,71 @@
- self.stats_data = stats_data
- self.currentCat = None
-
-+ self._giface = giface
+-(C) 2007-2011 by the GRASS Development Team
++(C) 2007-2011, 2013 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.
+@@ -27,6 +27,8 @@
+
+ import grass.script.core as grass
+
++from grass.pydispatch.signal import Signal
+
- self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+ from core.gcmd import GError
+ from core.debug import Debug
+ from core.settings import UserSettings
+@@ -176,7 +178,21 @@
+
+ if self.poMapInfo:
+ self.InitCats()
-
+
- self._createControlPanel()
++ self.emit_signals = False
++
++ # signals which describes features changes during digitization,
++ # activate them using EmitSignals method
++ #TODO signal for errors?
++ self.featureAdded = Signal('IVDigit.featureAdded')
++ self.areasDeleted = Signal('IVDigit.areasDeleted')
++ self.vertexMoved = Signal('IVDigit.vertexMoved')
++ self.vertexAdded = Signal('IVDigit.vertexAdded')
++ self.vertexRemoved = Signal('IVDigit.vertexRemoved')
++ self.featuresDeleted = Signal('IVDigit.featuresDeleted')
++ self.featuresMoved = Signal('IVDigit.featuresMoved')
++ self.lineEdited = Signal('IVDigit.lineEdited')
++
+ def __del__(self):
+ Debug.msg(1, "IVDigit.__del__()")
+ Vect_destroy_line_struct(self.poPoints)
+@@ -188,7 +204,12 @@
+ Vect_close(self.poBgMapInfo)
+ self.poBgMapInfo = self.popoBgMapInfo = None
+ del self.bgMapInfo
-
-+ self._createPlotPanel()
-+ self._createScatterPlotPanel()
++
++ def EmitSignals(self, emit):
++ """!Activate/deactivate signals which describes features changes during digitization.
++ """
++ self.emit_signals = emit
+
- self.SetSizer(self.mainSizer)
- self.mainSizer.Fit(self)
- self.Layout()
+ def CloseBackgroundMap(self):
+ """!Close background vector map"""
+ if not self.poBgMapInfo:
+@@ -394,7 +415,6 @@
+
+ @return tuple (number of added features, feature ids)
+ """
-
+ layer = self._getNewFeaturesLayer()
+ cat = self._getNewFeaturesCat()
+
+@@ -419,10 +439,14 @@
+ return (-1, None)
+
+ self.toolbar.EnableUndo()
+-
+- return self._addFeature(vtype, points, layer, cat,
+- self._getSnapMode(), self._display.GetThreshold())
+-
+
-+ def _createPlotPanel(self):
++ ret = self._addFeature(vtype, points, layer, cat,
++ self._getSnapMode(), self._display.GetThreshold())
++ if ret[0] > -1 and self.emit_signals:
++ self.featureAdded.emit(new_bboxs = [self._createBbox(points)], new_areas_cats = [[{layer : [cat]}, None]])
+
-+ self.canvasPanel = wx.Panel(parent=self)
-+ self.mainSizer.Add(item = self.canvasPanel, proportion = 1, flag = wx.EXPAND, border = 0)
-+ self.canvasSizer = wx.BoxSizer(wx.VERTICAL)
-+ self.canvasPanel.SetSizer(self.canvasSizer)
++ return ret
+
- def _createControlPanel(self):
- self.plotSwitch = wx.Choice(self, id = wx.ID_ANY,
- choices = [_("Histograms"),
-- _("Coincident plots")])
-+ _("Coincident plots"),
-+ _("Scatter plots")])
- self.mainSizer.Add(self.plotSwitch, proportion = 0, flag = wx.EXPAND|wx.ALL, border = 5)
- self.plotSwitch.Bind(wx.EVT_CHOICE, self.OnPlotTypeSelected)
+ def DeleteSelectedLines(self):
+ """!Delete selected features
+
+@@ -434,16 +458,27 @@
+ # collect categories for deleting if requested
+ deleteRec = UserSettings.Get(group = 'vdigit', key = 'delRecord', subkey = 'enabled')
+ catDict = dict()
++
++ old_bboxs = []
++ old_areas_cats = []
+ if deleteRec:
+ for i in self._display.selected['ids']:
++
+ if Vect_read_line(self.poMapInfo, None, self.poCats, i) < 0:
+ self._error.ReadLine(i)
+
+- cats = self.poCats.contents
+- for j in range(cats.n_cats):
+- if cats.field[j] not in catDict.keys():
+- catDict[cats.field[j]] = list()
+- catDict[cats.field[j]].append(cats.cat[j])
++ if self.emit_signals:
++ ret = self._getLineAreaBboxCats(i)
++ if ret:
++ old_bboxs += ret[0]
++ old_areas_cats += ret[1]
++
++ # catDict was not used -> put into comment
++ #cats = self.poCats.contents
++ #for j in range(cats.n_cats):
++ # if cats.field[j] not in catDict.keys():
++ # catDict[cats.field[j]] = list()
++ # catDict[cats.field[j]].append(cats.cat[j])
+
+ poList = self._display.GetSelectedIList()
+ nlines = Vedit_delete_lines(self.poMapInfo, poList)
+@@ -456,7 +491,10 @@
+ self._deleteRecords(catDict)
+ self._addChangeset()
+ self.toolbar.EnableUndo()
-
-+
-+ def _createScatterPlotPanel(self):
-+ """!Init interactive scatterplot tools
-+ """
-+ try:
-+ from scatt_plot.frame import IClassScatterPlotsPanel
-+ self.scatt_plot_panel = IClassScatterPlotsPanel(parent=self,
-+ giface=self._giface,
-+ iclass_mapwin = self.parent.GetFirstWindow())
-+ self.mainSizer.Add(self.scatt_plot_panel, proportion = 1, flag = wx.EXPAND, border = 0)
-+ self.scatt_plot_panel.Hide()
-+ except ImportError as e:#TODO
-+ self.scatt_error = _("Scatter plot functionality is disabled. Reason:\n" \
-+ "Unable to import packages needed for scatter plot.\n%s" % e)
-+ GError(self.scatt_error)
-+ self.scatt_plot_panel = None
+
- def OnPlotTypeSelected(self, event):
- """!Plot type selected"""
++ if self.emit_signals:
++ self.featuresDeleted.emit(old_bboxs = old_bboxs, old_areas_cats = old_areas_cats)
+
-+ if self.plotSwitch.GetSelection() in [0, 1]:
-+ self.SetupScrolling(scroll_x = False, scroll_y = True)
-+ if self.scatt_plot_panel:
-+ self.scatt_plot_panel.Hide()
-+ self.canvasPanel.Show()
-+ self.Layout()
+ return nlines
+
+ def _deleteRecords(self, cats):
+@@ -512,22 +550,173 @@
+
+ @return number of deleted
+ """
++ if len(self._display.selected['ids']) < 1:
++ return 0
++
+ poList = self._display.GetSelectedIList()
+ cList = poList.contents
+
+ nareas = 0
++ old_bboxs = []
++ old_areas_cats = []
+
-+ elif self.plotSwitch.GetSelection() == 2:
-+ self.SetupScrolling(scroll_x = False, scroll_y = False)
-+ if self.scatt_plot_panel:
-+ self.scatt_plot_panel.Show()
+ for i in range(cList.n_values):
++
+ if Vect_get_line_type(self.poMapInfo, cList.value[i]) != GV_CENTROID:
+ continue
+-
++
++ if self.emit_signals:
++ area = Vect_get_centroid_area(self.poMapInfo, cList.value[i]);
++ if area > 0:
++ bbox, cats = self._getaAreaBboxCats(area)
++ old_bboxs += bbox
++ old_areas_cats += cats
++
+ nareas += Vedit_delete_area_centroid(self.poMapInfo, cList.value[i])
+
+ if nareas > 0:
+ self._addChangeset()
+ self.toolbar.EnableUndo()
++ if self.emit_signals:
++ self.areasDeleted.emit(old_bboxs = old_bboxs, old_areas_cats = old_areas_cats)
++
++ return nareas
++
++ def _getLineAreaBboxCats(self, ln_id):
++ ltype = Vect_read_line(self.poMapInfo, None, None, ln_id)
++
++ if ltype == GV_CENTROID:
++ #TODO centroid opttimization, can be adited also its area -> it will appear two times in new_ lists
++ return self._getCentroidAreaBboxCats(ln_id)
++ else:
++ return [self._getBbox(ln_id)], [self._getLineAreasCategories(ln_id)]
++
++
++ def _getCentroidAreaBboxCats(self, centroid):
++ if not Vect_line_alive(self.poMapInfo, centroid):
++ return None
++
++ area = Vect_get_centroid_area(self.poMapInfo, centroid)
++ if area > 0:
++ return self._getaAreaBboxCats(area)
++ else:
++ return None
++
++ def _getaAreaBboxCats(self, area):
++
++ po_b_list = Vect_new_list()
++ Vect_get_area_boundaries(self.poMapInfo, area, po_b_list);
++ b_list = po_b_list.contents
++
++ geoms = []
++ areas_cats = []
++
++ if b_list.n_values > 0:
++ for i_line in range(b_list.n_values):
++
++ line = b_list.value[i_line];
++
++ geoms.append(self._getBbox(abs(line)))
++ areas_cats.append(self._getLineAreasCategories(abs(line)))
+
+- return nareas
++ Vect_destroy_list(po_b_list);
++
++ return geoms, areas_cats
++
++ def _getLineAreasCategories(self, ln_id):
++ if not Vect_line_alive (self.poMapInfo, ln_id):
++ return []
++
++ ltype = Vect_read_line(self.poMapInfo, None, None, ln_id)
++ if ltype != GV_BOUNDARY:
++ return []
++
++ cats = [None, None]
++
++ left = c_int()
++ right = c_int()
++
++ if Vect_get_line_areas(self.poMapInfo, ln_id, pointer(left), pointer(right)) == 1:
++ areas = [left.value, right.value]
++
++ for i, a in enumerate(areas):
++ if a > 0:
++ centroid = Vect_get_area_centroid(self.poMapInfo, a)
++ if centroid <= 0:
++ continue
++ c = self._getCategories(centroid)
++ if c:
++ cats[i] = c
++
++ return cats
++
++ def _getCategories(self, ln_id):
++ if not Vect_line_alive (self.poMapInfo, ln_id):
++ return none
++
++ poCats = Vect_new_cats_struct()
++ if Vect_read_line(self.poMapInfo, None, poCats, ln_id) < 0:
++ Vect_destroy_cats_struct(poCats)
++ return None
++
++ cCats = poCats.contents
++
++ cats = {}
++ for j in range(cCats.n_cats):
++ if cats.has_key(cCats.field[j]):
++ cats[cCats.field[j]].append(cCats.cat[j])
+ else:
-+ GError(self.scatt_error)
-+ self.canvasPanel.Hide()
-+ self.Layout()
++ cats[cCats.field[j]] = [cCats.cat[j]]
+
++ Vect_destroy_cats_struct(poCats)
++ return cats
+
- if self.currentCat is None:
- return
--
++ def _getBbox(self, ln_id):
++ if not Vect_line_alive (self.poMapInfo, ln_id):
++ return None
+
- if self.plotSwitch.GetSelection() == 0:
- stat = self.stats_data.GetStatistics(self.currentCat)
- if not stat.IsReady():
-@@ -66,7 +112,10 @@
- self.DrawHistograms(stat)
- else:
- self.DrawCoincidencePlots()
--
++ poPoints = Vect_new_line_struct()
++ if Vect_read_line(self.poMapInfo, poPoints, None, ln_id) < 0:
++ Vect_destroy_line_struct(poPoints)
++ return []
+
-+ self.Layout()
++ geom = self._convertGeom(poPoints)
++ bbox = self._createBbox(geom)
++ Vect_destroy_line_struct(poPoints)
++ return bbox
+
++ def _createBbox(self, points):
+
- def StddevChanged(self):
- """!Standard deviation multiplier changed, redraw histograms"""
- if self.plotSwitch.GetSelection() == 0:
-@@ -89,7 +138,7 @@
- panel.Destroy()
-
- self.canvasList = []
--
++ bbox = {}
++ for pt in points:
++ if not bbox.has_key('maxy'):
++ bbox['maxy'] = pt[1]
++ bbox['miny'] = pt[1]
++ bbox['maxx'] = pt[0]
++ bbox['minx'] = pt[0]
++ continue
++
++ if bbox['maxy'] < pt[1]:
++ bbox['maxy'] = pt[1]
++ elif bbox['miny'] > pt[1]:
++ bbox['miny'] = pt[1]
++
++ if bbox['maxx'] < pt[0]:
++ bbox['maxx'] = pt[0]
++ elif bbox['minx'] > pt[0]:
++ bbox['minx'] = pt[0]
++ return bbox
+
- def ClearPlots(self):
- """!Clears plot canvases"""
- for bandIdx in range(len(self.bandList)):
-@@ -104,15 +153,15 @@
- def CreatePlotCanvases(self):
- """!Create plot canvases according to the number of bands"""
- for band in self.bandList:
-- canvas = plot.PlotCanvas(self)
-+ canvas = plot.PlotCanvas(self.canvasPanel)
- canvas.SetMinSize((-1, 140))
- canvas.SetFontSizeTitle(10)
- canvas.SetFontSizeAxis(8)
- self.canvasList.append(canvas)
-
-- self.mainSizer.Add(item = canvas, proportion = 1, flag = wx.EXPAND, border = 0)
--
-- self.SetVirtualSize(self.GetBestVirtualSize())
-+ self.canvasSizer.Add(item = canvas, proportion = 1, flag = wx.EXPAND, border = 0)
++ def _convertGeom(self, poPoints):
++
++ Points = poPoints.contents
++
++ pts_geom = []
++ for j in range(Points.n_points):
++ pts_geom.append((Points.x[j], Points.y[j]))
++
++ return pts_geom
++
+ def MoveSelectedLines(self, move):
+ """!Move selected features
+
+@@ -536,16 +725,45 @@
+ if not self._checkMap():
+ return -1
+
++ nsel = len(self._display.selected['ids'])
++ if nsel < 1:
++ return -1
+
-+ self.SetVirtualSize(self.GetBestVirtualSize())
- self.Layout()
+ thresh = self._display.GetThreshold()
+ snap = self._getSnapMode()
- def UpdatePlots(self, group, currentCat, stats_data):
-@@ -138,7 +187,7 @@
+ poList = self._display.GetSelectedIList()
++
++ if self.emit_signals:
++ old_bboxs = []
++ old_areas_cats = []
++ for sel_id in self._display.selected['ids']:
++ ret = self._getLineAreaBboxCats(sel_id)
++ if ret:
++ old_bboxs += ret[0]
++ old_areas_cats += ret[1]
++
++ Vect_set_updated(self.poMapInfo, 1)
++ n_up_lines_old = Vect_get_num_updated_lines(self.poMapInfo)
++
+ nlines = Vedit_move_lines(self.poMapInfo, self.popoBgMapInfo, int(self.poBgMapInfo is not None),
+ poList,
+ move[0], move[1], 0,
+ snap, thresh)
++
+ Vect_destroy_list(poList)
+-
++
++ if nlines > 0 and self.emit_signals:
++ new_bboxs = []
++ new_areas_cats = []
++ n_up_lines = Vect_get_num_updated_lines(self.poMapInfo)
++ for i in range(n_up_lines_old, n_up_lines):
++ new_id = Vect_get_updated_line(self.poMapInfo, i)
++ ret = self._getLineAreaBboxCats(new_id)
++ if ret:
++ new_bboxs += ret[0]
++ new_areas_cats += ret[1]
++
+ if nlines > 0 and self._settings['breakLines']:
+ for i in range(1, nlines):
+ self._breakLineAtIntersection(nlines + i, None, changeset)
+@@ -553,7 +771,13 @@
+ if nlines > 0:
+ self._addChangeset()
+ self.toolbar.EnableUndo()
+-
++
++ if self.emit_signals:
++ self.featuresMoved.emit(new_bboxs = new_bboxs,
++ old_bboxs = old_bboxs,
++ old_areas_cats = old_areas_cats,
++ new_areas_cats = new_areas_cats)
++
+ return nlines
+
+ def MoveSelectedVertex(self, point, move):
+@@ -571,12 +795,21 @@
- def UpdateCategory(self, cat):
- self.currentCat = cat
+ if len(self._display.selected['ids']) != 1:
+ return -1
-
++
++ # move only first found vertex in bbox
++ poList = self._display.GetSelectedIList()
++
++ if self.emit_signals:
++ cList = poList.contents
++ old_bboxs = [self._getBbox(cList.value[0])]
++ old_areas_cats = [self._getLineAreasCategories(cList.value[0])]
++
++ Vect_set_updated(self.poMapInfo, 1)
++ n_up_lines_old = Vect_get_num_updated_lines(self.poMapInfo)
++
+ Vect_reset_line(self.poPoints)
+ Vect_append_point(self.poPoints, point[0], point[1], 0.0)
+-
+- # move only first found vertex in bbox
+- poList = self._display.GetSelectedIList()
++
+ moved = Vedit_move_vertex(self.poMapInfo, self.popoBgMapInfo, int(self.poBgMapInfo is not None),
+ poList, self.poPoints,
+ self._display.GetThreshold(type = 'selectThresh'),
+@@ -584,7 +817,17 @@
+ move[0], move[1], 0.0,
+ 1, self._getSnapMode())
+ Vect_destroy_list(poList)
+-
++
++ if moved > 0 and self.emit_signals:
++ n_up_lines = Vect_get_num_updated_lines(self.poMapInfo)
++
++ new_bboxs = []
++ new_areas_cats = []
++ for i in range(n_up_lines_old, n_up_lines):
++ new_id = Vect_get_updated_line(self.poMapInfo, i)
++ new_bboxs.append(self._getBbox(new_id))
++ new_areas_cats.append(self._getLineAreasCategories(new_id))
++
+ if moved > 0 and self._settings['breakLines']:
+ self._breakLineAtIntersection(Vect_get_num_lines(self.poMapInfo),
+ None)
+@@ -592,7 +835,13 @@
+ if moved > 0:
+ self._addChangeset()
+ self.toolbar.EnableUndo()
+-
++
++ if self.emit_signals:
++ self.vertexMoved.emit(new_bboxs = new_bboxs,
++ new_areas_cats = new_areas_cats,
++ old_areas_cats = old_areas_cats,
++ old_bboxs = old_bboxs)
++
+ return moved
+
+ def AddVertex(self, coords):
+@@ -681,6 +930,10 @@
+ self._error.ReadLine(line)
+ return -1
+
++ if self.emit_signals:
++ old_bboxs = [self._getBbox(line)]
++ old_areas_cats = [self._getLineAreasCategories(line)]
++
+ # build feature geometry
+ Vect_reset_line(self.poPoints)
+ for p in coords:
+@@ -696,6 +949,9 @@
+
+ newline = Vect_rewrite_line(self.poMapInfo, line, ltype,
+ self.poPoints, self.poCats)
++ if newline > 0 and self.emit_signals:
++ new_geom = [self._getBbox(newline)]
++ new_areas_cats = [self._getLineAreasCategories(newline)]
+
+ if newline > 0 and self._settings['breakLines']:
+ self._breakLineAtIntersection(newline, None)
+@@ -703,7 +959,13 @@
+ if newline > 0:
+ self._addChangeset()
+ self.toolbar.EnableUndo()
+-
+
- def DrawCoincidencePlots(self):
- """!Draw coincidence plots"""
- for bandIdx in range(len(self.bandList)):
++ if self.emit_signals:
++ self.lineEdited.emit(old_bboxs = old_bboxs,
++ old_areas_cats = old_areas_cats,
++ new_bboxs = new_bboxs,
++ new_areas_cats = new_areas_cats)
++
+ return newline
+
+ def FlipLine(self):
+@@ -1514,6 +1776,16 @@
+ return 0
+
+ poList = self._display.GetSelectedIList()
++
++ if self.emit_signals:
++ cList = poList.contents
++
++ old_bboxs = [self._getBbox(cList.value[0])]
++ old_areas_cats = [self._getLineAreasCategories(cList.value[0])]
++
++ Vect_set_updated(self.poMapInfo, 1)
++ n_up_lines_old = Vect_get_num_updated_lines(self.poMapInfo)
++
+ Vect_reset_line(self.poPoints)
+ Vect_append_point(self.poPoints, coords[0], coords[1], 0.0)
+
+@@ -1525,15 +1797,35 @@
+ else:
+ ret = Vedit_remove_vertex(self.poMapInfo, poList,
+ self.poPoints, thresh)
++
+ Vect_destroy_list(poList)
++
++ if ret > 0 and self.emit_signals:
++ new_bboxs = []
++ new_areas_cats = []
++
++ n_up_lines = Vect_get_num_updated_lines(self.poMapInfo)
++ for i in range(n_up_lines_old, n_up_lines):
++ new_id = Vect_get_updated_line(self.poMapInfo, i)
++ new_areas_cats.append(self._getLineAreasCategories(new_id))
++ new_bboxs.append(self._getBbox(new_id))
+
+ if not add and ret > 0 and self._settings['breakLines']:
+ self._breakLineAtIntersection(Vect_get_num_lines(self.poMapInfo),
+ None)
+-
++
+ if ret > 0:
+ self._addChangeset()
+-
++
++ if ret > 0 and self.emit_signals:
++ if add:
++ self.vertexAdded.emit(old_bboxs = old_bboxs, new_bboxs = new_bboxs)
++ else:
++ self.vertexRemoved.emit(old_bboxs = old_bboxs,
++ new_bboxs = new_bboxs,
++ old_areas_cats = old_areas_cats,
++ new_areas_cats = new_areas_cats)
++
+ return 1
+
+ def GetLineCats(self, line):
+Index: gui/wxpython/vdigit/toolbars.py
+===================================================================
+--- gui/wxpython/vdigit/toolbars.py (revision 57644)
++++ gui/wxpython/vdigit/toolbars.py (working copy)
+@@ -17,6 +17,7 @@
+ import wx
+
+ from grass.script import core as grass
++from grass.pydispatch.signal import Signal
+
+ from gui_core.toolbars import BaseToolbar, BaseIcons
+ from gui_core.dialogs import CreateNewVector
+@@ -42,6 +43,8 @@
+ self.digit = None
+ self._giface = giface
+
++ self.editingStarted = Signal("VDigitToolbar.editingStarted")
++
+ # currently selected map layer for editing (reference to MapLayer instance)
+ self.mapLayer = None
+ # list of vector layers from Layer Manager (only in the current mapset)
+@@ -860,6 +863,7 @@
+ alpha = int(opacity * 255)
+ self.digit.GetDisplay().UpdateSettings(alpha = alpha)
+
++ self.editingStarted.emit(vectMap = mapLayer.GetName(), digit = self.digit)
+ return True
+
+ def StopEditing(self):
Index: gui/wxpython/iclass/dialogs.py
===================================================================
---- gui/wxpython/iclass/dialogs.py (revision 57633)
+--- gui/wxpython/iclass/dialogs.py (revision 57644)
+++ gui/wxpython/iclass/dialogs.py (working copy)
@@ -333,13 +333,19 @@
toolbar.SetCategories(catNames = catNames, catIdx = cats)
@@ -1523,7 +1923,7 @@
def GetSelectedIndices(self, state = wx.LIST_STATE_SELECTED):
Index: gui/wxpython/iclass/toolbars.py
===================================================================
---- gui/wxpython/iclass/toolbars.py (revision 57633)
+--- gui/wxpython/iclass/toolbars.py (revision 57644)
+++ gui/wxpython/iclass/toolbars.py (working copy)
@@ -46,9 +46,7 @@
'importAreas' : MetaIcon(img = 'layer-import',
@@ -1559,7 +1959,7 @@
self.parent.OnCategoryManager),
Index: gui/wxpython/iclass/frame.py
===================================================================
---- gui/wxpython/iclass/frame.py (revision 57633)
+--- gui/wxpython/iclass/frame.py (revision 57644)
+++ gui/wxpython/iclass/frame.py (working copy)
@@ -64,6 +64,8 @@
IClassExportAreasDialog, IClassMapDialog
@@ -1815,9 +2215,158 @@
def test():
import core.render as render
+Index: gui/wxpython/iclass/plots.py
+===================================================================
+--- gui/wxpython/iclass/plots.py (revision 57644)
++++ gui/wxpython/iclass/plots.py (working copy)
+@@ -19,6 +19,7 @@
+ import wx.lib.plot as plot
+ import wx.lib.scrolledpanel as scrolled
+ from core.utils import _
++from core.gcmd import GError
+
+ class PlotPanel(scrolled.ScrolledPanel):
+ """!Panel for drawing multiple plots.
+@@ -28,7 +29,7 @@
+ for each band and for one category. Coincidence plots show min max range
+ of classes for each band.
+ """
+- def __init__(self, parent, stats_data):
++ def __init__(self, parent, giface, stats_data):
+ scrolled.ScrolledPanel.__init__(self, parent)
+
+ self.SetupScrolling(scroll_x = False, scroll_y = True)
+@@ -38,26 +39,71 @@
+ self.stats_data = stats_data
+ self.currentCat = None
+
++ self._giface = giface
++
+ self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+-
++
+ self._createControlPanel()
+-
++ self._createPlotPanel()
++ self._createScatterPlotPanel()
++
+ self.SetSizer(self.mainSizer)
+ self.mainSizer.Fit(self)
+ self.Layout()
+-
++
++ def _createPlotPanel(self):
++
++ self.canvasPanel = wx.Panel(parent=self)
++ self.mainSizer.Add(item = self.canvasPanel, proportion = 1, flag = wx.EXPAND, border = 0)
++ self.canvasSizer = wx.BoxSizer(wx.VERTICAL)
++ self.canvasPanel.SetSizer(self.canvasSizer)
++
+ def _createControlPanel(self):
+ self.plotSwitch = wx.Choice(self, id = wx.ID_ANY,
+ choices = [_("Histograms"),
+- _("Coincident plots")])
++ _("Coincident plots"),
++ _("Scatter plots")])
+ self.mainSizer.Add(self.plotSwitch, proportion = 0, flag = wx.EXPAND|wx.ALL, border = 5)
+ self.plotSwitch.Bind(wx.EVT_CHOICE, self.OnPlotTypeSelected)
+-
++
++ def _createScatterPlotPanel(self):
++ """!Init interactive scatterplot tools
++ """
++ try:
++ from scatt_plot.frame import IClassScatterPlotsPanel
++ self.scatt_plot_panel = IClassScatterPlotsPanel(parent=self,
++ giface=self._giface,
++ iclass_mapwin = self.parent.GetFirstWindow())
++ self.mainSizer.Add(self.scatt_plot_panel, proportion = 1, flag = wx.EXPAND, border = 0)
++ self.scatt_plot_panel.Hide()
++ except ImportError as e:#TODO
++ self.scatt_error = _("Scatter plot functionality is disabled. Reason:\n" \
++ "Unable to import packages needed for scatter plot.\n%s" % e)
++ GError(self.scatt_error)
++ self.scatt_plot_panel = None
++
+ def OnPlotTypeSelected(self, event):
+ """!Plot type selected"""
++
++ if self.plotSwitch.GetSelection() in [0, 1]:
++ self.SetupScrolling(scroll_x = False, scroll_y = True)
++ if self.scatt_plot_panel:
++ self.scatt_plot_panel.Hide()
++ self.canvasPanel.Show()
++ self.Layout()
++
++ elif self.plotSwitch.GetSelection() == 2:
++ self.SetupScrolling(scroll_x = False, scroll_y = False)
++ if self.scatt_plot_panel:
++ self.scatt_plot_panel.Show()
++ else:
++ GError(self.scatt_error)
++ self.canvasPanel.Hide()
++ self.Layout()
++
+ if self.currentCat is None:
+ return
+-
++
+ if self.plotSwitch.GetSelection() == 0:
+ stat = self.stats_data.GetStatistics(self.currentCat)
+ if not stat.IsReady():
+@@ -66,7 +112,10 @@
+ self.DrawHistograms(stat)
+ else:
+ self.DrawCoincidencePlots()
+-
++
++ self.Layout()
++
++
+ def StddevChanged(self):
+ """!Standard deviation multiplier changed, redraw histograms"""
+ if self.plotSwitch.GetSelection() == 0:
+@@ -89,7 +138,7 @@
+ panel.Destroy()
+
+ self.canvasList = []
+-
++
+ def ClearPlots(self):
+ """!Clears plot canvases"""
+ for bandIdx in range(len(self.bandList)):
+@@ -104,15 +153,15 @@
+ def CreatePlotCanvases(self):
+ """!Create plot canvases according to the number of bands"""
+ for band in self.bandList:
+- canvas = plot.PlotCanvas(self)
++ canvas = plot.PlotCanvas(self.canvasPanel)
+ canvas.SetMinSize((-1, 140))
+ canvas.SetFontSizeTitle(10)
+ canvas.SetFontSizeAxis(8)
+ self.canvasList.append(canvas)
+
+- self.mainSizer.Add(item = canvas, proportion = 1, flag = wx.EXPAND, border = 0)
+-
+- self.SetVirtualSize(self.GetBestVirtualSize())
++ self.canvasSizer.Add(item = canvas, proportion = 1, flag = wx.EXPAND, border = 0)
++
++ self.SetVirtualSize(self.GetBestVirtualSize())
+ self.Layout()
+
+ def UpdatePlots(self, group, currentCat, stats_data):
+@@ -138,7 +187,7 @@
+
+ def UpdateCategory(self, cat):
+ self.currentCat = cat
+-
++
+ def DrawCoincidencePlots(self):
+ """!Draw coincidence plots"""
+ for bandIdx in range(len(self.bandList)):
Index: gui/wxpython/mapdisp/toolbars.py
===================================================================
---- gui/wxpython/mapdisp/toolbars.py (revision 57633)
+--- gui/wxpython/mapdisp/toolbars.py (revision 57644)
+++ gui/wxpython/mapdisp/toolbars.py (working copy)
@@ -239,7 +239,8 @@
(MapIcons["scatter"], self.parent.OnScatterplot),
@@ -1831,7 +2380,7 @@
"""!Decorations overlay menu
Index: gui/wxpython/mapdisp/frame.py
===================================================================
---- gui/wxpython/mapdisp/frame.py (revision 57633)
+--- gui/wxpython/mapdisp/frame.py (revision 57644)
+++ gui/wxpython/mapdisp/frame.py (working copy)
@@ -225,6 +225,7 @@
#
@@ -1861,11 +2410,27 @@
def OnVNet(self, event):
"""!Dialog for v.net* modules
"""
+Index: gui/wxpython/scatt_plot/__init__.py
+===================================================================
+--- gui/wxpython/scatt_plot/__init__.py (revision 0)
++++ gui/wxpython/scatt_plot/__init__.py (working copy)
+@@ -0,0 +1,11 @@
++all = [
++ 'dialogs',
++ 'controllers',
++ 'frame',
++ 'gthreading',
++ 'plots',
++ 'scatt_core',
++ 'toolbars',
++ 'scatt_core',
++ 'core_c',
++ ]
Index: gui/wxpython/scatt_plot/plots.py
===================================================================
--- gui/wxpython/scatt_plot/plots.py (revision 0)
+++ gui/wxpython/scatt_plot/plots.py (working copy)
-@@ -0,0 +1,950 @@
+@@ -0,0 +1,944 @@
+"""!
+ at package scatt_plot.dialogs
+
@@ -1882,13 +2447,11 @@
+"""
+import wx
+import numpy as np
-+
++from math import ceil
+#TODO testing
+import time
+from multiprocessing import Process, Queue
+
-+#TODO
-+#from numpy.lib.stride_tricks import as_strided
+from copy import deepcopy
+from scatt_plot.core_c import MergeArrays, ApplyColormap
+from core.settings import UserSettings
@@ -1967,7 +2530,7 @@
+
+ self.canvas = FigCanvas(self, -1, self.fig)
+
-+ self.axes = self.fig.add_axes([0,0,1,1])
++ self.axes = self.fig.add_axes([0.0,0.0,1,1])
+
+ pol = Polygon(list(zip([0], [0])), animated=True)
+ self.axes.add_patch(pol)
@@ -2075,7 +2638,6 @@
+ else:
+ c = None
+
-+
+ #q = Queue()
+ #p = Process(target=MergeImg, args=(cats_order, scatts, styles, self.transpose, q))
+ #p.start()
@@ -2089,10 +2651,8 @@
+ if self.transpose:
+ merged_img = np.transpose(merged_img, (1, 0, 2))
+
-+ #print self.full_extend
-+
+ img = imshow(self.axes, merged_img,
-+ extent=self.full_extend,
++ extent= [int(ceil(x)) for x in self.full_extend],
+ origin='lower',
+ interpolation='nearest',
+ aspect="equal")
@@ -2210,8 +2770,9 @@
+ if x1 == x2 or y1 == y2:
+ return
+
-+ self.axes.set_xlim(x1, x2)#, auto = True)
-+ self.axes.set_ylim(y1, y2)#, auto = True)
++ self.axes.axis((x1, x2, y1, y2))
++ #self.axes.set_xlim(x1, x2)#, auto = True)
++ #self.axes.set_ylim(y1, y2)#, auto = True)
+ self.canvas.draw()
+
+ def Motion(self, event):
@@ -2237,10 +2798,10 @@
+
+ x,y = event.xdata, event.ydata
+
-+ mx = (x - self.zoom_wheel_coords['x']) * 0.5
-+ my = (y - self.zoom_wheel_coords['y']) * 0.5
++ mx = (x - self.zoom_wheel_coords['x']) * 0.6
++ my = (y - self.zoom_wheel_coords['y']) * 0.6
+
-+ extend = (cur_xlim[0] + mx, cur_xlim[1] + mx, cur_ylim[0] + my, cur_ylim[1] + my)
++ extend = (cur_xlim[0] - mx, cur_xlim[1] - mx, cur_ylim[0] - my, cur_ylim[1] - my)
+
+ self.zoom_wheel_coords['x'] = x
+ self.zoom_wheel_coords['y'] = y
@@ -2632,7 +3193,7 @@
+
+ self._A = self._full_res[y0 - self.miny:y1 - self.miny:sy,
+ x0 - self.minx:x1 - self.minx:sx]
-+ self._A = cbook.safe_masked_invalid(self._A)
++
+ x1 = x0 + self._A.shape[1] * sx
+ y1 = y0 + self._A.shape[0] * sy
+
@@ -2743,7 +3304,6 @@
+ cmap._lut[:, 1] = int(colors[1])/255.0
+ cmap._lut[:, 2] = int(colors[2])/255.0
+
-+
+ #if init:
+ tmp = time.clock()
+
@@ -2758,7 +3318,6 @@
+ masked_cat = np.uint8(masked_cat * (255.0 / float(vmax)))
+ norm_time += time.clock() - tmp
+
-+ #print "ahoj"
+ #print masked_cat
+ #print masked_cat.shape
+ #print masked_cat.mask.dtype
@@ -3206,8 +3765,8 @@
+ if not sel_cat_id:
+ return
+
-+ for scatt in self.plots.itervalues():
-+ scatt.SetEmpty()
++ #for scatt in self.plots.itervalues():
++ # scatt.SetEmpty()
+
+ self.computingStarted.emit()
+
@@ -4437,7 +4996,7 @@
===================================================================
--- gui/wxpython/scatt_plot/scatt_core.py (revision 0)
+++ gui/wxpython/scatt_plot/scatt_core.py (working copy)
-@@ -0,0 +1,813 @@
+@@ -0,0 +1,794 @@
+"""!
+ at package scatt_plot.scatt_plot
+
@@ -4584,14 +5143,12 @@
+ if self.scatt_conds_dt.AddScattPlot(cat_id, scatt_id) < 0:
+ return False
+
-+ b1, b2 = idScattToidBands(scatt_id, len(self.an_data.GetBands()))
++ b1, b2 = idScattToidBands(scatt_id, len(self.an_data.GetBands()))
++ b = self.scatts_dt.GetBandsInfo(scatt_id)
+
-+ b1_info = self.an_data.GetBandInfo(b1)
-+ b2_info = self.an_data.GetBandInfo(b2)
++ raster_pol = RasterizePolygon(coords, b['b1']['range'], b['b1']['min'],
++ b['b2']['range'], b['b2']['min'])
+
-+ raster_pol = RasterizePolygon(coords, b1_info['range'], b1_info['min'],
-+ b2_info['range'], b2_info['min'])
-+
+ raster_ind = np.where(raster_pol > 0)
+ arr = self.scatt_conds_dt.GetValuesArr(cat_id, scatt_id)
+
@@ -5091,6 +5648,7 @@
+
+ data = np.copy(self.cats[cat_id][scatt_id]['np_vals'])
+
++ b = self.GetBandsInfo(scatt_id)
+ sel_pts = np.where(data > 0)
+
+ x = sel_pts[1]
@@ -5104,7 +5662,7 @@
+
+ x_avg = np.average(x, weights=weights)
+ y_avg = np.average(y, weights=weights)
-+ pos = np.array([x_avg, y_avg])
++ pos = np.array([x_avg + b['b1']['min'], y_avg + b['b2']['min']])
+
+ x_diff = (x - x_avg)
+ y_diff = (y - y_avg)
@@ -5192,39 +5750,21 @@
+ nx = width
+ ny = height
+
-+ for p in pol:
-+ p[0] = p[0] - min_w
-+ p[1] = p[1] - min_h
-+
-+ x, y = np.meshgrid(np.arange(-0.5, nx+0.5, dtype=float), np.arange(-0.5, ny+0.5, dtype=float))
++ x, y = np.meshgrid(np.arange(-0.5 + min_w, nx + 0.5 + min_w, dtype=float),
++ np.arange(-0.5 + min_h, ny + 0.5 + min_h, dtype=float))
+ x, y = x.flatten(), y.flatten()
+
+ points = np.vstack((x,y)).T
+
-+
+ p = Path(pol)
+ grid = p.contains_points(points)
-+ grid = grid.reshape((ny + 1,nx + 1))
-+
++ grid = grid.reshape((ny + 1, nx + 1))
+ raster = np.zeros((height, width), dtype=np.uint8)#TODO bool
+
+ #TODO shift by 0.5
+ B = np.ones((2,2))/4
+ raster = convolve2d(grid, B, 'valid')
+
-+
-+ #TODO this part is very inefficient, replace it with better solution
-+ #for (y, x), value in np.ndenumerate(grid):
-+
-+ # if x >= width - 1: continue
-+ # if y >= height - 1: continue
-+
-+ # if grid[y, x]:
-+ # raster[y, x] = 1
-+ # raster[y + 1, x] = 1
-+ # raster[y, x + 1] = 1
-+ # raster[y + 1, x + 1] = 1
-+
+ return raster
+
+#TODO move to utils?
@@ -6088,25 +6628,9 @@
+
+ def GetScattId(self):
+ return self.scatt_id
-Index: gui/wxpython/scatt_plot/__init__.py
-===================================================================
---- gui/wxpython/scatt_plot/__init__.py (revision 0)
-+++ gui/wxpython/scatt_plot/__init__.py (working copy)
-@@ -0,0 +1,11 @@
-+all = [
-+ 'dialogs',
-+ 'controllers',
-+ 'frame',
-+ 'gthreading',
-+ 'plots',
-+ 'scatt_core',
-+ 'toolbars',
-+ 'scatt_core',
-+ 'core_c',
-+ ]
Index: gui/wxpython/vnet/dialogs.py
===================================================================
---- gui/wxpython/vnet/dialogs.py (revision 57633)
+--- gui/wxpython/vnet/dialogs.py (revision 57644)
+++ gui/wxpython/vnet/dialogs.py (working copy)
@@ -1218,7 +1218,7 @@
pos = (row, 1))
@@ -6119,7 +6643,7 @@
styleBoxSizer.Add(item = gridSizer, flag = wx.EXPAND)
Index: gui/wxpython/vnet/toolbars.py
===================================================================
---- gui/wxpython/vnet/toolbars.py (revision 57633)
+--- gui/wxpython/vnet/toolbars.py (revision 57644)
+++ gui/wxpython/vnet/toolbars.py (working copy)
@@ -19,9 +19,9 @@
@@ -6135,7 +6659,7 @@
class PointListToolbar(BaseToolbar):
Index: gui/wxpython/Makefile
===================================================================
---- gui/wxpython/Makefile (revision 57633)
+--- gui/wxpython/Makefile (revision 57644)
+++ gui/wxpython/Makefile (working copy)
@@ -13,7 +13,7 @@
$(wildcard animation/* core/*.py dbmgr/* gcp/*.py gmodeler/* \
@@ -6157,552 +6681,3 @@
DSTDIRS := $(patsubst %,$(ETCDIR)/%,icons scripts xml)
default: $(DSTFILES)
-Index: gui/wxpython/vdigit/wxdigit.py
-===================================================================
---- gui/wxpython/vdigit/wxdigit.py (revision 57633)
-+++ gui/wxpython/vdigit/wxdigit.py (working copy)
-@@ -17,7 +17,7 @@
- (and NumPy would be an excellent candidate for acceleration via
- e.g. OpenCL or CUDA; I'm surprised it hasn't happened already).
-
--(C) 2007-2011 by the GRASS Development Team
-+(C) 2007-2011, 2013 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.
-@@ -27,6 +27,8 @@
-
- import grass.script.core as grass
-
-+from grass.pydispatch.signal import Signal
-+
- from core.gcmd import GError
- from core.debug import Debug
- from core.settings import UserSettings
-@@ -176,7 +178,21 @@
-
- if self.poMapInfo:
- self.InitCats()
--
-+
-+ self.emit_signals = False
-+
-+ # signals which describes features changes during digitization,
-+ # activate them using EmitSignals method
-+ #TODO signal for errors?
-+ self.featureAdded = Signal('IVDigit.featureAdded')
-+ self.areasDeleted = Signal('IVDigit.areasDeleted')
-+ self.vertexMoved = Signal('IVDigit.vertexMoved')
-+ self.vertexAdded = Signal('IVDigit.vertexAdded')
-+ self.vertexRemoved = Signal('IVDigit.vertexRemoved')
-+ self.featuresDeleted = Signal('IVDigit.featuresDeleted')
-+ self.featuresMoved = Signal('IVDigit.featuresMoved')
-+ self.lineEdited = Signal('IVDigit.lineEdited')
-+
- def __del__(self):
- Debug.msg(1, "IVDigit.__del__()")
- Vect_destroy_line_struct(self.poPoints)
-@@ -188,7 +204,12 @@
- Vect_close(self.poBgMapInfo)
- self.poBgMapInfo = self.popoBgMapInfo = None
- del self.bgMapInfo
--
-+
-+ def EmitSignals(self, emit):
-+ """!Activate/deactivate signals which describes features changes during digitization.
-+ """
-+ self.emit_signals = emit
-+
- def CloseBackgroundMap(self):
- """!Close background vector map"""
- if not self.poBgMapInfo:
-@@ -394,7 +415,6 @@
-
- @return tuple (number of added features, feature ids)
- """
--
- layer = self._getNewFeaturesLayer()
- cat = self._getNewFeaturesCat()
-
-@@ -419,10 +439,14 @@
- return (-1, None)
-
- self.toolbar.EnableUndo()
--
-- return self._addFeature(vtype, points, layer, cat,
-- self._getSnapMode(), self._display.GetThreshold())
--
-+
-+ ret = self._addFeature(vtype, points, layer, cat,
-+ self._getSnapMode(), self._display.GetThreshold())
-+ if ret[0] > -1 and self.emit_signals:
-+ self.featureAdded.emit(new_bboxs = [self._createBbox(points)], new_areas_cats = [[{layer : [cat]}, None]])
-+
-+ return ret
-+
- def DeleteSelectedLines(self):
- """!Delete selected features
-
-@@ -434,16 +458,27 @@
- # collect categories for deleting if requested
- deleteRec = UserSettings.Get(group = 'vdigit', key = 'delRecord', subkey = 'enabled')
- catDict = dict()
-+
-+ old_bboxs = []
-+ old_areas_cats = []
- if deleteRec:
- for i in self._display.selected['ids']:
-+
- if Vect_read_line(self.poMapInfo, None, self.poCats, i) < 0:
- self._error.ReadLine(i)
-
-- cats = self.poCats.contents
-- for j in range(cats.n_cats):
-- if cats.field[j] not in catDict.keys():
-- catDict[cats.field[j]] = list()
-- catDict[cats.field[j]].append(cats.cat[j])
-+ if self.emit_signals:
-+ ret = self._getLineAreaBboxCats(i)
-+ if ret:
-+ old_bboxs += ret[0]
-+ old_areas_cats += ret[1]
-+
-+ # catDict was not used -> put into comment
-+ #cats = self.poCats.contents
-+ #for j in range(cats.n_cats):
-+ # if cats.field[j] not in catDict.keys():
-+ # catDict[cats.field[j]] = list()
-+ # catDict[cats.field[j]].append(cats.cat[j])
-
- poList = self._display.GetSelectedIList()
- nlines = Vedit_delete_lines(self.poMapInfo, poList)
-@@ -456,7 +491,10 @@
- self._deleteRecords(catDict)
- self._addChangeset()
- self.toolbar.EnableUndo()
--
-+
-+ if self.emit_signals:
-+ self.featuresDeleted.emit(old_bboxs = old_bboxs, old_areas_cats = old_areas_cats)
-+
- return nlines
-
- def _deleteRecords(self, cats):
-@@ -512,22 +550,173 @@
-
- @return number of deleted
- """
-+ if len(self._display.selected['ids']) < 1:
-+ return 0
-+
- poList = self._display.GetSelectedIList()
- cList = poList.contents
-
- nareas = 0
-+ old_bboxs = []
-+ old_areas_cats = []
-+
- for i in range(cList.n_values):
-+
- if Vect_get_line_type(self.poMapInfo, cList.value[i]) != GV_CENTROID:
- continue
--
-+
-+ if self.emit_signals:
-+ area = Vect_get_centroid_area(self.poMapInfo, cList.value[i]);
-+ if area > 0:
-+ bbox, cats = self._getaAreaBboxCats(area)
-+ old_bboxs += bbox
-+ old_areas_cats += cats
-+
- nareas += Vedit_delete_area_centroid(self.poMapInfo, cList.value[i])
-
- if nareas > 0:
- self._addChangeset()
- self.toolbar.EnableUndo()
-+ if self.emit_signals:
-+ self.areasDeleted.emit(old_bboxs = old_bboxs, old_areas_cats = old_areas_cats)
-+
-+ return nareas
-+
-+ def _getLineAreaBboxCats(self, ln_id):
-+ ltype = Vect_read_line(self.poMapInfo, None, None, ln_id)
-+
-+ if ltype == GV_CENTROID:
-+ #TODO centroid opttimization, can be adited also its area -> it will appear two times in new_ lists
-+ return self._getCentroidAreaBboxCats(ln_id)
-+ else:
-+ return [self._getBbox(ln_id)], [self._getLineAreasCategories(ln_id)]
-+
-+
-+ def _getCentroidAreaBboxCats(self, centroid):
-+ if not Vect_line_alive(self.poMapInfo, centroid):
-+ return None
-+
-+ area = Vect_get_centroid_area(self.poMapInfo, centroid)
-+ if area > 0:
-+ return self._getaAreaBboxCats(area)
-+ else:
-+ return None
-+
-+ def _getaAreaBboxCats(self, area):
-+
-+ po_b_list = Vect_new_list()
-+ Vect_get_area_boundaries(self.poMapInfo, area, po_b_list);
-+ b_list = po_b_list.contents
-+
-+ geoms = []
-+ areas_cats = []
-+
-+ if b_list.n_values > 0:
-+ for i_line in range(b_list.n_values):
-+
-+ line = b_list.value[i_line];
-+
-+ geoms.append(self._getBbox(abs(line)))
-+ areas_cats.append(self._getLineAreasCategories(abs(line)))
-
-- return nareas
-+ Vect_destroy_list(po_b_list);
-+
-+ return geoms, areas_cats
-+
-+ def _getLineAreasCategories(self, ln_id):
-+ if not Vect_line_alive (self.poMapInfo, ln_id):
-+ return []
-+
-+ ltype = Vect_read_line(self.poMapInfo, None, None, ln_id)
-+ if ltype != GV_BOUNDARY:
-+ return []
-+
-+ cats = [None, None]
-+
-+ left = c_int()
-+ right = c_int()
-+
-+ if Vect_get_line_areas(self.poMapInfo, ln_id, pointer(left), pointer(right)) == 1:
-+ areas = [left.value, right.value]
-+
-+ for i, a in enumerate(areas):
-+ if a > 0:
-+ centroid = Vect_get_area_centroid(self.poMapInfo, a)
-+ if centroid <= 0:
-+ continue
-+ c = self._getCategories(centroid)
-+ if c:
-+ cats[i] = c
-+
-+ return cats
-+
-+ def _getCategories(self, ln_id):
-+ if not Vect_line_alive (self.poMapInfo, ln_id):
-+ return none
-+
-+ poCats = Vect_new_cats_struct()
-+ if Vect_read_line(self.poMapInfo, None, poCats, ln_id) < 0:
-+ Vect_destroy_cats_struct(poCats)
-+ return None
-+
-+ cCats = poCats.contents
-+
-+ cats = {}
-+ for j in range(cCats.n_cats):
-+ if cats.has_key(cCats.field[j]):
-+ cats[cCats.field[j]].append(cCats.cat[j])
-+ else:
-+ cats[cCats.field[j]] = [cCats.cat[j]]
-
-+ Vect_destroy_cats_struct(poCats)
-+ return cats
-+
-+ def _getBbox(self, ln_id):
-+ if not Vect_line_alive (self.poMapInfo, ln_id):
-+ return None
-+
-+ poPoints = Vect_new_line_struct()
-+ if Vect_read_line(self.poMapInfo, poPoints, None, ln_id) < 0:
-+ Vect_destroy_line_struct(poPoints)
-+ return []
-+
-+ geom = self._convertGeom(poPoints)
-+ bbox = self._createBbox(geom)
-+ Vect_destroy_line_struct(poPoints)
-+ return bbox
-+
-+ def _createBbox(self, points):
-+
-+ bbox = {}
-+ for pt in points:
-+ if not bbox.has_key('maxy'):
-+ bbox['maxy'] = pt[1]
-+ bbox['miny'] = pt[1]
-+ bbox['maxx'] = pt[0]
-+ bbox['minx'] = pt[0]
-+ continue
-+
-+ if bbox['maxy'] < pt[1]:
-+ bbox['maxy'] = pt[1]
-+ elif bbox['miny'] > pt[1]:
-+ bbox['miny'] = pt[1]
-+
-+ if bbox['maxx'] < pt[0]:
-+ bbox['maxx'] = pt[0]
-+ elif bbox['minx'] > pt[0]:
-+ bbox['minx'] = pt[0]
-+ return bbox
-+
-+ def _convertGeom(self, poPoints):
-+
-+ Points = poPoints.contents
-+
-+ pts_geom = []
-+ for j in range(Points.n_points):
-+ pts_geom.append((Points.x[j], Points.y[j]))
-+
-+ return pts_geom
-+
- def MoveSelectedLines(self, move):
- """!Move selected features
-
-@@ -536,16 +725,45 @@
- if not self._checkMap():
- return -1
-
-+ nsel = len(self._display.selected['ids'])
-+ if nsel < 1:
-+ return -1
-+
- thresh = self._display.GetThreshold()
- snap = self._getSnapMode()
-
- poList = self._display.GetSelectedIList()
-+
-+ if self.emit_signals:
-+ old_bboxs = []
-+ old_areas_cats = []
-+ for sel_id in self._display.selected['ids']:
-+ ret = self._getLineAreaBboxCats(sel_id)
-+ if ret:
-+ old_bboxs += ret[0]
-+ old_areas_cats += ret[1]
-+
-+ Vect_set_updated(self.poMapInfo, 1)
-+ n_up_lines_old = Vect_get_num_updated_lines(self.poMapInfo)
-+
- nlines = Vedit_move_lines(self.poMapInfo, self.popoBgMapInfo, int(self.poBgMapInfo is not None),
- poList,
- move[0], move[1], 0,
- snap, thresh)
-+
- Vect_destroy_list(poList)
--
-+
-+ if nlines > 0 and self.emit_signals:
-+ new_bboxs = []
-+ new_areas_cats = []
-+ n_up_lines = Vect_get_num_updated_lines(self.poMapInfo)
-+ for i in range(n_up_lines_old, n_up_lines):
-+ new_id = Vect_get_updated_line(self.poMapInfo, i)
-+ ret = self._getLineAreaBboxCats(new_id)
-+ if ret:
-+ new_bboxs += ret[0]
-+ new_areas_cats += ret[1]
-+
- if nlines > 0 and self._settings['breakLines']:
- for i in range(1, nlines):
- self._breakLineAtIntersection(nlines + i, None, changeset)
-@@ -553,7 +771,13 @@
- if nlines > 0:
- self._addChangeset()
- self.toolbar.EnableUndo()
--
-+
-+ if self.emit_signals:
-+ self.featuresMoved.emit(new_bboxs = new_bboxs,
-+ old_bboxs = old_bboxs,
-+ old_areas_cats = old_areas_cats,
-+ new_areas_cats = new_areas_cats)
-+
- return nlines
-
- def MoveSelectedVertex(self, point, move):
-@@ -571,12 +795,21 @@
-
- if len(self._display.selected['ids']) != 1:
- return -1
--
-+
-+ # move only first found vertex in bbox
-+ poList = self._display.GetSelectedIList()
-+
-+ if self.emit_signals:
-+ cList = poList.contents
-+ old_bboxs = [self._getBbox(cList.value[0])]
-+ old_areas_cats = [self._getLineAreasCategories(cList.value[0])]
-+
-+ Vect_set_updated(self.poMapInfo, 1)
-+ n_up_lines_old = Vect_get_num_updated_lines(self.poMapInfo)
-+
- Vect_reset_line(self.poPoints)
- Vect_append_point(self.poPoints, point[0], point[1], 0.0)
--
-- # move only first found vertex in bbox
-- poList = self._display.GetSelectedIList()
-+
- moved = Vedit_move_vertex(self.poMapInfo, self.popoBgMapInfo, int(self.poBgMapInfo is not None),
- poList, self.poPoints,
- self._display.GetThreshold(type = 'selectThresh'),
-@@ -584,7 +817,17 @@
- move[0], move[1], 0.0,
- 1, self._getSnapMode())
- Vect_destroy_list(poList)
--
-+
-+ if moved > 0 and self.emit_signals:
-+ n_up_lines = Vect_get_num_updated_lines(self.poMapInfo)
-+
-+ new_bboxs = []
-+ new_areas_cats = []
-+ for i in range(n_up_lines_old, n_up_lines):
-+ new_id = Vect_get_updated_line(self.poMapInfo, i)
-+ new_bboxs.append(self._getBbox(new_id))
-+ new_areas_cats.append(self._getLineAreasCategories(new_id))
-+
- if moved > 0 and self._settings['breakLines']:
- self._breakLineAtIntersection(Vect_get_num_lines(self.poMapInfo),
- None)
-@@ -592,7 +835,13 @@
- if moved > 0:
- self._addChangeset()
- self.toolbar.EnableUndo()
--
-+
-+ if self.emit_signals:
-+ self.vertexMoved.emit(new_bboxs = new_bboxs,
-+ new_areas_cats = new_areas_cats,
-+ old_areas_cats = old_areas_cats,
-+ old_bboxs = old_bboxs)
-+
- return moved
-
- def AddVertex(self, coords):
-@@ -681,6 +930,10 @@
- self._error.ReadLine(line)
- return -1
-
-+ if self.emit_signals:
-+ old_bboxs = [self._getBbox(line)]
-+ old_areas_cats = [self._getLineAreasCategories(line)]
-+
- # build feature geometry
- Vect_reset_line(self.poPoints)
- for p in coords:
-@@ -696,6 +949,9 @@
-
- newline = Vect_rewrite_line(self.poMapInfo, line, ltype,
- self.poPoints, self.poCats)
-+ if newline > 0 and self.emit_signals:
-+ new_geom = [self._getBbox(newline)]
-+ new_areas_cats = [self._getLineAreasCategories(newline)]
-
- if newline > 0 and self._settings['breakLines']:
- self._breakLineAtIntersection(newline, None)
-@@ -703,7 +959,13 @@
- if newline > 0:
- self._addChangeset()
- self.toolbar.EnableUndo()
--
-+
-+ if self.emit_signals:
-+ self.lineEdited.emit(old_bboxs = old_bboxs,
-+ old_areas_cats = old_areas_cats,
-+ new_bboxs = new_bboxs,
-+ new_areas_cats = new_areas_cats)
-+
- return newline
-
- def FlipLine(self):
-@@ -1514,6 +1776,16 @@
- return 0
-
- poList = self._display.GetSelectedIList()
-+
-+ if self.emit_signals:
-+ cList = poList.contents
-+
-+ old_bboxs = [self._getBbox(cList.value[0])]
-+ old_areas_cats = [self._getLineAreasCategories(cList.value[0])]
-+
-+ Vect_set_updated(self.poMapInfo, 1)
-+ n_up_lines_old = Vect_get_num_updated_lines(self.poMapInfo)
-+
- Vect_reset_line(self.poPoints)
- Vect_append_point(self.poPoints, coords[0], coords[1], 0.0)
-
-@@ -1525,15 +1797,35 @@
- else:
- ret = Vedit_remove_vertex(self.poMapInfo, poList,
- self.poPoints, thresh)
-+
- Vect_destroy_list(poList)
-+
-+ if ret > 0 and self.emit_signals:
-+ new_bboxs = []
-+ new_areas_cats = []
-+
-+ n_up_lines = Vect_get_num_updated_lines(self.poMapInfo)
-+ for i in range(n_up_lines_old, n_up_lines):
-+ new_id = Vect_get_updated_line(self.poMapInfo, i)
-+ new_areas_cats.append(self._getLineAreasCategories(new_id))
-+ new_bboxs.append(self._getBbox(new_id))
-
- if not add and ret > 0 and self._settings['breakLines']:
- self._breakLineAtIntersection(Vect_get_num_lines(self.poMapInfo),
- None)
--
-+
- if ret > 0:
- self._addChangeset()
--
-+
-+ if ret > 0 and self.emit_signals:
-+ if add:
-+ self.vertexAdded.emit(old_bboxs = old_bboxs, new_bboxs = new_bboxs)
-+ else:
-+ self.vertexRemoved.emit(old_bboxs = old_bboxs,
-+ new_bboxs = new_bboxs,
-+ old_areas_cats = old_areas_cats,
-+ new_areas_cats = new_areas_cats)
-+
- return 1
-
- def GetLineCats(self, line):
-Index: gui/wxpython/vdigit/toolbars.py
-===================================================================
---- gui/wxpython/vdigit/toolbars.py (revision 57633)
-+++ gui/wxpython/vdigit/toolbars.py (working copy)
-@@ -17,6 +17,7 @@
- import wx
-
- from grass.script import core as grass
-+from grass.pydispatch.signal import Signal
-
- from gui_core.toolbars import BaseToolbar, BaseIcons
- from gui_core.dialogs import CreateNewVector
-@@ -42,6 +43,8 @@
- self.digit = None
- self._giface = giface
-
-+ self.editingStarted = Signal("VDigitToolbar.editingStarted")
-+
- # currently selected map layer for editing (reference to MapLayer instance)
- self.mapLayer = None
- # list of vector layers from Layer Manager (only in the current mapset)
-@@ -860,6 +863,7 @@
- alpha = int(opacity * 255)
- self.digit.GetDisplay().UpdateSettings(alpha = alpha)
-
-+ self.editingStarted.emit(vectMap = mapLayer.GetName(), digit = self.digit)
- return True
-
- def StopEditing(self):
More information about the grass-commit
mailing list