⛏️ index : haiku.git

/*
 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */

#include "chart/DefaultChartAxisLegendSource.h"

#include <math.h>
#include <stdio.h>

#include "chart/ChartDataRange.h"
#include "chart/StringChartLegend.h"


int32
DefaultChartAxisLegendSource::GetAxisLegends(const ChartDataRange& range,
	ChartLegend** legends, double* values, int32 maxLegends)
{
// TODO: Also support scientific notation! Otherwise the numbers can get really
// long.
	double start = range.min;
	double end = range.max;
	double rangeSpan = end - start;

	if (rangeSpan >= maxLegends / 2) {
		// We only need to consider the integer part.

		// find an interval so that we get maxLegends / 2 to maxLegends legends
		double baseInterval = 1;
		double relativeFactor = 1;
		while (rangeSpan / baseInterval / relativeFactor >= maxLegends) {
			if (relativeFactor == 1) {
				relativeFactor = 2;
			} else if (relativeFactor == 2) {
				relativeFactor = 5;
			} else if (relativeFactor == 5) {
				baseInterval *= 10;
				relativeFactor = 1;
			}
		}

		// generate the legends
		int32 count = 0;
		double interval = baseInterval * relativeFactor;
		double value = ceil(start / interval) * interval;
		for (; value <= end; value += interval) {
			char buffer[128];
			snprintf(buffer, sizeof(buffer), "%.0f", value);
			StringChartLegend* legend
				= new(std::nothrow) StringChartLegend(buffer, 1);
			if (legend == NULL)
				return count;
	
			legends[count] = legend;
			values[count++] = value;
		}

		return count;
	}

	// The range is so small that we need a fraction interval.

	// First find out how many places after the decimal point we need.
	int positions = 0;
	double factor = 1;
	while (rangeSpan * factor < maxLegends / 2) {
		factor *= 10;
		positions++;
	}

	double relativeFactor = 1;
	if (rangeSpan * factor / relativeFactor >= maxLegends) {
		relativeFactor = 2;
		if (rangeSpan * factor / relativeFactor >= maxLegends)
			relativeFactor = 5;
	}

	// generate the legends
	int32 count = 0;
	double interval = relativeFactor / factor;
	double shiftedValue = ceil(start / interval);
	for (; shiftedValue * interval <= end; shiftedValue++) {
		double value = shiftedValue * interval;
		char buffer[128];
		snprintf(buffer, sizeof(buffer), "%.*f", positions, value);
		StringChartLegend* legend
			= new(std::nothrow) StringChartLegend(buffer, 1);
		if (legend == NULL)
			return count;

		legends[count] = legend;
		values[count++] = value;
	}

	return count;
}