1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6 #include "chart/DefaultChartAxisLegendSource.h"
7
8 #include <math.h>
9 #include <stdio.h>
10
11 #include "chart/ChartDataRange.h"
12 #include "chart/StringChartLegend.h"
13
14
15 int32
GetAxisLegends(const ChartDataRange & range,ChartLegend ** legends,double * values,int32 maxLegends)16 DefaultChartAxisLegendSource::GetAxisLegends(const ChartDataRange& range,
17 ChartLegend** legends, double* values, int32 maxLegends)
18 {
19 // TODO: Also support scientific notation! Otherwise the numbers can get really
20 // long.
21 double start = range.min;
22 double end = range.max;
23 double rangeSpan = end - start;
24
25 if (rangeSpan >= maxLegends / 2) {
26 // We only need to consider the integer part.
27
28 // find an interval so that we get maxLegends / 2 to maxLegends legends
29 double baseInterval = 1;
30 double relativeFactor = 1;
31 while (rangeSpan / baseInterval / relativeFactor >= maxLegends) {
32 if (relativeFactor == 1) {
33 relativeFactor = 2;
34 } else if (relativeFactor == 2) {
35 relativeFactor = 5;
36 } else if (relativeFactor == 5) {
37 baseInterval *= 10;
38 relativeFactor = 1;
39 }
40 }
41
42 // generate the legends
43 int32 count = 0;
44 double interval = baseInterval * relativeFactor;
45 double value = ceil(start / interval) * interval;
46 for (; value <= end; value += interval) {
47 char buffer[128];
48 snprintf(buffer, sizeof(buffer), "%.0f", value);
49 StringChartLegend* legend
50 = new(std::nothrow) StringChartLegend(buffer, 1);
51 if (legend == NULL)
52 return count;
53
54 legends[count] = legend;
55 values[count++] = value;
56 }
57
58 return count;
59 }
60
61 // The range is so small that we need a fraction interval.
62
63 // First find out how many places after the decimal point we need.
64 int positions = 0;
65 double factor = 1;
66 while (rangeSpan * factor < maxLegends / 2) {
67 factor *= 10;
68 positions++;
69 }
70
71 double relativeFactor = 1;
72 if (rangeSpan * factor / relativeFactor >= maxLegends) {
73 relativeFactor = 2;
74 if (rangeSpan * factor / relativeFactor >= maxLegends)
75 relativeFactor = 5;
76 }
77
78 // generate the legends
79 int32 count = 0;
80 double interval = relativeFactor / factor;
81 double shiftedValue = ceil(start / interval);
82 for (; shiftedValue * interval <= end; shiftedValue++) {
83 double value = shiftedValue * interval;
84 char buffer[128];
85 snprintf(buffer, sizeof(buffer), "%.*f", positions, value);
86 StringChartLegend* legend
87 = new(std::nothrow) StringChartLegend(buffer, 1);
88 if (legend == NULL)
89 return count;
90
91 legends[count] = legend;
92 values[count++] = value;
93 }
94
95 return count;
96 }
97