From 7be4bae40736f364d65cfb56067203451da053a0 Mon Sep 17 00:00:00 2001 From: Johannes Hofmann Date: Sun, 7 Sep 2008 17:26:28 +0200 Subject: finish pnmcurvedit --- src/CurveEditor.cxx | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 src/CurveEditor.cxx (limited to 'src/CurveEditor.cxx') diff --git a/src/CurveEditor.cxx b/src/CurveEditor.cxx new file mode 100644 index 0000000..a0f4057 --- /dev/null +++ b/src/CurveEditor.cxx @@ -0,0 +1,185 @@ +// +// Copyright 2008 Johannes Hofmann +// +// This software may be used and distributed according to the terms +// of the GNU General Public License, incorporated herein by reference. + +#include +#include +#include +#include + +#include +#include + +#include "CurveEditor.H" + +CurveEditor::CurveEditor(int my_x, int my_y, int my_w, int my_h) : + Fl_Widget(my_x, my_y, my_w, my_h) { + + X = Y = NULL; + marked_point = -1; + cb = NULL; + cb_data = NULL; + n = 0; + acc = gsl_interp_accel_alloc(); + spline = NULL; +} + +void +CurveEditor::draw() { + double step = 1.0 / w() / 2; + + fl_color(FL_BLACK); + fl_rectf(x(), y(), w(), h()); + + fl_color(FL_GRAY); + fl_line_style(FL_DASH); + fl_xyline(x(), y() + h() / 2, x() + w()); + fl_yxline(x() + w() / 2, y(), y() + h()); + + if (n < 3) return; + + fl_push_clip(x(), y(), w(), h()); + fl_color(FL_WHITE); + fl_line_style(FL_SOLID); + fl_begin_line(); + for (double _x = 0.0; _x <= 1.0; _x = _x + step) { + double _y = gsl_spline_eval(spline, _x, acc); + + fl_vertex(x() + _x * w(), y() + h() - h() * _y); + } + fl_end_line(); + + for (int i = 0; i < n; i++) { + fl_rectf((int) rint(x() + w() * X[i] - 2), + (int) rint(y() + h() - h() * Y[i] - 2), 4, 4); + } + + fl_pop_clip(); +} + +int +CurveEditor::handle(int event) { + double mark_x = (double) (Fl::event_x() - x()) / w(); + double mark_y = 1.0 - (double) (Fl::event_y() - y()) / h(); + int i; + + switch (event) { + case FL_PUSH: + Fl::focus(this); + if (Fl::event_button() == 1) { + for (i = 0; i < n; i++) { + if (mark_x >= X[i] - 0.02 && mark_x <= X[i] + 0.02) { + marked_point = i; + move_point(i, mark_x, mark_y); + redraw(); + return 1; + } + } + + marked_point = add_point(mark_x, mark_y); + } + return 1; + case FL_DRAG: + if (marked_point < 0) return 1; + if (marked_point > 0 && mark_x <= X[marked_point - 1] || + marked_point < n - 1 && mark_x >= X[marked_point + 1]) { + remove_point(marked_point); + marked_point = -1; + } else { + move_point(marked_point, mark_x, mark_y); + } + return 1; + case FL_RELEASE: + if (marked_point >= 0) { + if (cb) cb(this, cb_data); + marked_point = -1; + } + return 1; + case FL_FOCUS: + return 1; + case FL_UNFOCUS: + return 0; + } + return 0; +} + +int +CurveEditor::add_point(double _x, double _y) { + int i; + + if (_x < 0.0 || _x > 1.0 || _y < 0.0 || _y > 1.0) { + return -1; + } + + X = (double*) realloc(X, (n + 1) * sizeof(double)); + Y = (double*) realloc(Y, (n + 1) * sizeof(double)); + + for (i = 0; i < n; i++) { + if (_x == X[i]) return -1; + if (_x < X[i]) { + memmove(&X[i + 1], &X[i], sizeof(double) * (n - i)); + memmove(&Y[i + 1], &Y[i], sizeof(double) * (n - i)); + break; + } + } + + X[i] = _x; + Y[i] = _y; + n++; + + init(); + + return i; +} + +void +CurveEditor::init() { + if (n < 3) return; + if (spline) gsl_spline_free(spline); + spline = gsl_spline_alloc(gsl_interp_cspline, n); + gsl_spline_init(spline, X, Y, n); + redraw(); +} + +void +CurveEditor::move_point(int i, double _x, double _y) { + if (i >= n || + (_x < 0.0 || _x > 1.0 || _y < 0.0 || _y > 1.0) || + (i < n - 1 && _x >= X[i + 1]) || + (i > 0 && _x <= X[i - 1])) { + return; + } + + X[i] = _x; + Y[i] = _y; + gsl_spline_init(spline, X, Y, n); + redraw(); +} + +void +CurveEditor::remove_point(int i) { + if (i < 0 || i >= n) return; + + memmove(&X[i], &X[i + 1], sizeof(double) * (n - i)); + memmove(&Y[i], &Y[i + 1], sizeof(double) * (n - i)); + n--; + init(); +} + +void +CurveEditor::get_point(int i, double *_x, double *_y) { + if (i < 0 || i >= n) return; + + *_x = X[i]; + *_y = Y[i]; +} + +void CurveEditor::clear() { + if (X) free(X); + if (Y) free(Y); + + X = Y = NULL; + n = 0; +} -- cgit v1.2.3