CursorCrossings[] added.
This commit is contained in:
parent
22761fa04f
commit
dc18d83414
184
src/Chart.vala
184
src/Chart.vala
|
@ -55,6 +55,8 @@ namespace Gtk.CairoChart {
|
||||||
|
|
||||||
set_vertical_axes_titles ();
|
set_vertical_axes_titles ();
|
||||||
|
|
||||||
|
get_cursors_crossings();
|
||||||
|
|
||||||
calc_plot_area (); // Calculate plot area
|
calc_plot_area (); // Calculate plot area
|
||||||
|
|
||||||
draw_horizontal_axis ();
|
draw_horizontal_axis ();
|
||||||
|
@ -1276,78 +1278,31 @@ namespace Gtk.CairoChart {
|
||||||
|
|
||||||
public LineStyle cursor_line_style = LineStyle(Color(0.2, 0.2, 0.2, 0.8));
|
public LineStyle cursor_line_style = LineStyle(Color(0.2, 0.2, 0.2, 0.8));
|
||||||
|
|
||||||
protected virtual bool get_cursor_limits (Series s, Point cursor, out Point low, out Point high) {
|
protected struct CursorCross {
|
||||||
bool ret = false;
|
uint series_index;
|
||||||
low.x = plot_area_x_max;
|
Point point;
|
||||||
low.y = plot_area_y_max;
|
}
|
||||||
high.x = plot_area_x_min;
|
protected struct CursorCrossings {
|
||||||
high.y = plot_area_y_min;
|
uint cursor_index;
|
||||||
Point[] points = {};
|
CursorCross[] crossings;
|
||||||
switch (cursors_orientation) {
|
|
||||||
case CursorOrientation.VERTICAL:
|
|
||||||
points = sort_points (s, s.sort);
|
|
||||||
break;
|
|
||||||
case CursorOrientation.HORIZONTAL:
|
|
||||||
points = sort_points (s, s.sort);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (var i = 0; i + 1 < points.length; ++i) {
|
|
||||||
switch (cursors_orientation) {
|
|
||||||
case CursorOrientation.VERTICAL:
|
|
||||||
Float128 y = 0.0;
|
|
||||||
if (vcross(get_scr_point(s, points[i]), get_scr_point(s, points[i+1]), rel2scr_x(cursor.x),
|
|
||||||
plot_area_y_min, plot_area_y_max, out y)) {
|
|
||||||
if (y < low.y /*&& y_in_plot_area(y)*/) low.y = y;
|
|
||||||
if (y > high.y /*&& y_in_plot_area(y)*/) high.y = y;
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CursorOrientation.HORIZONTAL:
|
|
||||||
Float128 x = 0.0;
|
|
||||||
if (hcross(get_scr_point(s, points[i]), get_scr_point(s, points[i+1]),
|
|
||||||
plot_area_x_min, plot_area_x_max, rel2scr_y(cursor.y), out x)) {
|
|
||||||
if (x < low.x /*&& x_in_plot_area(x)*/) low.x = x;
|
|
||||||
if (x > high.x /*&& x_in_plot_area(x)*/) high.x = x;
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (common_x_axes) {
|
|
||||||
switch (s.axis_x.position) {
|
|
||||||
case Axis.Position.LOW: high.y = plot_area_y_max + s.axis_x.font_indent; break;
|
|
||||||
case Axis.Position.HIGH: low.y = plot_area_y_min - s.axis_x.font_indent; break;
|
|
||||||
case Axis.Position.BOTH:
|
|
||||||
high.y = plot_area_y_max + s.axis_x.font_indent;
|
|
||||||
low.y = plot_area_y_min - s.axis_x.font_indent;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
if (common_y_axes) {
|
|
||||||
switch (s.axis_y.position) {
|
|
||||||
case Axis.Position.LOW: low.x = plot_area_x_min - s.axis_y.font_indent; break;
|
|
||||||
case Axis.Position.HIGH: high.x = plot_area_x_max + s.axis_y.font_indent; break;
|
|
||||||
case Axis.Position.BOTH:
|
|
||||||
low.x = plot_area_x_min - s.axis_y.font_indent;
|
|
||||||
high.x = plot_area_x_max + s.axis_y.font_indent;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void draw_cursors () {
|
protected CursorCrossings[] cursors_crossings = {};
|
||||||
if (series.length == 0) return;
|
|
||||||
|
|
||||||
|
protected List<Point?> get_all_cursors () {
|
||||||
var all_cursors = cursors.copy_deep ((src) => { return src; });
|
var all_cursors = cursors.copy_deep ((src) => { return src; });
|
||||||
if (is_cursor_active)
|
if (is_cursor_active)
|
||||||
all_cursors.append(active_cursor);
|
all_cursors.append(active_cursor);
|
||||||
|
return all_cursors;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var c in all_cursors) {
|
protected void get_cursors_crossings () {
|
||||||
|
var all_cursors = get_all_cursors();
|
||||||
|
|
||||||
|
CursorCrossings[] local_cursor_crossings = {};
|
||||||
|
|
||||||
|
for (var ci = 0, max_ci = all_cursors.length(); ci < max_ci; ++ci) {
|
||||||
|
var c = all_cursors.nth_data(ci);
|
||||||
switch (cursors_orientation) {
|
switch (cursors_orientation) {
|
||||||
case CursorOrientation.VERTICAL:
|
case CursorOrientation.VERTICAL:
|
||||||
if (c.x <= _rel_zoom_x_min || c.x >= _rel_zoom_x_max) continue; break;
|
if (c.x <= _rel_zoom_x_min || c.x >= _rel_zoom_x_max) continue; break;
|
||||||
|
@ -1355,23 +1310,103 @@ namespace Gtk.CairoChart {
|
||||||
if (c.y <= _rel_zoom_y_min || c.y >= _rel_zoom_y_max) continue; break;
|
if (c.y <= _rel_zoom_y_min || c.y >= _rel_zoom_y_max) continue; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var low = Point(plot_area_x_max, plot_area_y_max); // low and high
|
CursorCross[] crossings = {};
|
||||||
var high = Point(plot_area_x_min, plot_area_y_min); // points of the cursor
|
for (var si = 0, max_si = series.length; si < max_si; ++si) {
|
||||||
foreach (var s in series) {
|
var s = series[si];
|
||||||
if (!s.zoom_show) continue;
|
if (!s.zoom_show) continue;
|
||||||
var l = Point(), h = Point();
|
|
||||||
if (get_cursor_limits (s, c, out l, out h)) {
|
Point[] points = {};
|
||||||
if (l.x < low.x) low.x = l.x;
|
switch (cursors_orientation) {
|
||||||
if (l.y < low.y) low.y = l.y;
|
case CursorOrientation.VERTICAL:
|
||||||
if (h.x > high.x) high.x = h.x;
|
points = sort_points (s, s.sort);
|
||||||
if (h.y > high.y) high.y = h.y;
|
break;
|
||||||
|
case CursorOrientation.HORIZONTAL:
|
||||||
|
points = sort_points (s, s.sort);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i + 1 < points.length; ++i) {
|
||||||
|
switch (cursors_orientation) {
|
||||||
|
case CursorOrientation.VERTICAL:
|
||||||
|
Float128 y = 0.0;
|
||||||
|
if (vcross(get_scr_point(s, points[i]), get_scr_point(s, points[i+1]), rel2scr_x(c.x),
|
||||||
|
plot_area_y_min, plot_area_y_max, out y)) {
|
||||||
|
CursorCross cc = {si, Point(get_real_x(s, rel2scr_x(c.x)), get_real_y(s, y))};
|
||||||
|
crossings += cc;
|
||||||
|
//stdout.printf("si = %d, rel2scr_x(c.x) = %f, y = %f\n", si, rel2scr_x(c.x), y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CursorOrientation.HORIZONTAL:
|
||||||
|
Float128 x = 0.0;
|
||||||
|
if (hcross(get_scr_point(s, points[i]), get_scr_point(s, points[i+1]),
|
||||||
|
plot_area_x_min, plot_area_x_max, rel2scr_y(c.y), out x)) {
|
||||||
|
CursorCross cc = {si, Point(get_real_x(s, x), get_real_y(s, rel2scr_y(c.y)))};
|
||||||
|
crossings += cc;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (crossings.length != 0) {
|
||||||
|
CursorCrossings ccs = {ci, crossings};
|
||||||
|
local_cursor_crossings += ccs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursors_crossings = local_cursor_crossings;
|
||||||
|
//if (cursors_crossings.length != 0)
|
||||||
|
//stdout.printf("cursors_crossings[0].crossings.length = %d\n", cursors_crossings[0].crossings.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void draw_cursors () {
|
||||||
|
if (series.length == 0) return;
|
||||||
|
|
||||||
|
var all_cursors = get_all_cursors();
|
||||||
|
|
||||||
|
for (var cci = 0, max_cci = cursors_crossings.length; cci < max_cci; ++cci) {
|
||||||
|
var low = Point(plot_area_x_max, plot_area_y_max); // low and high
|
||||||
|
var high = Point(plot_area_x_min, plot_area_y_min); // points of the cursor
|
||||||
|
var ccs = cursors_crossings[cci].crossings;
|
||||||
|
for (var ci = 0, max_ci = ccs.length; ci < max_ci; ++ci) {
|
||||||
|
var si = ccs[ci].series_index;
|
||||||
|
var s = series[si];
|
||||||
|
var p = ccs[ci].point;
|
||||||
|
var scrx = get_scr_x(s, p.x);
|
||||||
|
var scry = get_scr_y(s, p.y);
|
||||||
|
if (scrx < low.x) low.x = scrx;
|
||||||
|
//stdout.printf("low.y = %f, high.y = %f\n", low.y, high.y);
|
||||||
|
if (scry < low.y) low.y = scry;
|
||||||
|
if (scrx > high.x) high.x = scrx;
|
||||||
|
if (scry > high.y) high.y = scry;
|
||||||
|
|
||||||
|
if (common_x_axes) {
|
||||||
|
switch (s.axis_x.position) {
|
||||||
|
case Axis.Position.LOW: high.y = plot_area_y_max + s.axis_x.font_indent; break;
|
||||||
|
case Axis.Position.HIGH: low.y = plot_area_y_min - s.axis_x.font_indent; break;
|
||||||
|
case Axis.Position.BOTH:
|
||||||
|
high.y = plot_area_y_max + s.axis_x.font_indent;
|
||||||
|
low.y = plot_area_y_min - s.axis_x.font_indent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (common_y_axes) {
|
||||||
|
switch (s.axis_y.position) {
|
||||||
|
case Axis.Position.LOW: low.x = plot_area_x_min - s.axis_y.font_indent; break;
|
||||||
|
case Axis.Position.HIGH: high.x = plot_area_x_max + s.axis_y.font_indent; break;
|
||||||
|
case Axis.Position.BOTH:
|
||||||
|
low.x = plot_area_x_min - s.axis_y.font_indent;
|
||||||
|
high.x = plot_area_x_max + s.axis_y.font_indent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var c = all_cursors.nth_data(cursors_crossings[cci].cursor_index);
|
||||||
|
|
||||||
switch (cursors_orientation) {
|
switch (cursors_orientation) {
|
||||||
case CursorOrientation.VERTICAL:
|
case CursorOrientation.VERTICAL:
|
||||||
if (low.y > high.y) continue;
|
if (low.y > high.y) continue;
|
||||||
set_line_style(cursor_line_style);
|
set_line_style(cursor_line_style);
|
||||||
|
//stdout.printf("rel2scr_x(c.x) = %f, low.y = %f\n", rel2scr_x(c.x), low.y);
|
||||||
context.move_to (rel2scr_x(c.x), low.y);
|
context.move_to (rel2scr_x(c.x), low.y);
|
||||||
context.line_to (rel2scr_x(c.x), high.y);
|
context.line_to (rel2scr_x(c.x), high.y);
|
||||||
context.stroke();
|
context.stroke();
|
||||||
|
@ -1419,6 +1454,7 @@ namespace Gtk.CairoChart {
|
||||||
chart.cursor_line_style = this.cursor_line_style;
|
chart.cursor_line_style = this.cursor_line_style;
|
||||||
chart.cursor_max_rm_distance = this.cursor_max_rm_distance;
|
chart.cursor_max_rm_distance = this.cursor_max_rm_distance;
|
||||||
chart.cursors = this.cursors.copy();
|
chart.cursors = this.cursors.copy();
|
||||||
|
chart.cursors_crossings = this.cursors_crossings.copy(); // no deep copying for .crossings
|
||||||
chart.cursors_orientation = this.cursors_orientation;
|
chart.cursors_orientation = this.cursors_orientation;
|
||||||
chart.height = this.height;
|
chart.height = this.height;
|
||||||
chart.is_cursor_active = this.is_cursor_active;
|
chart.is_cursor_active = this.is_cursor_active;
|
||||||
|
|
Loading…
Reference in New Issue