[goffice] Implement custom grids in xyz plots. [#624273]
- From: Jean Bréfort <jbrefort src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Implement custom grids in xyz plots. [#624273]
- Date: Thu, 23 Sep 2010 14:51:08 +0000 (UTC)
commit a2c9cde8524ea3b1c7e471d7c8a1526e1fa4ab16
Author: Jean Brefort <jean brefort normalesup org>
Date: Thu Sep 23 16:52:22 2010 +0200
Implement custom grids in xyz plots. [#624273]
ChangeLog | 11 +
NEWS | 3 +
plugins/plot_surface/gog-contour.c | 2 +-
plugins/plot_surface/gog-contour.h | 2 +-
plugins/plot_surface/gog-xyz-surface-prefs.c | 92 ++++++++-
plugins/plot_surface/gog-xyz-surface-prefs.ui | 194 ++++++++++++++++--
plugins/plot_surface/gog-xyz-surface.c | 273 ++++++++++++++++++++-----
plugins/plot_surface/gog-xyz-surface.h | 11 +-
plugins/plot_surface/gog-xyz.h | 1 +
9 files changed, 502 insertions(+), 87 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index a4d108f..75d487d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2010-09-23 Jean Brefort <jean brefort normalesup org>
+
+ * plugins/plot_surface/gog-contour.c: implement
+ custom grids in xyz plots. [#624273]
+ * plugins/plot_surface/gog-contour.h: ditto.
+ * plugins/plot_surface/gog-xyz-surface-prefs.c: ditto.
+ * plugins/plot_surface/gog-xyz-surface-prefs.ui: ditto.
+ * plugins/plot_surface/gog-xyz-surface.c: ditto.
+ * plugins/plot_surface/gog-xyz-surface.h: ditto.
+ * plugins/plot_surface/gog-xyz.h: ditto.
+
2010-09-20 Jon Nordby <jonn openismus com>
* docs/reference/goffice-docs.sgml: update API documentation.
diff --git a/NEWS b/NEWS
index ccfbf16..5c5e661 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
goffice 0.8.11:
+Jean:
+ * Implement custom grids in xyz plots. [#624273]
+
Jon Nordby:
* Update API documentation.
diff --git a/plugins/plot_surface/gog-contour.c b/plugins/plot_surface/gog-contour.c
index 71d260e..7f9ba57 100644
--- a/plugins/plot_surface/gog-contour.c
+++ b/plugins/plot_surface/gog-contour.c
@@ -288,7 +288,7 @@ gog_contour_view_render (GogView *view, GogViewAllocation const *bbox)
imax = plot->rows;
jmax = plot->columns;
}
- if (imax ==0 || jmax == 0)
+ if (imax == 0 || jmax == 0)
return;
if (plot->plotted_data)
diff --git a/plugins/plot_surface/gog-contour.h b/plugins/plot_surface/gog-contour.h
index 82c80e5..01d0116 100644
--- a/plugins/plot_surface/gog-contour.h
+++ b/plugins/plot_surface/gog-contour.h
@@ -38,7 +38,7 @@ typedef GogXYZPlotClass GogContourPlotClass;
#define GOG_TYPE_CONTOUR_PLOT (gog_contour_plot_get_type ())
#define GOG_CONTOUR_PLOT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_TYPE_CONTOUR_PLOT, GogContourPlot))
-#define GOG_IS_PLOT_CONTOUR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_TYPE_CONTOUR_PLOT))
+#define GOG_IS_CONTOUR_PLOT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_TYPE_CONTOUR_PLOT))
GType gog_contour_plot_get_type (void);
void gog_contour_plot_register_type (GTypeModule *module);
diff --git a/plugins/plot_surface/gog-xyz-surface-prefs.c b/plugins/plot_surface/gog-xyz-surface-prefs.c
index c6eb5eb..1ecf9df 100644
--- a/plugins/plot_surface/gog-xyz-surface-prefs.c
+++ b/plugins/plot_surface/gog-xyz-surface-prefs.c
@@ -27,7 +27,12 @@
#include <string.h>
-GtkWidget *gog_xyz_surface_plot_pref (GogXYZSurfacePlot *plot, GOCmdContext *cc);
+GtkWidget *gog_xyz_surface_plot_pref (GogXYZPlot *plot, GogDataAllocator *dalloc, GOCmdContext *cc);
+
+typedef struct {
+ GogXYZPlot *plot;
+ GtkWidget *x_spin, *y_spin, *x_label, *y_label, *x_entry, *y_entry;
+} XYZSurfPrefsState;
static void
cb_rows_changed (GtkAdjustment *adj, GObject *plot)
@@ -41,33 +46,100 @@ cb_columns_changed (GtkAdjustment *adj, GObject *plot)
g_object_set (plot, "columns", (int) gtk_adjustment_get_value (adj), NULL);
}
+static void
+cb_cols_toggled (GtkToggleButton *btn, XYZSurfPrefsState *state)
+{
+ if (gtk_toggle_button_get_active (btn)) {
+ gtk_widget_show (state->x_spin);
+ gtk_widget_show (state->x_label);
+ gtk_widget_hide (state->x_entry);
+ g_object_set (state->plot, "auto-columns", TRUE, NULL);
+ } else {
+ gtk_widget_hide (state->x_spin);
+ gtk_widget_hide (state->x_label);
+ gtk_widget_show (state->x_entry);
+ g_object_set (state->plot, "auto-columns", FALSE, NULL);
+ }
+}
+
+static void
+cb_rows_toggled (GtkToggleButton *btn, XYZSurfPrefsState *state)
+{
+ if (gtk_toggle_button_get_active (btn)) {
+ gtk_widget_show (state->y_spin);
+ gtk_widget_show (state->y_label);
+ gtk_widget_hide (state->y_entry);
+ g_object_set (state->plot, "auto-rows", TRUE, NULL);
+ } else {
+ gtk_widget_hide (state->y_spin);
+ gtk_widget_hide (state->y_label);
+ gtk_widget_show (state->y_entry);
+ g_object_set (state->plot, "auto-rows", FALSE, NULL);
+ }
+}
+
GtkWidget *
-gog_xyz_surface_plot_pref (GogXYZSurfacePlot *plot, GOCmdContext *cc)
+gog_xyz_surface_plot_pref (GogXYZPlot *plot, GogDataAllocator *dalloc, GOCmdContext *cc)
{
- GogXYZPlot *xyz = GOG_XYZ_PLOT (plot);
- GtkWidget *w;
+ XYZSurfPrefsState *state;
+ GtkWidget *w, *box;
char const *dir = go_plugin_get_dir_name (
go_plugins_get_plugin_by_id ("GOffice_plot_surface"));
char *path = g_build_filename (dir, "gog-xyz-surface-prefs.ui", NULL);
GtkBuilder *gui = go_gtk_builder_new (path, GETTEXT_PACKAGE, cc);
+ GogDataset *set = GOG_DATASET (plot);
g_free (path);
if (gui == NULL)
return NULL;
- w = go_gtk_builder_get_widget (gui, "rows_spinner");
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (w), xyz->rows);
+ state = g_new (XYZSurfPrefsState, 1);
+ state->plot = plot;
+
+ state->x_spin = w = go_gtk_builder_get_widget (gui, "columns_spinner");
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (w), plot->columns);
g_signal_connect (G_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (w))),
"value_changed",
- G_CALLBACK (cb_rows_changed), plot);
+ G_CALLBACK (cb_columns_changed), plot);
+ state->x_label = go_gtk_builder_get_widget (gui, "cols-nb-lbl");
- w = go_gtk_builder_get_widget (gui, "columns_spinner");
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (w), xyz->columns);
+ box = go_gtk_builder_get_widget (gui, "cols-box");
+ state->x_entry = GTK_WIDGET (gog_data_allocator_editor (dalloc, set, 0, GOG_DATA_VECTOR));
+ gtk_widget_show_all (state->x_entry);
+ gtk_box_pack_start (GTK_BOX (box), state->x_entry, TRUE, TRUE, 0);
+ w = go_gtk_builder_get_widget (gui, "preset-cols-btn");
+ if (!state->plot->auto_x) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), TRUE);
+ gtk_widget_hide (state->x_spin);
+ gtk_widget_hide (state->x_label);
+ } else
+ gtk_widget_hide (state->x_entry);
+ w = go_gtk_builder_get_widget (gui, "calc-cols-btn");
+ g_signal_connect (G_OBJECT (w), "toggled", G_CALLBACK (cb_cols_toggled), state);
+
+ state->y_spin = w = go_gtk_builder_get_widget (gui, "rows_spinner");
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (w), plot->rows);
g_signal_connect (G_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (w))),
"value_changed",
- G_CALLBACK (cb_columns_changed), plot);
+ G_CALLBACK (cb_rows_changed), plot);
+ state->y_label = go_gtk_builder_get_widget (gui, "rows-nb-lbl");
+
+ box = go_gtk_builder_get_widget (gui, "rows-box");
+ state->y_entry = GTK_WIDGET (gog_data_allocator_editor (dalloc, set, 1, GOG_DATA_VECTOR));
+ gtk_widget_show_all (state->y_entry);
+ gtk_box_pack_start (GTK_BOX (box), state->y_entry, TRUE, TRUE, 0);
+ w = go_gtk_builder_get_widget (gui, "preset-rows-btn");
+ if (!state->plot->auto_y) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), TRUE);
+ gtk_widget_hide (state->y_spin);
+ gtk_widget_hide (state->y_label);
+ } else
+ gtk_widget_hide (state->y_entry);
+ w = go_gtk_builder_get_widget (gui, "calc-rows-btn");
+ g_signal_connect (G_OBJECT (w), "toggled", G_CALLBACK (cb_rows_toggled), state);
w = GTK_WIDGET (g_object_ref (gtk_builder_get_object (gui, "gog_xyz_surface_prefs")));
+ g_object_set_data_full (G_OBJECT (w), "state", state, g_free);
g_object_unref (gui);
return w;
diff --git a/plugins/plot_surface/gog-xyz-surface-prefs.ui b/plugins/plot_surface/gog-xyz-surface-prefs.ui
index 8b8dda5..e1d01f1 100644
--- a/plugins/plot_surface/gog-xyz-surface-prefs.ui
+++ b/plugins/plot_surface/gog-xyz-surface-prefs.ui
@@ -1,5 +1,6 @@
<?xml version="1.0"?>
<interface>
+ <!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy toplevel-contextual -->
<object class="GtkAdjustment" id="adjustment1">
<property name="value">10</property>
@@ -18,65 +19,103 @@
<object class="GtkTable" id="gog_xyz_surface_prefs">
<property name="visible">True</property>
<property name="border_width">12</property>
- <property name="n_rows">2</property>
- <property name="n_columns">2</property>
+ <property name="n_rows">6</property>
+ <property name="n_columns">3</property>
<property name="column_spacing">12</property>
<property name="row_spacing">6</property>
<child>
- <object class="GtkLabel" id="label61">
+ <object class="GtkLabel" id="rows_lbl">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
- <property name="label" translatable="yes">_Rows:</property>
+ <property name="label" translatable="yes"><b>_Rows:</b></property>
+ <property name="use_markup">True</property>
<property name="use_underline">True</property>
- <property name="mnemonic_widget">rows_spinner</property>
</object>
<packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="label64">
+ <object class="GtkLabel" id="cols_lbl">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">_Columns:</property>
+ <property name="yalign">0.46000000834465027</property>
+ <property name="label" translatable="yes"><b>_Columns:</b></property>
+ <property name="use_markup">True</property>
<property name="use_underline">True</property>
- <property name="mnemonic_widget">columns_spinner</property>
</object>
<packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
- <object class="GtkSpinButton" id="rows_spinner">
+ <object class="GtkRadioButton" id="calc-rows-btn">
+ <property name="label" translatable="yes">Calculated</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ <property name="x_padding">12</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="preset-rows-btn">
+ <property name="label" translatable="yes">Preset:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="invisible_char">•</property>
- <property name="adjustment">adjustment1</property>
- <property name="climb_rate">10</property>
- <property name="snap_to_ticks">True</property>
- <property name="numeric">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">calc-rows-btn</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ <property name="x_padding">12</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="calc-cols-btn">
+ <property name="label" translatable="yes">Calculated</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
+ <property name="x_padding">12</property>
</packing>
</child>
<child>
- <object class="GtkSpinButton" id="columns_spinner">
+ <object class="GtkRadioButton" id="preset-cols-btn">
+ <property name="label" translatable="yes">Preset:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="invisible_char">•</property>
- <property name="adjustment">adjustment2</property>
- <property name="climb_rate">0.10000000000000001</property>
- <property name="snap_to_ticks">True</property>
- <property name="numeric">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">calc-cols-btn</property>
</object>
<packing>
<property name="left_attach">1</property>
@@ -85,7 +124,118 @@
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
+ <property name="x_padding">12</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="rows-box">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="rows-nb-lbl">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Count:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="rows_spinner">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="climb_rate">10</property>
+ <property name="snap_to_ticks">True</property>
+ <property name="numeric">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="y_options"></property>
+ <property name="x_padding">12</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="cols-box">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="cols-nb-lbl">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Count:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="columns_spinner">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="adjustment">adjustment2</property>
+ <property name="climb_rate">0.10000000000000001</property>
+ <property name="snap_to_ticks">True</property>
+ <property name="numeric">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ <property name="x_padding">12</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="xalign">0.46000000834465027</property>
+ <property name="label" translatable="yes">
+</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
</packing>
</child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
</object>
</interface>
diff --git a/plugins/plot_surface/gog-xyz-surface.c b/plugins/plot_surface/gog-xyz-surface.c
index 4975cbb..f904735 100644
--- a/plugins/plot_surface/gog-xyz-surface.c
+++ b/plugins/plot_surface/gog-xyz-surface.c
@@ -38,7 +38,9 @@
enum {
XYZ_SURFACE_PROP_0,
XYZ_SURFACE_PROP_ROWS,
- XYZ_SURFACE_PROP_COLUMNS
+ XYZ_SURFACE_PROP_COLUMNS,
+ XYZ_SURFACE_PROP_AUTO_ROWS,
+ XYZ_SURFACE_PROP_AUTO_COLUMNS
};
static GogObjectClass *plot_xyz_contour_parent_klass;
@@ -46,44 +48,112 @@ static GogObjectClass *plot_xyz_surface_parent_klass;
#define EPSILON 1e-13
+typedef struct {
+ double const *values[2];
+ unsigned cur_series;
+} xyz_data;
+
+static int
+data_compare (unsigned const *a, unsigned const *b, xyz_data *data)
+{
+ double xa = data->values[data->cur_series][*a],
+ xb = data->values[data->cur_series][*b];
+ if (xa < xb)
+ return -1;
+ else if (xa == xb)
+ return 0;
+ else
+ return 1;
+}
+
static double *
gog_xyz_surface_plot_build_matrix (GogXYZPlot const *plot, gboolean *cardinality_changed)
{
- unsigned i, j, k, index;
+ unsigned i, j, k, l, index;
GogSeries *series = GOG_SERIES (plot->base.series->data);
const double *x_vals, *y_vals, *z_vals = NULL;
+ double *x_limits, *y_limits;
double *data;
- unsigned *grid;
- unsigned n = plot->rows * plot->columns;
- unsigned kmax = gog_series_get_xyz_data (GOG_SERIES (series),
+ unsigned *grid, n, kmax, imax, jmax;
+ double xmin, ymin, xinc, yinc;
+ xyz_data raw_data;
+ unsigned *sort;
+ if (GOG_IS_CONTOUR_PLOT (plot)) {
+ GogXYZContourPlot *xyz = GOG_XYZ_CONTOUR_PLOT (plot);
+ if (xyz->grid[0].data) {
+ xyz->base.x_vals = g_object_ref (xyz->grid[0].data);
+ xyz->base.columns = go_data_get_vector_size (plot->x_vals);
+ }
+ if (xyz->grid[1].data) {
+ xyz->base.y_vals = g_object_ref (xyz->grid[1].data);
+ xyz->base.rows = go_data_get_vector_size (plot->y_vals);
+ }
+ } else {
+ GogXYZSurfacePlot *xyz = GOG_XYZ_SURFACE_PLOT (plot);
+ if (xyz->grid[0].data) {
+ xyz->base.x_vals = g_object_ref (xyz->grid[0].data);
+ xyz->base.columns = go_data_get_vector_size (plot->x_vals);
+ }
+ if (xyz->grid[1].data) {
+ xyz->base.y_vals = g_object_ref (xyz->grid[1].data);
+ xyz->base.rows = go_data_get_vector_size (plot->y_vals);
+ }
+ }
+ n = plot->rows * plot->columns;
+ if (n == 0)
+ return NULL;
+ x_limits = go_range_sort (go_data_get_values (gog_xyz_plot_get_x_vals ((GogXYZPlot *) plot)), plot->columns);
+ for (i = 0; i < plot->columns - 1; i++)
+ x_limits[i] = (x_limits[i] + x_limits[i+1]) / 2.;
+ x_limits[i] = G_MAXDOUBLE;
+ y_limits = go_range_sort (go_data_get_values (gog_xyz_plot_get_y_vals ((GogXYZPlot *) plot)), plot->rows);
+ for (i = 0; i < plot->rows - 1; i++)
+ y_limits[i] = (y_limits[i] + y_limits[i+1]) / 2.;
+ y_limits[i] = G_MAXDOUBLE;
+ kmax = gog_series_get_xyz_data (GOG_SERIES (series),
&x_vals, &y_vals, &z_vals);
- unsigned imax = plot->rows;
- unsigned jmax = plot->columns;
- double xmin = plot->x.minima;
- double ymin = plot->y.minima;
- double xinc = (plot->x.maxima - xmin) / (jmax - 1);
- double yinc = (plot->y.maxima - ymin) / (imax - 1);
+ /* sort the data by column and row */
+ raw_data.values[0] = x_vals;
+ raw_data.values[1] = y_vals;
+ raw_data.cur_series = 1;
+ sort = g_new0 (unsigned, kmax);
+ for (i = 0; i < kmax; i++)
+ sort[i] = i;
+ g_qsort_with_data (sort, kmax, sizeof (unsigned), (GCompareDataFunc) data_compare, &raw_data);
+ raw_data.cur_series = 0;
+ imax = plot->rows;
+ jmax = plot->columns;
+ xmin = plot->x.minima;
+ ymin = plot->y.minima;
+ xinc = (plot->x.maxima - xmin) / (jmax - 1);
+ yinc = (plot->y.maxima - ymin) / (imax - 1);
data = g_new0 (double, n);
grid = g_new0 (unsigned, n);
- for (k = 0; k < kmax; ++k) {
- j = (int) floor ((x_vals[k] - xmin) / xinc + 0.5);
- i = (int) floor ((y_vals[k] - ymin) / yinc + 0.5);
- index = i * jmax + j;
- /* Watch out not to fall beyond array limits; however,
- * its unlikely and shouldn't happen normally */
- if (G_LIKELY (index < n)) {
- data[index] += z_vals[k];
- grid[index]++;
+ k = l = index = 0;
+ for (i = 0; i < imax; i++) {
+ while (l < kmax && y_vals[sort[l]] < y_limits[i])
+ l++;
+ g_qsort_with_data (sort + k, l - k, sizeof (unsigned), (GCompareDataFunc) data_compare, &raw_data);
+ for (j = 0; j < jmax && k < l; j++) {
+ index = i * jmax + j;
+ while (k < l && x_vals[sort[k]] < x_limits[j]) {
+ if (G_LIKELY (index < n)) {
+ data[index] += z_vals[sort[k]];
+ grid[index]++;
+ }
+ k++;
+ }
}
+ k = l;
}
for (k = 0; k < n; ++k)
if (grid[k] != 0)
data[k] /= grid[k];
- if (GOG_IS_PLOT_CONTOUR (plot)) {
+ if (GOG_IS_CONTOUR_PLOT (plot)) {
GogAxisMap *map;
GogAxisTick *zticks;
GogAxis *axis = plot->base.axis[GOG_AXIS_PSEUDO_3D];
@@ -91,7 +161,7 @@ gog_xyz_surface_plot_build_matrix (GogXYZPlot const *plot, gboolean *cardinality
double *x, val, minimum, maximum, slope, offset = 0.;
unsigned max;
- if (!gog_axis_get_bounds (axis, &minimum, &maximum)) {
+ if (!gog_axis_get_bounds (axis, &minimum, &maximum)) {
g_free (grid);
g_free (data);
return NULL;
@@ -145,6 +215,9 @@ gog_xyz_surface_plot_build_matrix (GogXYZPlot const *plot, gboolean *cardinality
}
} else
*cardinality_changed = FALSE;
+ g_free (x_limits);
+ g_free (y_limits);
+ g_free (sort);
g_free (grid);
return data;
}
@@ -166,17 +239,17 @@ gog_xyz_surface_plot_type_name (G_GNUC_UNUSED GogObject const *item)
}
#ifdef GOFFICE_WITH_GTK
-extern gpointer gog_xyz_surface_plot_pref (GogXYZPlot *plot, GOCmdContext *cc);
+extern gpointer gog_xyz_surface_plot_pref (GogXYZPlot *plot, GogDataAllocator *dalloc, GOCmdContext *cc);
static void
gog_xyz_surface_plot_populate_editor (GogObject *item,
GOEditor *editor,
- G_GNUC_UNUSED GogDataAllocator *dalloc,
+ GogDataAllocator *dalloc,
GOCmdContext *cc)
{
- GogObjectClass *klass = (GOG_IS_PLOT_CONTOUR (item))?
+ GogObjectClass *klass = (GOG_IS_CONTOUR_PLOT (item))?
plot_xyz_contour_parent_klass:
plot_xyz_surface_parent_klass;
- GtkWidget *w = gog_xyz_surface_plot_pref (GOG_XYZ_PLOT (item), cc);
+ GtkWidget *w = gog_xyz_surface_plot_pref (GOG_XYZ_PLOT (item), dalloc, cc);
go_editor_add_page (editor, w, _("Properties"));
g_object_unref (G_OBJECT (w));
@@ -190,10 +263,9 @@ gog_xyz_surface_plot_update (GogObject *obj)
GogXYZPlot *model = GOG_XYZ_PLOT(obj);
GogXYZSeries *series;
double tmp_min, tmp_max;
- GogObjectClass *klass = (GOG_IS_PLOT_CONTOUR (obj))?
+ GogObjectClass *klass = (GOG_IS_CONTOUR_PLOT (obj))?
plot_xyz_contour_parent_klass:
plot_xyz_surface_parent_klass;
-
if (model->base.series == NULL)
return;
@@ -243,7 +315,7 @@ gog_xyz_surface_plot_update (GogObject *obj)
model->z.date_conv = go_data_date_conv (series->base.values[2].data);
model->z.minima = tmp_min;
model->z.maxima = tmp_max;
- gog_axis_bound_changed (model->base.axis[((GOG_IS_PLOT_CONTOUR (model))? GOG_AXIS_PSEUDO_3D: GOG_AXIS_Z)], GOG_OBJECT (model));
+ gog_axis_bound_changed (model->base.axis[((GOG_IS_CONTOUR_PLOT (model))? GOG_AXIS_PSEUDO_3D: GOG_AXIS_Z)], GOG_OBJECT (model));
gog_object_emit_changed (GOG_OBJECT (obj), FALSE);
if (klass->update)
@@ -258,25 +330,47 @@ gog_xyz_surface_plot_set_property (GObject *obj, guint param_id,
switch (param_id) {
case XYZ_SURFACE_PROP_ROWS :
- if (plot->rows != g_value_get_uint (value)) {
- plot->rows = g_value_get_uint (value);
- g_free (plot->plotted_data);
- plot->plotted_data = NULL;
- if (plot->y_vals != NULL) {
- g_object_unref (plot->y_vals);
- plot->y_vals = NULL;
- }
+ if (plot->rows == g_value_get_uint (value))
+ return;
+ plot->rows = g_value_get_uint (value);
+ g_free (plot->plotted_data);
+ plot->plotted_data = NULL;
+ if (plot->y_vals != NULL) {
+ g_object_unref (plot->y_vals);
+ plot->y_vals = NULL;
}
break;
case XYZ_SURFACE_PROP_COLUMNS :
- if (plot->columns != g_value_get_uint (value)) {
- plot->columns = g_value_get_uint (value);
- g_free (plot->plotted_data);
- plot->plotted_data = NULL;
- if (plot->x_vals != NULL) {
- g_object_unref (plot->x_vals);
- plot->x_vals = NULL;
- }
+ if (plot->columns == g_value_get_uint (value))
+ return;
+ plot->columns = g_value_get_uint (value);
+ g_free (plot->plotted_data);
+ plot->plotted_data = NULL;
+ if (plot->x_vals != NULL) {
+ g_object_unref (plot->x_vals);
+ plot->x_vals = NULL;
+ }
+ break;
+ case XYZ_SURFACE_PROP_AUTO_ROWS :
+ if (plot->auto_y == g_value_get_boolean (value))
+ return;
+ plot->auto_y = g_value_get_boolean (value);
+ g_free (plot->plotted_data);
+ plot->plotted_data = NULL;
+ if (plot->y_vals != NULL) {
+ g_object_unref (plot->y_vals);
+ plot->y_vals = NULL;
+ }
+ break;
+ case XYZ_SURFACE_PROP_AUTO_COLUMNS :
+ if (plot->auto_x == g_value_get_boolean (value))
+ return;
+ plot->auto_x = g_value_get_boolean (value);
+ g_free (plot->plotted_data);
+ plot->plotted_data = NULL;
+ if (plot->x_vals != NULL) {
+ g_object_unref (plot->x_vals);
+ plot->x_vals = NULL;
}
break;
@@ -299,6 +393,12 @@ gog_xyz_surface_plot_get_property (GObject *obj, guint param_id,
case XYZ_SURFACE_PROP_COLUMNS :
g_value_set_uint (value, plot->columns);
break;
+ case XYZ_SURFACE_PROP_AUTO_ROWS :
+ g_value_set_boolean (value, plot->auto_y);
+ break;
+ case XYZ_SURFACE_PROP_AUTO_COLUMNS :
+ g_value_set_boolean (value, plot->auto_x);
+ break;
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
break;
@@ -306,6 +406,14 @@ gog_xyz_surface_plot_get_property (GObject *obj, guint param_id,
}
static void
+gog_xyz_surface_finalize (GObject *obj)
+{
+ GObjectClass *klass = g_type_class_peek_parent (G_OBJECT_GET_CLASS (obj));
+ gog_dataset_finalize (GOG_DATASET (obj));
+ klass->finalize (obj);
+}
+
+static void
common_init_class (GogXYZPlotClass *klass)
{
GogPlotClass *gog_plot_klass = (GogPlotClass*) klass;
@@ -314,18 +422,31 @@ common_init_class (GogXYZPlotClass *klass)
gobject_klass->set_property = gog_xyz_surface_plot_set_property;
gobject_klass->get_property = gog_xyz_surface_plot_get_property;
+ gobject_klass->finalize = gog_xyz_surface_finalize;
g_object_class_install_property (gobject_klass, XYZ_SURFACE_PROP_ROWS,
g_param_spec_uint ("rows",
_("Rows"),
_("Number of rows"),
2, 1000, 10,
GSF_PARAM_STATIC | G_PARAM_READWRITE | GO_PARAM_PERSISTENT));
+ g_object_class_install_property (gobject_klass, XYZ_SURFACE_PROP_AUTO_ROWS,
+ g_param_spec_boolean ("auto-rows",
+ _("Auto Rows"),
+ _("Whether the rows limts should be evaluated"),
+ TRUE,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE | GO_PARAM_PERSISTENT));
g_object_class_install_property (gobject_klass, XYZ_SURFACE_PROP_COLUMNS,
g_param_spec_uint ("columns",
_("Columns"),
_("Number of columns"),
2, 1000, 10,
GSF_PARAM_STATIC | G_PARAM_READWRITE | GO_PARAM_PERSISTENT));
+ g_object_class_install_property (gobject_klass, XYZ_SURFACE_PROP_AUTO_COLUMNS,
+ g_param_spec_boolean ("auto-columns",
+ _("Auto Columns"),
+ _("Whether the columns limts should be evaluated"),
+ TRUE,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE | GO_PARAM_PERSISTENT));
gog_object_klass->update = gog_xyz_surface_plot_update;
@@ -371,12 +492,62 @@ gog_xyz_surface_plot_init (GogXYZPlot *xyz)
xyz->data_xyz = TRUE;
xyz->rows = 10;
xyz->columns = 10;
+ xyz->auto_x = xyz->auto_y = TRUE;
+}
+
+static void
+gog_xyz_surface_plot_dataset_dims (GogDataset const *set, int *first, int *last)
+{
+ *first = 0;
+ *last = 1;
+}
+
+static GogDatasetElement *
+gog_xyz_contour_plot_dataset_get_elem (GogDataset const *set, int dim_i)
+{
+ GogXYZContourPlot *plot = GOG_XYZ_CONTOUR_PLOT (set);
+ g_return_val_if_fail (2 > dim_i, NULL);
+ g_return_val_if_fail (dim_i >= 0, NULL);
+ return plot->grid + dim_i;
+}
+
+static GogDatasetElement *
+gog_xyz_surface_plot_dataset_get_elem (GogDataset const *set, int dim_i)
+{
+ GogXYZSurfacePlot *plot = GOG_XYZ_SURFACE_PLOT (set);
+ g_return_val_if_fail (2 > dim_i, NULL);
+ g_return_val_if_fail (dim_i >= 0, NULL);
+ return plot->grid + dim_i;
+}
+
+static void
+gog_xyz_surface_plot_dataset_dim_changed (GogDataset *set, int dim_i)
+{
+ gog_object_request_update (GOG_OBJECT (set));
+}
+
+static void
+gog_xyz_contour_plot_dataset_init (GogDatasetClass *iface)
+{
+ iface->get_elem = gog_xyz_contour_plot_dataset_get_elem;
+ iface->dims = gog_xyz_surface_plot_dataset_dims;
+ iface->dim_changed = gog_xyz_surface_plot_dataset_dim_changed;
+}
+
+static void
+gog_xyz_surface_plot_dataset_init (GogDatasetClass *iface)
+{
+ iface->get_elem = gog_xyz_surface_plot_dataset_get_elem;
+ iface->dims = gog_xyz_surface_plot_dataset_dims;
+ iface->dim_changed = gog_xyz_surface_plot_dataset_dim_changed;
}
-GSF_DYNAMIC_CLASS (GogXYZContourPlot, gog_xyz_contour_plot,
- gog_xyz_contour_plot_class_init, gog_xyz_surface_plot_init,
- GOG_TYPE_CONTOUR_PLOT)
+GSF_DYNAMIC_CLASS_FULL (GogXYZContourPlot, gog_xyz_contour_plot,
+ NULL, NULL, gog_xyz_contour_plot_class_init, NULL,
+ gog_xyz_surface_plot_init, GOG_TYPE_CONTOUR_PLOT, 0,
+ GSF_INTERFACE (gog_xyz_contour_plot_dataset_init, GOG_TYPE_DATASET))
-GSF_DYNAMIC_CLASS (GogXYZSurfacePlot, gog_xyz_surface_plot,
- gog_xyz_surface_plot_class_init, gog_xyz_surface_plot_init,
- GOG_TYPE_SURFACE_PLOT)
+GSF_DYNAMIC_CLASS_FULL (GogXYZSurfacePlot, gog_xyz_surface_plot,
+ NULL, NULL, gog_xyz_surface_plot_class_init, NULL,
+ gog_xyz_surface_plot_init, GOG_TYPE_SURFACE_PLOT, 0,
+ GSF_INTERFACE (gog_xyz_surface_plot_dataset_init, GOG_TYPE_DATASET))
diff --git a/plugins/plot_surface/gog-xyz-surface.h b/plugins/plot_surface/gog-xyz-surface.h
index 08d9f19..65099d6 100644
--- a/plugins/plot_surface/gog-xyz-surface.h
+++ b/plugins/plot_surface/gog-xyz-surface.h
@@ -34,7 +34,11 @@ G_BEGIN_DECLS
*-----------------------------------------------------------------------------
*/
-typedef GogContourPlot GogXYZContourPlot;
+
+typedef struct {
+ GogContourPlot base;
+ GogDatasetElement grid[2]; /* for preset cols and rows */
+} GogXYZContourPlot;
typedef GogContourPlotClass GogXYZContourPlotClass;
#define GOG_TYPE_XYZ_CONTOUR_PLOT (gog_xyz_contour_plot_get_type ())
@@ -52,7 +56,10 @@ void gog_xyz_contour_plot_register_type (GTypeModule *module);
*-----------------------------------------------------------------------------
*/
-typedef GogSurfacePlot GogXYZSurfacePlot;
+typedef struct {
+ GogSurfacePlot base;
+ GogDatasetElement grid[2]; /* for preset cols and rows */
+} GogXYZSurfacePlot;
typedef GogSurfacePlotClass GogXYZSurfacePlotClass;
#define GOG_TYPE_XYZ_SURFACE_PLOT (gog_xyz_surface_plot_get_type ())
diff --git a/plugins/plot_surface/gog-xyz.h b/plugins/plot_surface/gog-xyz.h
index ad3b09f..f52a2be 100644
--- a/plugins/plot_surface/gog-xyz.h
+++ b/plugins/plot_surface/gog-xyz.h
@@ -39,6 +39,7 @@ typedef struct {
unsigned rows, columns;
gboolean transposed;
gboolean data_xyz;
+ gboolean auto_x, auto_y; /* automatic limits for xyz plots */
struct {
double minima, maxima;
GOFormat *fmt;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]