/* This is -*- C -*- */
/* $Id: guppi-curve-func.c,v 1.1 2002/01/08 06:28:59 trow Exp $ */
/*
* guppi-curve-func-impl.c
*
* Copyright (C) 2000 EMC Capital Management, Inc.
* Copyright (C) 2001 The Free Software Foundation
*
* Developed by Jon Trowbridge <trow@gnu.org> and
* Havoc Pennington <hp@pobox.com>.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <config.h>
#include "guppi-curve-func.h"
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-config.h>
#include <libgnome/gnome-i18n.h>
#include <guppi-useful.h>
#include <guppi-memory.h>
#include <guppi-data-plug-in.h>
static GtkObjectClass *parent_class = NULL;
enum {
ARG_0,
ARG_CURVE,
ARG_REPARAMETERIZE,
ARG_T0,
ARG_T1,
ARG_T_FUNC,
ARG_X_FUNC,
ARG_Y_FUNC,
ARG_X_BINARY_FUNC,
ARG_Y_BINARY_FUNC,
ARG_USE_2x2_MATRIX,
ARG_MATRIX_A,
ARG_MATRIX_B,
ARG_MATRIX_C,
ARG_MATRIX_D
};
static void
guppi_curve_func_get_arg (GtkObject *obj, GtkArg *arg, guint arg_id)
{
switch (arg_id) {
default:
break;
};
}
static void
guppi_curve_func_set_arg (GtkObject *obj, GtkArg *arg, guint arg_id)
{
GuppiCurveFunc *func = GUPPI_CURVE_FUNC (obj);
GuppiCurve *c;
gboolean rp;
double t;
GuppiFnWrapper *fw;
switch (arg_id) {
case ARG_CURVE:
c = GUPPI_CURVE (GTK_VALUE_POINTER (*arg));
if (func->base_curve != c) {
guppi_refcounting_assign (func->base_curve, c);
guppi_data_changed (GUPPI_DATA (obj));
};
break;
case ARG_REPARAMETERIZE:
rp = GTK_VALUE_BOOL (*arg);
if (func->reparameterize != rp) {
func->reparameterize = rp;
guppi_data_changed (GUPPI_DATA (obj));
}
break;
case ARG_T0:
t = GTK_VALUE_DOUBLE (*arg);
if (func->t0 != t || !func->reparameterize) {
func->t0 = t;
func->reparameterize = TRUE;
guppi_data_changed (GUPPI_DATA (obj));
}
break;
case ARG_T1:
t = GTK_VALUE_DOUBLE (*arg);
if (func->t1 != t || !func->reparameterize) {
func->t1 = t;
func->reparameterize = TRUE;
guppi_data_changed (GUPPI_DATA (obj));
}
break;
case ARG_T_FUNC:
fw = GUPPI_FN_WRAPPER (GTK_VALUE_POINTER (*arg));
if (func->t_fn_wrapper != fw || !func->reparameterize) {
func->reparameterize = TRUE;
guppi_refcounting_assign (func->t_fn_wrapper, fw);
guppi_data_changed (GUPPI_DATA (obj));
}
break;
case ARG_X_FUNC:
fw = GUPPI_FN_WRAPPER (GTK_VALUE_POINTER (*arg));
if (func->x_fn_wrapper != fw) {
guppi_refcounting_assign (func->x_fn_wrapper, fw);
guppi_data_changed (GUPPI_DATA (obj));
}
break;
case ARG_Y_FUNC:
fw = GUPPI_FN_WRAPPER (GTK_VALUE_POINTER (*arg));
if (func->y_fn_wrapper != fw) {
guppi_refcounting_assign (func->y_fn_wrapper, fw);
guppi_data_changed (GUPPI_DATA (obj));
}
break;
case ARG_X_BINARY_FUNC:
fw = GUPPI_FN_WRAPPER (GTK_VALUE_POINTER (*arg));
if (func->x_binary_fn_wrapper != fw) {
guppi_refcounting_assign (func->x_binary_fn_wrapper, fw);
guppi_data_changed (GUPPI_DATA (obj));
}
break;
case ARG_Y_BINARY_FUNC:
fw = GUPPI_FN_WRAPPER (GTK_VALUE_POINTER (*arg));
if (func->y_binary_fn_wrapper != fw) {
guppi_refcounting_assign (func->y_binary_fn_wrapper, fw);
guppi_data_changed (GUPPI_DATA (obj));
}
break;
case ARG_USE_2x2_MATRIX:
rp = GTK_VALUE_BOOL (*arg);
if (func->use_2x2_matrix != rp) {
func->use_2x2_matrix = rp;
guppi_data_changed (GUPPI_DATA (obj));
}
break;
case ARG_MATRIX_A:
t = GTK_VALUE_DOUBLE (*arg);
if (func->a != t) {
func->a = t;
guppi_data_changed (GUPPI_DATA (obj));
}
break;
case ARG_MATRIX_B:
t = GTK_VALUE_DOUBLE (*arg);
if (func->b != t) {
func->b = t;
guppi_data_changed (GUPPI_DATA (obj));
}
break;
case ARG_MATRIX_C:
t = GTK_VALUE_DOUBLE (*arg);
if (func->c != t) {
func->c = t;
guppi_data_changed (GUPPI_DATA (obj));
}
break;
case ARG_MATRIX_D:
t = GTK_VALUE_DOUBLE (*arg);
if (func->d != t) {
func->d = t;
guppi_data_changed (GUPPI_DATA (obj));
}
break;
default:
break;
};
}
static void
guppi_curve_func_finalize (GtkObject *obj)
{
GuppiCurveFunc *func = GUPPI_CURVE_FUNC (obj);
guppi_unref0 (func->t_fn_wrapper);
guppi_unref0 (func->x_fn_wrapper);
guppi_unref0 (func->y_fn_wrapper);
guppi_unref0 (func->x_binary_fn_wrapper);
guppi_unref0 (func->y_binary_fn_wrapper);
guppi_unref0 (func->base_curve);
if (parent_class->finalize)
parent_class->finalize (obj);
}
/**************************************************************************/
static void
v_curve_bounds (GuppiCurve *curve, double *a, double *b)
{
GuppiCurveFunc *cfi = GUPPI_CURVE_FUNC (curve);
if (cfi->reparameterize) {
if (a)
*a = cfi->t0;
if (b)
*b = cfi->t1;
} else {
guppi_curve_parameter_bounds (cfi->base_curve, a, b);
}
}
static void
v_curve_get (GuppiCurve *curve, double t, double *x, double *y)
{
GuppiCurveFunc *cfi = GUPPI_CURVE_FUNC (curve);
double xx, yy;
if (cfi->reparameterize) {
if (cfi->t_fn_wrapper) {
t = guppi_fn_wrapper_eval_d__d (cfi->t_fn_wrapper, t);
t = guppi_curve_clamp_parameter (cfi->base_curve, t);
} else {
double a, b, u;
guppi_curve_parameter_bounds (cfi->base_curve, &a, &b);
u = (t - cfi->t0)/(cfi->t1 - cfi->t0);
t = a * u + b * (1-u);
}
}
guppi_curve_get (cfi->base_curve, t, &xx, &yy);
if (cfi->use_2x2_matrix) {
if (x) *x = cfi->a * xx + cfi->b * yy;
if (y) *y = cfi->c * xx + cfi->d * yy;
return;
}
if (x) {
if (cfi->x_binary_fn_wrapper)
*x = guppi_fn_wrapper_eval_d__d_d (cfi->x_binary_fn_wrapper, xx, yy);
else if (cfi->x_fn_wrapper)
*x = guppi_fn_wrapper_eval_d__d (cfi->x_fn_wrapper, xx);
else /* default is identity fn. */
*x = xx;
}
if (y) {
if (cfi->y_binary_fn_wrapper)
*y = guppi_fn_wrapper_eval_d__d_d (cfi->y_binary_fn_wrapper, xx, yy);
else if (cfi->y_fn_wrapper)
*y = guppi_fn_wrapper_eval_d__d (cfi->y_fn_wrapper, yy);
else /* default is identity fn. */
*y = yy;
}
}
/**************************************************************************/
#define add_arg(str, t, symb) \
gtk_object_add_arg_type("GuppiCurveFunc::" str, t, GTK_ARG_WRITABLE, symb)
static void
guppi_curve_func_class_init (GuppiCurveFuncClass *klass)
{
GtkObjectClass *object_class = (GtkObjectClass *) klass;
GuppiCurveClass *curve_class = GUPPI_CURVE_CLASS (klass);
GuppiDataClass *data_class = GUPPI_DATA_CLASS (klass);
parent_class = gtk_type_class (GUPPI_TYPE_CURVE);
object_class->get_arg = guppi_curve_func_get_arg;
object_class->set_arg = guppi_curve_func_set_arg;
object_class->finalize = guppi_curve_func_finalize;
data_class->is_leaf_type = TRUE;
curve_class->bounds = v_curve_bounds;
curve_class->get = v_curve_get;
add_arg ("curve", GTK_TYPE_POINTER, ARG_CURVE);
add_arg ("reparameterize", GTK_TYPE_BOOL, ARG_REPARAMETERIZE);
add_arg ("t0", GTK_TYPE_DOUBLE, ARG_T0);
add_arg ("t1", GTK_TYPE_DOUBLE, ARG_T1);
add_arg ("t_function", GTK_TYPE_POINTER, ARG_T_FUNC);
add_arg ("x_function", GTK_TYPE_POINTER, ARG_X_FUNC);
add_arg ("y_function", GTK_TYPE_POINTER, ARG_Y_FUNC);
add_arg ("x_binary_function", GTK_TYPE_POINTER, ARG_X_BINARY_FUNC);
add_arg ("y_binary_function", GTK_TYPE_POINTER, ARG_Y_BINARY_FUNC);
add_arg ("use_2x2_matrix", GTK_TYPE_BOOL, ARG_USE_2x2_MATRIX);
add_arg ("matrix_a", GTK_TYPE_DOUBLE, ARG_MATRIX_A);
add_arg ("matrix_b", GTK_TYPE_DOUBLE, ARG_MATRIX_B);
add_arg ("matrix_c", GTK_TYPE_DOUBLE, ARG_MATRIX_C);
add_arg ("matrix_d", GTK_TYPE_DOUBLE, ARG_MATRIX_D);
}
static void
guppi_curve_func_init (GuppiCurveFunc *obj)
{
obj->t0 = 0;
obj->t1 = 1;
}
GtkType guppi_curve_func_get_type (void)
{
static GtkType guppi_curve_func_type = 0;
if (!guppi_curve_func_type) {
static const GtkTypeInfo guppi_curve_func_info = {
"GuppiCurveFunc",
sizeof (GuppiCurveFunc),
sizeof (GuppiCurveFuncClass),
(GtkClassInitFunc) guppi_curve_func_class_init,
(GtkObjectInitFunc) guppi_curve_func_init,
NULL, NULL, (GtkClassInitFunc) NULL
};
guppi_curve_func_type =
gtk_type_unique (GUPPI_TYPE_CURVE, &guppi_curve_func_info);
}
return guppi_curve_func_type;
}
/**************************************************************************/
#if 0
GuppiData *
guppi_curve_new_reparameterize_linearly (double t0, double t1,
GuppiCurve *curve)
{
g_return_val_if_fail (curve && GUPPI_IS_CURVE (curve), NULL);
return guppi_data_new_by_type (GUPPI_TYPE_CURVE,
GUPPI_TYPE_CURVE_FUNC,
"curve", curve,
"t0", t0,
"t1", t1,
NULL);
}
GuppiData *
guppi_curve_new_reparameterize (double t0, double t1,
GuppiFnWrapper *t_fn,
GuppiCurve *curve)
{
g_return_val_if_fail (curve && GUPPI_IS_CURVE (curve), NULL);
g_return_val_if_fail (t_fn && GUPPI_IS_FN_WRAPPER (t_fn), NULL);
return guppi_data_new_by_type (GUPPI_TYPE_CURVE,
GUPPI_TYPE_CURVE_FUNC,
"curve", curve,
"t0", t0,
"t1", t1,
"t_function", t_fn,
NULL);
}
#endif
/* $Id: guppi-curve-func.c,v 1.1 2002/01/08 06:28:59 trow Exp $ */
syntax highlighted by Code2HTML, v. 0.9.1