2015-06-29 94 views
0

我有一張繪製數據的圖表,但製圖組件爲刻度和刻度間隔選取了模糊的數字。我試圖定義一個簡單的算法來做到這一點。圖表將在中間水平顯示爲0,兩個顯示一個向左延伸,另一個向右延伸。例如可以說值繪製的-60和75我會顯示類似下面(道歉粗陋)Auto Scaling和Tick Interval Charting

-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

(不知道C#的任何事情),我認爲一般的做法可能如下。

首先,確定10的功率接近您的maxValue。這是可以做到以10爲底的對數,像這樣(僞)

logMax = floor(log10(maxValue)) 

籌集100回這個權力得到10的最大功率是小於maxValue

base = pow(10, logMax) 

現在,你想找到的base最小乘法超過您maxValue

roundedMax = ceil(maxValue/base) * base 

然後可以做一些手動校正如果你想在你的例子中避免特定的值,例如70或90。

現在您已經舍入了最大值。您可以以相同的方式舍入最小值,或者分別更好地計算最大值和最小值的base s,並取最大值base,然後對相同的base進行舍入。

在此之後,您可以分配滴答。你可以想到很多算法,其中大部分算法都需要一些手工編碼。基本方法可能如下:假設你想要大概10個分數。因此,「理想」剔距離會

idealTick = (roundedMax - roundedMin)/10 

現在你可以使用相同的方法idealTick四捨五入至10最近的電源:

idealTick = pow10(ceil(log10(idealTick))) 

(我拿ceil,以確保它是< = 10個蜱),現在是idealTick 10.

電源現在可以微調它,以允許2×功率的-10或5 *冪的十個步驟:

if (roundedMax-roundedMin)/idealTick <= 2 
    idealTick *= 5 
else if (roundedMax-roundedMin)/idealTick <= 5 
    idealTick *= 2 

我希望這些想法很明確。我沒有測試代碼,你可能想更好地調整它。

+1

謝謝彼得。我用了一個稍微不同的解決方案,但使用了許多這些想法。 – user630190