From d44f4c4cc63843b72ea06d65ccdaecb2f4c89657 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 6 Sep 2012 12:45:34 +0200 Subject: [PATCH] iowatcher: Improve xticks logic Ticks on x axis used integral step and fixed number of ticks. That generates wrong results e.g. for 13s long trace with 10 ticks... Allow the code to somewhat alter the number of ticks and also use non-integral step. Signed-off-by: Jan Kara Signed-off-by: Chris Mason --- iowatcher/plot.c | 60 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/iowatcher/plot.c b/iowatcher/plot.c index c19da54..d3505e8 100644 --- a/iowatcher/plot.c +++ b/iowatcher/plot.c @@ -455,14 +455,34 @@ void set_plot_title(struct plot *plot, char *title) write(fd, line, len); } +#define TICK_MINI_STEPS 3 + +static double find_step(double first, double last, int num_ticks) +{ + int mini_step[TICK_MINI_STEPS] = { 1, 2, 5 }; + int cur_mini_step = 0; + double step = (last - first) / num_ticks; + double log10 = log(10); + + /* Round to power of 10 */ + step = exp(floor(log(step) / log10) * log10); + /* Scale down step to provide enough ticks */ + while ((last - first) / (step * mini_step[cur_mini_step]) > num_ticks + && cur_mini_step < TICK_MINI_STEPS) + cur_mini_step++; + step *= mini_step[cur_mini_step - 1]; + + return step; +} + /* * create evenly spread out ticks along the xaxis. if tick only is set * this just makes the ticks, otherwise it labels each tick as it goes */ void set_xticks(struct plot *plot, int num_ticks, int first, int last) { - int pixels_per_tick = graph_width / num_ticks; - int step = (last - first) / num_ticks; + int pixels_per_tick; + double step; int i; int tick_y = axis_y_off(graph_tick_len) + graph_inner_y_margin; int tick_x = axis_x(); @@ -473,6 +493,14 @@ void set_xticks(struct plot *plot, int num_ticks, int first, int last) char *middle = "middle"; char *start = "start"; + step = find_step(first, last, num_ticks); + /* + * We don't want last two ticks to be too close together so subtract + * 20% of the step from the interval + */ + num_ticks = (double)(last - first - step / 5) / step + 1; + pixels_per_tick = graph_width * step / (double)(last - first); + for (i = 0; i < num_ticks; i++) { char *anchor; if (i != 0) { @@ -485,20 +513,32 @@ void set_xticks(struct plot *plot, int num_ticks, int first, int last) } if (!tick_only) { - snprintf(line, line_len, "%d\n", - tick_x, text_y, font_family, tick_font_size, anchor, - first + step * i); + if (step >= 1) + snprintf(line, line_len, "%d\n", + tick_x, text_y, font_family, tick_font_size, anchor, + (int)(first + step * i)); + else + snprintf(line, line_len, "%.2f\n", + tick_x, text_y, font_family, tick_font_size, anchor, + first + step * i); write(plot->fd, line, strlen(line)); } tick_x += pixels_per_tick; } if (!tick_only) { - snprintf(line, line_len, "%d\n", - axis_x_off(graph_width - 2), - text_y, font_family, tick_font_size, last); + if (step >= 1) + snprintf(line, line_len, "%d\n", + axis_x_off(graph_width - 2), + text_y, font_family, tick_font_size, last); + else + snprintf(line, line_len, "%.2f\n", + axis_x_off(graph_width - 2), + text_y, font_family, tick_font_size, (double)last); write(plot->fd, line, strlen(line)); } } -- 2.25.1