goffice r2085 - in trunk: . goffice goffice/data goffice/graph goffice/math plugins/plot_surface
- From: jbrefort svn gnome org
- To: svn-commits-list gnome org
- Subject: goffice r2085 - in trunk: . goffice goffice/data goffice/graph goffice/math plugins/plot_surface
- Date: Mon, 12 May 2008 10:02:13 +0100 (BST)
Author: jbrefort
Date: Mon May 12 09:02:12 2008
New Revision: 2085
URL: http://svn.gnome.org/viewvc/goffice?rev=2085&view=rev
Log:
2008-05-12 Jean Brefort <jean brefort normalesup org>
* goffice/data/go-data.c: (go_data_vector_increasing),
(go_data_vector_decreasing), (go_data_vector_vary_uniformly):
new functions.
* goffice/data/go-data.h: ditto.
* goffice/goffice.c: (libgoffice_init): add initial 3d plots support.
* goffice/graph/Makefile.am: ditto.
* goffice/graph/goffice-graph.h: ditto.
* goffice/graph/gog-3d-box.c: (gog_3d_box_class_init),
(gog_3d_box_init): ditto.
* goffice/graph/gog-3d-box.h: ditto.
* goffice/graph/gog-axis-line.c: (xyz_process),
(gog_axis_base_view_point), (gog_axis_base_view_padding_request):
* goffice/graph/gog-axis.c: (gog_axis_view_size_allocate): ditto.
* goffice/graph/gog-chart-impl.h: ditto.
* goffice/graph/gog-chart-map-3d.c: (null_map_3D),
(xyz_map_3D_to_view), (gog_chart_map_3d_new),
(gog_chart_map_3d_to_view), (gog_chart_map_3d_is_valid),
(gog_chart_map_3d_free): ditto.
* goffice/graph/gog-chart-map-3d.h: ditto.
* goffice/graph/gog-chart.c: (role_3d_box_can_add),
(role_3d_box_can_remove), (gog_chart_is_3d),
(gog_chart_3d_process), (gog_chart_view_size_allocate),
(gog_chart_view_render): ditto.
* goffice/graph/gog-chart.h: ditto.
* goffice/math/Makefile.am: ditto.
* goffice/math/go-matrix3x3.c: (go_matrix3x3_transform),
(go_matrix3x3_from_euler): ditto.
* goffice/math/go-matrix3x3.h: ditto.
* goffice/math/go-rangefunc.c: (go_range_decreasing),
(go_range_vary_uniformly): new functions.
* goffice/math/go-rangefunc.h: ditto.
* plugins/plot_surface/Makefile.am: new surface plot type.
* plugins/plot_surface/gog-contour-prefs.c: ditto.
* plugins/plot_surface/gog-contour-prefs.glade: ditto.
* plugins/plot_surface/gog-contour.c: ditto.
(gog_contour_plot_build_matrix), (gog_contour_plot_type_name),
(gog_contour_plot_foreach_elem), (gog_contour_plot_class_init),
(gog_contour_plot_init), (gog_contour_view_render),
(gog_contour_view_class_init): ditto.
* plugins/plot_surface/gog-contour.h: ditto.
* plugins/plot_surface/gog-surface.c: ditto.
(gog_surface_plot_build_matrix), (gog_surface_plot_type_name),
(gog_surface_plot_class_init), (gog_surface_plot_init),
(gog_surface_view_render), (gog_surface_view_class_init):
* plugins/plot_surface/gog-surface.h:
* plugins/plot_surface/gog-xyz-prefs.c:
* plugins/plot_surface/gog-xyz-prefs.glade:
* plugins/plot_surface/gog-xyz.c: (gog_xyz_plot_build_matrix),
(gog_xyz_plot_update_3d), (gog_xyz_plot_populate_editor),
(gog_xyz_plot_clear_formats), (gog_xyz_plot_update),
(gog_xyz_plot_axis_get_bounds), (gog_xyz_plot_finalize),
(gog_xyz_plot_set_property), (gog_xyz_plot_get_property),
(gog_xyz_plot_class_init), (gog_xyz_plot_init),
(gog_xyz_series_update), (gog_xyz_series_init_style),
(gog_xyz_series_class_init), (go_plugin_init),
(go_plugin_shutdown): ditto.
* plugins/plot_surface/gog-xyz.h: ditto.
* plugins/plot_surface/plot-types.xml.in: ditto.
* plugins/plot_surface/plugin.xml.in: ditto.
* plugins/plot_surface/xl-surface.c: (xl_labels_init),
(xl_xyz_series_update), (xl_xyz_series_init_style),
(xl_xyz_series_class_init), (xl_xyz_plot_update), (get_y_vector),
(xl_xyz_plot_axis_get_bounds), (xl_contour_plot_build_matrix),
(xl_contour_plot_finalize), (xl_contour_plot_class_init),
(xl_surface_plot_build_matrix), (xl_surface_plot_finalize),
(xl_surface_plot_class_init): ditto.
* plugins/plot_surface/xl-surface.h: ditto.
Added:
trunk/goffice/graph/gog-3d-box.c
trunk/goffice/graph/gog-3d-box.h
trunk/goffice/graph/gog-chart-map-3d.c
trunk/goffice/graph/gog-chart-map-3d.h
trunk/goffice/math/go-matrix3x3.c
trunk/goffice/math/go-matrix3x3.h
trunk/plugins/plot_surface/gog-contour.c
trunk/plugins/plot_surface/gog-contour.h
trunk/plugins/plot_surface/gog-xyz-prefs.c
- copied, changed from r2048, /trunk/plugins/plot_surface/gog-contour-prefs.c
trunk/plugins/plot_surface/gog-xyz-prefs.glade
- copied, changed from r2048, /trunk/plugins/plot_surface/gog-contour-prefs.glade
trunk/plugins/plot_surface/gog-xyz.c
trunk/plugins/plot_surface/gog-xyz.h
Removed:
trunk/plugins/plot_surface/gog-contour-prefs.c
trunk/plugins/plot_surface/gog-contour-prefs.glade
Modified:
trunk/ChangeLog
trunk/goffice/data/go-data.c
trunk/goffice/data/go-data.h
trunk/goffice/goffice.c
trunk/goffice/graph/Makefile.am
trunk/goffice/graph/goffice-graph.h
trunk/goffice/graph/gog-axis-line.c
trunk/goffice/graph/gog-axis.c
trunk/goffice/graph/gog-chart-impl.h
trunk/goffice/graph/gog-chart.c
trunk/goffice/graph/gog-chart.h
trunk/goffice/math/Makefile.am
trunk/goffice/math/go-rangefunc.c
trunk/goffice/math/go-rangefunc.h
trunk/plugins/plot_surface/Makefile.am
trunk/plugins/plot_surface/gog-surface.c
trunk/plugins/plot_surface/gog-surface.h
trunk/plugins/plot_surface/plot-types.xml.in
trunk/plugins/plot_surface/plugin.xml.in
trunk/plugins/plot_surface/xl-surface.c
trunk/plugins/plot_surface/xl-surface.h
Modified: trunk/goffice/data/go-data.c
==============================================================================
--- trunk/goffice/data/go-data.c (original)
+++ trunk/goffice/data/go-data.c Mon May 12 09:02:12 2008
@@ -23,6 +23,7 @@
#include "go-data.h"
#include "go-data-impl.h"
#include <goffice/math/go-math.h>
+#include <goffice/math/go-rangefunc.h>
#include <gsf/gsf-impl-utils.h>
#include <glib/gi18n-lib.h>
@@ -334,6 +335,30 @@
*max = vec->maximum;
}
+gboolean
+go_data_vector_increasing (GODataVector *vec)
+{
+ double *data = go_data_vector_get_values (vec);
+ int length = go_data_vector_get_len (vec);
+ return go_range_increasing (data, length);
+}
+
+gboolean
+go_data_vector_decreasing (GODataVector *vec)
+{
+ double *data = go_data_vector_get_values (vec);
+ int length = go_data_vector_get_len (vec);
+ return go_range_decreasing (data, length);
+}
+
+gboolean
+go_data_vector_vary_uniformly (GODataVector *vec)
+{
+ double *data = go_data_vector_get_values (vec);
+ int length = go_data_vector_get_len (vec);
+ return go_range_vary_uniformly (data, length);
+}
+
/*************************************************************************/
#define GO_DATA_MATRIX_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GO_DATA_MATRIX_TYPE, GODataMatrixClass))
Modified: trunk/goffice/data/go-data.h
==============================================================================
--- trunk/goffice/data/go-data.h (original)
+++ trunk/goffice/data/go-data.h Mon May 12 09:02:12 2008
@@ -63,6 +63,9 @@
double go_data_vector_get_value (GODataVector *vec, unsigned i);
char *go_data_vector_get_str (GODataVector *vec, unsigned i);
void go_data_vector_get_minmax (GODataVector *vec, double *min, double *max);
+gboolean go_data_vector_increasing (GODataVector *vec);
+gboolean go_data_vector_decreasing (GODataVector *vec);
+gboolean go_data_vector_vary_uniformly (GODataVector *vec);
/*************************************************************************/
Modified: trunk/goffice/goffice.c
==============================================================================
--- trunk/goffice/goffice.c (original)
+++ trunk/goffice/goffice.c Mon May 12 09:02:12 2008
@@ -35,6 +35,7 @@
#include <goffice/graph/gog-theme.h>
#include <goffice/graph/gog-error-bar.h>
#include <goffice/graph/gog-series-lines.h>
+#include <goffice/graph/gog-3d-box.h>
#include <goffice/data/go-data-simple.h>
#include <goffice/math/go-math.h>
#include <goffice/utils/go-format.h>
@@ -126,6 +127,7 @@
(void) GOG_SERIES_LINES_TYPE;
(void) GO_DATA_SCALAR_VAL_TYPE;
(void) GO_DATA_SCALAR_STR_TYPE;
+ (void) GOG_3D_BOX_TYPE;
gog_themes_init ();
go_number_format_init ();
go_currency_date_format_init ();
Modified: trunk/goffice/graph/Makefile.am
==============================================================================
--- trunk/goffice/graph/Makefile.am (original)
+++ trunk/goffice/graph/Makefile.am Mon May 12 09:02:12 2008
@@ -11,6 +11,8 @@
gog-chart.c \
\
gog-chart-map.c \
+ gog-chart-map-3d.c \
+ gog-3d-box.c \
\
gog-axis.c \
gog-axis-line.c \
@@ -48,6 +50,8 @@
gog-chart.h \
gog-chart-impl.h \
gog-chart-map.h \
+ gog-chart-map-3d.h \
+ gog-3d-box.h \
gog-axis.h \
gog-axis-line.h \
gog-axis-line-impl.h \
Modified: trunk/goffice/graph/goffice-graph.h
==============================================================================
--- trunk/goffice/graph/goffice-graph.h (original)
+++ trunk/goffice/graph/goffice-graph.h Mon May 12 09:02:12 2008
@@ -55,6 +55,7 @@
typedef struct _GogTrendLineType GogTrendLineType;
typedef struct _GogSeriesLines GogSeriesLines;
typedef struct _GogSmoothedCurve GogSmoothedCurve;
+typedef struct _Gog3DBox Gog3DBox;
/* formating */
typedef struct _GogTheme GogTheme;
Added: trunk/goffice/graph/gog-3d-box.c
==============================================================================
--- (empty file)
+++ trunk/goffice/graph/gog-3d-box.c Mon May 12 09:02:12 2008
@@ -0,0 +1,46 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gog-3d-box.h :
+ *
+ * Copyright (C) 2007 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include <goffice/goffice-config.h>
+#include <goffice/graph/gog-3d-box.h>
+#include <goffice/math/go-math.h>
+#include <gsf/gsf-impl-utils.h>
+
+typedef GogObjectClass Gog3DBoxClass;
+
+static void
+gog_3d_box_class_init (Gog3DBoxClass *klass)
+{
+}
+
+static void
+gog_3d_box_init (Gog3DBox *box)
+{
+ box->fov = 10. / 180. * M_PI;
+ box->psi = 70. / 180. * M_PI;
+ box->theta = 10. / 180. * M_PI;
+ box->phi = -90. / 180. * M_PI;
+ go_matrix3x3_from_euler (&box->mat, box->psi, box->theta, box->phi);
+}
+
+GSF_CLASS (Gog3DBox, gog_3d_box,
+ gog_3d_box_class_init, gog_3d_box_init,
+ GOG_OBJECT_TYPE)
Added: trunk/goffice/graph/gog-3d-box.h
==============================================================================
--- (empty file)
+++ trunk/goffice/graph/gog-3d-box.h Mon May 12 09:02:12 2008
@@ -0,0 +1,50 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gog-3d-box.h :
+ *
+ * Copyright (C) 2007 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#ifndef GOG_3D_BOX_H
+#define GOG_3D_BOX_H
+
+#include <goffice/graph/goffice-graph.h>
+#include <goffice/graph/gog-object.h>
+#include <goffice/math/go-matrix3x3.h>
+
+G_BEGIN_DECLS
+
+struct _Gog3DBox {
+ GogObject base;
+
+ double fov, psi, theta, phi; /* field of view and orientation */
+ double dx, dy, dz; /* box size */
+ double r; /* distance from view point to the center of the box */
+ double ratio; /* ratio to use to be certain that everything fits
+ in the view */
+ GOMatrix3x3 mat; /* the matrix based on psi, theta, and phi */
+};
+
+#define GOG_3D_BOX_TYPE (gog_3d_box_get_type ())
+#define GOG_3D_BOX(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_3D_BOX_TYPE, Gog3DBox))
+#define IS_GOG_3D_BOX(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_3D_BOX_TYPE))
+
+GType gog_3d_box_get_type (void);
+
+G_END_DECLS
+
+#endif /* GOG_3D_BOX_H */
Modified: trunk/goffice/graph/gog-axis-line.c
==============================================================================
--- trunk/goffice/graph/gog-axis-line.c (original)
+++ trunk/goffice/graph/gog-axis-line.c Mon May 12 09:02:12 2008
@@ -1766,6 +1766,20 @@
}
static gboolean
+xyz_process (GogAxisBaseAction action, GogView *view, GogViewPadding *padding,
+ GogViewAllocation const *plot_area, double x, double y)
+{
+ GogAxisBase *axis_base = GOG_AXIS_BASE (view->model);
+ GogAxisType axis_type = gog_axis_get_atype (axis_base->axis);
+ g_return_val_if_fail (axis_type == GOG_AXIS_X ||
+ axis_type == GOG_AXIS_Y ||
+ axis_type == GOG_AXIS_Z, FALSE);
+
+ return TRUE;
+
+}
+
+static gboolean
gog_axis_base_view_point (GogView *view, double x, double y)
{
GogAxisBase *axis_base = GOG_AXIS_BASE (view->model);
@@ -1800,6 +1814,9 @@
case GOG_AXIS_SET_RADAR:
pointed = radar_process (GOG_AXIS_BASE_POINT, view, NULL, plot_area, x, y);
break;
+ case GOG_AXIS_SET_XYZ:
+ xyz_process (GOG_AXIS_BASE_PADDING_REQUEST, view, NULL, plot_area, x, y);
+ break;
default:
g_warning ("[AxisBaseView::point] not implemented for this axis set (%i)",
axis_set);
@@ -1834,6 +1851,8 @@
case GOG_AXIS_SET_RADAR:
radar_process (GOG_AXIS_BASE_PADDING_REQUEST, view, padding, bbox, 0., 0.);
break;
+ case GOG_AXIS_SET_XYZ:
+ break;
default:
g_warning ("[AxisBaseView::padding_request] not implemented for this axis set (%i)",
axis_set);
Modified: trunk/goffice/graph/gog-axis.c
==============================================================================
--- trunk/goffice/graph/gog-axis.c (original)
+++ trunk/goffice/graph/gog-axis.c Mon May 12 09:02:12 2008
@@ -2317,6 +2317,9 @@
double const pad_h = gog_renderer_pt2r_y (view->renderer, PAD_HACK);
double const pad_w = gog_renderer_pt2r_x (view->renderer, PAD_HACK);
+ if (gog_chart_is_3d (GOG_CHART (gog_object_get_parent (view->model))))
+ return;
+
available.w = bbox->w;
available.h = bbox->h;
Modified: trunk/goffice/graph/gog-chart-impl.h
==============================================================================
--- trunk/goffice/graph/gog-chart-impl.h (original)
+++ trunk/goffice/graph/gog-chart-impl.h Mon May 12 09:02:12 2008
@@ -29,6 +29,8 @@
G_BEGIN_DECLS
+typedef struct _GogChart3dParms GogChart3dParms;
+
struct _GogChart {
GogOutlinedObject base;
@@ -45,6 +47,7 @@
GogViewAllocation plot_area;
gboolean is_plot_area_manual;
+ GogChart3dParms *p3d;
};
typedef GogOutlinedObjectClass GogChartClass;
Added: trunk/goffice/graph/gog-chart-map-3d.c
==============================================================================
--- (empty file)
+++ trunk/goffice/graph/gog-chart-map-3d.c Mon May 12 09:02:12 2008
@@ -0,0 +1,182 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gog-chart-map-3d.c :
+ *
+ * Copyright (C) 2007 Jean Brefort <jean brefort normalesup org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include <goffice/graph/gog-chart-map-3d.h>
+#include <goffice/graph/gog-3d-box.h>
+#include <goffice/math/go-matrix3x3.h>
+
+struct _GogChartMap3D {
+ GogChart *chart;
+ GogViewAllocation area;
+ gpointer data;
+ GogAxisMap *axis_map[3];
+ gboolean is_valid;
+ GOMatrix3x3 mat;
+
+ void (*map_3D_to_view) (GogChartMap3D *map, double x, double y, double z, double *u, double *v, double *w);
+};
+
+static void
+null_map_3D (GogChartMap3D *map, double x, double y, double z, double *u, double *v, double *w)
+{
+ g_warning ("[GogChartMap::map_3D] not implemented");
+}
+
+static void
+xyz_map_3D_to_view (GogChartMap3D *map, double x, double y, double z, double *u, double *v, double *w)
+{
+ Gog3DBox *box = GOG_3D_BOX (gog_object_get_child_by_name (GOG_OBJECT (map->chart), "3D-Box"));
+ x = gog_axis_map_to_view (map->axis_map[0], x);
+ y = gog_axis_map_to_view (map->axis_map[1], y);
+ z = gog_axis_map_to_view (map->axis_map[2], z);
+ go_matrix3x3_transform (&box->mat, x, y, z, &x, &y, &z);
+ if (box->fov > 0.) {
+ x *= (1. + y / box->r) / box->ratio;
+ z *= (1. + y / box->r) / box->ratio;
+ } else {
+ x /= box->ratio;
+ z /= box->ratio;
+ }
+ if (u)
+ *u = map->area.x + map->area.w / 2. * (1. + x / box->dx);
+ if (v)
+ *v = map->area.y + map->area.h / 2. * (1. - z / box->dz);
+ if (w)
+ *w = y;
+}
+
+/**
+ * gog_chart_3d_map_new:
+ * @chart: a #GogChart with 3D support
+ * @area: area allocated to chart
+ * @axis0: 1st dimension axis
+ * @axis1: 2nd dimension axis
+ * @axis2: 3rd dimension axis
+ * @fill_area: does chart fill allocated area
+ *
+ * Creates a new #GogChartMap3D, used for conversion from data space
+ * to canvas space.
+ *
+ * returns: a new #GogChartMap3D object.
+ **/
+
+GogChartMap3D*
+gog_chart_map_3d_new (GogChart *chart, GogViewAllocation const *area,
+ GogAxis *axis0, GogAxis *axis1, GogAxis *axis2)
+{
+ GogChartMap3D *map;
+ GogAxisSet axis_set;
+ Gog3DBox *box;
+
+ g_return_val_if_fail (IS_GOG_CHART (chart), NULL);
+
+ map = g_new (GogChartMap3D, 1);
+
+ g_object_ref (chart);
+ map->chart = chart;
+ map->area = *area;
+ map->data = NULL;
+ map->is_valid = FALSE;
+ box = GOG_3D_BOX (gog_object_get_child_by_name (GOG_OBJECT (chart), "3D-Box"));
+
+ axis_set = gog_chart_get_axis_set (chart);
+ switch (axis_set & GOG_AXIS_SET_FUNDAMENTAL) {
+ case GOG_AXIS_SET_XYZ: {
+ map->axis_map[0] = gog_axis_map_new (axis0, -box->dx, 2 * box->dx);
+ map->axis_map[1] = gog_axis_map_new (axis1, -box->dy, 2 * box->dy);
+ map->axis_map[2] = gog_axis_map_new (axis2, -box->dz, 2 * box->dz);
+
+ map->data = NULL;
+ map->map_3D_to_view = xyz_map_3D_to_view;
+
+ map->is_valid = gog_axis_map_is_valid (map->axis_map[0]) &&
+ gog_axis_map_is_valid (map->axis_map[1]) &&
+ gog_axis_map_is_valid (map->axis_map[2]);
+
+ break;
+ }
+ default:
+ g_warning ("[Chart3D::map_new] not implemented for this axis set (%i)",
+ axis_set);
+ map->map_3D_to_view = null_map_3D;
+ break;
+ }
+
+ return map;
+}
+
+/**
+ * gog_chart_map_3d_to_view:
+ * @map: a #GogChartMap3D
+ * @x: data x value
+ * @y: data y value
+ * @z: data y value
+ * @u: placeholder for x converted value
+ * @v: placeholder for y converted value
+ *
+ * Converts a 3D coordinate from data space to canvas space.
+ **/
+
+void
+gog_chart_map_3d_to_view (GogChartMap3D *map, double x, double y, double z, double *u, double *v, double *w)
+{
+ (map->map_3D_to_view) (map, x, y, z, u, v, w);
+}
+
+/**
+ * gog_chart_map_3d_is_valid:
+ * @map: a #GogChartMap3D
+ *
+ * Tests if @map was correctly initialized.
+ *
+ * returns: %TRUE if @map is valid.
+ **/
+
+gboolean
+gog_chart_map_3d_is_valid (GogChartMap3D *map)
+{
+ g_return_val_if_fail (map != NULL, FALSE);
+
+ return map->is_valid;
+}
+
+/**
+ * gog_chart_map_3d_free:
+ * @map: a #GogChartMap3D
+ *
+ * Frees @map object.
+ **/
+
+void
+gog_chart_map_3d_free (GogChartMap3D *map)
+{
+ int i;
+
+ g_return_if_fail (map != NULL);
+
+ for (i = 0; i < 3; i++)
+ if (map->axis_map[i] != NULL)
+ gog_axis_map_free (map->axis_map[i]);
+
+ g_free (map->data);
+ g_object_unref (map->chart);
+ g_free (map);
+}
Added: trunk/goffice/graph/gog-chart-map-3d.h
==============================================================================
--- (empty file)
+++ trunk/goffice/graph/gog-chart-map-3d.h Mon May 12 09:02:12 2008
@@ -0,0 +1,43 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gog-chart-map-3d.h :
+ *
+ * Copyright (C) 2007 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#ifndef GOG_CHART_MAP_3D_H
+#define GOG_CHART_MAP_3D_H
+
+#include <goffice/graph/gog-axis.h>
+#include <goffice/graph/gog-chart.h>
+#include <goffice/graph/gog-series.h>
+#include <goffice/utils/go-path.h>
+#include <goffice/utils/go-line.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GogChartMap3D GogChartMap3D;
+
+GogChartMap3D *gog_chart_map_3d_new (GogChart *chart, GogViewAllocation const *area,
+ GogAxis *axis0, GogAxis *axis1, GogAxis *axis2);
+void gog_chart_map_3d_to_view (GogChartMap3D *map, double x, double y, double z, double *u, double *v, double *w);
+gboolean gog_chart_map_3d_is_valid (GogChartMap3D *map);
+void gog_chart_map_3d_free (GogChartMap3D *map);
+
+G_END_DECLS
+
+#endif /* GOG_CHART_MAP_3D_H */
Modified: trunk/goffice/graph/gog-chart.c
==============================================================================
--- trunk/goffice/graph/gog-chart.c (original)
+++ trunk/goffice/graph/gog-chart.c Mon May 12 09:02:12 2008
@@ -22,6 +22,8 @@
#include <goffice/goffice-config.h>
#include <goffice/graph/gog-chart-impl.h>
#include <goffice/graph/gog-chart-map.h>
+#include <goffice/graph/gog-chart-map-3d.h>
+#include <goffice/graph/gog-3d-box.h>
#include <goffice/graph/gog-plot-impl.h>
#include <goffice/graph/gog-graph-impl.h>
#include <goffice/graph/gog-style.h>
@@ -32,6 +34,7 @@
#include <goffice/graph/gog-grid-line.h>
#include <goffice/graph/gog-renderer.h>
#include <goffice/math/go-math.h>
+#include <goffice/math/go-matrix3x3.h>
#include <gsf/gsf-impl-utils.h>
#include <glib/gi18n-lib.h>
@@ -80,7 +83,6 @@
}
/*****************************************************************************/
-
enum {
CHART_PROP_0,
CHART_PROP_CARDINALITY_VALID,
@@ -351,6 +353,8 @@
static void bubble_axis_post_add (GogObject *parent, GogObject *child) { axis_post_add (child, GOG_AXIS_BUBBLE); }
static gboolean color_axis_can_add (GogObject const *parent) { return axis_can_add (parent, GOG_AXIS_COLOR); }
static void color_axis_post_add (GogObject *parent, GogObject *child) { axis_post_add (child, GOG_AXIS_COLOR); }
+static gboolean role_3d_box_can_add (GogObject const *parent) {return FALSE;}
+static gboolean role_3d_box_can_remove (GogObject const *parent) {return FALSE;}
static GogObjectRole const roles[] = {
{ N_("Backplane"), "GogGrid", 0,
@@ -400,7 +404,10 @@
GOG_POSITION_COMPASS|GOG_POSITION_ANY_MANUAL,
GOG_POSITION_E|GOG_POSITION_ALIGN_CENTER,
GOG_OBJECT_NAME_BY_ROLE,
- NULL, NULL, NULL, NULL, NULL, NULL, { -1 } }
+ NULL, NULL, NULL, NULL, NULL, NULL, { -1 } },
+ { N_("3D-Box"), "Gog3DBox", 0,
+ GOG_POSITION_SPECIAL, GOG_POSITION_SPECIAL, GOG_OBJECT_NAME_BY_ROLE,
+ role_3d_box_can_add, role_3d_box_can_remove, NULL, NULL, NULL, NULL, { -1 } }
};
static void
@@ -760,6 +767,144 @@
return GOG_GRID (chart->grid);
}
+gboolean
+gog_chart_is_3d (GogChart const *chart)
+{
+ return chart->axis_set == GOG_AXIS_SET_XYZ;
+}
+
+static void
+gog_chart_3d_process (GogChart *chart, GogViewAllocation const *bbox)
+{
+ /* A XYZ axis set in supposed. If new sets (cylindrical, spherical or
+ other are added, we'll need to change this code */
+ GogViewAllocation tmp = *bbox;
+ GogAxis *axisX, *axisY, *axisZ;
+ GSList *axes;
+ double xmin, xmax, ymin, ymax, zmin, zmax;
+ double o[3], x[3], y[3], z[3], tg, d;
+ Gog3DBox *box;
+ GogObject *obj = gog_object_get_child_by_name (GOG_OBJECT (chart), "3D-Box");
+
+ if (!obj) {
+ obj = g_object_new (GOG_3D_BOX_TYPE, NULL);
+ gog_object_add_by_name (GOG_OBJECT (chart), "3D-Box", obj);
+ }
+ box = GOG_3D_BOX (obj);
+
+ /* Only use the first of the axes. */
+ axes = gog_chart_get_axes (chart, GOG_AXIS_X);
+ axisX = GOG_AXIS (axes->data);
+ g_slist_free (axes);
+ gog_axis_get_bounds (axisX, &xmin, &xmax);
+ axes = gog_chart_get_axes (chart, GOG_AXIS_Y);
+ axisY = GOG_AXIS (axes->data);
+ g_slist_free (axes);
+ gog_axis_get_bounds (axisY, &ymin, &ymax);
+ axes = gog_chart_get_axes (chart, GOG_AXIS_Z);
+ axisZ = GOG_AXIS (axes->data);
+ g_slist_free (axes);
+ gog_axis_get_bounds (axisZ, &zmin, &zmax);
+ /* define the 3d box */
+ /* FIXME: take axes into account */
+ box->dz = tmp.h;
+ if (ymax - ymin > xmax - xmin) {
+ box->dy = tmp.w;
+ box->dx = (xmax - xmin) / (ymax - ymin) * tmp.w;
+ } else {
+ box->dx = tmp.w;
+ box->dy = (ymax - ymin) / (xmax - xmin) * tmp.w;
+ }
+
+ /* now compute the position of each vertex, ignoring the fov */
+ go_matrix3x3_transform (&box->mat, -box->dx, -box->dy, -box->dz, o, o + 1, o + 2);
+ go_matrix3x3_transform (&box->mat, box->dx, -box->dy, -box->dz, x, x + 1, x + 2);
+ go_matrix3x3_transform (&box->mat, -box->dx, box->dy, -box->dz, y, y + 1, y + 2);
+ go_matrix3x3_transform (&box->mat, -box->dx, -box->dy, box->dz, z, z + 1, z + 2);
+ /* for each diagonal, we need to take the vertex closer to the view point */
+ if (o[1] > 0) {
+ o[0] = -o[0];
+ o[1] = -o[1];
+ o[2] = -o[2];
+ }
+ if (x[1] > 0) {
+ x[0] = -x[0];
+ x[1] = -x[1];
+ x[2] = -x[2];
+ }
+ if (y[1] > 0) {
+ y[0] = -y[0];
+ y[1] = -y[1];
+ y[2] = -y[2];
+ }
+ if (z[1] > 0) {
+ z[0] = -z[0];
+ z[1] = -z[1];
+ z[2] = -z[2];
+ }
+ /* if the fov is positive, calculate the position of the viewpoint */
+ if (box->fov > 0.) {
+ tg = tan (box->fov / 2.);
+ box->r = -sqrt (o[0] * o[0] + o[2] * o[2]) / tg + o[1];
+ d = -sqrt (x[0] * x[0] + x[2] * x[2]) / tg + x[1];
+ if (d < box->r)
+ box->r = d;
+ d = -sqrt (y[0] * y[0] + y[2] * y[2]) / tg + y[1];
+ if (d < box->r)
+ box->r = d;
+ d = -sqrt (z[0] *z[0] + z[2] * z[2]) / tg + z[1];
+ if (d < box->r)
+ box->r = d;
+ /* also calculate the reduction factor we need to make things fit in the bbox */
+ xmax = fabs (o[0]) * (1. + o[1] / box->r);
+ zmax = fabs (o[2]) * (1. + o[1] / box->r);
+ d = fabs (x[0]) * (1. + x[1] / box->r);
+ if (d > xmax)
+ xmax = d;
+ d = fabs (x[2]) * (1. + x[1] / box->r);
+ if (d > zmax)
+ zmax = d;
+ d = fabs (y[0]) * (1. + y[1] / box->r);
+ if (d > xmax)
+ xmax = d;
+ d = fabs (y[2]) * (1. + y[1] / box->r);
+ if (d > zmax)
+ zmax = d;
+ d = fabs (z[0]) * (1. + z[1] / box->r);
+ if (d > xmax)
+ xmax = d;
+ d = fabs (z[2]) * (1. + z[1] / box->r);
+ if (d > zmax)
+ zmax = d;
+ } else {
+ /* calculate the reduction factor we need to make things fit in the bbox */
+ xmax = fabs (o[0]);
+ zmax = fabs (o[2]);
+ d = fabs (x[0]);
+ if (d > xmax)
+ xmax = d;
+ d = fabs (x[2]);
+ if (d > zmax)
+ zmax = d;
+ d = fabs (y[0]);
+ if (d > xmax)
+ xmax = d;
+ d = fabs (y[2]);
+ if (d > zmax)
+ zmax = d;
+ d = fabs (z[0]);
+ if (d > xmax)
+ xmax = d;
+ d = fabs (z[2]);
+ if (d > zmax)
+ zmax = d;
+ }
+ /* use d and tg as x and z ratios, respectively */
+ d = xmax / tmp.w;
+ tg = zmax / tmp.h;
+ box->ratio = (d > tg)? d: tg;
+}
+
/*********************************************************************/
typedef struct {
@@ -823,6 +968,10 @@
if (GOG_POSITION_IS_SPECIAL (child->model->position))
gog_view_size_allocate (child, plot_area);
}
+
+ /* special treatment for 3d charts */
+ if (gog_chart_is_3d (chart))
+ gog_chart_3d_process (chart, plot_area);
}
static void
@@ -896,24 +1045,38 @@
GSList *ptr;
GogView *child_view;
gboolean grid_line_rendered = FALSE;
+ GogChart *chart = GOG_CHART (gog_view_get_model (view));
cview_parent_klass->render (view, bbox);
- /* KLUDGE: render grid lines before axis */
- for (ptr = view->children ; ptr != NULL ; ptr = ptr->next) {
- child_view = ptr->data;
- if (!grid_line_rendered && IS_GOG_AXIS (child_view->model)) {
- grid_line_render (ptr, bbox);
- plot_render (view, bbox);
- grid_line_rendered = TRUE;
+ if (gog_chart_is_3d (chart)) {
+ for (ptr = view->children ; ptr != NULL ; ptr = ptr->next) {
+ child_view = ptr->data;
+ if (!IS_GOG_AXIS (child_view->model) && !IS_GOG_PLOT (child_view->model))
+ gog_view_render (ptr->data, bbox);
+ }
+ /* now render plot and axes */
+ for (ptr = view->children ; ptr != NULL ; ptr = ptr->next) {
+ child_view = ptr->data;
+ if (IS_GOG_PLOT (child_view->model))
+ gog_view_render (ptr->data, bbox);
+ }
+ } else {
+ /* KLUDGE: render grid lines before axis */
+ for (ptr = view->children ; ptr != NULL ; ptr = ptr->next) {
+ child_view = ptr->data;
+ if (!grid_line_rendered && IS_GOG_AXIS (child_view->model)) {
+ grid_line_render (ptr, bbox);
+ plot_render (view, bbox);
+ grid_line_rendered = TRUE;
+ }
+ if (IS_GOG_PLOT (child_view->model)) {
+ if (!GOG_PLOT (child_view->model)->render_before_axes)
+ gog_view_render (ptr->data, bbox);
+ } else
+ gog_view_render (ptr->data, bbox);
}
- if (IS_GOG_PLOT (child_view->model)) {
- if (!GOG_PLOT (child_view->model)->render_before_axes)
- gog_view_render (ptr->data, bbox);
- } else
- gog_view_render (ptr->data, bbox);
}
-
}
static void
Modified: trunk/goffice/graph/gog-chart.h
==============================================================================
--- trunk/goffice/graph/gog-chart.h (original)
+++ trunk/goffice/graph/gog-chart.h Mon May 12 09:02:12 2008
@@ -29,7 +29,7 @@
G_BEGIN_DECLS
GogAxisSet gog_axis_set_from_str (char const *str);
-
+
#define GOG_CHART_TYPE (gog_chart_get_type ())
#define GOG_CHART(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_CHART_TYPE, GogChart))
#define IS_GOG_CHART(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_CHART_TYPE))
@@ -60,6 +60,8 @@
/* View utils */
GogViewAllocation const *gog_chart_view_get_plot_area (GogView const *view);
+gboolean gog_chart_is_3d (GogChart const *chart);
+
G_END_DECLS
#endif /* GOG_CHART_H */
Modified: trunk/goffice/math/Makefile.am
==============================================================================
--- trunk/goffice/math/Makefile.am (original)
+++ trunk/goffice/math/Makefile.am Mon May 12 09:02:12 2008
@@ -6,7 +6,8 @@
go-regression.c \
go-cspline.c \
go-complex.c \
- go-fft.c
+ go-fft.c \
+ go-matrix3x3.c
libgoffice_math_ladir = $(goffice_include_dir)/math
libgoffice_math_la_HEADERS = \
@@ -15,7 +16,8 @@
go-regression.h \
go-cspline.h \
go-complex.h \
- go-fft.h
+ go-fft.h \
+ go-matrix3x3.h
include $(top_srcdir)/goffice.mk
Added: trunk/goffice/math/go-matrix3x3.c
==============================================================================
--- (empty file)
+++ trunk/goffice/math/go-matrix3x3.c Mon May 12 09:02:12 2008
@@ -0,0 +1,56 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * go-matrix3x3.c
+ *
+ * Copyright (C) 2007 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include <goffice/goffice-config.h>
+#include <goffice/math/go-matrix3x3.h>
+#include <math.h>
+
+void
+go_matrix3x3_transform (GOMatrix3x3 *mat,
+ gdouble xo, gdouble yo, gdouble zo,
+ gdouble *x, gdouble *y, gdouble *z)
+{
+ *x = xo * mat->a11 + yo * mat->a12 + zo * mat->a13;
+ *y = xo * mat->a21 + yo * mat->a22 + zo * mat->a23;
+ *z = xo * mat->a31 + yo * mat->a32 + zo * mat->a33;
+}
+
+void
+go_matrix3x3_from_euler (GOMatrix3x3 *mat,
+ gdouble Psi, gdouble Theta, gdouble Phi)
+{
+ gdouble sp = sin(Psi);
+ gdouble cp = cos(Psi);
+ gdouble st = sin(Theta);
+ gdouble ct = cos(Theta);
+ gdouble sf = sin(Phi);
+ gdouble cf = cos(Phi);
+ mat->a11 = cf * cp - sf * sp * ct;
+ mat->a12 = - cp * sf - sp * cf * ct;
+ mat->a13 = st * sp;
+ mat->a21 = sp * cf + cp * sf * ct;
+ mat->a22 = cf * cp * ct - sf * sp;
+ mat->a23 = - st * cp;
+ mat->a31 = st * sf;
+ mat->a32 = st * cf;
+ mat->a33 = ct;
+}
Added: trunk/goffice/math/go-matrix3x3.h
==============================================================================
--- (empty file)
+++ trunk/goffice/math/go-matrix3x3.h Mon May 12 09:02:12 2008
@@ -0,0 +1,39 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * go-matrix3x3.h
+ *
+ * Copyright (C) 2007 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#ifndef GO_MATRIX3X3_H
+#define GO_MATRIX3X3_H
+
+#include <glib/gtypes.h>
+
+typedef struct {
+ gdouble a11, a12, a13, a21, a22, a23, a31, a32, a33;
+} GOMatrix3x3;
+
+void go_matrix3x3_transform (GOMatrix3x3 *mat,
+ gdouble xo, gdouble yo, gdouble zo,
+ gdouble *x, gdouble *y, gdouble *z);
+
+void go_matrix3x3_from_euler (GOMatrix3x3 *mat,
+ gdouble Psi, gdouble Theta, gdouble Phi);
+
+#endif /* GO_MATRIX3X3_H */
Modified: trunk/goffice/math/go-rangefunc.c
==============================================================================
--- trunk/goffice/math/go-rangefunc.c (original)
+++ trunk/goffice/math/go-rangefunc.c Mon May 12 09:02:12 2008
@@ -233,3 +233,19 @@
return 0;
return 1;
}
+
+int
+SUFFIX(go_range_decreasing) (DOUBLE const *xs, int n)
+{
+ int i;
+ for (i = 1; i < n; i++)
+ if (xs[i - 1] <= xs[i])
+ return 0;
+ return 1;
+}
+
+int
+SUFFIX(go_range_vary_uniformly) (DOUBLE const *xs, int n)
+{
+ return SUFFIX(go_range_increasing) (xs, n) || SUFFIX(go_range_decreasing) (xs, n);
+}
Modified: trunk/goffice/math/go-rangefunc.h
==============================================================================
--- trunk/goffice/math/go-rangefunc.h (original)
+++ trunk/goffice/math/go-rangefunc.h Mon May 12 09:02:12 2008
@@ -17,6 +17,8 @@
int go_range_median_inter (double const *xs, int n, double *res);
int go_range_median_inter_nonconst (double *xs, int n, double *res);
int go_range_increasing (double const *xs, int n);
+int go_range_decreasing (double const *xs, int n);
+int go_range_vary_uniformly (double const *xs, int n);
#ifdef GOFFICE_WITH_LONG_DOUBLE
int go_range_suml (long double const *xs, int n, long double *res);
@@ -32,6 +34,8 @@
int go_range_median_interl (long double const *xs, int n, long double *res);
int go_range_median_inter_nonconstl (long double *xs, int n, long double *res);
int go_range_increasingl (long double const *xs, int n);
+int go_range_decreasingl (long double const *xs, int n);
+int go_range_vary_uniformlyl (long double const *xs, int n);
#endif
G_END_DECLS
Modified: trunk/plugins/plot_surface/Makefile.am
==============================================================================
--- trunk/plugins/plot_surface/Makefile.am (original)
+++ trunk/plugins/plot_surface/Makefile.am Mon May 12 09:02:12 2008
@@ -7,6 +7,10 @@
surface_la_LIBADD = $(GOFFICE_PLUGIN_LIBADD)
surface_la_SOURCES = \
+ gog-xyz.c \
+ gog-xyz.h \
+ gog-contour.c \
+ gog-contour.h \
gog-surface.c \
gog-surface.h \
xl-surface.c \
@@ -18,8 +22,8 @@
@INTLTOOL_XML_RULE@
if WITH_GTK
-dist_glade_DATA = gog-contour-prefs.glade
-surface_la_SOURCES += gog-contour-prefs.c
+dist_glade_DATA = gog-xyz-prefs.glade
+surface_la_SOURCES += gog-xyz-prefs.c
endif
# do not use the intl-tool stuff to merge the text back
Added: trunk/plugins/plot_surface/gog-contour.c
==============================================================================
--- (empty file)
+++ trunk/plugins/plot_surface/gog-contour.c Mon May 12 09:02:12 2008
@@ -0,0 +1,1146 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gog-xyz.c
+ *
+ * Copyright (C) 2004-2007 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include <goffice/goffice-config.h>
+#include "gog-contour.h"
+#include <goffice/data/go-data.h>
+#include <goffice/graph/gog-chart.h>
+#include <goffice/graph/gog-renderer.h>
+#include <goffice/graph/gog-theme.h>
+#include <goffice/math/go-math.h>
+#include <goffice/utils/go-color.h>
+
+#include <gsf/gsf-impl-utils.h>
+#include <glib/gi18n-lib.h>
+
+#include <string.h>
+
+#define EPSILON 1e-13
+
+static GType gog_contour_view_get_type (void);
+
+/*-----------------------------------------------------------------------------
+ *
+ * GogContourPlot
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static double *
+gog_contour_plot_build_matrix (GogXYZPlot const *plot, gboolean *cardinality_changed)
+{
+ unsigned i, j;
+ GogAxisMap *map;
+ GogAxisTick *zticks;
+ GogAxis *axis = plot->base.axis[GOG_AXIS_PSEUDO_3D];
+ unsigned nticks;
+ double *x, val;
+ GogSeries *series = GOG_SERIES (plot->base.series->data);
+ GODataMatrix *mat = GO_DATA_MATRIX (series->values[2].data);
+ unsigned n = plot->rows * plot->columns;
+ double *data, minimum, maximum, slope, offset = 0.;
+ unsigned max;
+
+ if (!gog_axis_get_bounds (axis, &minimum, &maximum))
+ return NULL;
+ data = g_new (double, n);
+ nticks = gog_axis_get_ticks (axis, &zticks);
+ map = gog_axis_map_new (axis, 0, 1);
+ x = g_new (double, nticks);
+ for (i = j = 0; i < nticks; i++)
+ if (zticks[i].type == GOG_AXIS_TICK_MAJOR) {
+ x[j++] = gog_axis_map_to_view (map, zticks[i].position);
+ }
+ max = --j;
+ if (x[1] > x[0]) {
+ if (x[0] > EPSILON) {
+ offset = 1.;
+ max++;
+ }
+ if (x[j] < 1. - EPSILON)
+ max++;
+ slope = 1 / (x[1] - x[0]);
+ } else {
+ offset = j;
+ if (x[0] < 1. - EPSILON)
+ max++;
+ if (x[j] > EPSILON) {
+ max++;
+ offset += 1.;
+ }
+ slope = 1 / (x[0] - x[1]);
+ }
+
+ for (i = 0; i < plot->rows; i++)
+ for (j = 0; j < plot->columns; j++) {
+ val = gog_axis_map_to_view (map,
+ go_data_matrix_get_value (mat, i, j));
+ if (fabs (val) == DBL_MAX)
+ val = go_nan;
+ else {
+ val = offset + slope * (val - x[0]);
+ if (val < 0)
+ val = (val < -EPSILON)? go_nan: 0.;
+ }
+ if (plot->transposed)
+ data[j * plot->rows + i] = val;
+ else
+ data[i * plot->columns + j] = val;
+ }
+ if (series->num_elements != max) {
+ series->num_elements = max;
+ *cardinality_changed = TRUE;
+ }
+ gog_axis_map_free (map);
+ g_free (x);
+ return data;
+}
+
+static char const *
+gog_contour_plot_type_name (G_GNUC_UNUSED GogObject const *item)
+{
+ /* xgettext : the base for how to name contour plot objects
+ */
+ return N_("PlotContour");
+}
+
+static void
+gog_contour_plot_foreach_elem (GogPlot *plot, gboolean only_visible,
+ GogEnumFunc func, gpointer data)
+{
+ unsigned i, j, nticks;
+ char *label;
+ static char separator = 0;
+ GogStyle *style = gog_style_new ();
+ GogTheme *theme = gog_object_get_theme (GOG_OBJECT (plot));
+ GogAxis *axis = plot->axis[GOG_AXIS_PSEUDO_3D];
+ GOColor *color;
+ GogAxisTick *zticks;
+ double *limits;
+ double minimum, maximum;
+
+ gog_axis_get_bounds (axis, &minimum, &maximum);
+
+ if (separator == 0) {
+ struct lconv *lc = localeconv ();
+ separator = (strcmp (lc->decimal_point, ","))? ',': ';';
+ }
+ nticks = gog_axis_get_ticks (axis, &zticks);
+ limits = g_new (double, nticks + 1);
+ for (i = j = 0; i < nticks; i++)
+ if (zticks[i].type == GOG_AXIS_TICK_MAJOR)
+ limits[j++] = zticks[i].position;
+ j--;
+ if (maximum > limits[j])
+ limits[++j] = maximum;
+ /* build the colors table */
+ color = g_new0 (GOColor, (j > 0)? j: 1);
+ if (j < 2)
+ color[0] = RGBA_WHITE;
+ else for (i = 0; i < j; i++) {
+ gog_theme_fillin_style (theme, style, GOG_OBJECT (plot->series->data), i, FALSE);
+ color[i] = style->fill.pattern.back;
+ }
+ g_object_unref (style);
+
+ style = gog_style_new ();
+ style->interesting_fields = GOG_STYLE_FILL;
+ style->disable_theming = GOG_STYLE_ALL;
+ style->fill.type = GOG_FILL_STYLE_PATTERN;
+ style->fill.pattern.pattern = GO_PATTERN_SOLID;
+
+ if (gog_axis_is_inverted (axis)) {
+ for (i = 0; i < j; i++) {
+ style->fill.pattern.back = color[i];
+ label = g_strdup_printf ("[%g%c %g%c", limits[j - i - 1], separator,
+ limits[j - i], (limits[i - j] > minimum)? '[':']');
+ (func) (i, style, label, data);
+ g_free (label);
+ }
+ if (limits[i - j] > minimum) {
+ gog_theme_fillin_style (theme, style, GOG_OBJECT (plot->series->data), i, FALSE);
+ label = g_strdup_printf ("[%g%c %g]", minimum, separator,
+ limits[i - j]);
+ (func) (i, style, label, data);
+ g_free (label);
+ }
+ } else {
+ if (minimum < limits[0]) {
+ style->fill.pattern.back = color[0];
+ label = g_strdup_printf ("[%g%c %g]", minimum, separator,
+ limits[0]);
+ (func) (0, style, label, data);
+ g_free (label);
+ i = 1;
+ j++;
+ } else
+ i = 0;
+ for (; i < j; i++) {
+ style->fill.pattern.back = color[i];
+ label = g_strdup_printf ("[%g%c %g%c", limits[i], separator,
+ limits[i + 1], (i == j - 1)? ']':'[');
+ (func) (i, style, label, data);
+ g_free (label);
+ }
+ }
+ g_free (limits);
+ g_object_unref (style);
+ g_free (color);
+}
+
+static void
+gog_contour_plot_class_init (GogContourPlotClass *klass)
+{
+ GogXYZPlotClass *gog_xyz_plot_klass = (GogXYZPlotClass *) klass;
+ GogPlotClass *gog_plot_klass = (GogPlotClass*) klass;
+ GogObjectClass *gog_object_klass = (GogObjectClass *) klass;
+
+ /* Fill in GogObject superclass values */
+ gog_object_klass->type_name = gog_contour_plot_type_name;
+ gog_object_klass->view_type = gog_contour_view_get_type ();
+
+ gog_plot_klass->axis_set = GOG_AXIS_SET_XY_pseudo_3d;
+ gog_plot_klass->foreach_elem = gog_contour_plot_foreach_elem;
+
+ gog_xyz_plot_klass->third_axis = GOG_AXIS_PSEUDO_3D;
+ gog_xyz_plot_klass->build_matrix = gog_contour_plot_build_matrix;
+}
+
+static void
+gog_contour_plot_init (GogContourPlot *contour)
+{
+ GogPlot *plot = GOG_PLOT (contour);
+
+ plot->render_before_axes = TRUE;
+}
+
+GSF_DYNAMIC_CLASS (GogContourPlot, gog_contour_plot,
+ gog_contour_plot_class_init, gog_contour_plot_init,
+ GOG_XYZ_PLOT_TYPE)
+
+/*****************************************************************************/
+
+typedef GogPlotView GogContourView;
+typedef GogPlotViewClass GogContourViewClass;
+#define CONTOUR_EPSILON 1e-10
+
+static void
+gog_contour_view_render (GogView *view, GogViewAllocation const *bbox)
+{
+ GogXYZPlot const *plot = GOG_XYZ_PLOT (view->model);
+ GogSeries const *series;
+ GODataVector *x_vec = NULL, *y_vec = NULL;
+ GogAxisMap *x_map, *y_map;
+ double zval0, zval1, zval2 = 0., zval3, t;
+ double x[4], y[4], zval[4];
+ int z[4];
+ int z0 = 0, z1 = 0, z2 = 0, z3 = 0, zmin, zmax, nans, nan = 0;
+ int k, kmax, r = 0, s, h;
+ unsigned i, imax, j, jmax, l, lmax, p;
+ GogRenderer *rend = view->renderer;
+ GogStyle *style;
+ GogTheme *theme = gog_object_get_theme (GOG_OBJECT (plot));
+ double x0, x1, y0, y1;
+ ArtVpath *path, *lines;
+ GOColor *color;
+ gboolean cw;
+ double *data;
+ int max;
+ gboolean xdiscrete, ydiscrete;
+
+ if (plot->base.series == NULL)
+ return;
+ series = GOG_SERIES (plot->base.series->data);
+ max = series->num_elements;
+ if (plot->transposed) {
+ imax = plot->columns;
+ jmax = plot->rows;
+ } else {
+ imax = plot->rows;
+ jmax = plot->columns;
+ }
+ if (imax ==0 || jmax == 0)
+ return;
+
+ x_map = gog_axis_map_new (plot->base.axis[0],
+ view->residual.x , view->residual.w);
+ y_map = gog_axis_map_new (plot->base.axis[1],
+ view->residual.y + view->residual.h,
+ -view->residual.h);
+
+ if (!(gog_axis_map_is_valid (x_map) &&
+ gog_axis_map_is_valid (y_map))) {
+ gog_axis_map_free (x_map);
+ gog_axis_map_free (y_map);
+ return;
+ }
+
+ if (plot->plotted_data)
+ data = plot->plotted_data;
+ else
+ data = gog_xyz_plot_build_matrix (plot, &cw);
+
+ /* Set cw to ensure that polygons will allways be drawn clockwise */
+ xdiscrete = gog_axis_is_discrete (plot->base.axis[0]) ||
+ series->values[(plot->transposed)? 1: 0].data == NULL;
+ if (xdiscrete) {
+ x0 = gog_axis_map_to_view (x_map, 0.);
+ x1 = gog_axis_map_to_view (x_map, 1.);
+ }else {
+ x_vec = GO_DATA_VECTOR (series->values[(plot->transposed)? 1: 0].data);
+ x0 = gog_axis_map_to_view (x_map, go_data_vector_get_value (x_vec, 0));
+ x1 = gog_axis_map_to_view (x_map, go_data_vector_get_value (x_vec, 1));
+ }
+ ydiscrete = gog_axis_is_discrete (plot->base.axis[1]) ||
+ series->values[(plot->transposed)? 0: 1].data == NULL;
+ if (ydiscrete) {
+ y0 = gog_axis_map_to_view (y_map, 0.);
+ y1 = gog_axis_map_to_view (y_map, 1.);
+ }else {
+ y_vec = GO_DATA_VECTOR (series->values[(plot->transposed)? 0: 1].data);
+ y0 = gog_axis_map_to_view (y_map, go_data_vector_get_value (y_vec, 0));
+ y1 = gog_axis_map_to_view (y_map, go_data_vector_get_value (y_vec, 1));
+ }
+ cw = (x1 > x0) == (y1 > y0);
+
+ style = gog_style_new ();
+ path = art_new (ArtVpath, 10);
+ /* build the colors table */
+ color = g_new0 (GOColor, max);
+ if (max < 2)
+ color[0] = RGBA_WHITE;
+ else for (i = 0; i < (unsigned) max; i++) {
+ gog_theme_fillin_style (theme, style, GOG_OBJECT (series), i, FALSE);
+ color[i] = style->fill.pattern.back;
+ }
+ g_object_unref (style);
+
+ /* clip to avoid problems with logarithmic axes */
+ gog_renderer_push_clip_rectangle (rend, view->residual.x, view->residual.y,
+ view->residual.w, view->residual.h);
+
+ style = gog_style_new ();
+ style->interesting_fields = GOG_STYLE_FILL | GOG_STYLE_OUTLINE;
+ style->disable_theming = GOG_STYLE_ALL;
+ style->fill.type = GOG_FILL_STYLE_PATTERN;
+ style->fill.pattern.pattern = GO_PATTERN_SOLID;
+ style->outline.dash_type = GO_LINE_SOLID;
+ style->outline.auto_dash = FALSE;
+ style->outline.auto_color = FALSE;
+ style->outline.width = 0.5;
+ style->outline.color = RGBA_BLACK;
+
+ lines = art_new (ArtVpath, lmax = 64);
+ l = 0;
+
+ for (j = 1; j < jmax; j++) {
+ if (xdiscrete) {
+ x0 = gog_axis_map_to_view (x_map, j);
+ x1 = gog_axis_map_to_view (x_map, j + 1);
+ }else {
+ x0 = gog_axis_map_to_view (x_map, go_data_vector_get_value (x_vec, j - 1));
+ x1 = gog_axis_map_to_view (x_map, go_data_vector_get_value (x_vec, j));
+ }
+
+ for (i = 1; i < imax; i++) {
+ if (ydiscrete) {
+ y0 = gog_axis_map_to_view (y_map, i);
+ y1 = gog_axis_map_to_view (y_map, i + 1);
+ }else {
+ y0 = gog_axis_map_to_view (y_map, go_data_vector_get_value (y_vec, i - 1));
+ y1 = gog_axis_map_to_view (y_map, go_data_vector_get_value (y_vec, i));
+ }
+ nans = 0;
+ nan = 4;
+ zmin = max;
+ zmax = 0;
+ zval0 = data[(i - 1) * jmax + j - 1];
+ if (!isnan (zval0)) {
+ z0 = floor (zval0);
+ if (z0 > zmax)
+ zmax = z0;
+ if (z0 < zmin) {
+ zmin = z0;
+ r = 0;
+ }
+ } else {
+ nans++;
+ nan = 0;
+ }
+ zval1 = data[(i - 1) * jmax + j];
+ if (!isnan (zval1)) {
+ z1 = floor (zval1);
+ if (z1 > zmax)
+ zmax = z1;
+ if (z1 < zmin) {
+ zmin = z1;
+ r = 1;
+ }
+ } else {
+ nans++;
+ nan = 1;
+ }
+ zval2 = data[i * jmax + j];
+ if (!isnan (zval2)) {
+ z2 = floor (zval2);
+ if (z2 > zmax)
+ zmax = z2;
+ if (z2 < zmin) {
+ zmin = z2;
+ r = 2;
+ }
+ } else {
+ nans++;
+ nan = 2;
+ }
+ zval3 = data[i * jmax + j - 1];
+ if (!isnan (zval3)) {
+ z3 = floor (zval3);
+ if (z3 > zmax)
+ zmax = z3;
+ if (z3 < zmin) {
+ zmin = z3;
+ r = 3;
+ }
+ } else {
+ nans++;
+ nan = 3;
+ }
+ if (nans > 1)
+ continue;
+ /* Build the x, y and z arrays for the tile */
+ k = r;
+ s = 0;
+ do {
+ if (k != nan) {
+ switch (k) {
+ case 0:
+ x[s] = x0;
+ y[s] = y0;
+ z[s] = z0;
+ zval[s++] = zval0;
+ break;
+ case 1:
+ x[s] = x1;
+ y[s] = y0;
+ z[s] = z1;
+ zval[s++] = zval1;
+ break;
+ case 2:
+ x[s] = x1;
+ y[s] = y1;
+ z[s] = z2;
+ zval[s++] = zval2;
+ break;
+ default:
+ x[s] = x0;
+ y[s] = y1;
+ z[s] = z3;
+ zval[s++] = zval3;
+ }
+ }
+ if (cw) {
+ k++;
+ k %= 4;
+ } else {
+ if (k == 0)
+ k = 3;
+ else
+ k--;
+ }
+ } while (k != r);
+ if (zmin == zmax) {
+ /* paint everything with one color*/
+ style->outline.color = color[zmin];
+ style->fill.pattern.back = color[zmin];
+ gog_renderer_push_style (rend, style);
+ path[0].code = ART_MOVETO;
+ for (k = 0; k < s; ) {
+ path[k].x = x[k];
+ path[k].y = y[k];
+ path[++k].code = ART_LINETO;
+ }
+ path[k].x = x[0];
+ path[k].y = y[0];
+ path[k + 1].code = ART_END;
+ /* narrow parameter is TRUE below to avoid border effects */
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ } else {
+ kmax = 3 - nans;
+ if (!nans && (((z0 < z1) && (z1 > z2) && (z2 < z3) && (z3 > z0)) ||
+ ((z0 > z1) && (z1 < z2) && (z2 > z3) && (z3 < z0)))) {
+ /* we have a saddle point */
+ /* first find the most probable altitude of the saddle point */
+ int zn, zx;
+ gboolean crossing = FALSE, up = FALSE, odd;
+ double xl[8], yl[8];
+ /* crossing is TRUE if the saddle point occurs at a slices border */
+ zn = MAX (z[0], z[2]);
+ if (zval[1] > zval[3])
+ zx = (zval[3] == z[3])? z[3] - 1: z[3];
+ else
+ zx = (zval[1] == z[1])? z[1] - 1: z[1];
+ odd = (zx - zn) % 2;
+ if (odd) {
+ if ((zx - zn) == 1) {
+ double sum = 0.;
+ sum += (z[0] == zn)? zval[0]: zn;
+ sum += (z[1] == zx)? zval[1]: zx + 1;
+ sum += (z[2] == zn)? zval[2]: zn;
+ sum += (z[3] == zx)? zval[3]: zx + 1;
+ sum /= 4.;
+ if (fabs ((sum - zx)) < DBL_EPSILON)
+ crossing = TRUE;
+ else
+ up = (sum - zx) < 0;
+ } else
+ crossing = TRUE;
+ zn = (zn + zx) / 2;
+ zx = zn + 1;
+ } else
+ zn = zx = (zn + zx) / 2;
+ /* low values slices */
+ if (z[0] < zn) {
+ k = z[0];
+ style->outline.color = color[k];
+ style->fill.pattern.back = color[k];
+ k++;
+ path[0].code = ART_MOVETO;
+ path[1].code = ART_LINETO;
+ path[2].code = ART_LINETO;
+ path[3].code = ART_LINETO;
+ path[4].code = ART_END;
+ path[0].x = path[3].x = x[0];
+ path[0].y = path[3].y = y[0];
+ if ((l + 3) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ lines[l].code = ART_MOVETO_OPEN;
+ t = (k - zval[0]) / (zval[3] - zval[0]);
+ xl[7] = lines[l].x = path[1].x = x[0] + t * (x[3] - x[0]);
+ yl[7] = lines[l++].y = path[1].y = y[0] + t * (y[3] - y[0]);
+ lines[l].code = ART_LINETO;
+ t = (k - zval[0]) / (zval[1] - zval[0]);
+ xl[0] = lines[l].x = path[2].x = x[0] + t * (x[1] - x[0]);
+ yl[0] = lines[l++].y = path[2].y = y[0] + t * (y[1] - y[0]);
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ path[4].code = ART_LINETO;
+ path[5].code = ART_END;
+ while (k < zn) {
+ style->outline.color = color[k];
+ style->fill.pattern.back = color[k];
+ k++;
+ path[0].x = path[4].x = xl[7];
+ path[0].y = path[4].y = yl[7];
+ path[3].x = xl[0];
+ path[3].y = yl[0];
+ if ((l + 3) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ lines[l].code = ART_MOVETO_OPEN;
+ t = (k - zval[0]) / (zval[3] - zval[0]);
+ xl[7] = lines[l].x = path[1].x = x[0] + t * (x[3] - x[0]);
+ yl[7] = lines[l++].y = path[1].y = y[0] + t * (y[3] - y[0]);
+ lines[l].code = ART_LINETO;
+ t = (k - zval[0]) / (zval[1] - zval[0]);
+ xl[0] = lines[l].x = path[2].x = x[0] + t * (x[1] - x[0]);
+ yl[0] = lines[l++].y = path[2].y = y[0] + t * (y[1] - y[0]);
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ }
+ } else
+ xl[0] = xl[7] = -1.;
+ if (z[2] < zn) {
+ k = z[2];
+ style->outline.color = color[k];
+ style->fill.pattern.back = color[k];
+ k++;
+ path[0].code = ART_MOVETO;
+ path[1].code = ART_LINETO;
+ path[2].code = ART_LINETO;
+ path[3].code = ART_LINETO;
+ path[4].code = ART_END;
+ path[0].x = path[3].x = x[2];
+ path[0].y = path[3].y = y[2];
+ if ((l + 3) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ lines[l].code = ART_MOVETO_OPEN;
+ t = (k - zval[2]) / (zval[1] - zval[2]);
+ xl[3] = lines[l].x = path[1].x = x[2] + t * (x[1] - x[2]);
+ yl[3] = lines[l++].y = path[1].y = y[2] + t * (y[1] - y[2]);
+ lines[l].code = ART_LINETO;
+ t = (k - zval[2]) / (zval[3] - zval[2]);
+ xl[4] = lines[l].x = path[2].x = x[2] + t * (x[3] - x[2]);
+ yl[4] = lines[l++].y = path[2].y = y[2] + t * (y[3] - y[2]);
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ path[4].code = ART_LINETO;
+ path[5].code = ART_END;
+ while (k < zn) {
+ style->outline.color = color[k];
+ style->fill.pattern.back = color[k];
+ k++;
+ path[0].x = path[4].x = xl[3];
+ path[0].y = path[4].y = yl[3];
+ path[3].x = xl[4];
+ path[3].y = yl[4];
+ if ((l + 3) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ lines[l].code = ART_MOVETO_OPEN;
+ t = (k - zval[2]) / (zval[1] - zval[2]);
+ xl[3] = lines[l].x = path[1].x = x[2] + t * (x[1] - x[2]);
+ yl[3] = lines[l++].y = path[1].y = y[2] + t * (y[1] - y[2]);
+ lines[l].code = ART_LINETO;
+ t = (k - zval[2]) / (zval[3] - zval[2]);
+ xl[4] = lines[l].x = path[2].x = x[2] + t * (x[3] - x[2]);
+ yl[4] = lines[l++].y = path[2].y = y[2] + t * (y[3] - y[2]);
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ }
+ } else
+ xl[3] = xl[4] = -1.;
+ /* high values slices */
+ k = z[1];
+ if (zval[1] == k)
+ k--;
+ if (k > zx) {
+ path[0].code = ART_MOVETO;
+ path[1].code = ART_LINETO;
+ path[2].code = ART_LINETO;
+ path[3].code = ART_LINETO;
+ path[4].code = ART_END;
+ path[0].x = path[3].x = x[1];
+ path[0].y = path[3].y = y[1];
+ if ((l + 3) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ lines[l].code = ART_MOVETO_OPEN;
+ t = (k - zval[1]) / (zval[0] - zval[1]);
+ xl[1] = lines[l].x = path[1].x = x[1] + t * (x[0] - x[1]);
+ yl[1] = lines[l++].y = path[1].y = y[1] + t * (y[0] - y[1]);
+ lines[l].code = ART_LINETO;
+ t = (k - zval[1]) / (zval[2] - zval[1]);
+ xl[2] = lines[l].x = path[2].x = x[1] + t * (x[2] - x[1]);
+ yl[2] = lines[l++].y = path[2].y = y[1] + t * (y[2] - y[1]);
+ style->outline.color = color[k];
+ style->fill.pattern.back = color[k];
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ path[4].code = ART_LINETO;
+ path[5].code = ART_END;
+ k--;
+ while (k > zx) {
+ path[0].x = path[4].x = xl[1];
+ path[0].y = path[4].y = yl[1];
+ path[3].x = xl[2];
+ path[3].y = yl[2];
+ if ((l + 3) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ lines[l].code = ART_MOVETO_OPEN;
+ t = (k - zval[1]) / (zval[0] - zval[1]);
+ xl[1] = lines[l].x = path[1].x = x[1] + t * (x[0] - x[1]);
+ yl[1] = lines[l++].y = path[1].y = y[1] + t * (y[0] - y[1]);
+ lines[l].code = ART_LINETO;
+ t = (k - zval[1]) / (zval[2] - zval[1]);
+ xl[2] = lines[l].x = path[2].x = x[1] + t * (x[2] - x[1]);
+ yl[2] = lines[l++].y = path[2].y = y[1] + t * (y[2] - y[1]);
+ style->outline.color = color[k];
+ style->fill.pattern.back = color[k];
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ k--;
+ }
+ } else
+ xl[1] = xl[2] = -1.;
+ k = z[3];
+ if (zval[3] == k)
+ k--;
+ if (k > zx) {
+ path[0].code = ART_MOVETO;
+ path[1].code = ART_LINETO;
+ path[2].code = ART_LINETO;
+ path[3].code = ART_LINETO;
+ path[4].code = ART_END;
+ path[0].x = path[3].x = x[3];
+ path[0].y = path[3].y = y[3];
+ if ((l + 3) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ lines[l].code = ART_MOVETO_OPEN;
+ t = (k - zval[3]) / (zval[2] - zval[3]);
+ xl[5] = lines[l].x = path[1].x = x[3] + t * (x[2] - x[3]);
+ yl[5] = lines[l++].y = path[1].y = y[3] + t * (y[2] - y[3]);
+ lines[l].code = ART_LINETO;
+ t = (k - zval[3]) / (zval[0] - zval[3]);
+ xl[6] = lines[l].x = path[2].x = x[3] + t * (x[0] - x[3]);
+ yl[6] = lines[l++].y = path[2].y = y[3] + t * (y[0] - y[3]);
+ style->outline.color = color[k];
+ style->fill.pattern.back = color[k];
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ path[4].code = ART_LINETO;
+ path[5].code = ART_END;
+ k--;
+ while (k > zx) {
+ path[0].x = path[4].x = xl[5];
+ path[0].y = path[4].y = yl[5];
+ path[3].x = xl[6];
+ path[3].y = yl[6];
+ if ((l + 3) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ lines[l].code = ART_MOVETO_OPEN;
+ t = (k - zval[3]) / (zval[2] - zval[3]);
+ xl[5] = lines[l].x = path[1].x = x[3] + t * (x[2] - x[3]);
+ yl[5] = lines[l++].y = path[1].y = y[3] + t * (y[2] - y[3]);
+ lines[l].code = ART_LINETO;
+ t = (k - zval[3]) / (zval[0] - zval[3]);
+ xl[6] = lines[l].x = path[2].x = x[3] + t * (x[0] - x[3]);
+ yl[6] = lines[l++].y = path[2].y = y[3] + t * (y[0] - y[3]);
+ style->outline.color = color[k];
+ style->fill.pattern.back = color[k];
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ k--;
+ }
+ } else
+ xl[5] = xl[6] = -1.;
+ /* middle values slices */
+ if (odd) {
+ if (crossing) {
+ double xb[4], yb[4], xc, yc;
+ for (k = 0; k < 4; k++) {
+ s = (k + 1) % 4;
+ t = (zx - zval[s]) / (zval[k] - zval[s]);
+ xb[k] = x[s] + t * (x[k] - x[s]);
+ yb[k] = y[s] + t * (y[k] - y[s]);
+ }
+ if ((l + 5) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ lines[l].code = ART_MOVETO_OPEN;
+ lines[l].x = xb[0];
+ lines[l++].y = yb[0];
+ lines[l].code = ART_LINETO;
+ lines[l].x = xb[2];
+ lines[l++].y = yb[2];
+ lines[l].code = ART_MOVETO_OPEN;
+ lines[l].x = xb[1];
+ lines[l++].y = yb[1];
+ lines[l].code = ART_LINETO;
+ lines[l].x = xb[3];
+ lines[l++].y = yb[3];
+ /* calculate the coordinates xc and yc of crossing point */
+ t = ((xb[1] - xb[0]) * (yb[3] - yb[1])
+ + (xb[1] - xb[3]) * (yb[1] - yb[0])) /
+ ((xb[2] - xb[0]) * (yb[3] - yb[1])
+ + (xb[1] - xb[3]) * (yb[2] - yb[0]));
+ xc = xb[0] + t * (xb[2] - xb[0]);
+ yc = yb[0] + t * (yb[2] - yb[0]);
+ /* fill */
+ path[0].code = ART_MOVETO;
+ path[1].code = ART_LINETO;
+ path[2].code = ART_LINETO;
+ path[3].code = ART_LINETO;
+ path[4].code = ART_LINETO;
+ if (xl[0] < 0.) {
+ path[4].x = path[0].x = x[0];
+ path[4].y = path[0].y = y[0];
+ path[5].code = ART_END;
+ } else {
+ path[5].x = path[0].x = xl[7];
+ path[5].y = path[0].y = yl[7];
+ path[4].x = xl[0];
+ path[4].y = yl[0];
+ path[5].code = ART_LINETO;
+ path[6].code = ART_END;
+ }
+ path[1].x = xb[3];
+ path[1].y = yb[3];
+ path[2].x = xc;
+ path[2].y = yc;
+ path[3].x = xb[0];
+ path[3].y = yb[0];
+ style->outline.color = color[zn];
+ style->fill.pattern.back = color[zn];
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ if (xl[2] < 0.) {
+ path[4].x = path[0].x = x[2];
+ path[4].y = path[0].y = y[2];
+ path[5].code = ART_END;
+ } else {
+ path[5].x = path[0].x = xl[3];
+ path[5].y = path[0].y = yl[3];
+ path[4].x = xl[4];
+ path[4].y = yl[4];
+ path[5].code = ART_LINETO;
+ path[6].code = ART_END;
+ }
+ path[1].x = xb[1];
+ path[1].y = yb[1];
+ path[3].x = xb[2];
+ path[3].y = yb[2];
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ if (xl[2] < 0.) {
+ path[4].x = path[0].x = x[1];
+ path[4].y = path[0].y = y[1];
+ path[5].code = ART_END;
+ } else {
+ path[5].x = path[0].x = xl[1];
+ path[5].y = path[0].y = yl[1];
+ path[4].x = xl[2];
+ path[4].y = yl[2];
+ path[5].code = ART_LINETO;
+ path[6].code = ART_END;
+ }
+ path[1].x = xb[0];
+ path[1].y = yb[0];
+ path[3].x = xb[1];
+ path[3].y = yb[1];
+ style->outline.color = color[zx];
+ style->fill.pattern.back = color[zx];
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ if (xl[6] < 0.) {
+ path[4].x = path[0].x = x[3];
+ path[4].y = path[0].y = y[3];
+ path[5].code = ART_END;
+ } else {
+ path[5].x = path[0].x = xl[5];
+ path[5].y = path[0].y = yl[5];
+ path[4].x = xl[6];
+ path[4].y = yl[6];
+ path[5].code = ART_LINETO;
+ path[6].code = ART_END;
+ }
+ path[1].x = xb[2];
+ path[1].y = yb[2];
+ path[3].x = xb[3];
+ path[3].y = yb[3];
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ } else {
+ if (up) {
+ /* saddle point is in the lower slice */
+ /* draw the upper slices */
+ path[0].code = ART_MOVETO;
+ path[1].code = ART_LINETO;
+ path[2].code = ART_LINETO;
+ path[3].code = ART_LINETO;
+ if (xl[1] < 0.) {
+ path[4].code = ART_END;
+ path[0].x = path[3].x = x[1];
+ path[0].y = path[3].y = y[1];
+ } else {
+ path[4].code = ART_LINETO;
+ path[5].code = ART_END;
+ path[0].x = path[4].x = xl[1];
+ path[0].y = path[4].y = yl[1];
+ path[3].x = xl[2];
+ path[3].y = yl[2];
+ }
+ if ((l + 5) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ lines[l].code = ART_MOVETO_OPEN;
+ t = (zx - zval[1]) / (zval[0] - zval[1]);
+ xl[1] = lines[l].x = path[1].x = x[1] + t * (x[0] - x[1]);
+ yl[1] = lines[l++].y = path[1].y = y[1] + t * (y[0] - y[1]);
+ lines[l].code = ART_LINETO;
+ t = (zx - zval[1]) / (zval[2] - zval[1]);
+ xl[2] = lines[l].x = path[2].x = x[1] + t * (x[2] - x[1]);
+ yl[2] = lines[l++].y = path[2].y = y[1] + t * (y[2] - y[1]);
+ style->outline.color = color[zx];
+ style->fill.pattern.back = color[zx];
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ if (xl[5] < 0.) {
+ path[4].code = ART_END;
+ path[0].x = path[3].x = x[3];
+ path[0].y = path[3].y = y[3];
+ } else {
+ path[4].code = ART_LINETO;
+ path[5].code = ART_END;
+ path[0].x = path[4].x = xl[5];
+ path[0].y = path[4].y = yl[5];
+ path[3].x = xl[6];
+ path[3].y = yl[6];
+ }
+ if ((l + 5) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ lines[l].code = ART_MOVETO_OPEN;
+ t = (zx - zval[3]) / (zval[2] - zval[3]);
+ xl[5] = lines[l].x = path[1].x = x[3] + t * (x[2] - x[3]);
+ yl[5] = lines[l++].y = path[1].y = y[3] + t * (y[2] - y[3]);
+ lines[l].code = ART_LINETO;
+ t = (zx - zval[3]) / (zval[0] - zval[3]);
+ xl[6] = lines[l].x = path[2].x = x[3] + t * (x[0] - x[3]);
+ yl[6] = lines[l++].y = path[2].y = y[3] + t * (y[0] - y[3]);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ } else {
+ /* saddle point is in the upper slice */
+ path[0].code = ART_MOVETO;
+ path[1].code = ART_LINETO;
+ path[2].code = ART_LINETO;
+ path[3].code = ART_LINETO;
+ if (xl[0] < 0.) {
+ path[4].code = ART_END;
+ path[0].x = path[3].x = x[0];
+ path[0].y = path[3].y = y[0];
+ } else {
+ path[4].code = ART_LINETO;
+ path[5].code = ART_END;
+ path[0].x = path[4].x = xl[7];
+ path[0].y = path[4].y = yl[7];
+ path[3].x = xl[0];
+ path[3].y = yl[0];
+ }
+ if ((l + 5) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ lines[l].code = ART_MOVETO_OPEN;
+ t = (k - zval[0]) / (zval[3] - zval[0]);
+ xl[7] = lines[l].x = path[1].x = x[0] + t * (x[3] - x[0]);
+ yl[7] = lines[l++].y = path[1].y = y[0] + t * (y[3] - y[0]);
+ lines[l].code = ART_LINETO;
+ t = (k - zval[0]) / (zval[1] - zval[0]);
+ xl[0] = lines[l].x = path[2].x = x[0] + t * (x[1] - x[0]);
+ yl[0] = lines[l++].y = path[2].y = y[0] + t * (y[1] - y[0]);
+ style->outline.color = color[zn];
+ style->fill.pattern.back = color[zn];
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ if (xl[4] < 0.) {
+ path[4].code = ART_END;
+ path[0].x = path[3].x = x[2];
+ path[0].y = path[3].y = y[2];
+ } else {
+ path[4].code = ART_LINETO;
+ path[5].code = ART_END;
+ path[0].x = path[4].x = xl[3];
+ path[0].y = path[4].y = yl[3];
+ path[3].x = xl[4];
+ path[3].y = yl[4];
+ }
+ lines[l].code = ART_MOVETO_OPEN;
+ t = (k - zval[2]) / (zval[1] - zval[2]);
+ xl[3] = lines[l].x = path[1].x = x[2] + t * (x[1] - x[2]);
+ yl[3] = lines[l++].y = path[1].y = y[2] + t * (y[1] - y[2]);
+ lines[l].code = ART_LINETO;
+ t = (k - zval[2]) / (zval[3] - zval[2]);
+ xl[4] = lines[l].x = path[2].x = x[2] + t * (x[3] - x[2]);
+ yl[4] = lines[l++].y = path[2].y = y[2] + t * (y[3] - y[2]);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ zn = zx;
+ }
+ /* draw the saddle containing slice */
+ k = 0;
+ for (s = 0; s < 8; s++) {
+ path[k].code = (k)? ART_LINETO: ART_MOVETO;
+ if (xl[s] < 0.) {
+ if (s == 7)
+ break;
+ else if (s > 0)
+ s++;
+ r = s / 2;
+ path[k].x = x[r];
+ path[k++].y = y[r];
+ } else {
+ path[k].x = xl[s];
+ path[k++].y = yl[s];
+ }
+ }
+ path[k].code = ART_LINETO;
+ path[k].x = path[0].x;
+ path[k++].y = path[0].y;
+ path[k].code = ART_END;
+ style->outline.color = color[zn];
+ style->fill.pattern.back = color[zn];
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ }
+ } else {
+ k = 0;
+ for (s = 0; s < 8; s++) {
+ path[k].code = (k)? ART_LINETO: ART_MOVETO;
+ if (xl[s] < 0.) {
+ if (s == 7)
+ break;
+ else if (s > 0)
+ s++;
+ r = s / 2;
+ path[k].x = x[r];
+ path[k++].y = y[r];
+ } else {
+ path[k].x = xl[s];
+ path[k++].y = yl[s];
+ }
+ }
+ path[k].code = ART_LINETO;
+ path[k].x = path[0].x;
+ path[k++].y = path[0].y;
+ path[k].code = ART_END;
+ style->outline.color = color[zx];
+ style->fill.pattern.back = color[zx];
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ }
+ } else {
+ /* no saddle point visible */
+ if ((l + (zmax - zmin) * 2 + 1) >= lmax)
+ lines = art_renew (lines, ArtVpath, lmax += 64);
+ path[0].code = ART_MOVETO;
+ path[0].x = x[0];
+ path[0].y = y[0];
+ p = 1;
+ k = 1;
+ s = 0;
+ r = kmax;
+ while (zmin < zmax) {
+ style->outline.color = color[zmin];
+ style->fill.pattern.back = color[zmin];
+ gog_renderer_push_style (rend, style);
+ while (z[k] <= zmin && k < kmax) {
+ if (fabs (path[p-1].x - x[k]) > CONTOUR_EPSILON ||
+ fabs (path[p-1].y - y[k]) > CONTOUR_EPSILON) {
+ path[p].code = ART_LINETO;
+ path[p].x = x[k];
+ path[p++].y = y[k++];
+ } else
+ k++;
+ }
+ while (z[r] <= zmin && r > 0)
+ r--;
+ zmin++;
+ t = (zmin - zval[k - 1]) / (zval[k] - zval[k - 1]);
+ path[p].code = ART_LINETO;
+ lines[l].code = ART_MOVETO_OPEN;
+ lines[l].x = path[p].x = x[k - 1] + t * (x[k] - x[k - 1]);
+ lines[l++].y = path[p].y = y[k - 1] + t * (y[k] - y[k - 1]);
+ if (fabs (path[p-1].x - path[p].x) > CONTOUR_EPSILON ||
+ fabs (path[p-1].y - path[p].y) > CONTOUR_EPSILON)
+ p++;
+ path[p].code = ART_LINETO;
+ lines[l].code = ART_LINETO;
+ if (r < kmax) {
+ t = (zmin - zval[r]) / (zval[r + 1] - zval[r]);
+ lines[l].x = path[p].x = x[r] + t * (x[r + 1] - x[r]);
+ lines[l++].y = path[p].y = y[r] + t * (y[r + 1] - y[r]);
+ } else {
+ t = (zmin - zval[r]) / (zval[0] - zval[r]);
+ lines[l].x = path[p].x = x[r] + t * (x[0] - x[r]);
+ lines[l++].y = path[p].y = y[r] + t * (y[0] - y[r]);
+ }
+ if (fabs (path[p-1].x - path[p].x) > CONTOUR_EPSILON ||
+ fabs (path[p-1].y - path[p].y) > CONTOUR_EPSILON)
+ p++;
+ if (s == 0) {
+ for (h = r + 1; h <= kmax; h++) {
+ if (fabs (path[p-1].x - x[h]) > CONTOUR_EPSILON ||
+ fabs (path[p-1].y - y[h]) > CONTOUR_EPSILON) {
+ path[p].code = ART_LINETO;
+ path[p].x = x[h];
+ path[p++].y = y[h];
+ }
+ }
+ } else {
+ for (h = r + 1; h < s; h++) {
+ if (fabs (path[p-1].x - x[h]) > CONTOUR_EPSILON ||
+ fabs (path[p-1].y - y[h]) > CONTOUR_EPSILON) {
+ path[p].code = ART_LINETO;
+ path[p].x = x[h];
+ path[p++].y = y[h];
+ }
+ }
+ }
+ s = r + 1;
+ if (fabs (path[p-1].x - path[0].x) > CONTOUR_EPSILON ||
+ fabs (path[p-1].y -path[0].y) > CONTOUR_EPSILON) {
+ path[p].code = ART_LINETO;
+ path[p].x = path[0].x;
+ path[p++].y = path[0].y;
+ } else {
+ /* use the exact values so that the polygon is closed */
+ path[p-1].x = path[0].x;
+ path[p-1].y = path[0].y;
+ }
+ path[p].code = ART_END;
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ path[0].x = lines[l - 1].x;
+ path[0].y = lines[l - 1].y;
+ path[1].x = lines[l - 2].x;
+ path[1].y = lines[l - 2].y;
+ p = (fabs (path[0].x - path[1].x) > CONTOUR_EPSILON ||
+ fabs (path[0].y - path[1].y) > CONTOUR_EPSILON)?
+ 2: 1;
+ }
+ if (fabs (path[0].x - path[1].x) < CONTOUR_EPSILON
+ && fabs (path[0].y - path[1].y) < CONTOUR_EPSILON)
+ continue;
+ while (k < s) {
+ path[p].code = ART_LINETO;
+ path[p].x = x[k];
+ path[p++].y = y[k++];
+ }
+ path[p].code = ART_LINETO;
+ path[p].x = path[0].x;
+ path[p++].y = path[0].y;
+ path[p].code = ART_END;
+ style->outline.color = color[zmin];
+ style->fill.pattern.back = color[zmin];
+ gog_renderer_push_style (rend, style);
+ gog_renderer_draw_polygon (rend, path, FALSE);
+ gog_renderer_pop_style (rend);
+ }
+ }
+ }
+ }
+ lines[l].code = ART_END;
+ gog_renderer_push_style (rend, GOG_STYLED_OBJECT (series)->style);
+ gog_renderer_draw_path (rend, lines);
+ gog_renderer_pop_style (rend);
+ gog_renderer_pop_clip (rend);
+ art_free (lines);
+ art_free (path);
+ g_object_unref (style);
+ gog_axis_map_free (x_map);
+ gog_axis_map_free (y_map);
+}
+
+static void
+gog_contour_view_class_init (GogViewClass *view_klass)
+{
+ view_klass->render = gog_contour_view_render;
+}
+
+GSF_DYNAMIC_CLASS (GogContourView, gog_contour_view,
+ gog_contour_view_class_init, NULL,
+ GOG_PLOT_VIEW_TYPE)
+
Added: trunk/plugins/plot_surface/gog-contour.h
==============================================================================
--- (empty file)
+++ trunk/plugins/plot_surface/gog-contour.h Mon May 12 09:02:12 2008
@@ -0,0 +1,50 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gog-contour.h
+ *
+ * Copyright (C) 2004-2007 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#ifndef GOG_CONTOUR_H
+#define GOG_CONTOUR_H
+
+#include "gog-xyz.h"
+
+G_BEGIN_DECLS
+
+/*-----------------------------------------------------------------------------
+ *
+ * GogContourPlot
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+typedef GogXYZPlot GogContourPlot;
+typedef GogXYZPlotClass GogContourPlotClass;
+
+#define GOG_CONTOUR_PLOT_TYPE (gog_contour_plot_get_type ())
+#define GOG_CONTOUR_PLOT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_CONTOUR_PLOT_TYPE, GogContourPlot))
+#define GOG_IS_PLOT_CONTOUR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_CONTOUR_PLOT_TYPE))
+
+GType gog_contour_plot_get_type (void);
+void gog_contour_plot_register_type (GTypeModule *module);
+
+void gog_contour_view_register_type (GTypeModule *module);
+
+G_END_DECLS
+
+#endif /* GOG_CONTOUR_H */
Modified: trunk/plugins/plot_surface/gog-surface.c
==============================================================================
--- trunk/plugins/plot_surface/gog-surface.c (original)
+++ trunk/plugins/plot_surface/gog-surface.c Mon May 12 09:02:12 2008
@@ -21,1548 +21,222 @@
#include <goffice/goffice-config.h>
#include "gog-surface.h"
-#include "xl-surface.h"
#include <goffice/data/go-data.h>
-#include <goffice/graph/gog-axis.h>
-#include <goffice/graph/gog-chart.h>
+#include <goffice/graph/gog-chart-map-3d.h>
#include <goffice/graph/gog-renderer.h>
-#include <goffice/graph/gog-theme.h>
-#include <goffice/math/go-math.h>
-#include <goffice/utils/go-format.h>
-#include <goffice/utils/go-color.h>
-#include <goffice/app/module-plugin-defs.h>
+#include <goffice/utils/go-path.h>
#include <glib/gi18n-lib.h>
#include <gsf/gsf-impl-utils.h>
-#include <locale.h>
-#include <string.h>
-
-GOFFICE_PLUGIN_MODULE_HEADER;
-
-enum {
- CONTOUR_PROP_0,
- CONTOUR_PROP_TRANSPOSED
-};
-
-#define EPSILON 1e-13
-
-static GogObjectClass *plot_contour_parent_klass;
-
-typedef struct {
- GogSeries base;
-
- unsigned rows, columns;
-} GogSurfaceSeries;
-typedef GogSeriesClass GogSurfaceSeriesClass;
-
-#define GOG_SURFACE_SERIES_TYPE (gog_surface_series_get_type ())
-#define GOG_SURFACE_SERIES(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_SURFACE_SERIES_TYPE, GogSurfaceSeries))
-#define GOG_IS_SURFACE_SERIES(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_SURFACE_SERIES_TYPE))
-
-static GType gog_surface_series_get_type (void);
-static GType gog_contour_view_get_type (void);
-
-static gboolean
-vary_uniformly (GODataVector *vec)
-{
- int len = go_data_vector_get_len (vec), i = 0;
- double x, x0;
- if (len < 2)
- return TRUE;
- x0 = go_data_vector_get_value (vec, 0);
- x = go_data_vector_get_value (vec, 1);
- if (!go_finite( x0) || !go_finite (x))
- return FALSE;
- if (x > x0) {
- for (i = 2; i < len; i++) {
- x0 = go_data_vector_get_value (vec, i);
- if (!go_finite (x0) || (x0 <= x))
- return FALSE;
- x = x0;
- }
- } else if (x < x0) {
- for (i = 2; i < len; i++) {
- x0 = go_data_vector_get_value (vec, i);
- if (!go_finite (x0) || (x0 >= x))
- return FALSE;
- x = x0;
- }
- }
- return TRUE;
-}
-
-/*-----------------------------------------------------------------------------
- *
- * GogContourPlot
- *
- *-----------------------------------------------------------------------------
- */
-
-/**
- * gog_contour_plot_build_matrix :
- * @plot :
- *
- * builds a table of normalized values: first slice = 0-1 second = 1-2,...
- **/
+/*****************************************************************************/
-static double *
-gog_contour_plot_build_matrix (GogContourPlot const *plot, gboolean *cardinality_changed)
-{
- GogContourPlotClass *klass = GOG_CONTOUR_PLOT_GET_CLASS (plot);
- return klass->build_matrix (plot, cardinality_changed);
-}
+static GType gog_surface_view_get_type (void);
static double *
-gog_contour_plot_real_build_matrix (GogContourPlot const *plot, gboolean *cardinality_changed)
+gog_surface_plot_build_matrix (GogXYZPlot const *plot, gboolean *cardinality_changed)
{
unsigned i, j;
- GogAxisMap *map;
- GogAxisTick *zticks;
- GogAxis *axis = plot->base.axis[GOG_AXIS_PSEUDO_3D];
- unsigned nticks;
- double *x, val;
+ double val;
GogSeries *series = GOG_SERIES (plot->base.series->data);
GODataMatrix *mat = GO_DATA_MATRIX (series->values[2].data);
unsigned n = plot->rows * plot->columns;
- double *data, minimum, maximum, slope, offset = 0.;
- unsigned max;
+ double *data;
- if (!gog_axis_get_bounds (axis, &minimum, &maximum))
- return NULL;
data = g_new (double, n);
- nticks = gog_axis_get_ticks (axis, &zticks);
- map = gog_axis_map_new (axis, 0, 1);
- x = g_new (double, nticks);
- for (i = j = 0; i < nticks; i++)
- if (zticks[i].type == GOG_AXIS_TICK_MAJOR) {
- x[j++] = gog_axis_map_to_view (map, zticks[i].position);
- }
- max = --j;
- if (x[1] > x[0]) {
- if (x[0] > EPSILON) {
- offset = 1.;
- max++;
- }
- if (x[j] < 1. - EPSILON)
- max++;
- slope = 1 / (x[1] - x[0]);
- } else {
- offset = j;
- if (x[0] < 1. - EPSILON)
- max++;
- if (x[j] > EPSILON) {
- max++;
- offset += 1.;
- }
- slope = 1 / (x[0] - x[1]);
- }
for (i = 0; i < plot->rows; i++)
for (j = 0; j < plot->columns; j++) {
- val = gog_axis_map_to_view (map,
- go_data_matrix_get_value (mat, i, j));
- if (fabs (val) == DBL_MAX)
- val = go_nan;
- else {
- val = offset + slope * (val - x[0]);
- if (val < 0)
- val = (val < -EPSILON)? go_nan: 0.;
- }
+ val = go_data_matrix_get_value (mat, i, j);
if (plot->transposed)
data[j * plot->rows + i] = val;
else
data[i * plot->columns + j] = val;
}
- if (series->num_elements != max) {
- series->num_elements = max;
- *cardinality_changed = TRUE;
- }
- gog_axis_map_free (map);
- g_free (x);
+ *cardinality_changed = FALSE;
return data;
}
-static void
-gog_contour_plot_update_3d (GogPlot *plot)
-{
- GogContourPlot *contour = GOG_CONTOUR_PLOT (plot);
- gboolean cardinality_changed = FALSE;
-
- if (plot->series == NULL)
- return;
-
- contour->plotted_data = gog_contour_plot_build_matrix (contour, &cardinality_changed);
- if (cardinality_changed) {
- /* gog_plot_request_cardinality_update can't be called from here
- * since the plot might be updating.
- */
- GogChart *chart = GOG_CHART (GOG_OBJECT (plot)->parent);
- plot->cardinality_valid = FALSE;
- if (chart != NULL)
- gog_chart_request_cardinality_update (chart);
- }
-}
-
static char const *
-gog_contour_plot_type_name (G_GNUC_UNUSED GogObject const *item)
+gog_surface_plot_type_name (G_GNUC_UNUSED GogObject const *item)
{
- /* xgettext : the base for how to name contour plot objects
+ /* xgettext : the base for how to name surface plot objects
*/
- return N_("PlotContour");
-}
-
-extern gpointer gog_contour_plot_pref (GogContourPlot *plot, GOCmdContext *cc);
-static void
-gog_contour_plot_populate_editor (GogObject *item,
- GogEditor *editor,
- G_GNUC_UNUSED GogDataAllocator *dalloc,
- GOCmdContext *cc)
-{
- gog_editor_add_page (editor,
- gog_contour_plot_pref (GOG_CONTOUR_PLOT (item), cc),
- _("Properties"));
-
- (GOG_OBJECT_CLASS (plot_contour_parent_klass)->populate_editor) (item, editor, dalloc, cc);
+ return N_("PlotSurface");
}
static void
-gog_contour_plot_clear_formats (GogContourPlot *plot)
-{
- if (plot->x.fmt != NULL) {
- go_format_unref (plot->x.fmt);
- plot->x.fmt = NULL;
- }
- if (plot->y.fmt != NULL) {
- go_format_unref (plot->y.fmt);
- plot->y.fmt = NULL;
- }
- if (plot->z.fmt != NULL) {
- go_format_unref (plot->z.fmt);
- plot->z.fmt = NULL;
- }
-}
-
-static void
-gog_contour_plot_update (GogObject *obj)
-{
- GogContourPlot * model = GOG_CONTOUR_PLOT(obj);
- GogSurfaceSeries * series;
- GODataVector *vec;
- GODataMatrix *mat;
- double tmp_min, tmp_max;
-
- if (model->base.series == NULL)
- return;
-
- series = GOG_SURFACE_SERIES (model->base.series->data);
- if (!gog_series_is_valid (GOG_SERIES (series)))
- return;
-
- if ((vec = GO_DATA_VECTOR (series->base.values[0].data)) != NULL) {
- if (model->x.fmt == NULL)
- model->x.fmt = go_data_preferred_fmt (series->base.values[0].data);
- if (vary_uniformly (vec))
- go_data_vector_get_minmax (vec, &tmp_min, &tmp_max);
- else
- tmp_min = tmp_max = go_nan;
- } else {
- tmp_min = 0;
- tmp_max = series->columns - 1;
- }
-
- if ((model->columns != series->columns)
- || (tmp_min != model->x.minima)
- || (tmp_max != model->x.maxima)) {
- model->columns = series->columns;
- model->x.minima = tmp_min;
- model->x.maxima = tmp_max;
- gog_axis_bound_changed (model->base.axis[(model->transposed)? GOG_AXIS_Y: GOG_AXIS_X],
- GOG_OBJECT (model));
- }
-
- if ((vec = GO_DATA_VECTOR (series->base.values[1].data)) != NULL) {
- if (model->y.fmt == NULL)
- model->y.fmt = go_data_preferred_fmt (series->base.values[1].data);
- if (vary_uniformly (vec))
- go_data_vector_get_minmax (vec, &tmp_min, &tmp_max);
- else
- tmp_min = tmp_max = go_nan;
- } else {
- tmp_min = 0;
- tmp_max = series->rows - 1;
- }
-
- if ((model->rows != series->rows)
- || (tmp_min != model->y.minima)
- || (tmp_max != model->y.maxima)) {
- model->rows = series->rows;
- model->y.minima = tmp_min;
- model->y.maxima = tmp_max;
- gog_axis_bound_changed (model->base.axis[(model->transposed)? GOG_AXIS_X: GOG_AXIS_Y],
- GOG_OBJECT (model));
- }
-
- g_free (model->plotted_data);
- model->plotted_data = NULL;
- mat = GO_DATA_MATRIX (series->base.values[2].data);
- go_data_matrix_get_minmax (mat, &tmp_min, &tmp_max);
- if ((tmp_min != model->z.minima)
- || (tmp_max != model->z.maxima)) {
- model->z.minima = tmp_min;
- model->z.maxima = tmp_max;
- gog_axis_bound_changed (model->base.axis[GOG_AXIS_PSEUDO_3D], GOG_OBJECT (model));
- } else
- gog_contour_plot_update_3d (GOG_PLOT (model));
-
- gog_object_emit_changed (GOG_OBJECT (obj), FALSE);
- if (plot_contour_parent_klass->update)
- plot_contour_parent_klass->update (obj);
-}
-
-static GOData *
-gog_contour_plot_axis_get_bounds (GogPlot *plot, GogAxisType axis,
- GogPlotBoundInfo * bounds)
-{
- GogSurfaceSeries *series;
- GogContourPlot *contour = GOG_CONTOUR_PLOT (plot);
- GODataVector *vec = NULL;
- double min, max;
- GOFormat *fmt;
- if (!plot->series)
- return NULL;
- series = GOG_SURFACE_SERIES (plot->series->data);
- if ((axis == GOG_AXIS_Y && contour->transposed) ||
- (axis == GOG_AXIS_X && !contour->transposed)) {
- vec = GO_DATA_VECTOR (series->base.values[0].data);
- fmt = contour->x.fmt;
- min = contour->x.minima;
- max = contour->x.maxima;
- } else if (axis == GOG_AXIS_X || axis == GOG_AXIS_Y) {
- vec = GO_DATA_VECTOR (series->base.values[1].data);
- fmt = contour->y.fmt;
- min = contour->y.minima;
- max = contour->y.maxima;
- } else {
- if (bounds->fmt == NULL && contour->z.fmt != NULL)
- bounds->fmt = go_format_ref (contour->z.fmt);
- bounds->val.minima = contour->z.minima;
- bounds->val.maxima = contour->z.maxima;
- return NULL;
- }
- if (bounds->fmt == NULL && fmt != NULL)
- bounds->fmt = go_format_ref (fmt);
- if (go_finite (min)) {
- bounds->logical.minima = bounds->val.minima = min;
- bounds->logical.maxima = bounds->val.maxima = max;
- bounds->is_discrete = FALSE;
- } else {
- bounds->val.minima = 1.;
- bounds->logical.minima = 1.;
- bounds->logical.maxima = go_nan;
- bounds->is_discrete = TRUE;
- bounds->center_on_ticks = TRUE;
- bounds->val.maxima = ((axis == GOG_AXIS_Y && contour->transposed) ||
- (axis == GOG_AXIS_X && !contour->transposed)) ?
- series->columns:
- series->rows;
- }
- return (GOData*) vec;
-}
-
-static void
-gog_contour_plot_foreach_elem (GogPlot *plot, gboolean only_visible,
- GogEnumFunc func, gpointer data)
-{
- unsigned i, j, nticks;
- char *label;
- static char separator = 0;
- GogStyle *style = gog_style_new ();
- GogTheme *theme = gog_object_get_theme (GOG_OBJECT (plot));
- GogAxis *axis = plot->axis[GOG_AXIS_PSEUDO_3D];
- GOColor *color;
- GogAxisTick *zticks;
- double *limits;
- double minimum, maximum;
-
- gog_axis_get_bounds (axis, &minimum, &maximum);
-
- if (separator == 0) {
- struct lconv *lc = localeconv ();
- separator = (strcmp (lc->decimal_point, ","))? ',': ';';
- }
- nticks = gog_axis_get_ticks (axis, &zticks);
- limits = g_new (double, nticks + 1);
- for (i = j = 0; i < nticks; i++)
- if (zticks[i].type == GOG_AXIS_TICK_MAJOR)
- limits[j++] = zticks[i].position;
- j--;
- if (maximum > limits[j])
- limits[++j] = maximum;
- /* build the colors table */
- color = g_new0 (GOColor, (j > 0)? j: 1);
- if (j < 2)
- color[0] = RGBA_WHITE;
- else for (i = 0; i < j; i++) {
- gog_theme_fillin_style (theme, style, GOG_OBJECT (plot->series->data), i, FALSE);
- color[i] = style->fill.pattern.back;
- }
- g_object_unref (style);
-
- style = gog_style_new ();
- style->interesting_fields = GOG_STYLE_FILL;
- style->disable_theming = GOG_STYLE_ALL;
- style->fill.type = GOG_FILL_STYLE_PATTERN;
- style->fill.pattern.pattern = GO_PATTERN_SOLID;
-
- if (gog_axis_is_inverted (axis)) {
- for (i = 0; i < j; i++) {
- style->fill.pattern.back = color[i];
- label = g_strdup_printf ("[%g%c %g%c", limits[j - i - 1], separator,
- limits[j - i], (limits[i - j] > minimum)? '[':']');
- (func) (i, style, label, data);
- g_free (label);
- }
- if (limits[i - j] > minimum) {
- gog_theme_fillin_style (theme, style, GOG_OBJECT (plot->series->data), i, FALSE);
- label = g_strdup_printf ("[%g%c %g]", minimum, separator,
- limits[i - j]);
- (func) (i, style, label, data);
- g_free (label);
- }
- } else {
- if (minimum < limits[0]) {
- style->fill.pattern.back = color[0];
- label = g_strdup_printf ("[%g%c %g]", minimum, separator,
- limits[0]);
- (func) (0, style, label, data);
- g_free (label);
- i = 1;
- j++;
- } else
- i = 0;
- for (; i < j; i++) {
- style->fill.pattern.back = color[i];
- label = g_strdup_printf ("[%g%c %g%c", limits[i], separator,
- limits[i + 1], (i == j - 1)? ']':'[');
- (func) (i, style, label, data);
- g_free (label);
- }
- }
- g_free (limits);
- g_object_unref (style);
- g_free (color);
-}
-
-static void
-gog_contour_plot_finalize (GObject *obj)
-{
- GogContourPlot *plot = GOG_CONTOUR_PLOT (obj);
- gog_contour_plot_clear_formats (plot);
- g_free (plot->plotted_data);
- G_OBJECT_CLASS (plot_contour_parent_klass)->finalize (obj);
-}
-
-static void
-gog_contour_plot_set_property (GObject *obj, guint param_id,
- GValue const *value, GParamSpec *pspec)
-{
- GogContourPlot *plot = GOG_CONTOUR_PLOT (obj);
-
- switch (param_id) {
- case CONTOUR_PROP_TRANSPOSED :
- if (!plot->transposed != !g_value_get_boolean (value)) {
- plot->transposed = g_value_get_boolean (value);
- if (NULL != plot->base.axis[GOG_AXIS_X])
- gog_axis_bound_changed (plot->base.axis[GOG_AXIS_X], GOG_OBJECT (plot));
- if (NULL != plot->base.axis[GOG_AXIS_Y])
- gog_axis_bound_changed (plot->base.axis[GOG_AXIS_Y], GOG_OBJECT (plot));
- g_free (plot->plotted_data);
- plot->plotted_data = NULL;
- }
- break;
-
- default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
- return; /* NOTE : RETURN */
- }
- gog_object_emit_changed (GOG_OBJECT (obj), FALSE);
-}
-
-static void
-gog_contour_plot_get_property (GObject *obj, guint param_id,
- GValue *value, GParamSpec *pspec)
-{
- GogContourPlot *plot = GOG_CONTOUR_PLOT (obj);
-
- switch (param_id) {
- case CONTOUR_PROP_TRANSPOSED :
- g_value_set_boolean (value, plot->transposed);
- break;
-
- default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
- break;
- }
-}
-
-static void
-gog_contour_plot_class_init (GogContourPlotClass *klass)
+gog_surface_plot_class_init (GogSurfacePlotClass *klass)
{
+ GogXYZPlotClass *gog_xyz_plot_klass = (GogXYZPlotClass *) klass;
GogPlotClass *gog_plot_klass = (GogPlotClass*) klass;
- GObjectClass *gobject_klass = (GObjectClass *) klass;
GogObjectClass *gog_object_klass = (GogObjectClass *) klass;
- plot_contour_parent_klass = g_type_class_peek_parent (klass);
-
- gobject_klass->finalize = gog_contour_plot_finalize;
- gobject_klass->set_property = gog_contour_plot_set_property;
- gobject_klass->get_property = gog_contour_plot_get_property;
- g_object_class_install_property (gobject_klass, CONTOUR_PROP_TRANSPOSED,
- g_param_spec_boolean ("transposed",
- _("Transposed"),
- _("Transpose the plot"),
- FALSE,
- GSF_PARAM_STATIC | G_PARAM_READWRITE|GOG_PARAM_PERSISTENT));
-
- /* Fill in GOGObject superclass values */
- gog_object_klass->update = gog_contour_plot_update;
- gog_object_klass->type_name = gog_contour_plot_type_name;
- gog_object_klass->view_type = gog_contour_view_get_type ();
- gog_object_klass->populate_editor = gog_contour_plot_populate_editor;
-
- {
- static GogSeriesDimDesc dimensions[] = {
- { N_("X"), GOG_SERIES_SUGGESTED, FALSE,
- GOG_DIM_LABEL, GOG_MS_DIM_CATEGORIES },
- { N_("Y"), GOG_SERIES_SUGGESTED, FALSE,
- GOG_DIM_LABEL, GOG_MS_DIM_CATEGORIES },
- { N_("Z"), GOG_SERIES_REQUIRED, FALSE,
- GOG_DIM_MATRIX, GOG_MS_DIM_VALUES },
- };
- gog_plot_klass->desc.series.dim = dimensions;
- gog_plot_klass->desc.series.num_dim = G_N_ELEMENTS (dimensions);
- gog_plot_klass->desc.series.style_fields = GOG_STYLE_LINE;
- }
+ gog_object_klass->type_name = gog_surface_plot_type_name;
+ gog_object_klass->view_type = gog_surface_view_get_type ();
/* Fill in GogPlotClass methods */
- gog_plot_klass->desc.num_series_min = 1;
- gog_plot_klass->desc.num_series_max = 1;
- gog_plot_klass->series_type = gog_surface_series_get_type();
- gog_plot_klass->axis_set = GOG_AXIS_SET_XY_pseudo_3d;
- gog_plot_klass->axis_get_bounds = gog_contour_plot_axis_get_bounds;
- gog_plot_klass->foreach_elem = gog_contour_plot_foreach_elem;
- gog_plot_klass->update_3d = gog_contour_plot_update_3d;
+ gog_plot_klass->axis_set = GOG_AXIS_SET_XYZ;
+ gog_plot_klass->desc.series.style_fields = GOG_STYLE_LINE | GOG_STYLE_FILL;
- klass->build_matrix = gog_contour_plot_real_build_matrix;
+ gog_xyz_plot_klass->third_axis = GOG_AXIS_Z;
+ gog_xyz_plot_klass->build_matrix = gog_surface_plot_build_matrix;
}
static void
-gog_contour_plot_init (GogContourPlot *contour)
+gog_surface_plot_init (GogSurfacePlot *surface)
{
- GogPlot *plot = GOG_PLOT (contour);
+ GogPlot *plot = GOG_PLOT (surface);
- contour->rows = contour->columns = 0;
- contour->transposed = FALSE;
- contour->base.vary_style_by_element = TRUE;
- contour->x.minima = contour->x.maxima = contour->y.minima
- = contour->y.maxima = contour->z.minima = contour->z.maxima = go_nan;
- contour->x.fmt = contour->y.fmt = contour->z.fmt = NULL;
- contour->plotted_data = NULL;
-
- plot->render_before_axes = TRUE;
+ plot->render_before_axes = FALSE;
}
-GSF_DYNAMIC_CLASS (GogContourPlot, gog_contour_plot,
- gog_contour_plot_class_init, gog_contour_plot_init,
- GOG_PLOT_TYPE)
+GSF_DYNAMIC_CLASS (GogSurfacePlot, gog_surface_plot,
+ gog_surface_plot_class_init, gog_surface_plot_init,
+ GOG_XYZ_PLOT_TYPE)
/*****************************************************************************/
-typedef GogPlotView GogContourView;
-typedef GogPlotViewClass GogContourViewClass;
-#define CONTOUR_EPSILON 1e-10
+typedef GogPlotView GogSurfaceView;
+typedef GogPlotViewClass GogSurfaceViewClass;
static void
-gog_contour_view_render (GogView *view, GogViewAllocation const *bbox)
+gog_surface_view_render (GogView *view, GogViewAllocation const *bbox)
{
- GogContourPlot const *plot = GOG_CONTOUR_PLOT (view->model);
+ GogSurfacePlot const *plot = GOG_SURFACE_PLOT (view->model);
GogSeries const *series;
- GODataVector *x_vec = NULL, *y_vec = NULL;
- GogAxisMap *x_map, *y_map;
- double zval0, zval1, zval2 = 0., zval3, t;
- double x[4], y[4], zval[4];
- int z[4];
- int z0 = 0, z1 = 0, z2 = 0, z3 = 0, zmin, zmax, nans, nan = 0;
- int k, kmax, r = 0, s, h;
- unsigned i, imax, j, jmax, l, lmax, p;
+ GogChartMap3D *chart_map;
+ GogChart *chart = GOG_CHART (view->model->parent);
+ GogViewAllocation const *area;
+ int i, imax, j, jmax, max, istep, jstep, jstart, iend, jend;
+ double x[2], y[2], z[3], x0, y0, x1, y1;
GogRenderer *rend = view->renderer;
GogStyle *style;
- GogTheme *theme = gog_object_get_theme (GOG_OBJECT (plot));
- double x0, x1, y0, y1;
- ArtVpath *path, *lines;
- GOColor *color;
- gboolean cw;
double *data;
- int max;
+ GODataVector *x_vec = NULL, *y_vec = NULL;
gboolean xdiscrete, ydiscrete;
+ GOPath *path;
+ gboolean cw;
if (plot->base.series == NULL)
return;
series = GOG_SERIES (plot->base.series->data);
max = series->num_elements;
if (plot->transposed) {
- imax = plot->columns;
- jmax = plot->rows;
- } else {
imax = plot->rows;
jmax = plot->columns;
+ } else {
+ imax = plot->columns;
+ jmax = plot->rows;
}
if (imax ==0 || jmax == 0)
return;
-
- x_map = gog_axis_map_new (plot->base.axis[0],
- view->residual.x , view->residual.w);
- y_map = gog_axis_map_new (plot->base.axis[1],
- view->residual.y + view->residual.h,
- -view->residual.h);
-
- if (!(gog_axis_map_is_valid (x_map) &&
- gog_axis_map_is_valid (y_map))) {
- gog_axis_map_free (x_map);
- gog_axis_map_free (y_map);
+ area = gog_chart_view_get_plot_area (view->parent);
+ chart_map = gog_chart_map_3d_new (chart, area,
+ GOG_PLOT (plot)->axis[GOG_AXIS_X],
+ GOG_PLOT (plot)->axis[GOG_AXIS_Y],
+ GOG_PLOT (plot)->axis[GOG_AXIS_Z]);
+ if (!gog_chart_map_3d_is_valid (chart_map)) {
+ gog_chart_map_3d_free (chart_map);
return;
}
+
+ style = gog_styled_object_get_style (GOG_STYLED_OBJECT (series));
+
if (plot->plotted_data)
data = plot->plotted_data;
else
- data = gog_contour_plot_build_matrix (plot, &cw);
+ data = gog_xyz_plot_build_matrix (plot, &cw);
- /* Set cw to ensure that polygons will allways be drawn clockwise */
+ /* check the drawing order */
xdiscrete = gog_axis_is_discrete (plot->base.axis[0]) ||
series->values[(plot->transposed)? 1: 0].data == NULL;
if (xdiscrete) {
- x0 = gog_axis_map_to_view (x_map, 0.);
- x1 = gog_axis_map_to_view (x_map, 1.);
+ x[0] = 0.;
+ x[1] = 1.;
}else {
x_vec = GO_DATA_VECTOR (series->values[(plot->transposed)? 1: 0].data);
- x0 = gog_axis_map_to_view (x_map, go_data_vector_get_value (x_vec, 0));
- x1 = gog_axis_map_to_view (x_map, go_data_vector_get_value (x_vec, 1));
+ x[0] = go_data_vector_get_value (x_vec, 0);
+ x[1] = go_data_vector_get_value (x_vec, 1);
}
ydiscrete = gog_axis_is_discrete (plot->base.axis[1]) ||
series->values[(plot->transposed)? 0: 1].data == NULL;
if (ydiscrete) {
- y0 = gog_axis_map_to_view (y_map, 0.);
- y1 = gog_axis_map_to_view (y_map, 1.);
+ y[0] = 0.;
+ y[1] = 1.;
}else {
y_vec = GO_DATA_VECTOR (series->values[(plot->transposed)? 0: 1].data);
- y0 = gog_axis_map_to_view (y_map, go_data_vector_get_value (y_vec, 0));
- y1 = gog_axis_map_to_view (y_map, go_data_vector_get_value (y_vec, 1));
+ y[0] = go_data_vector_get_value (y_vec, 0);
+ y[1] = go_data_vector_get_value (y_vec, 1);
}
- cw = (x1 > x0) == (y1 > y0);
-
- style = gog_style_new ();
- path = art_new (ArtVpath, 10);
- /* build the colors table */
- color = g_new0 (GOColor, max);
- if (max < 2)
- color[0] = RGBA_WHITE;
- else for (i = 0; i < (unsigned) max; i++) {
- gog_theme_fillin_style (theme, style, GOG_OBJECT (series), i, FALSE);
- color[i] = style->fill.pattern.back;
- }
- g_object_unref (style);
-
- /* clip to avoid problems with logarithmic axes */
- gog_renderer_push_clip_rectangle (rend, view->residual.x, view->residual.y,
- view->residual.w, view->residual.h);
-
- style = gog_style_new ();
- style->interesting_fields = GOG_STYLE_FILL | GOG_STYLE_OUTLINE;
- style->disable_theming = GOG_STYLE_ALL;
- style->fill.type = GOG_FILL_STYLE_PATTERN;
- style->fill.pattern.pattern = GO_PATTERN_SOLID;
- style->outline.dash_type = GO_LINE_SOLID;
- style->outline.auto_dash = FALSE;
- style->outline.auto_color = FALSE;
- style->outline.width = 0.5;
- style->outline.color = RGBA_BLACK;
-
- lines = art_new (ArtVpath, lmax = 64);
- l = 0;
-
- for (j = 1; j < jmax; j++) {
- if (xdiscrete) {
- x0 = gog_axis_map_to_view (x_map, j);
- x1 = gog_axis_map_to_view (x_map, j + 1);
- }else {
- x0 = gog_axis_map_to_view (x_map, go_data_vector_get_value (x_vec, j - 1));
- x1 = gog_axis_map_to_view (x_map, go_data_vector_get_value (x_vec, j));
- }
-
- for (i = 1; i < imax; i++) {
- if (ydiscrete) {
- y0 = gog_axis_map_to_view (y_map, i);
- y1 = gog_axis_map_to_view (y_map, i + 1);
- }else {
- y0 = gog_axis_map_to_view (y_map, go_data_vector_get_value (y_vec, i - 1));
- y1 = gog_axis_map_to_view (y_map, go_data_vector_get_value (y_vec, i));
- }
- nans = 0;
- nan = 4;
- zmin = max;
- zmax = 0;
- zval0 = data[(i - 1) * jmax + j - 1];
- if (!isnan (zval0)) {
- z0 = floor (zval0);
- if (z0 > zmax)
- zmax = z0;
- if (z0 < zmin) {
- zmin = z0;
- r = 0;
- }
- } else {
- nans++;
- nan = 0;
- }
- zval1 = data[(i - 1) * jmax + j];
- if (!isnan (zval1)) {
- z1 = floor (zval1);
- if (z1 > zmax)
- zmax = z1;
- if (z1 < zmin) {
- zmin = z1;
- r = 1;
- }
+ gog_chart_map_3d_to_view (chart_map, x[0], y[0], data[0], NULL, NULL, z + 1);
+ gog_chart_map_3d_to_view (chart_map, x[1], y[0], data[0], NULL, NULL, z + 2);
+ if (z[2] > z[1]) {
+ i = imax - 1;
+ iend = 0;
+ istep = -1;
+ } else {
+ i = 1;
+ iend = imax;
+ istep = 1;
+ }
+ gog_chart_map_3d_to_view (chart_map, x[0], y[1], data[0], NULL, NULL, z + 2);
+ if (z[2] > z[1]) {
+ jstart = jmax - 1;
+ jend = 0;
+ jstep = -1;
+ } else {
+ jstart = 1;
+ jstep = 1;
+ jend = jmax;
+ }
+ gog_renderer_push_style (rend, style);
+ for (; i != iend; i +=istep)
+ for (j = jstart; j != jend; j += jstep) {
+ path = go_path_new ();
+ if (xdiscrete) {
+ x0 = i;
+ x1 = i + 1;
} else {
- nans++;
- nan = 1;
+ x0 = go_data_vector_get_value (x_vec, i - 1);
+ x1 = go_data_vector_get_value (x_vec, i);
}
- zval2 = data[i * jmax + j];
- if (!isnan (zval2)) {
- z2 = floor (zval2);
- if (z2 > zmax)
- zmax = z2;
- if (z2 < zmin) {
- zmin = z2;
- r = 2;
- }
- } else {
- nans++;
- nan = 2;
- }
- zval3 = data[i * jmax + j - 1];
- if (!isnan (zval3)) {
- z3 = floor (zval3);
- if (z3 > zmax)
- zmax = z3;
- if (z3 < zmin) {
- zmin = z3;
- r = 3;
- }
- } else {
- nans++;
- nan = 3;
- }
- if (nans > 1)
- continue;
- /* Build the x, y and z arrays for the tile */
- k = r;
- s = 0;
- do {
- if (k != nan) {
- switch (k) {
- case 0:
- x[s] = x0;
- y[s] = y0;
- z[s] = z0;
- zval[s++] = zval0;
- break;
- case 1:
- x[s] = x1;
- y[s] = y0;
- z[s] = z1;
- zval[s++] = zval1;
- break;
- case 2:
- x[s] = x1;
- y[s] = y1;
- z[s] = z2;
- zval[s++] = zval2;
- break;
- default:
- x[s] = x0;
- y[s] = y1;
- z[s] = z3;
- zval[s++] = zval3;
- }
- }
- if (cw) {
- k++;
- k %= 4;
- } else {
- if (k == 0)
- k = 3;
- else
- k--;
- }
- } while (k != r);
- if (zmin == zmax) {
- /* paint everything with one color*/
- style->outline.color = color[zmin];
- style->fill.pattern.back = color[zmin];
- gog_renderer_push_style (rend, style);
- path[0].code = ART_MOVETO;
- for (k = 0; k < s; ) {
- path[k].x = x[k];
- path[k].y = y[k];
- path[++k].code = ART_LINETO;
- }
- path[k].x = x[0];
- path[k].y = y[0];
- path[k + 1].code = ART_END;
- /* narrow parameter is TRUE below to avoid border effects */
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
+ if (ydiscrete) {
+ y0 = j;
+ y1 = j + 1;
} else {
- kmax = 3 - nans;
- if (!nans && (((z0 < z1) && (z1 > z2) && (z2 < z3) && (z3 > z0)) ||
- ((z0 > z1) && (z1 < z2) && (z2 > z3) && (z3 < z0)))) {
- /* we have a saddle point */
- /* first find the most probable altitude of the saddle point */
- int zn, zx;
- gboolean crossing = FALSE, up = FALSE, odd;
- double xl[8], yl[8];
- /* crossing is TRUE if the saddle point occurs at a slices border */
- zn = MAX (z[0], z[2]);
- if (zval[1] > zval[3])
- zx = (zval[3] == z[3])? z[3] - 1: z[3];
- else
- zx = (zval[1] == z[1])? z[1] - 1: z[1];
- odd = (zx - zn) % 2;
- if (odd) {
- if ((zx - zn) == 1) {
- double sum = 0.;
- sum += (z[0] == zn)? zval[0]: zn;
- sum += (z[1] == zx)? zval[1]: zx + 1;
- sum += (z[2] == zn)? zval[2]: zn;
- sum += (z[3] == zx)? zval[3]: zx + 1;
- sum /= 4.;
- if (fabs ((sum - zx)) < DBL_EPSILON)
- crossing = TRUE;
- else
- up = (sum - zx) < 0;
- } else
- crossing = TRUE;
- zn = (zn + zx) / 2;
- zx = zn + 1;
- } else
- zn = zx = (zn + zx) / 2;
- /* low values slices */
- if (z[0] < zn) {
- k = z[0];
- style->outline.color = color[k];
- style->fill.pattern.back = color[k];
- k++;
- path[0].code = ART_MOVETO;
- path[1].code = ART_LINETO;
- path[2].code = ART_LINETO;
- path[3].code = ART_LINETO;
- path[4].code = ART_END;
- path[0].x = path[3].x = x[0];
- path[0].y = path[3].y = y[0];
- if ((l + 3) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- lines[l].code = ART_MOVETO_OPEN;
- t = (k - zval[0]) / (zval[3] - zval[0]);
- xl[7] = lines[l].x = path[1].x = x[0] + t * (x[3] - x[0]);
- yl[7] = lines[l++].y = path[1].y = y[0] + t * (y[3] - y[0]);
- lines[l].code = ART_LINETO;
- t = (k - zval[0]) / (zval[1] - zval[0]);
- xl[0] = lines[l].x = path[2].x = x[0] + t * (x[1] - x[0]);
- yl[0] = lines[l++].y = path[2].y = y[0] + t * (y[1] - y[0]);
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- path[4].code = ART_LINETO;
- path[5].code = ART_END;
- while (k < zn) {
- style->outline.color = color[k];
- style->fill.pattern.back = color[k];
- k++;
- path[0].x = path[4].x = xl[7];
- path[0].y = path[4].y = yl[7];
- path[3].x = xl[0];
- path[3].y = yl[0];
- if ((l + 3) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- lines[l].code = ART_MOVETO_OPEN;
- t = (k - zval[0]) / (zval[3] - zval[0]);
- xl[7] = lines[l].x = path[1].x = x[0] + t * (x[3] - x[0]);
- yl[7] = lines[l++].y = path[1].y = y[0] + t * (y[3] - y[0]);
- lines[l].code = ART_LINETO;
- t = (k - zval[0]) / (zval[1] - zval[0]);
- xl[0] = lines[l].x = path[2].x = x[0] + t * (x[1] - x[0]);
- yl[0] = lines[l++].y = path[2].y = y[0] + t * (y[1] - y[0]);
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- }
- } else
- xl[0] = xl[7] = -1.;
- if (z[2] < zn) {
- k = z[2];
- style->outline.color = color[k];
- style->fill.pattern.back = color[k];
- k++;
- path[0].code = ART_MOVETO;
- path[1].code = ART_LINETO;
- path[2].code = ART_LINETO;
- path[3].code = ART_LINETO;
- path[4].code = ART_END;
- path[0].x = path[3].x = x[2];
- path[0].y = path[3].y = y[2];
- if ((l + 3) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- lines[l].code = ART_MOVETO_OPEN;
- t = (k - zval[2]) / (zval[1] - zval[2]);
- xl[3] = lines[l].x = path[1].x = x[2] + t * (x[1] - x[2]);
- yl[3] = lines[l++].y = path[1].y = y[2] + t * (y[1] - y[2]);
- lines[l].code = ART_LINETO;
- t = (k - zval[2]) / (zval[3] - zval[2]);
- xl[4] = lines[l].x = path[2].x = x[2] + t * (x[3] - x[2]);
- yl[4] = lines[l++].y = path[2].y = y[2] + t * (y[3] - y[2]);
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- path[4].code = ART_LINETO;
- path[5].code = ART_END;
- while (k < zn) {
- style->outline.color = color[k];
- style->fill.pattern.back = color[k];
- k++;
- path[0].x = path[4].x = xl[3];
- path[0].y = path[4].y = yl[3];
- path[3].x = xl[4];
- path[3].y = yl[4];
- if ((l + 3) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- lines[l].code = ART_MOVETO_OPEN;
- t = (k - zval[2]) / (zval[1] - zval[2]);
- xl[3] = lines[l].x = path[1].x = x[2] + t * (x[1] - x[2]);
- yl[3] = lines[l++].y = path[1].y = y[2] + t * (y[1] - y[2]);
- lines[l].code = ART_LINETO;
- t = (k - zval[2]) / (zval[3] - zval[2]);
- xl[4] = lines[l].x = path[2].x = x[2] + t * (x[3] - x[2]);
- yl[4] = lines[l++].y = path[2].y = y[2] + t * (y[3] - y[2]);
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- }
- } else
- xl[3] = xl[4] = -1.;
- /* high values slices */
- k = z[1];
- if (zval[1] == k)
- k--;
- if (k > zx) {
- path[0].code = ART_MOVETO;
- path[1].code = ART_LINETO;
- path[2].code = ART_LINETO;
- path[3].code = ART_LINETO;
- path[4].code = ART_END;
- path[0].x = path[3].x = x[1];
- path[0].y = path[3].y = y[1];
- if ((l + 3) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- lines[l].code = ART_MOVETO_OPEN;
- t = (k - zval[1]) / (zval[0] - zval[1]);
- xl[1] = lines[l].x = path[1].x = x[1] + t * (x[0] - x[1]);
- yl[1] = lines[l++].y = path[1].y = y[1] + t * (y[0] - y[1]);
- lines[l].code = ART_LINETO;
- t = (k - zval[1]) / (zval[2] - zval[1]);
- xl[2] = lines[l].x = path[2].x = x[1] + t * (x[2] - x[1]);
- yl[2] = lines[l++].y = path[2].y = y[1] + t * (y[2] - y[1]);
- style->outline.color = color[k];
- style->fill.pattern.back = color[k];
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- path[4].code = ART_LINETO;
- path[5].code = ART_END;
- k--;
- while (k > zx) {
- path[0].x = path[4].x = xl[1];
- path[0].y = path[4].y = yl[1];
- path[3].x = xl[2];
- path[3].y = yl[2];
- if ((l + 3) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- lines[l].code = ART_MOVETO_OPEN;
- t = (k - zval[1]) / (zval[0] - zval[1]);
- xl[1] = lines[l].x = path[1].x = x[1] + t * (x[0] - x[1]);
- yl[1] = lines[l++].y = path[1].y = y[1] + t * (y[0] - y[1]);
- lines[l].code = ART_LINETO;
- t = (k - zval[1]) / (zval[2] - zval[1]);
- xl[2] = lines[l].x = path[2].x = x[1] + t * (x[2] - x[1]);
- yl[2] = lines[l++].y = path[2].y = y[1] + t * (y[2] - y[1]);
- style->outline.color = color[k];
- style->fill.pattern.back = color[k];
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- k--;
- }
- } else
- xl[1] = xl[2] = -1.;
- k = z[3];
- if (zval[3] == k)
- k--;
- if (k > zx) {
- path[0].code = ART_MOVETO;
- path[1].code = ART_LINETO;
- path[2].code = ART_LINETO;
- path[3].code = ART_LINETO;
- path[4].code = ART_END;
- path[0].x = path[3].x = x[3];
- path[0].y = path[3].y = y[3];
- if ((l + 3) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- lines[l].code = ART_MOVETO_OPEN;
- t = (k - zval[3]) / (zval[2] - zval[3]);
- xl[5] = lines[l].x = path[1].x = x[3] + t * (x[2] - x[3]);
- yl[5] = lines[l++].y = path[1].y = y[3] + t * (y[2] - y[3]);
- lines[l].code = ART_LINETO;
- t = (k - zval[3]) / (zval[0] - zval[3]);
- xl[6] = lines[l].x = path[2].x = x[3] + t * (x[0] - x[3]);
- yl[6] = lines[l++].y = path[2].y = y[3] + t * (y[0] - y[3]);
- style->outline.color = color[k];
- style->fill.pattern.back = color[k];
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- path[4].code = ART_LINETO;
- path[5].code = ART_END;
- k--;
- while (k > zx) {
- path[0].x = path[4].x = xl[5];
- path[0].y = path[4].y = yl[5];
- path[3].x = xl[6];
- path[3].y = yl[6];
- if ((l + 3) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- lines[l].code = ART_MOVETO_OPEN;
- t = (k - zval[3]) / (zval[2] - zval[3]);
- xl[5] = lines[l].x = path[1].x = x[3] + t * (x[2] - x[3]);
- yl[5] = lines[l++].y = path[1].y = y[3] + t * (y[2] - y[3]);
- lines[l].code = ART_LINETO;
- t = (k - zval[3]) / (zval[0] - zval[3]);
- xl[6] = lines[l].x = path[2].x = x[3] + t * (x[0] - x[3]);
- yl[6] = lines[l++].y = path[2].y = y[3] + t * (y[0] - y[3]);
- style->outline.color = color[k];
- style->fill.pattern.back = color[k];
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- k--;
- }
- } else
- xl[5] = xl[6] = -1.;
- /* middle values slices */
- if (odd) {
- if (crossing) {
- double xb[4], yb[4], xc, yc;
- for (k = 0; k < 4; k++) {
- s = (k + 1) % 4;
- t = (zx - zval[s]) / (zval[k] - zval[s]);
- xb[k] = x[s] + t * (x[k] - x[s]);
- yb[k] = y[s] + t * (y[k] - y[s]);
- }
- if ((l + 5) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- lines[l].code = ART_MOVETO_OPEN;
- lines[l].x = xb[0];
- lines[l++].y = yb[0];
- lines[l].code = ART_LINETO;
- lines[l].x = xb[2];
- lines[l++].y = yb[2];
- lines[l].code = ART_MOVETO_OPEN;
- lines[l].x = xb[1];
- lines[l++].y = yb[1];
- lines[l].code = ART_LINETO;
- lines[l].x = xb[3];
- lines[l++].y = yb[3];
- /* calculate the coordinates xc and yc of crossing point */
- t = ((xb[1] - xb[0]) * (yb[3] - yb[1])
- + (xb[1] - xb[3]) * (yb[1] - yb[0])) /
- ((xb[2] - xb[0]) * (yb[3] - yb[1])
- + (xb[1] - xb[3]) * (yb[2] - yb[0]));
- xc = xb[0] + t * (xb[2] - xb[0]);
- yc = yb[0] + t * (yb[2] - yb[0]);
- /* fill */
- path[0].code = ART_MOVETO;
- path[1].code = ART_LINETO;
- path[2].code = ART_LINETO;
- path[3].code = ART_LINETO;
- path[4].code = ART_LINETO;
- if (xl[0] < 0.) {
- path[4].x = path[0].x = x[0];
- path[4].y = path[0].y = y[0];
- path[5].code = ART_END;
- } else {
- path[5].x = path[0].x = xl[7];
- path[5].y = path[0].y = yl[7];
- path[4].x = xl[0];
- path[4].y = yl[0];
- path[5].code = ART_LINETO;
- path[6].code = ART_END;
- }
- path[1].x = xb[3];
- path[1].y = yb[3];
- path[2].x = xc;
- path[2].y = yc;
- path[3].x = xb[0];
- path[3].y = yb[0];
- style->outline.color = color[zn];
- style->fill.pattern.back = color[zn];
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- if (xl[2] < 0.) {
- path[4].x = path[0].x = x[2];
- path[4].y = path[0].y = y[2];
- path[5].code = ART_END;
- } else {
- path[5].x = path[0].x = xl[3];
- path[5].y = path[0].y = yl[3];
- path[4].x = xl[4];
- path[4].y = yl[4];
- path[5].code = ART_LINETO;
- path[6].code = ART_END;
- }
- path[1].x = xb[1];
- path[1].y = yb[1];
- path[3].x = xb[2];
- path[3].y = yb[2];
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- if (xl[2] < 0.) {
- path[4].x = path[0].x = x[1];
- path[4].y = path[0].y = y[1];
- path[5].code = ART_END;
- } else {
- path[5].x = path[0].x = xl[1];
- path[5].y = path[0].y = yl[1];
- path[4].x = xl[2];
- path[4].y = yl[2];
- path[5].code = ART_LINETO;
- path[6].code = ART_END;
- }
- path[1].x = xb[0];
- path[1].y = yb[0];
- path[3].x = xb[1];
- path[3].y = yb[1];
- style->outline.color = color[zx];
- style->fill.pattern.back = color[zx];
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- if (xl[6] < 0.) {
- path[4].x = path[0].x = x[3];
- path[4].y = path[0].y = y[3];
- path[5].code = ART_END;
- } else {
- path[5].x = path[0].x = xl[5];
- path[5].y = path[0].y = yl[5];
- path[4].x = xl[6];
- path[4].y = yl[6];
- path[5].code = ART_LINETO;
- path[6].code = ART_END;
- }
- path[1].x = xb[2];
- path[1].y = yb[2];
- path[3].x = xb[3];
- path[3].y = yb[3];
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- } else {
- if (up) {
- /* saddle point is in the lower slice */
- /* draw the upper slices */
- path[0].code = ART_MOVETO;
- path[1].code = ART_LINETO;
- path[2].code = ART_LINETO;
- path[3].code = ART_LINETO;
- if (xl[1] < 0.) {
- path[4].code = ART_END;
- path[0].x = path[3].x = x[1];
- path[0].y = path[3].y = y[1];
- } else {
- path[4].code = ART_LINETO;
- path[5].code = ART_END;
- path[0].x = path[4].x = xl[1];
- path[0].y = path[4].y = yl[1];
- path[3].x = xl[2];
- path[3].y = yl[2];
- }
- if ((l + 5) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- lines[l].code = ART_MOVETO_OPEN;
- t = (zx - zval[1]) / (zval[0] - zval[1]);
- xl[1] = lines[l].x = path[1].x = x[1] + t * (x[0] - x[1]);
- yl[1] = lines[l++].y = path[1].y = y[1] + t * (y[0] - y[1]);
- lines[l].code = ART_LINETO;
- t = (zx - zval[1]) / (zval[2] - zval[1]);
- xl[2] = lines[l].x = path[2].x = x[1] + t * (x[2] - x[1]);
- yl[2] = lines[l++].y = path[2].y = y[1] + t * (y[2] - y[1]);
- style->outline.color = color[zx];
- style->fill.pattern.back = color[zx];
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- if (xl[5] < 0.) {
- path[4].code = ART_END;
- path[0].x = path[3].x = x[3];
- path[0].y = path[3].y = y[3];
- } else {
- path[4].code = ART_LINETO;
- path[5].code = ART_END;
- path[0].x = path[4].x = xl[5];
- path[0].y = path[4].y = yl[5];
- path[3].x = xl[6];
- path[3].y = yl[6];
- }
- if ((l + 5) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- lines[l].code = ART_MOVETO_OPEN;
- t = (zx - zval[3]) / (zval[2] - zval[3]);
- xl[5] = lines[l].x = path[1].x = x[3] + t * (x[2] - x[3]);
- yl[5] = lines[l++].y = path[1].y = y[3] + t * (y[2] - y[3]);
- lines[l].code = ART_LINETO;
- t = (zx - zval[3]) / (zval[0] - zval[3]);
- xl[6] = lines[l].x = path[2].x = x[3] + t * (x[0] - x[3]);
- yl[6] = lines[l++].y = path[2].y = y[3] + t * (y[0] - y[3]);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- } else {
- /* saddle point is in the upper slice */
- path[0].code = ART_MOVETO;
- path[1].code = ART_LINETO;
- path[2].code = ART_LINETO;
- path[3].code = ART_LINETO;
- if (xl[0] < 0.) {
- path[4].code = ART_END;
- path[0].x = path[3].x = x[0];
- path[0].y = path[3].y = y[0];
- } else {
- path[4].code = ART_LINETO;
- path[5].code = ART_END;
- path[0].x = path[4].x = xl[7];
- path[0].y = path[4].y = yl[7];
- path[3].x = xl[0];
- path[3].y = yl[0];
- }
- if ((l + 5) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- lines[l].code = ART_MOVETO_OPEN;
- t = (k - zval[0]) / (zval[3] - zval[0]);
- xl[7] = lines[l].x = path[1].x = x[0] + t * (x[3] - x[0]);
- yl[7] = lines[l++].y = path[1].y = y[0] + t * (y[3] - y[0]);
- lines[l].code = ART_LINETO;
- t = (k - zval[0]) / (zval[1] - zval[0]);
- xl[0] = lines[l].x = path[2].x = x[0] + t * (x[1] - x[0]);
- yl[0] = lines[l++].y = path[2].y = y[0] + t * (y[1] - y[0]);
- style->outline.color = color[zn];
- style->fill.pattern.back = color[zn];
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- if (xl[4] < 0.) {
- path[4].code = ART_END;
- path[0].x = path[3].x = x[2];
- path[0].y = path[3].y = y[2];
- } else {
- path[4].code = ART_LINETO;
- path[5].code = ART_END;
- path[0].x = path[4].x = xl[3];
- path[0].y = path[4].y = yl[3];
- path[3].x = xl[4];
- path[3].y = yl[4];
- }
- lines[l].code = ART_MOVETO_OPEN;
- t = (k - zval[2]) / (zval[1] - zval[2]);
- xl[3] = lines[l].x = path[1].x = x[2] + t * (x[1] - x[2]);
- yl[3] = lines[l++].y = path[1].y = y[2] + t * (y[1] - y[2]);
- lines[l].code = ART_LINETO;
- t = (k - zval[2]) / (zval[3] - zval[2]);
- xl[4] = lines[l].x = path[2].x = x[2] + t * (x[3] - x[2]);
- yl[4] = lines[l++].y = path[2].y = y[2] + t * (y[3] - y[2]);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- zn = zx;
- }
- /* draw the saddle containing slice */
- k = 0;
- for (s = 0; s < 8; s++) {
- path[k].code = (k)? ART_LINETO: ART_MOVETO;
- if (xl[s] < 0.) {
- if (s == 7)
- break;
- else if (s > 0)
- s++;
- r = s / 2;
- path[k].x = x[r];
- path[k++].y = y[r];
- } else {
- path[k].x = xl[s];
- path[k++].y = yl[s];
- }
- }
- path[k].code = ART_LINETO;
- path[k].x = path[0].x;
- path[k++].y = path[0].y;
- path[k].code = ART_END;
- style->outline.color = color[zn];
- style->fill.pattern.back = color[zn];
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- }
- } else {
- k = 0;
- for (s = 0; s < 8; s++) {
- path[k].code = (k)? ART_LINETO: ART_MOVETO;
- if (xl[s] < 0.) {
- if (s == 7)
- break;
- else if (s > 0)
- s++;
- r = s / 2;
- path[k].x = x[r];
- path[k++].y = y[r];
- } else {
- path[k].x = xl[s];
- path[k++].y = yl[s];
- }
- }
- path[k].code = ART_LINETO;
- path[k].x = path[0].x;
- path[k++].y = path[0].y;
- path[k].code = ART_END;
- style->outline.color = color[zx];
- style->fill.pattern.back = color[zx];
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- }
- } else {
- /* no saddle point visible */
- if ((l + (zmax - zmin) * 2 + 1) >= lmax)
- lines = art_renew (lines, ArtVpath, lmax += 64);
- path[0].code = ART_MOVETO;
- path[0].x = x[0];
- path[0].y = y[0];
- p = 1;
- k = 1;
- s = 0;
- r = kmax;
- while (zmin < zmax) {
- style->outline.color = color[zmin];
- style->fill.pattern.back = color[zmin];
- gog_renderer_push_style (rend, style);
- while (z[k] <= zmin && k < kmax) {
- if (fabs (path[p-1].x - x[k]) > CONTOUR_EPSILON ||
- fabs (path[p-1].y - y[k]) > CONTOUR_EPSILON) {
- path[p].code = ART_LINETO;
- path[p].x = x[k];
- path[p++].y = y[k++];
- } else
- k++;
- }
- while (z[r] <= zmin && r > 0)
- r--;
- zmin++;
- t = (zmin - zval[k - 1]) / (zval[k] - zval[k - 1]);
- path[p].code = ART_LINETO;
- lines[l].code = ART_MOVETO_OPEN;
- lines[l].x = path[p].x = x[k - 1] + t * (x[k] - x[k - 1]);
- lines[l++].y = path[p].y = y[k - 1] + t * (y[k] - y[k - 1]);
- if (fabs (path[p-1].x - path[p].x) > CONTOUR_EPSILON ||
- fabs (path[p-1].y - path[p].y) > CONTOUR_EPSILON)
- p++;
- path[p].code = ART_LINETO;
- lines[l].code = ART_LINETO;
- if (r < kmax) {
- t = (zmin - zval[r]) / (zval[r + 1] - zval[r]);
- lines[l].x = path[p].x = x[r] + t * (x[r + 1] - x[r]);
- lines[l++].y = path[p].y = y[r] + t * (y[r + 1] - y[r]);
- } else {
- t = (zmin - zval[r]) / (zval[0] - zval[r]);
- lines[l].x = path[p].x = x[r] + t * (x[0] - x[r]);
- lines[l++].y = path[p].y = y[r] + t * (y[0] - y[r]);
- }
- if (fabs (path[p-1].x - path[p].x) > CONTOUR_EPSILON ||
- fabs (path[p-1].y - path[p].y) > CONTOUR_EPSILON)
- p++;
- if (s == 0) {
- for (h = r + 1; h <= kmax; h++) {
- if (fabs (path[p-1].x - x[h]) > CONTOUR_EPSILON ||
- fabs (path[p-1].y - y[h]) > CONTOUR_EPSILON) {
- path[p].code = ART_LINETO;
- path[p].x = x[h];
- path[p++].y = y[h];
- }
- }
- } else {
- for (h = r + 1; h < s; h++) {
- if (fabs (path[p-1].x - x[h]) > CONTOUR_EPSILON ||
- fabs (path[p-1].y - y[h]) > CONTOUR_EPSILON) {
- path[p].code = ART_LINETO;
- path[p].x = x[h];
- path[p++].y = y[h];
- }
- }
- }
- s = r + 1;
- if (fabs (path[p-1].x - path[0].x) > CONTOUR_EPSILON ||
- fabs (path[p-1].y -path[0].y) > CONTOUR_EPSILON) {
- path[p].code = ART_LINETO;
- path[p].x = path[0].x;
- path[p++].y = path[0].y;
- } else {
- /* use the exact values so that the polygon is closed */
- path[p-1].x = path[0].x;
- path[p-1].y = path[0].y;
- }
- path[p].code = ART_END;
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- path[0].x = lines[l - 1].x;
- path[0].y = lines[l - 1].y;
- path[1].x = lines[l - 2].x;
- path[1].y = lines[l - 2].y;
- p = (fabs (path[0].x - path[1].x) > CONTOUR_EPSILON ||
- fabs (path[0].y - path[1].y) > CONTOUR_EPSILON)?
- 2: 1;
- }
- if (fabs (path[0].x - path[1].x) < CONTOUR_EPSILON
- && fabs (path[0].y - path[1].y) < CONTOUR_EPSILON)
- continue;
- while (k < s) {
- path[p].code = ART_LINETO;
- path[p].x = x[k];
- path[p++].y = y[k++];
- }
- path[p].code = ART_LINETO;
- path[p].x = path[0].x;
- path[p++].y = path[0].y;
- path[p].code = ART_END;
- style->outline.color = color[zmin];
- style->fill.pattern.back = color[zmin];
- gog_renderer_push_style (rend, style);
- gog_renderer_draw_polygon (rend, path, FALSE);
- gog_renderer_pop_style (rend);
- }
+ y0 = go_data_vector_get_value (y_vec, j - 1);
+ y1 = go_data_vector_get_value (y_vec, j);
}
+ gog_chart_map_3d_to_view (chart_map, x0, y0,
+ data[(j - 1) * imax + i - 1], x, y, NULL);
+ go_path_move_to (path, *x, *y);
+ gog_chart_map_3d_to_view (chart_map, x1, y0,
+ data[(j - 1) * imax + i], x, y, NULL);
+ go_path_line_to (path, *x, *y);
+ gog_chart_map_3d_to_view (chart_map, x1, y1,
+ data[j * imax + i], x, y, NULL);
+ go_path_line_to (path, *x, *y);
+ gog_chart_map_3d_to_view (chart_map, x0, y1,
+ data[j * imax + i - 1], x, y, NULL);
+ go_path_line_to (path, *x, *y);
+ go_path_close (path);
+ gog_renderer_draw_shape (rend, path);
+ go_path_free (path);
+ //break;
}
- }
- lines[l].code = ART_END;
- gog_renderer_push_style (rend, GOG_STYLED_OBJECT (series)->style);
- gog_renderer_draw_path (rend, lines);
gog_renderer_pop_style (rend);
- gog_renderer_pop_clip (rend);
- art_free (lines);
- art_free (path);
- g_object_unref (style);
- gog_axis_map_free (x_map);
- gog_axis_map_free (y_map);
+ gog_chart_map_3d_free (chart_map);
}
static void
-gog_contour_view_class_init (GogViewClass *view_klass)
+gog_surface_view_class_init (GogViewClass *view_klass)
{
- view_klass->render = gog_contour_view_render;
+ view_klass->render = gog_surface_view_render;
}
-GSF_DYNAMIC_CLASS (GogContourView, gog_contour_view,
- gog_contour_view_class_init, NULL,
+GSF_DYNAMIC_CLASS (GogSurfaceView, gog_surface_view,
+ gog_surface_view_class_init, NULL,
GOG_PLOT_VIEW_TYPE)
-
-/*****************************************************************************/
-
-static GogStyledObjectClass *series_parent_klass;
-
-static void
-gog_surface_series_update (GogObject *obj)
-{
- GogSurfaceSeries *series = GOG_SURFACE_SERIES (obj);
- GODataMatrixSize size, old_size;
- GODataMatrix *mat;
- GODataVector *vec;
- int length;
- size.rows = 0;
- size.columns = 0;
- if (series->base.values[2].data != NULL) {
- old_size.rows = series->rows;
- old_size.columns = series->columns;
- mat = GO_DATA_MATRIX (series->base.values[2].data);
- go_data_matrix_get_values (mat);
- size = go_data_matrix_get_size (mat);
- }
- if (series->base.values[0].data != NULL) {
- vec = GO_DATA_VECTOR (series->base.values[0].data);
- go_data_vector_get_values (vec);
- length = go_data_vector_get_len (vec);
- if (length < size.columns)
- size.columns = length;
- }
- if (series->base.values[1].data != NULL) {
- vec = GO_DATA_VECTOR (series->base.values[1].data);
- go_data_vector_get_values (vec);
- length = go_data_vector_get_len (vec);
- if (length < size.rows)
- size.rows = length;
- }
- series->rows = size.rows;
- series->columns = size.columns;
-
- /* queue plot for redraw */
- gog_object_request_update (GOG_OBJECT (series->base.plot));
-/* gog_plot_request_cardinality_update (series->base.plot);*/
-
- if (series_parent_klass->base.update)
- series_parent_klass->base.update (obj);
-}
-
-static void
-gog_surface_series_init_style (GogStyledObject *gso, GogStyle *style)
-{
- series_parent_klass->init_style (gso, style);
-}
-
-static void
-gog_surface_series_class_init (GogStyledObjectClass *gso_klass)
-{
- GogObjectClass * obj_klass = (GogObjectClass *) gso_klass;
-
- series_parent_klass = g_type_class_peek_parent (gso_klass);
- gso_klass->init_style = gog_surface_series_init_style;
- obj_klass->update = gog_surface_series_update;
-}
-
-
-GSF_DYNAMIC_CLASS (GogSurfaceSeries, gog_surface_series,
- gog_surface_series_class_init, NULL,
- GOG_SERIES_TYPE)
-
-G_MODULE_EXPORT void
-go_plugin_init (GOPlugin *plugin, GOCmdContext *cc)
-{
- GTypeModule *module = go_plugin_get_type_module (plugin);
- gog_contour_plot_register_type (module);
- gog_contour_view_register_type (module);
- gog_surface_series_register_type (module);
- xl_contour_plot_register_type (module);
- xl_surface_series_register_type (module);
-}
-
-G_MODULE_EXPORT void
-go_plugin_shutdown (GOPlugin *plugin, GOCmdContext *cc)
-{
-}
Modified: trunk/plugins/plot_surface/gog-surface.h
==============================================================================
--- trunk/plugins/plot_surface/gog-surface.h (original)
+++ trunk/plugins/plot_surface/gog-surface.h Mon May 12 09:02:12 2008
@@ -22,42 +22,28 @@
#ifndef GOG_SURFACE_H
#define GOG_SURFACE_H
-#include <goffice/graph/gog-plot-impl.h>
+#include "gog-xyz.h"
G_BEGIN_DECLS
/*-----------------------------------------------------------------------------
*
- * GogContourPlot
+ * GogSurfacePlot
*
*-----------------------------------------------------------------------------
*/
-typedef struct {
- GogPlot base;
-
- unsigned rows, columns;
- gboolean transposed;
- struct {
- double minima, maxima;
- GOFormat *fmt;
- } x, y, z;
- double *plotted_data;
-} GogContourPlot;
-
-#define GOG_CONTOUR_PLOT_TYPE (gog_contour_plot_get_type ())
-#define GOG_CONTOUR_PLOT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_CONTOUR_PLOT_TYPE, GogContourPlot))
-#define GOG_IS_PLOT_CONTOUR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_CONTOUR_PLOT_TYPE))
-
-GType gog_contour_plot_get_type (void);
+typedef GogXYZPlot GogSurfacePlot;
+typedef GogXYZPlotClass GogSurfacePlotClass;
+
+#define GOG_SURFACE_PLOT_TYPE (gog_surface_plot_get_type ())
+#define GOG_SURFACE_PLOT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_SURFACE_PLOT_TYPE, GogSurfacePlot))
+#define GOG_IS_SURFACE_PLOT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_SURFACE_PLOT_TYPE))
-typedef struct {
- GogPlotClass base;
+GType gog_surface_plot_get_type (void);
+void gog_surface_plot_register_type (GTypeModule *module);
- double * (*build_matrix) (GogContourPlot const *plot, gboolean *cardinality_changed);
-} GogContourPlotClass;
-
-#define GOG_CONTOUR_PLOT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOG_CONTOUR_PLOT_TYPE, GogContourPlotClass))
+void gog_surface_view_register_type (GTypeModule *module);
G_END_DECLS
Copied: trunk/plugins/plot_surface/gog-xyz-prefs.c (from r2048, /trunk/plugins/plot_surface/gog-contour-prefs.c)
==============================================================================
--- /trunk/plugins/plot_surface/gog-contour-prefs.c (original)
+++ trunk/plugins/plot_surface/gog-xyz-prefs.c Mon May 12 09:02:12 2008
@@ -1,64 +0,0 @@
-/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * gog-bubble-prefs.c
- *
- * Copyright (C) 2004 Jean Brefort (jean brefort normalesup org)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#include <goffice/goffice-config.h>
-#include "gog-surface.h"
-#include <goffice/gtk/goffice-gtk.h>
-#include <goffice/app/go-plugin.h>
-
-#include <gtk/gtktogglebutton.h>
-
-#include <string.h>
-
-GtkWidget *gog_contour_plot_pref (GogContourPlot *plot, GOCmdContext *cc);
-
-static void
-cb_transpose (GtkToggleButton *btn, GObject *plot)
-{
- g_object_set (plot, "transposed", gtk_toggle_button_get_active (btn), NULL);
-}
-
-GtkWidget *
-gog_contour_plot_pref (GogContourPlot *plot, GOCmdContext *cc)
-{
- GtkWidget *w;
- char const *dir = go_plugin_get_dir_name (
- go_plugins_get_plugin_by_id ("GOffice_plot_surface"));
- char *path = g_build_filename (dir, "gog-contour-prefs.glade", NULL);
- GladeXML *gui = go_libglade_new (path, "gog_contour_prefs", GETTEXT_PACKAGE, cc);
-
- g_free (path);
- if (gui == NULL)
- return NULL;
-
-
- w = glade_xml_get_widget (gui, "transpose");
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), plot->transposed);
- g_signal_connect (G_OBJECT (w),
- "toggled",
- G_CALLBACK (cb_transpose), plot);
-
- w = glade_xml_get_widget (gui, "gog_contour_prefs");
- g_object_set_data_full (G_OBJECT (w),
- "state", gui, (GDestroyNotify)g_object_unref);
-
- return w;
-}
Copied: trunk/plugins/plot_surface/gog-xyz-prefs.glade (from r2048, /trunk/plugins/plot_surface/gog-contour-prefs.glade)
==============================================================================
--- /trunk/plugins/plot_surface/gog-contour-prefs.glade (original)
+++ trunk/plugins/plot_surface/gog-xyz-prefs.glade Mon May 12 09:02:12 2008
@@ -1,54 +0,0 @@
-<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
-<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
-
-<glade-interface>
-
-<widget class="GtkWindow" id="window1">
- <property name="title" translatable="yes">window1</property>
- <property name="type">GTK_WINDOW_TOPLEVEL</property>
- <property name="window_position">GTK_WIN_POS_NONE</property>
- <property name="modal">False</property>
- <property name="resizable">True</property>
- <property name="destroy_with_parent">False</property>
- <property name="decorated">True</property>
- <property name="skip_taskbar_hint">False</property>
- <property name="skip_pager_hint">False</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
- <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
-
- <child>
- <widget class="GtkTable" id="gog_contour_prefs">
- <property name="border_width">5</property>
- <property name="visible">True</property>
- <property name="n_rows">1</property>
- <property name="n_columns">1</property>
- <property name="homogeneous">False</property>
- <property name="row_spacing">5</property>
- <property name="column_spacing">5</property>
-
- <child>
- <widget class="GtkCheckButton" id="transpose">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Transpose</property>
- <property name="use_underline">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
- <property name="active">False</property>
- <property name="inconsistent">False</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="left_attach">0</property>
- <property name="right_attach">1</property>
- <property name="top_attach">0</property>
- <property name="bottom_attach">1</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
- </packing>
- </child>
- </widget>
- </child>
-</widget>
-
-</glade-interface>
Added: trunk/plugins/plot_surface/gog-xyz.c
==============================================================================
--- (empty file)
+++ trunk/plugins/plot_surface/gog-xyz.c Mon May 12 09:02:12 2008
@@ -0,0 +1,448 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gog-xyz.c
+ *
+ * Copyright (C) 2004-2007 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include <goffice/goffice-config.h>
+#include "gog-xyz.h"
+#include "gog-contour.h"
+#include "gog-surface.h"
+#include "xl-surface.h"
+#include <goffice/app/module-plugin-defs.h>
+#include <goffice/data/go-data.h>
+#include <goffice/graph/gog-chart.h>
+#include <goffice/math/go-math.h>
+#include <goffice/utils/go-format.h>
+
+#include <glib/gi18n-lib.h>
+#include <gsf/gsf-impl-utils.h>
+
+GOFFICE_PLUGIN_MODULE_HEADER;
+/*-----------------------------------------------------------------------------
+ *
+ * GogContourPlot
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+enum {
+ XYZ_PROP_0,
+ XYZ_PROP_TRANSPOSED
+};
+
+static GogObjectClass *plot_xyz_parent_klass;
+
+/**
+ * gog_xyz_plot_build_matrix :
+ * @plot :
+ *
+ * builds a table of normalized values: first slice = 0-1 second = 1-2,... if any.
+ **/
+
+double *
+gog_xyz_plot_build_matrix (GogXYZPlot const *plot, gboolean *cardinality_changed)
+{
+ GogXYZPlotClass *klass = GOG_XYZ_PLOT_GET_CLASS (plot);
+ return klass->build_matrix (plot, cardinality_changed);
+}
+
+static void
+gog_xyz_plot_update_3d (GogPlot *plot)
+{
+ GogXYZPlot *xyz = GOG_XYZ_PLOT (plot);
+ gboolean cardinality_changed = FALSE;
+
+ if (plot->series == NULL)
+ return;
+
+ xyz->plotted_data = gog_xyz_plot_build_matrix (xyz, &cardinality_changed);
+ if (cardinality_changed) {
+ /* gog_plot_request_cardinality_update can't be called from here
+ * since the plot might be updating.
+ */
+ GogChart *chart = GOG_CHART (GOG_OBJECT (plot)->parent);
+ plot->cardinality_valid = FALSE;
+ if (chart != NULL)
+ gog_chart_request_cardinality_update (chart);
+ }
+}
+
+#ifdef GOFFICE_WITH_GTK
+extern gpointer gog_xyz_plot_pref (GogXYZPlot *plot, GOCmdContext *cc);
+static void
+gog_xyz_plot_populate_editor (GogObject *item,
+ GogEditor *editor,
+ G_GNUC_UNUSED GogDataAllocator *dalloc,
+ GOCmdContext *cc)
+{
+ gog_editor_add_page (editor,
+ gog_xyz_plot_pref (GOG_XYZ_PLOT (item), cc),
+ _("Properties"));
+
+ (GOG_OBJECT_CLASS (plot_xyz_parent_klass)->populate_editor) (item, editor, dalloc, cc);
+}
+#endif
+
+static void
+gog_xyz_plot_clear_formats (GogXYZPlot *plot)
+{
+ if (plot->x.fmt != NULL) {
+ go_format_unref (plot->x.fmt);
+ plot->x.fmt = NULL;
+ }
+ if (plot->y.fmt != NULL) {
+ go_format_unref (plot->y.fmt);
+ plot->y.fmt = NULL;
+ }
+ if (plot->z.fmt != NULL) {
+ go_format_unref (plot->z.fmt);
+ plot->z.fmt = NULL;
+ }
+}
+
+static void
+gog_xyz_plot_update (GogObject *obj)
+{
+ GogXYZPlot * model = GOG_XYZ_PLOT(obj);
+ GogXYZSeries * series;
+ GODataVector *vec;
+ GODataMatrix *mat;
+ double tmp_min, tmp_max;
+
+ if (model->base.series == NULL)
+ return;
+
+ series = GOG_XYZ_SERIES (model->base.series->data);
+ if (!gog_series_is_valid (GOG_SERIES (series)))
+ return;
+
+ if ((vec = GO_DATA_VECTOR (series->base.values[0].data)) != NULL) {
+ if (model->x.fmt == NULL)
+ model->x.fmt = go_data_preferred_fmt (series->base.values[0].data);
+ if (go_data_vector_vary_uniformly (vec))
+ go_data_vector_get_minmax (vec, &tmp_min, &tmp_max);
+ else
+ tmp_min = tmp_max = go_nan;
+ } else {
+ tmp_min = 0;
+ tmp_max = series->columns - 1;
+ }
+
+ if ((model->columns != series->columns)
+ || (tmp_min != model->x.minima)
+ || (tmp_max != model->x.maxima)) {
+ model->columns = series->columns;
+ model->x.minima = tmp_min;
+ model->x.maxima = tmp_max;
+ gog_axis_bound_changed (model->base.axis[(model->transposed)? GOG_AXIS_Y: GOG_AXIS_X],
+ GOG_OBJECT (model));
+ }
+
+ if ((vec = GO_DATA_VECTOR (series->base.values[1].data)) != NULL) {
+ if (model->y.fmt == NULL)
+ model->y.fmt = go_data_preferred_fmt (series->base.values[1].data);
+ if (go_data_vector_vary_uniformly (vec))
+ go_data_vector_get_minmax (vec, &tmp_min, &tmp_max);
+ else
+ tmp_min = tmp_max = go_nan;
+ } else {
+ tmp_min = 0;
+ tmp_max = series->rows - 1;
+ }
+
+ if ((model->rows != series->rows)
+ || (tmp_min != model->y.minima)
+ || (tmp_max != model->y.maxima)) {
+ model->rows = series->rows;
+ model->y.minima = tmp_min;
+ model->y.maxima = tmp_max;
+ gog_axis_bound_changed (model->base.axis[(model->transposed)? GOG_AXIS_X: GOG_AXIS_Y],
+ GOG_OBJECT (model));
+ }
+
+ g_free (model->plotted_data);
+ model->plotted_data = NULL;
+ mat = GO_DATA_MATRIX (series->base.values[2].data);
+ go_data_matrix_get_minmax (mat, &tmp_min, &tmp_max);
+ if ((tmp_min != model->z.minima)
+ || (tmp_max != model->z.maxima)) {
+ model->z.minima = tmp_min;
+ model->z.maxima = tmp_max;
+ gog_axis_bound_changed (
+ model->base.axis[GOG_XYZ_PLOT_GET_CLASS (model)->third_axis],
+ GOG_OBJECT (model));
+ } else
+ gog_xyz_plot_update_3d (GOG_PLOT (model));
+
+ gog_object_emit_changed (GOG_OBJECT (obj), FALSE);
+ if (plot_xyz_parent_klass->update)
+ plot_xyz_parent_klass->update (obj);
+}
+
+static GOData *
+gog_xyz_plot_axis_get_bounds (GogPlot *plot, GogAxisType axis,
+ GogPlotBoundInfo * bounds)
+{
+ GogXYZSeries *series;
+ GogXYZPlot *xyz = GOG_XYZ_PLOT (plot);
+ GODataVector *vec = NULL;
+ double min, max;
+ GOFormat *fmt;
+ if (!plot->series)
+ return NULL;
+ series = GOG_XYZ_SERIES (plot->series->data);
+ if ((axis == GOG_AXIS_Y && xyz->transposed) ||
+ (axis == GOG_AXIS_X && !xyz->transposed)) {
+ vec = GO_DATA_VECTOR (series->base.values[0].data);
+ fmt = xyz->x.fmt;
+ min = xyz->x.minima;
+ max = xyz->x.maxima;
+ } else if (axis == GOG_AXIS_X || axis == GOG_AXIS_Y) {
+ vec = GO_DATA_VECTOR (series->base.values[1].data);
+ fmt = xyz->y.fmt;
+ min = xyz->y.minima;
+ max = xyz->y.maxima;
+ } else {
+ if (bounds->fmt == NULL && xyz->z.fmt != NULL)
+ bounds->fmt = go_format_ref (xyz->z.fmt);
+ bounds->val.minima = xyz->z.minima;
+ bounds->val.maxima = xyz->z.maxima;
+ return NULL;
+ }
+ if (bounds->fmt == NULL && fmt != NULL)
+ bounds->fmt = go_format_ref (fmt);
+ if (go_finite (min)) {
+ bounds->logical.minima = bounds->val.minima = min;
+ bounds->logical.maxima = bounds->val.maxima = max;
+ bounds->is_discrete = FALSE;
+ } else {
+ bounds->val.minima = 1.;
+ bounds->logical.minima = 1.;
+ bounds->logical.maxima = go_nan;
+ bounds->is_discrete = TRUE;
+ bounds->center_on_ticks = TRUE;
+ bounds->val.maxima = ((axis == GOG_AXIS_Y && xyz->transposed) ||
+ (axis == GOG_AXIS_X && !xyz->transposed)) ?
+ series->columns:
+ series->rows;
+ }
+ return (GOData*) vec;
+}
+
+static void
+gog_xyz_plot_finalize (GObject *obj)
+{
+ GogXYZPlot *plot = GOG_XYZ_PLOT (obj);
+ gog_xyz_plot_clear_formats (plot);
+ g_free (plot->plotted_data);
+ G_OBJECT_CLASS (plot_xyz_parent_klass)->finalize (obj);
+}
+
+static void
+gog_xyz_plot_set_property (GObject *obj, guint param_id,
+ GValue const *value, GParamSpec *pspec)
+{
+ GogXYZPlot *plot = GOG_XYZ_PLOT (obj);
+
+ switch (param_id) {
+ case XYZ_PROP_TRANSPOSED :
+ if (!plot->transposed != !g_value_get_boolean (value)) {
+ plot->transposed = g_value_get_boolean (value);
+ if (NULL != plot->base.axis[GOG_AXIS_X])
+ gog_axis_bound_changed (plot->base.axis[GOG_AXIS_X], GOG_OBJECT (plot));
+ if (NULL != plot->base.axis[GOG_AXIS_Y])
+ gog_axis_bound_changed (plot->base.axis[GOG_AXIS_Y], GOG_OBJECT (plot));
+ g_free (plot->plotted_data);
+ plot->plotted_data = NULL;
+ }
+ break;
+
+ default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+ return; /* NOTE : RETURN */
+ }
+ gog_object_emit_changed (GOG_OBJECT (obj), FALSE);
+}
+
+static void
+gog_xyz_plot_get_property (GObject *obj, guint param_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GogXYZPlot *plot = GOG_XYZ_PLOT (obj);
+
+ switch (param_id) {
+ case XYZ_PROP_TRANSPOSED :
+ g_value_set_boolean (value, plot->transposed);
+ break;
+
+ default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+gog_xyz_plot_class_init (GogXYZPlotClass *klass)
+{
+ GogPlotClass *gog_plot_klass = (GogPlotClass*) klass;
+ GObjectClass *gobject_klass = (GObjectClass *) klass;
+ GogObjectClass *gog_object_klass = (GogObjectClass *) klass;
+
+ plot_xyz_parent_klass = g_type_class_peek_parent (klass);
+
+ gobject_klass->finalize = gog_xyz_plot_finalize;
+ gobject_klass->set_property = gog_xyz_plot_set_property;
+ gobject_klass->get_property = gog_xyz_plot_get_property;
+ g_object_class_install_property (gobject_klass, XYZ_PROP_TRANSPOSED,
+ g_param_spec_boolean ("transposed",
+ _("Transposed"),
+ _("Transpose the plot"),
+ FALSE,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE|GOG_PARAM_PERSISTENT));
+
+ /* Fill in GOGObject superclass values */
+ gog_object_klass->update = gog_xyz_plot_update;
+#ifdef GOFFICE_WITH_GTK
+ gog_object_klass->populate_editor = gog_xyz_plot_populate_editor;
+#endif
+
+ {
+ static GogSeriesDimDesc dimensions[] = {
+ { N_("X"), GOG_SERIES_SUGGESTED, FALSE,
+ GOG_DIM_LABEL, GOG_MS_DIM_CATEGORIES },
+ { N_("Y"), GOG_SERIES_SUGGESTED, FALSE,
+ GOG_DIM_LABEL, GOG_MS_DIM_CATEGORIES },
+ { N_("Z"), GOG_SERIES_REQUIRED, FALSE,
+ GOG_DIM_MATRIX, GOG_MS_DIM_VALUES },
+ };
+ gog_plot_klass->desc.series.dim = dimensions;
+ gog_plot_klass->desc.series.num_dim = G_N_ELEMENTS (dimensions);
+ gog_plot_klass->desc.series.style_fields = GOG_STYLE_LINE;
+ }
+
+ /* Fill in GogPlotClass methods */
+ gog_plot_klass->desc.num_series_min = 1;
+ gog_plot_klass->desc.num_series_max = 1;
+ gog_plot_klass->series_type = gog_xyz_series_get_type();
+ gog_plot_klass->axis_get_bounds = gog_xyz_plot_axis_get_bounds;
+ gog_plot_klass->update_3d = gog_xyz_plot_update_3d;
+}
+
+static void
+gog_xyz_plot_init (GogXYZPlot *xyz)
+{
+ xyz->rows = xyz->columns = 0;
+ xyz->transposed = FALSE;
+ xyz->x.minima = xyz->x.maxima = xyz->y.minima
+ = xyz->y.maxima = xyz->z.minima = xyz->z.maxima = go_nan;
+ xyz->x.fmt = xyz->y.fmt = xyz->z.fmt = NULL;
+ xyz->plotted_data = NULL;
+}
+
+GSF_DYNAMIC_CLASS_ABSTRACT (GogXYZPlot, gog_xyz_plot,
+ gog_xyz_plot_class_init, gog_xyz_plot_init,
+ GOG_PLOT_TYPE)
+
+/*****************************************************************************/
+
+static GogStyledObjectClass *series_parent_klass;
+
+static void
+gog_xyz_series_update (GogObject *obj)
+{
+ GogXYZSeries *series = GOG_XYZ_SERIES (obj);
+ GODataMatrixSize size, old_size;
+ GODataMatrix *mat;
+ GODataVector *vec;
+ int length;
+ size.rows = 0;
+ size.columns = 0;
+ if (series->base.values[2].data != NULL) {
+ old_size.rows = series->rows;
+ old_size.columns = series->columns;
+ mat = GO_DATA_MATRIX (series->base.values[2].data);
+ go_data_matrix_get_values (mat);
+ size = go_data_matrix_get_size (mat);
+ }
+ if (series->base.values[0].data != NULL) {
+ vec = GO_DATA_VECTOR (series->base.values[0].data);
+ go_data_vector_get_values (vec);
+ length = go_data_vector_get_len (vec);
+ if (length < size.columns)
+ size.columns = length;
+ }
+ if (series->base.values[1].data != NULL) {
+ vec = GO_DATA_VECTOR (series->base.values[1].data);
+ go_data_vector_get_values (vec);
+ length = go_data_vector_get_len (vec);
+ if (length < size.rows)
+ size.rows = length;
+ }
+ series->rows = size.rows;
+ series->columns = size.columns;
+
+ /* queue plot for redraw */
+ gog_object_request_update (GOG_OBJECT (series->base.plot));
+/* gog_plot_request_cardinality_update (series->base.plot);*/
+
+ if (series_parent_klass->base.update)
+ series_parent_klass->base.update (obj);
+}
+
+static void
+gog_xyz_series_init_style (GogStyledObject *gso, GogStyle *style)
+{
+ series_parent_klass->init_style (gso, style);
+}
+
+static void
+gog_xyz_series_class_init (GogStyledObjectClass *gso_klass)
+{
+ GogObjectClass * obj_klass = (GogObjectClass *) gso_klass;
+
+ series_parent_klass = g_type_class_peek_parent (gso_klass);
+ gso_klass->init_style = gog_xyz_series_init_style;
+ obj_klass->update = gog_xyz_series_update;
+}
+
+
+GSF_DYNAMIC_CLASS (GogXYZSeries, gog_xyz_series,
+ gog_xyz_series_class_init, NULL,
+ GOG_SERIES_TYPE)
+
+/*****************************************************************************/
+
+G_MODULE_EXPORT void
+go_plugin_init (GOPlugin *plugin, GOCmdContext *cc)
+{
+ GTypeModule *module = go_plugin_get_type_module (plugin);
+ gog_xyz_plot_register_type (module);
+ gog_contour_plot_register_type (module);
+ gog_contour_view_register_type (module);
+ gog_surface_plot_register_type (module);
+ gog_surface_view_register_type (module);
+ gog_xyz_series_register_type (module);
+ xl_y_labels_register_type (module);
+ xl_xyz_series_register_type (module);
+ xl_contour_plot_register_type (module);
+ xl_surface_plot_register_type (module);
+}
+
+G_MODULE_EXPORT void
+go_plugin_shutdown (GOPlugin *plugin, GOCmdContext *cc)
+{
+}
Added: trunk/plugins/plot_surface/gog-xyz.h
==============================================================================
--- (empty file)
+++ trunk/plugins/plot_surface/gog-xyz.h Mon May 12 09:02:12 2008
@@ -0,0 +1,81 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gog-xyz.h
+ *
+ * Copyright (C) 2004-2007 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#ifndef GOG_XYZ_H
+#define GOG_XYZ_H
+
+#include <goffice/graph/gog-plot-impl.h>
+
+G_BEGIN_DECLS
+
+/*-----------------------------------------------------------------------------
+ *
+ * GogContourPlot
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+typedef struct {
+ GogPlot base;
+
+ unsigned rows, columns;
+ gboolean transposed;
+ struct {
+ double minima, maxima;
+ GOFormat *fmt;
+ } x, y, z;
+ double *plotted_data;
+} GogXYZPlot;
+
+#define GOG_XYZ_PLOT_TYPE (gog_xyz_plot_get_type ())
+#define GOG_XYZ_PLOT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_XYZ_PLOT_TYPE, GogXYZPlot))
+#define GOG_IS_PLOT_XYZ(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_XYZ_PLOT_TYPE))
+
+GType gog_xyz_plot_get_type (void);
+
+typedef struct {
+ GogPlotClass base;
+
+ GogAxisType third_axis;
+
+ double * (*build_matrix) (GogXYZPlot const *plot, gboolean *cardinality_changed);
+} GogXYZPlotClass;
+
+#define GOG_XYZ_PLOT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOG_XYZ_PLOT_TYPE, GogXYZPlotClass))
+
+double *gog_xyz_plot_build_matrix (GogXYZPlot const *plot, gboolean *cardinality_changed);
+
+typedef struct {
+ GogSeries base;
+
+ unsigned rows, columns;
+} GogXYZSeries;
+typedef GogSeriesClass GogXYZSeriesClass;
+
+#define GOG_XYZ_SERIES_TYPE (gog_xyz_series_get_type ())
+#define GOG_XYZ_SERIES(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_XYZ_SERIES_TYPE, GogXYZSeries))
+#define GOG_IS_XYZ_SERIES(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_XYZ_SERIES_TYPE))
+
+GType gog_xyz_series_get_type (void);
+
+G_END_DECLS
+
+#endif /* GOG_XYZ_H */
Modified: trunk/plugins/plot_surface/plot-types.xml.in
==============================================================================
--- trunk/plugins/plot_surface/plot-types.xml.in (original)
+++ trunk/plugins/plot_surface/plot-types.xml.in Mon May 12 09:02:12 2008
@@ -7,4 +7,9 @@
_description="Contour plot."
sample_image_file="chart_contour_1_1.png">
</Type>
+ <Type _name="Surface" row="2" col="1"
+ engine="GogSurfacePlot" family="Surface"
+ _description="Surface plot."
+ sample_image_file="chart_surface_2_1.png">
+ </Type>
</Types>
Modified: trunk/plugins/plot_surface/plugin.xml.in
==============================================================================
--- trunk/plugins/plot_surface/plugin.xml.in (original)
+++ trunk/plugins/plot_surface/plugin.xml.in Mon May 12 09:02:12 2008
@@ -18,6 +18,16 @@
<description>Excel (TM) compatibility contour plotting engine</description>
</information>
</service>
+ <service type="plot_engine" id="GogSurfacePlot">
+ <information>
+ <_description>Surface plotting engine</_description>
+ </information>
+ </service>
+ <service type="plot_engine" id="XLSurfacePlot">
+ <information>
+ <description>Excel (TM) compatibility surface plotting engine</description>
+ </information>
+ </service>
<service type="plot_type" id="surface">
<file>plot-types.xml</file>
<information>
Modified: trunk/plugins/plot_surface/xl-surface.c
==============================================================================
--- trunk/plugins/plot_surface/xl-surface.c (original)
+++ trunk/plugins/plot_surface/xl-surface.c Mon May 12 09:02:12 2008
@@ -30,91 +30,91 @@
#include <goffice/math/go-math.h>
#include <goffice/utils/go-format.h>
-static GogObjectClass *xl_contour_parent_klass;
-typedef GogSeries XLSurfaceSeries;
-typedef GogSeriesClass XLSurfaceSeriesClass;
+typedef struct {
+ char const **y_labels;
+} XlYLabels;
+
+typedef GTypeInterface XlYLabelsClass;
+
+#define XL_Y_LABELS_TYPE (xl_y_labels_get_type ())
+#define XL_Y_LABELS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XL_Y_LABELS_TYPE, XlYLabels))
+//#define IS_XL_Y_LABELS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), XL_Y_LABELS_TYPE))
+//#define XL_Y_LABELS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), XL_Y_LABELS_TYPE, XlYLabelsClass))
+//#define IS_XL_Y_LABELS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), XL_Y_LABELS))
+//#define XL_Y_LABELS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), XL_Y_LABELS, XlYLabelsClass))
-#define XL_SURFACE_SERIES_TYPE (xl_surface_series_get_type ())
-#define XL_SURFACE_SERIES(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XL_SURFACE_SERIES_TYPE, XLSurfaceSeries))
-#define XL_IS_SURFACE_SERIES(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), XL_SURFACE_SERIES_TYPE))
+GSF_DYNAMIC_CLASS (XlYLabels, xl_y_labels, NULL, NULL, G_TYPE_INTERFACE);
-static GType xl_surface_series_get_type (void);
+static void
+xl_labels_init (XlYLabels *labels)
+{
+ labels->y_labels = NULL;
+}
/*****************************************************************************/
-typedef GogContourPlotClass XLContourPlotClass;
+typedef GogSeries XlXYZSeries;
+typedef GogSeriesClass XlXYZSeriesClass;
-static double *
-xl_contour_plot_build_matrix (GogContourPlot const *plot,
- gboolean *cardinality_changed)
+#define XL_XYZ_SERIES_TYPE (xl_xyz_series_get_type ())
+#define XL_XYZ_SERIES(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XL_XYZ_SERIES_TYPE, XlXYZSeries))
+#define XL_IS_XYZ_SERIES(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), XL_XYZ_SERIES_TYPE))
+
+static GType xl_xyz_series_get_type (void);
+
+static GogStyledObjectClass *series_parent_klass;
+
+static void
+xl_xyz_series_update (GogObject *obj)
{
- unsigned i, j, length;
- GogAxisMap *map;
- GogAxisTick *zticks;
- GogAxis *axis = plot->base.axis[GOG_AXIS_PSEUDO_3D];
- unsigned nticks;
- double x[2], val;
- GogSeries *series = NULL;
- GODataVector *vec;
- unsigned n = plot->rows * plot->columns;
- double *data, minimum, maximum;
- unsigned max;
- GSList *ptr;
+ XlXYZSeries *series = XL_XYZ_SERIES (obj);
+ int x_len = 0, z_len = 0;
- if (!gog_axis_get_bounds (axis, &minimum, &maximum))
- return NULL;
- data = g_new (double, n);
- nticks = gog_axis_get_ticks (axis, &zticks);
- map = gog_axis_map_new (axis, 0, 1);
- for (i = j = 0; i < nticks; i++)
- if (zticks[i].type == GOG_AXIS_TICK_MAJOR) {
- x[j++] = gog_axis_map_to_view (map, zticks[i].position);
- if (j > 1)
- break;
- }
- x[1] -= x[0];
+ if (series->values[1].data != NULL)
+ z_len = go_data_vector_get_len (
+ GO_DATA_VECTOR (series->values[1].data));
+ if (series->values[0].data != NULL)
+ x_len = go_data_vector_get_len (
+ GO_DATA_VECTOR (series->values[0].data));
+ else
+ x_len = z_len;
+ series->num_elements = MIN (x_len, z_len);
- for (i = 0, ptr = plot->base.series ; ptr != NULL ; ptr = ptr->next) {
- series = ptr->data;
- if (!gog_series_is_valid (GOG_SERIES (series)))
- continue;
- vec = GO_DATA_VECTOR (series->values[1].data);
- length = go_data_vector_get_len (vec);
- for (j = 0; j < plot->columns; j++) {
- /* The vector might be too short, excel is so ugly ;-) */
- val = (j < length)? gog_axis_map_to_view (map,
- go_data_vector_get_value (vec, j)): 0.;
- /* This is an excel compatible plot, so let's be compatible */
- if (val == go_nan || !go_finite (val))
- val = 0.;
- if (fabs (val) == DBL_MAX)
- val = go_nan;
- else {
- val = val/ x[1] - x[0];
- if (val < 0) {
- val = go_nan;
- }
- }
- data[i * plot->columns + j] = val;
- }
- i++;
- }
- g_return_val_if_fail (series != NULL, NULL);
- max = (unsigned) ceil (1 / x[1]);
- series = plot->base.series->data;
- if (series->num_elements != max) {
- series->num_elements = max;
- *cardinality_changed = TRUE;
- }
- gog_axis_map_free (map);
- return data;
+ /* queue plot for redraw */
+ gog_object_request_update (GOG_OBJECT (series->plot));
+
+ if (series_parent_klass->base.update)
+ series_parent_klass->base.update (obj);
}
static void
-xl_contour_plot_update (GogObject *obj)
+xl_xyz_series_init_style (GogStyledObject *gso, GogStyle *style)
{
- GogContourPlot * model = GOG_CONTOUR_PLOT(obj);
- XLSurfaceSeries * series;
+ series_parent_klass->init_style (gso, style);
+}
+
+static void
+xl_xyz_series_class_init (GogStyledObjectClass *gso_klass)
+{
+ GogObjectClass * obj_klass = (GogObjectClass *) gso_klass;
+
+ series_parent_klass = g_type_class_peek_parent (gso_klass);
+ gso_klass->init_style = xl_xyz_series_init_style;
+ obj_klass->update = xl_xyz_series_update;
+}
+
+
+GSF_DYNAMIC_CLASS (XlXYZSeries, xl_xyz_series,
+ xl_xyz_series_class_init, NULL,
+ GOG_SERIES_TYPE)
+
+/*****************************************************************************/
+
+static void
+xl_xyz_plot_update (GogObject *obj)
+{
+ GogXYZPlot * model = GOG_XYZ_PLOT(obj);
+ XlXYZSeries * series;
double zmin = DBL_MAX, zmax = -DBL_MAX, tmp_min, tmp_max;
GSList *ptr;
model->rows = 0;
@@ -161,7 +161,7 @@
|| (zmax != model->z.maxima)) {
model->z.minima = zmin;
model->z.maxima = zmax;
- gog_axis_bound_changed (model->base.axis[GOG_AXIS_PSEUDO_3D], GOG_OBJECT (model));
+ gog_axis_bound_changed (model->base.axis[GOG_XYZ_PLOT_GET_CLASS (model)->third_axis], obj);
} else
gog_plot_update_3d (GOG_PLOT (model));
@@ -172,47 +172,48 @@
static GODataVector *
get_y_vector (GogPlot *plot)
{
- XLContourPlot *contour = XL_CONTOUR_PLOT (plot);
+ GogXYZPlot *xyz = GOG_XYZ_PLOT (plot);
+ XlYLabels *labels = XL_Y_LABELS (plot);
GSList *ptr;
int i;
- g_free (contour->y_labels);
- contour->y_labels = g_new0 (char const *, contour->base.rows);
+ g_free (labels->y_labels);
+ labels->y_labels = g_new0 (char const *, xyz->rows);
for (ptr = plot->series, i = 0 ; ptr != NULL ; ptr = ptr->next, i++) {
- XLSurfaceSeries *series = ptr->data;
+ XlXYZSeries *series = ptr->data;
if (!gog_series_is_valid (GOG_SERIES (series)))
continue;
- contour->y_labels[i] = go_data_scalar_get_str (GO_DATA_SCALAR (
+ labels->y_labels[i] = go_data_scalar_get_str (GO_DATA_SCALAR (
series->values[-1].data));
}
- return GO_DATA_VECTOR (go_data_vector_str_new (contour->y_labels, i, NULL));
+ return GO_DATA_VECTOR (go_data_vector_str_new (labels->y_labels, i, NULL));
}
static GOData *
-xl_contour_plot_axis_get_bounds (GogPlot *plot, GogAxisType axis,
+xl_xyz_plot_axis_get_bounds (GogPlot *plot, GogAxisType axis,
GogPlotBoundInfo * bounds)
{
- XLContourPlot *contour = XL_CONTOUR_PLOT (plot);
+ GogXYZPlot *xyz = GOG_XYZ_PLOT (plot);
GODataVector *vec = NULL;
GOFormat *fmt;
if (axis == GOG_AXIS_X) {
- XLSurfaceSeries *series = XL_SURFACE_SERIES (plot->series->data);
+ XlXYZSeries *series = XL_XYZ_SERIES (plot->series->data);
vec = GO_DATA_VECTOR (series->values[0].data);
- fmt = contour->base.x.fmt;
+ fmt = xyz->x.fmt;
} else if (axis == GOG_AXIS_Y) {
- if (!contour->base.rows)
+ if (!xyz->rows)
return NULL;
vec = get_y_vector (plot);
- fmt = contour->base.y.fmt;
+ fmt = xyz->y.fmt;
} else {
- if (bounds->fmt == NULL && contour->base.z.fmt != NULL)
- bounds->fmt = go_format_ref (contour->base.z.fmt);
- bounds->val.minima = contour->base.z.minima;
- bounds->val.maxima = contour->base.z.maxima;
+ if (bounds->fmt == NULL && xyz->z.fmt != NULL)
+ bounds->fmt = go_format_ref (xyz->z.fmt);
+ bounds->val.minima = xyz->z.minima;
+ bounds->val.maxima = xyz->z.maxima;
return NULL;
}
if (bounds->fmt == NULL && fmt != NULL)
@@ -223,16 +224,87 @@
bounds->is_discrete = TRUE;
bounds->center_on_ticks = TRUE;
bounds->val.maxima = (axis == GOG_AXIS_X)?
- contour->base.columns:
- contour->base.rows;
+ xyz->columns:
+ xyz->rows;
return (GOData*) vec;
}
+/*****************************************************************************/
+
+static GogObjectClass *xl_contour_parent_klass;
+
+typedef GogContourPlotClass XlContourPlotClass;
+
+static double *
+xl_contour_plot_build_matrix (GogXYZPlot const *plot,
+ gboolean *cardinality_changed)
+{
+ unsigned i, j, length;
+ GogAxisMap *map;
+ GogAxisTick *zticks;
+ GogAxis *axis = plot->base.axis[GOG_AXIS_PSEUDO_3D];
+ unsigned nticks;
+ double x[2], val;
+ GogSeries *series = NULL;
+ GODataVector *vec;
+ unsigned n = plot->rows * plot->columns;
+ double *data, minimum, maximum;
+ unsigned max;
+ GSList *ptr;
+
+ if (!gog_axis_get_bounds (axis, &minimum, &maximum))
+ return NULL;
+ data = g_new (double, n);
+ nticks = gog_axis_get_ticks (axis, &zticks);
+ map = gog_axis_map_new (axis, 0, 1);
+ for (i = j = 0; i < nticks; i++)
+ if (zticks[i].type == GOG_AXIS_TICK_MAJOR) {
+ x[j++] = gog_axis_map_to_view (map, zticks[i].position);
+ if (j > 1)
+ break;
+ }
+ x[1] -= x[0];
+
+ for (i = 0, ptr = plot->base.series ; ptr != NULL ; ptr = ptr->next) {
+ series = ptr->data;
+ if (!gog_series_is_valid (GOG_SERIES (series)))
+ continue;
+ vec = GO_DATA_VECTOR (series->values[1].data);
+ length = go_data_vector_get_len (vec);
+ for (j = 0; j < plot->columns; j++) {
+ /* The vector might be too short, excel is so ugly ;-) */
+ val = (j < length)? gog_axis_map_to_view (map,
+ go_data_vector_get_value (vec, j)): 0.;
+ /* This is an excel compatible plot, so let's be compatible */
+ if (val == go_nan || !go_finite (val))
+ val = 0.;
+ if (fabs (val) == DBL_MAX)
+ val = go_nan;
+ else {
+ val = val/ x[1] - x[0];
+ if (val < 0) {
+ val = go_nan;
+ }
+ }
+ data[i * plot->columns + j] = val;
+ }
+ i++;
+ }
+ g_return_val_if_fail (series != NULL, NULL);
+ max = (unsigned) ceil (1 / x[1]);
+ series = plot->base.series->data;
+ if (series->num_elements != max) {
+ series->num_elements = max;
+ *cardinality_changed = TRUE;
+ }
+ gog_axis_map_free (map);
+ return data;
+}
static void
xl_contour_plot_finalize (GObject *obj)
{
- XLContourPlot *plot = XL_CONTOUR_PLOT (obj);
- g_free (plot->y_labels);
+ XlYLabels *labels = XL_Y_LABELS (obj);
+ g_free (labels->y_labels);
G_OBJECT_CLASS (xl_contour_parent_klass)->finalize (obj);
}
@@ -248,7 +320,7 @@
gobject_klass->finalize = xl_contour_plot_finalize;
/* Fill in GOGObject superclass values */
- gog_object_klass->update = xl_contour_plot_update;
+ gog_object_klass->update = xl_xyz_plot_update;
gog_object_klass->populate_editor = NULL;
{
@@ -263,69 +335,101 @@
gog_plot_klass->desc.series.style_fields = 0;
}
/* Fill in GogPlotClass methods */
- gog_plot_klass->axis_get_bounds = xl_contour_plot_axis_get_bounds;
- gog_plot_klass->series_type = xl_surface_series_get_type();
+ gog_plot_klass->axis_get_bounds = xl_xyz_plot_axis_get_bounds;
+ gog_plot_klass->series_type = xl_xyz_series_get_type();
klass->build_matrix = xl_contour_plot_build_matrix;
}
-static void
-xl_contour_plot_init (XLContourPlot *contour)
-{
- contour->y_labels = NULL;
-}
-
-GSF_DYNAMIC_CLASS (XLContourPlot, xl_contour_plot,
- xl_contour_plot_class_init, xl_contour_plot_init,
- GOG_CONTOUR_PLOT_TYPE)
+GSF_DYNAMIC_CLASS_FULL (XlContourPlot, xl_contour_plot,
+ NULL, NULL, xl_contour_plot_class_init, NULL,
+ NULL, GOG_CONTOUR_PLOT_TYPE, 0,
+ GSF_INTERFACE (xl_labels_init, XL_Y_LABELS_TYPE))
/*****************************************************************************/
-static GogStyledObjectClass *series_parent_klass;
+static GogObjectClass *xl_surface_parent_klass;
-static void
-xl_surface_series_update (GogObject *obj)
-{
- XLSurfaceSeries *series = XL_SURFACE_SERIES (obj);
- int x_len = 0, z_len = 0;
-/* unsigned old_num = series->num_elements;*/
-
- if (series->values[1].data != NULL)
- z_len = go_data_vector_get_len (
- GO_DATA_VECTOR (series->values[1].data));
- if (series->values[0].data != NULL)
- x_len = go_data_vector_get_len (
- GO_DATA_VECTOR (series->values[0].data));
- else
- x_len = z_len;
- series->num_elements = MIN (x_len, z_len);
+typedef GogSurfacePlotClass XlSurfacePlotClass;
- /* queue plot for redraw */
- gog_object_request_update (GOG_OBJECT (series->plot));
-/* if (old_num != series->base.num_elements)
- gog_plot_request_cardinality_update (series->plot);*/
+static double *
+xl_surface_plot_build_matrix (GogXYZPlot const *plot,
+ gboolean *cardinality_changed)
+{
+ unsigned i, j, length;
+ double val;
+ GogSeries *series = NULL;
+ GODataVector *vec;
+ unsigned n = plot->rows * plot->columns;
+ double *data;
+ GSList *ptr;
- if (series_parent_klass->base.update)
- series_parent_klass->base.update (obj);
+ data = g_new (double, n);
+ for (i = 0, ptr = plot->base.series ; ptr != NULL ; ptr = ptr->next) {
+ series = ptr->data;
+ if (!gog_series_is_valid (GOG_SERIES (series)))
+ continue;
+ vec = GO_DATA_VECTOR (series->values[1].data);
+ length = go_data_vector_get_len (vec);
+ for (j = 0; j < plot->columns; j++) {
+ /* The vector might be too short, excel is so ugly ;-) */
+ val = (j < length)? go_data_vector_get_value (vec, j): 0.;
+ /* This is an excel compatible plot, so let's be compatible */
+ if (val == go_nan || !go_finite (val))
+ val = 0.;
+ if (fabs (val) == DBL_MAX)
+ val = go_nan;
+ data[i * plot->columns + j] = val;
+ }
+ i++;
+ }
+ *cardinality_changed = FALSE;
+ return data;
}
static void
-xl_surface_series_init_style (GogStyledObject *gso, GogStyle *style)
+xl_surface_plot_finalize (GObject *obj)
{
- series_parent_klass->init_style (gso, style);
+ XlYLabels *labels = XL_Y_LABELS (obj);
+ g_free (labels->y_labels);
+ G_OBJECT_CLASS (xl_surface_parent_klass)->finalize (obj);
}
static void
-xl_surface_series_class_init (GogStyledObjectClass *gso_klass)
+xl_surface_plot_class_init (GogSurfacePlotClass *klass)
{
- GogObjectClass * obj_klass = (GogObjectClass *) gso_klass;
+ GogPlotClass *gog_plot_klass = (GogPlotClass*) klass;
+ GogObjectClass *gog_object_klass = (GogObjectClass *) klass;
+ GObjectClass *gobject_klass = (GObjectClass *) klass;
- series_parent_klass = g_type_class_peek_parent (gso_klass);
- gso_klass->init_style = xl_surface_series_init_style;
- obj_klass->update = xl_surface_series_update;
+ xl_surface_parent_klass = g_type_class_peek_parent (klass);
+
+ gobject_klass->finalize = xl_surface_plot_finalize;
+
+ /* Fill in GOGObject superclass values */
+ gog_object_klass->update = xl_xyz_plot_update;
+ gog_object_klass->populate_editor = NULL;
+
+ {
+ static GogSeriesDimDesc dimensions[] = {
+ { N_("X"), GOG_SERIES_REQUIRED, FALSE,
+ GOG_DIM_LABEL, GOG_MS_DIM_CATEGORIES },
+ { N_("Z"), GOG_SERIES_REQUIRED, FALSE,
+ GOG_DIM_VALUE, GOG_MS_DIM_VALUES },
+ };
+ gog_plot_klass->desc.series.dim = dimensions;
+ gog_plot_klass->desc.series.num_dim = G_N_ELEMENTS (dimensions);
+ gog_plot_klass->desc.series.style_fields = 0;
+ }
+ /* Fill in GogPlotClass methods */
+ gog_plot_klass->axis_get_bounds = xl_xyz_plot_axis_get_bounds;
+ gog_plot_klass->series_type = xl_xyz_series_get_type();
+
+ klass->build_matrix = xl_surface_plot_build_matrix;
}
+GSF_DYNAMIC_CLASS_FULL (XlSurfacePlot, xl_surface_plot,
+ NULL, NULL, xl_surface_plot_class_init, NULL,
+ NULL, GOG_SURFACE_PLOT_TYPE, 0,
+ GSF_INTERFACE (xl_labels_init, XL_Y_LABELS_TYPE))
-GSF_DYNAMIC_CLASS (XLSurfaceSeries, xl_surface_series,
- xl_surface_series_class_init, NULL,
- GOG_SERIES_TYPE)
Modified: trunk/plugins/plot_surface/xl-surface.h
==============================================================================
--- trunk/plugins/plot_surface/xl-surface.h (original)
+++ trunk/plugins/plot_surface/xl-surface.h Mon May 12 09:02:12 2008
@@ -1,6 +1,6 @@
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * xl-contour.h
+ * xl-surface.h
*
* Copyright (C) 2005 Jean Brefort (jean brefort normalesup org)
*
@@ -19,13 +19,17 @@
* USA
*/
-#ifndef XL_CONTOUR_H
-#define XL_CONTOUR_H
+#ifndef XL_SURFACE_H
+#define XL_SURFACE_H
+#include "gog-contour.h"
#include "gog-surface.h"
G_BEGIN_DECLS
+void xl_y_labels_register_type (GTypeModule *plugin);
+void xl_xyz_series_register_type (GTypeModule *plugin);
+
/*-----------------------------------------------------------------------------
*
* XLContourPlot
@@ -33,19 +37,31 @@
*-----------------------------------------------------------------------------
*/
-typedef struct {
- GogContourPlot base;
- char const **y_labels;
-} XLContourPlot;
+typedef GogContourPlot XlContourPlot;
#define XL_CONTOUR_PLOT_TYPE (xl_contour_plot_get_type ())
-#define XL_CONTOUR_PLOT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XL_CONTOUR_PLOT_TYPE, XLContourPlot))
+#define XL_CONTOUR_PLOT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XL_CONTOUR_PLOT_TYPE, XlContourPlot))
#define XL_PLOT_CONTOUR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), XL_CONTOUR_PLOT_TYPE))
GType xl_contour_plot_get_type (void);
void xl_contour_plot_register_type (GTypeModule *plugin);
-void xl_surface_series_register_type (GTypeModule *plugin);
+
+/*-----------------------------------------------------------------------------
+ *
+ * XLSurfacePlot
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+typedef GogSurfacePlot XlSurfacePlot;
+
+#define XL_SURFACE_PLOT_TYPE (xl_surface_plot_get_type ())
+#define XL_SURFACE_PLOT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XL_SURFACE_PLOT_TYPE, XlSurfacePlot))
+#define XL_PLOT_SURFACE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), XL_SURFACE_PLOT_TYPE))
+
+GType xl_surface_plot_get_type (void);
+void xl_surface_plot_register_type (GTypeModule *plugin);
G_END_DECLS
-#endif /* XL_CONTOUR_H */
+#endif /* XL_SURFACE_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]