Auto Scaling和Tick Interval Charting

时间:2015-06-29 13:53:49

标签: c# algorithm math charts

我有一个绘制数据的图表,但图表组件选择了比例和刻度间隔的模糊数字。我正在尝试定义一个简单的算法来做到这一点。图表将水平绘制,中间为0,两个条形图一个向左延伸,另一个向右延伸。例如,假设要绘制的值是-60和75.我会显示类似下面的内容(对粗糙道歉)

-80 -60 -40 -20 0 20 40 60 80

     <--------|--------->

所以我需要一种方法将最大数字四舍五入到最接近的10,100,1000等,以及一种决定时间间隔的方法。为了使0可见,滴答间隔必须分成舍入的数字而没有余数。

这是我到目前为止所拥有的。我知道这可能是一种更简单的数学“纯”方法。

        //Find the max number rounded
        double factor = 10d;

        if (maxValue >= 1000)
            factor = 1000d;
        else if (maxValue >= 100)
            factor = 100d;

        var roundedMax = Convert.ToInt32(Math.Floor((maxValue.GetValueOrDefault() + factor) / factor) * factor);

        if (roundedMax == 70 || roundedMax == 90)
            roundedMax += 10;
        else if (roundedMax == 700 || roundedMax == 900)
            roundedMax += 100;

        ViewModel.MaximumValue = roundedMax;
        ViewModel.MinimumValue = roundedMax * -1;

        //Work out the interval for tick marks
        int interval;
        var roundedMax = Convert.ToInt32(ViewModel.MaximumValue);

        if (roundedMax <= 10)
            interval = 2;
        else if (roundedMax <= 20)
            interval = 5;
        else if (roundedMax <= 50)
            interval = 10;
        else if (roundedMax < 100)
            interval = 20;
        else if (roundedMax == 100)
            interval = 25;
        else if (roundedMax <= 200)
            interval = 50;
        else if (roundedMax <= 500)
            interval = 100;
        else if (roundedMax < 1000)
            interval = 200;
        else if (roundedMax == 1000)
            interval = 250;
        else if (roundedMax <= 2000)
            interval = 500;
        else
            interval = 1000;

        ViewModel.TickInterval = interval;

1 个答案:

答案 0 :(得分:2)

(对C#一无所知),我认为一般方法可能如下。

首先,确定接近maxValue的10的力量。这可以通过基数为10的对数来完成,类似这样(伪代码)

logMax = floor(log10(maxValue))

将10增加回此功率以获得小于maxValue的最大功率10:

base = pow(10, logMax)

现在您要查找超出base的{​​{1}}的最小乘数:

maxValue

如果您想避免在示例中使用特定值(例如70或90),则可以对roundedMax = ceil(maxValue / base) * base 进行一些手动更正。

现在你已经舍入了最大值。您可以采用相同的方式舍入最小值,或者更好地分别计算roundedMax的最大值和最小值,并取最大值base,然后将两者相对于同一base

在此之后您可以指定刻度。您可以想到许多算法,其中大部分都需要一些手动编码。基本方法可能如下:假设您想要大约10个分数。因此,“理想的”刻度距离将是

base

现在,您可以使用相同的方法将idealTick = (roundedMax - roundedMin)/10 舍入到最接近的幂10:

idealTick

(我使用idealTick = pow10(ceil(log10(idealTick))) 确保它是&lt; = 10个刻度线),现在ceil是10的幂。

您现在可以对其进行微调,以实现2 * 10或10 * 10次幂:

idealTick

我希望这些想法很清楚。我没有测试代码,你可能想要对它进行更多的微调。