summaryrefslogtreecommitdiff
path: root/src/CurveEditor.cxx
blob: c163812c81a66de0dbf2030eebdce7715ffcb8d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//
// Copyright 2008 Johannes Hofmann <Johannes.Hofmann@gmx.de>
//
// This software may be used and distributed according to the terms
// of the GNU General Public License, incorporated herein by reference.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <FL/Fl.H>
#include <FL/fl_draw.H>

#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) {

	marked_point = -1;

	n = 0;
	X = NULL;
	Y = NULL;

	acc = gsl_interp_accel_alloc ();
	spline = NULL;
}

void
CurveEditor::draw() {
	fl_color(FL_BLACK);
	fl_rectf(x(), y(), w(), h());

	fl_color(FL_WHITE);
	fl_begin_line();	
	for (double _x = 0.0; _x < 1.0; _x = _x + 0.01) {
		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(x() + w() * X[i] - 2, y() + h() - h() * Y[i] - 2, 4, 4);
	}
}


int
CurveEditor::handle(int event) {
	int	mark_x = Fl::event_x() - x();
	int	mark_y = Fl::event_y() - y();

	switch(event) {

		case FL_PUSH:    
			if (Fl::event_button() == 1) {
				for (int i = 0; i < n; i++) {
					int x_i = (int) rint(X[i] * w());
					int y_i = (int) rint(h() - Y[i] * h());

					if (mark_x >= x_i - 2 && mark_x <= x_i + 2 &&
						mark_y >= y_i - 2 && mark_y <= y_i + 2) {
						marked_point = i;
						redraw();
						break;
					}
				}
			}
			Fl::focus(this);
			return 1;
		case FL_DRAG:
			set_point(marked_point,  (double) mark_x / w(), 1.0 - (double) mark_y / h());

			return 1;
		case FL_RELEASE:
			marked_point = -1;
			printf("%g,%g", X[0], Y[0]);	
			for (int i = 1; i < n; i++) {
				printf(";%g,%g", X[i], Y[i]);	
			}
			printf("\n");
			fflush(stdout);
			return 1;
		case FL_FOCUS:
			return 1;
		case FL_UNFOCUS:
			return 0;
        }
	return 0;
}

void
CurveEditor::add_point(double _x, double _y) {
	if ((_x < 0.0 || _x > 1.0 || _y < 0.0 || _y > 1.0) ||
		n > 0 && _x <= X[n]) {
		return;
	}
	n++;
	X = (double*) realloc(X, n * sizeof(double));
	Y = (double*) realloc(Y, n * sizeof(double));

	X[n - 1] = _x;
	Y[n - 1] = _y;
}

void
CurveEditor::init() {
	if (spline) gsl_spline_free(spline);
	spline = gsl_spline_alloc (gsl_interp_cspline, n);
	gsl_spline_init (spline, X, Y, n);
}

void
CurveEditor::set_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();
}