xref: /haiku/src/apps/debuganalyzer/gui/chart/DefaultChartAxisLegendSource.cpp (revision c90684742e7361651849be4116d0e5de3a817194)
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
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