Я являюсь автором " Алгоритма оптимального масштабирования по оси диаграммы ".Раньше он размещался на trollop.org, но недавно я переместил домены / движки блогов.В любом случае, я опубликую здесь содержимое для более легкого доступа.
Я работал над приложением для создания графиков на Android для задания и столкнулся с небольшой проблемой, когда дело дошло до представления диаграммы в хорошем виде.масштабированный формат.Я потратил некоторое время, пытаясь создать этот алгоритм самостоятельно, и подошел очень близко, но в итоге я нашел пример псевдокода в книге Эндрю С. Гласснера под названием «Графика, самоцветы, том 1».Отличное описание проблемы дано в главе « Хорошие числа для меток графиков »:
При создании графа на компьютере желательно пометить x иОси Y с "хорошими" числами: простые десятичные числа.Например, если диапазон данных составляет от 105 до 543, мы, вероятно, хотели бы построить диапазон от 100 до 600 и поставить отметки каждые 100 единиц.Или, если диапазон данных от 2,04 до 2,16, мы, вероятно, построим диапазон от 2,00 до 2,20 с интервалом между тиками 0,05.Люди хороши в выборе таких «хороших» чисел, а упрощенные алгоритмы - нет.Наивный алгоритм выбора меток берет диапазон данных и делит его на n равных интервалов, но обычно это приводит к появлению уродливых меток.Здесь мы опишем простой метод создания хороших графовых меток.
Основное наблюдение состоит в том, что «самые хорошие» десятичные числа - это 1, 2 и 5, и все кратные этим числам степени десяти.Мы будем использовать только такие числа для интервала между тиками и ставить метки в кратные интервалы между тиками ...
Я использовал пример псевдокода в этой книге, чтобы создать следующий класс в Java:
public class NiceScale {
private double minPoint;
private double maxPoint;
private double maxTicks = 10;
private double tickSpacing;
private double range;
private double niceMin;
private double niceMax;
/**
* Instantiates a new instance of the NiceScale class.
*
* @param min the minimum data point on the axis
* @param max the maximum data point on the axis
*/
public NiceScale(double min, double max) {
this.minPoint = min;
this.maxPoint = max;
calculate();
}
/**
* Calculate and update values for tick spacing and nice
* minimum and maximum data points on the axis.
*/
private void calculate() {
this.range = niceNum(maxPoint - minPoint, false);
this.tickSpacing = niceNum(range / (maxTicks - 1), true);
this.niceMin =
Math.floor(minPoint / tickSpacing) * tickSpacing;
this.niceMax =
Math.ceil(maxPoint / tickSpacing) * tickSpacing;
}
/**
* Returns a "nice" number approximately equal to range Rounds
* the number if round = true Takes the ceiling if round = false.
*
* @param range the data range
* @param round whether to round the result
* @return a "nice" number to be used for the data range
*/
private double niceNum(double range, boolean round) {
double exponent; /** exponent of range */
double fraction; /** fractional part of range */
double niceFraction; /** nice, rounded fraction */
exponent = Math.floor(Math.log10(range));
fraction = range / Math.pow(10, exponent);
if (round) {
if (fraction < 1.5)
niceFraction = 1;
else if (fraction < 3)
niceFraction = 2;
else if (fraction < 7)
niceFraction = 5;
else
niceFraction = 10;
} else {
if (fraction <= 1)
niceFraction = 1;
else if (fraction <= 2)
niceFraction = 2;
else if (fraction <= 5)
niceFraction = 5;
else
niceFraction = 10;
}
return niceFraction * Math.pow(10, exponent);
}
/**
* Sets the minimum and maximum data points for the axis.
*
* @param minPoint the minimum data point on the axis
* @param maxPoint the maximum data point on the axis
*/
public void setMinMaxPoints(double minPoint, double maxPoint) {
this.minPoint = minPoint;
this.maxPoint = maxPoint;
calculate();
}
/**
* Sets maximum number of tick marks we're comfortable with
*
* @param maxTicks the maximum number of tick marks for the axis
*/
public void setMaxTicks(double maxTicks) {
this.maxTicks = maxTicks;
calculate();
}
}
Затем мы можем использовать вышеуказанный код следующим образом:
NiceScale numScale = new NiceScale(-0.085, 0.173);
System.out.println("Tick Spacing:\t" + numScale.getTickSpacing());
System.out.println("Nice Minimum:\t" + numScale.getNiceMin());
System.out.println("Nice Maximum:\t" + numScale.getNiceMax());
, который затем выведет красиво отформатированные числа для использования в любом приложении, для которого вам нужно создать красивоенапольные весы.= D
Tick Spacing: 0.05
Nice Minimum: -0.1
Nice Maximum: 0.2