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