aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2012-09-06 12:45:34 +0200
committerChris Mason <chris.mason@oracle.com>2012-09-10 20:53:05 -0400
commit1b6d49249326660812f205a0259dbc98b2abd922 (patch)
treee51439e9747cb78778ecae522bed7aead86fd747
parent4a8f23a608e0dde4061dacb3818653f0a2cbf0b4 (diff)
downloadiowatcher-1b6d49249326660812f205a0259dbc98b2abd922.tar.gz
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 <jack@suse.cz> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
-rw-r--r--plot.c60
1 files changed, 50 insertions, 10 deletions
diff --git a/plot.c b/plot.c
index c19da54..d3505e8 100644
--- a/plot.c
+++ b/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, "<text x=\"%d\" y=\"%d\" font-family=\"%s\" font-size=\"%d\" "
- "fill=\"black\" style=\"text-anchor: %s\">%d</text>\n",
- tick_x, text_y, font_family, tick_font_size, anchor,
- first + step * i);
+ if (step >= 1)
+ snprintf(line, line_len, "<text x=\"%d\" y=\"%d\" font-family=\"%s\" font-size=\"%d\" "
+ "fill=\"black\" style=\"text-anchor: %s\">%d</text>\n",
+ tick_x, text_y, font_family, tick_font_size, anchor,
+ (int)(first + step * i));
+ else
+ snprintf(line, line_len, "<text x=\"%d\" y=\"%d\" font-family=\"%s\" font-size=\"%d\" "
+ "fill=\"black\" style=\"text-anchor: %s\">%.2f</text>\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, "<text x=\"%d\" y=\"%d\" font-family=\"%s\" font-size=\"%d\" "
- "fill=\"black\" style=\"text-anchor: middle\">%d</text>\n",
- axis_x_off(graph_width - 2),
- text_y, font_family, tick_font_size, last);
+ if (step >= 1)
+ snprintf(line, line_len, "<text x=\"%d\" y=\"%d\" font-family=\"%s\" font-size=\"%d\" "
+ "fill=\"black\" style=\"text-anchor: middle\">%d</text>\n",
+ axis_x_off(graph_width - 2),
+ text_y, font_family, tick_font_size, last);
+ else
+ snprintf(line, line_len, "<text x=\"%d\" y=\"%d\" font-family=\"%s\" font-size=\"%d\" "
+ "fill=\"black\" style=\"text-anchor: middle\">%.2f</text>\n",
+ axis_x_off(graph_width - 2),
+ text_y, font_family, tick_font_size, (double)last);
write(plot->fd, line, strlen(line));
}
}