it-swarm.com.de

Auswählen einer attraktiven linearen Skala für die Y-Achse eines Diagramms

Ich schreibe ein bisschen Code, um ein Balken- (oder Linien-) Diagramm in unserer Software anzuzeigen. Alles läuft gut. Was mich stumm macht, ist das Beschriften der Y-Achse.

Der Anrufer kann mir sagen, wie genau er die Y-Skala beschriften möchte, aber ich scheine genau darauf zu achten, was er "attraktiv" beschriftet. Ich kann "attraktiv" nicht beschreiben, und wahrscheinlich auch Sie nicht, aber wir wissen es, wenn wir es sehen, richtig?

Wenn also die Datenpunkte sind:

   15, 234, 140, 65, 90

Und der Benutzer fragt nach 10 Etiketten auf der Y-Achse, ein wenig mit Papier und Bleistift zu feilen, und das kommt mit:

  0, 25, 50, 75, 100, 125, 150, 175, 200, 225, 250

Es gibt also 10 (nicht einschließlich 0), der letzte Wert liegt knapp über dem höchsten Wert (234 <250) und ist ein "Nizza" -Schritt von jeweils 25. Wenn sie nach 8 Etiketten gefragt hätten, hätte eine Erhöhung von 30 Nizza ausgesehen:

  0, 30, 60, 90, 120, 150, 180, 210, 240

Neun wären schwierig gewesen. Vielleicht habe ich einfach entweder 8 oder 10 benutzt und nenne es nah genug wäre okay. Und was tun, wenn einige Punkte negativ sind?

Ich kann sehen, dass Excel dieses Problem gut anpackt. 

Kennt jemand einen Allzweck-Algorithmus (auch etwas rohe Gewalt ist okay), um dieses Problem zu lösen? Ich muss es nicht schnell machen, aber es sollte schön aussehen.

66
Clinton Pierce

Vor langer Zeit habe ich ein Graph-Modul geschrieben, das dies gut abdeckt. Beim Graben in der grauen Masse erhält man Folgendes:

  • Bestimmen Sie die Unter- und Obergrenze der Daten. (Hüten Sie sich vor dem Sonderfall, bei dem Untergrenze = Obergrenze!
  • Bereich in die erforderliche Anzahl von Zecken teilen.
  • Runden Sie den Tick-Bereich in Nizza-Beträge ab.
  • Passen Sie die untere und obere Grenze entsprechend an.

Nehmen wir Ihr Beispiel:

15, 234, 140, 65, 90 with 10 ticks
  1. untergrenze = 15
  2. obere Grenze = 234
  3. bereich = 234-15 = 219
  4. tick-Bereich = 21,9. Dies sollte 25,0 sein
  5. neue untere Grenze = 25 * Runde (15/25) = 0
  6. neue obere Grenze = 25 * Runde (1 + 235/25) = 250

Also der Bereich = 0,25,50, ..., 225,250

Sie können den Nice-Tick-Bereich mit den folgenden Schritten erhalten:

  1. durch 10 ^ x teilen, so dass das Ergebnis zwischen 0,1 und 1,0 liegt (einschließlich 0,1 ohne 1).
  2. entsprechend übersetzen:
    • 0,1 → 0,1
    • <= 0,2 -> 0,2
    • <= 0,25 -> 0,25
    • <= 0,3 -> 0,3
    • <= 0,4 -> 0,4
    • <= 0,5 -> 0,5
    • <= 0,6 -> 0,6
    • <= 0,7 -> 0,7
    • <= 0,75 -> 0,75
    • <= 0,8 -> 0,8
    • <= 0,9 -> 0,9
    • <= 1,0 -> 1,0
  3. multiplizieren Sie mit 10 ^ x. 

In diesem Fall wird 21,9 durch 10 ^ 2 geteilt, um 0,219 zu erhalten. Das ist <= 0,25, also haben wir jetzt 0,25. Multipliziert mit 10 ^ 2 ergibt dies 25.

Schauen wir uns das gleiche Beispiel mit 8 Ticks an:

15, 234, 140, 65, 90 with 8 ticks
  1. untergrenze = 15
  2. obere Grenze = 234
  3. bereich = 234-15 = 219
  4. tick-Bereich = 27.375
    1. Division durch 10 ^ 2 für 0,27375, übersetzt auf 0,3, was (multipliziert mit 10 ^ 2) 30 ergibt.
  5. neue untere Grenze = 30 * Runde (15/30) = 0
  6. neue obere Grenze = 30 * Runde (1 + 235/30) = 240

Welche geben das angeforderte Ergebnis ;-).

------ Hinzugefügt von KD ------

Hier ist der Code, der diesen Algorithmus ohne Verwendung von Nachschlagetabellen usw. erreicht ...:

double range = ...;
int tickCount = ...;
double unroundedTickSize = range/(tickCount-1);
double x = Math.ceil(Math.log10(unroundedTickSize)-1);
double pow10x = Math.pow(10, x);
double roundedTickRange = Math.ceil(unroundedTickSize / pow10x) * pow10x;
return roundedTickRange;

Im Allgemeinen umfasst die Anzahl der Teilstriche den unteren Teilstrich, so dass die tatsächlichen Segmente der y-Achse um eins kleiner sind als die Anzahl der Teilstriche.

90
Toon Krijthe

Hier ist ein PHP Beispiel, das ich verwende. Diese Funktion gibt ein Array von hübschen Y-Achsenwerten zurück, die die übergebenen min- und max-Y-Werte umfassen. Natürlich kann diese Routine auch für X-Achsenwerte verwendet werden.

Sie können "vorschlagen", wie viele Ticks Sie möchten, aber die Routine kehrt zurück. Was gut aussieht. Ich habe einige Beispieldaten hinzugefügt und die Ergebnisse für diese gezeigt.

#!/usr/bin/php -q
<?php

function makeYaxis($yMin, $yMax, $ticks = 10)
{
  // This routine creates the Y axis values for a graph.
  //
  // Calculate Min AMD Max graphical labels and graph
  // increments.  The number of ticks defaults to
  // 10 which is the SUGGESTED value.  Any tick value
  // entered is used as a suggested value which is
  // adjusted to be a 'pretty' value.
  //
  // Output will be an array of the Y axis values that
  // encompass the Y values.
  $result = array();
  // If yMin and yMax are identical, then
  // adjust the yMin and yMax values to actually
  // make a graph. Also avoids division by zero errors.
  if($yMin == $yMax)
  {
    $yMin = $yMin - 10;   // some small value
    $yMax = $yMax + 10;   // some small value
  }
  // Determine Range
  $range = $yMax - $yMin;
  // Adjust ticks if needed
  if($ticks < 2)
    $ticks = 2;
  else if($ticks > 2)
    $ticks -= 2;
  // Get raw step value
  $tempStep = $range/$ticks;
  // Calculate pretty step value
  $mag = floor(log10($tempStep));
  $magPow = pow(10,$mag);
  $magMsd = (int)($tempStep/$magPow + 0.5);
  $stepSize = $magMsd*$magPow;

  // build Y label array.
  // Lower and upper bounds calculations
  $lb = $stepSize * floor($yMin/$stepSize);
  $ub = $stepSize * ceil(($yMax/$stepSize));
  // Build array
  $val = $lb;
  while(1)
  {
    $result[] = $val;
    $val += $stepSize;
    if($val > $ub)
      break;
  }
  return $result;
}

// Create some sample data for demonstration purposes
$yMin = 60;
$yMax = 330;
$scale =  makeYaxis($yMin, $yMax);
print_r($scale);

$scale = makeYaxis($yMin, $yMax,5);
print_r($scale);

$yMin = 60847326;
$yMax = 73425330;
$scale =  makeYaxis($yMin, $yMax);
print_r($scale);
?>

Ergebnisausgabe aus Probendaten

# ./test1.php
Array
(
    [0] => 60
    [1] => 90
    [2] => 120
    [3] => 150
    [4] => 180
    [5] => 210
    [6] => 240
    [7] => 270
    [8] => 300
    [9] => 330
)

Array
(
    [0] => 0
    [1] => 90
    [2] => 180
    [3] => 270
    [4] => 360
)

Array
(
    [0] => 60000000
    [1] => 62000000
    [2] => 64000000
    [3] => 66000000
    [4] => 68000000
    [5] => 70000000
    [6] => 72000000
    [7] => 74000000
)
19
Scott Guthrie

Versuchen Sie diesen Code. Ich habe es in einigen Diagrammszenarien verwendet und es funktioniert gut. Es ist auch ziemlich schnell.

public static class AxisUtil
{
    public static float CalculateStepSize(float range, float targetSteps)
    {
        // calculate an initial guess at step size
        float tempStep = range/targetSteps;

        // get the magnitude of the step size
        float mag = (float)Math.Floor(Math.Log10(tempStep));
        float magPow = (float)Math.Pow(10, mag);

        // calculate most significant digit of the new step size
        float magMsd = (int)(tempStep/magPow + 0.5);

        // promote the MSD to either 1, 2, or 5
        if (magMsd > 5.0)
            magMsd = 10.0f;
        else if (magMsd > 2.0)
            magMsd = 5.0f;
        else if (magMsd > 1.0)
            magMsd = 2.0f;

        return magMsd*magPow;
    }
}
8
Drew Noakes

Klingt so, als würde der Anrufer Ihnen nicht die gewünschten Bereiche mitteilen.

Sie können also die Endpunkte so lange ändern, bis sie durch die Anzahl der Labels gut teilbar sind.

Definieren wir "Nizza". Ich würde Nice anrufen, wenn die Etiketten ausgeschaltet sind:

1. 2^n, for some integer n. eg. ..., .25, .5, 1, 2, 4, 8, 16, ...
2. 10^n, for some integer n. eg. ..., .01, .1, 1, 10, 100
3. n/5 == 0, for some positive integer n, eg, 5, 10, 15, 20, 25, ...
4. n/2 == 0, for some positive integer n, eg, 2, 4, 6, 8, 10, 12, 14, ...

Finden Sie das Maximum und Min Ihrer Datenreihe. Nennen wir diese Punkte:

min_point and max_point.

Jetzt müssen Sie nur noch 3 Werte finden:

- start_label, where start_label < min_point and start_label is an integer
- end_label, where end_label > max_point and end_label is an integer
- label_offset, where label_offset is "Nice"

das passt die Gleichung:

(end_label - start_label)/label_offset == label_count

Es gibt wahrscheinlich viele Lösungen, also wählen Sie einfach eine. Meistens wette ich, dass Sie setzen können 

start_label to 0

probieren Sie also einfach eine andere Ganzzahl aus

end_label

bis der Offset "Nizza" ist

6
Pyrolistical

Ich kämpfe immer noch damit :)

Die ursprüngliche Gamecat-Antwort scheint die meiste Zeit zu funktionieren, aber versuchen Sie es mit "3 Ticks" als Anzahl der erforderlichen Ticks (für die gleichen Datenwerte 15, 234, 140, 65, 90) scheint einen Tick-Bereich von 73 zu ergeben, der nach Division durch 10 ^ 2 0,73 ergibt, was 0,75 entspricht, was einen 'Nice'-Tick-Bereich von 75 ergibt. 

Berechnen Sie dann die obere Grenze: 75 * Runde (1 + 234/75) = 300

und die untere Grenze: 75 * round (15/75) = 0

Wenn Sie jedoch bei 0 beginnen und in Schritten von 75 bis zur oberen Grenze von 300 vorgehen, erhalten Sie am Ende die Zahl 0,75,150,225,300 ) nicht die 3 erforderlichen Ticks.

Nur frustrierend, dass es nicht 100% der Zeit funktioniert ... was natürlich an meinem Fehler liegen könnte, natürlich irgendwo!

3
StillPondering

Die Antwort von Toon Krijthe funktioniert meistens. Manchmal werden jedoch zu viele Ticks erzeugt. Es funktioniert auch nicht mit negativen Zahlen. Die allgemeine Herangehensweise an das Problem ist in Ordnung, aber es gibt einen besseren Weg, um damit umzugehen. Der Algorithmus, den Sie verwenden möchten, hängt davon ab, was Sie wirklich wollen. Im Folgenden stelle ich Ihnen meinen Code vor, den ich in meiner JS-Ploting-Bibliothek verwendet habe. Ich habe es getestet und es funktioniert immer (hoffentlich;)). Hier sind die wichtigsten Schritte:

  • globale Extremas xMin und xMax erhalten (alle Diagramme, die Sie im Algorithmus drucken möchten)
  • berechnen Sie den Bereich zwischen xMin und xMax 
  • berechnen Sie die Größenordnung Ihres Bereichs
  • berechnen Sie die Tickgröße, indem Sie den Bereich durch die Anzahl der Ticks minus eins dividieren
  • dieser ist optional. Wenn Sie immer einen Nullstrich drucken möchten, verwenden Sie die Tickgröße, um die Anzahl der positiven und negativen Ticks zu berechnen. Gesamtanzahl der Ticks ist ihre Summe + 1 (der Null-Tick)
  • dieses ist nicht erforderlich, wenn Sie immer einen Nullstrich haben. Berechnen Sie die untere und obere Grenze, denken Sie jedoch daran, die Darstellung zu zentrieren

Lasst uns beginnen. Zuerst die grundlegenden Berechnungen

    var range = Math.abs(xMax - xMin); //both can be negative
    var rangeOrder = Math.floor(Math.log10(range)) - 1; 
    var power10 = Math.pow(10, rangeOrder);
    var maxRound = (xMax > 0) ? Math.ceil(xMax / power10) : Math.floor(xMax / power10);
    var minRound = (xMin < 0) ? Math.floor(xMin / power10) : Math.ceil(xMin / power10);

Ich runde Mindest- und Höchstwerte auf, um 100% sicher zu sein, dass mein Plot alle Daten abdeckt. Es ist auch sehr wichtig, den Bereich log10 des Bereichs zu bestimmen, ob er negativ ist oder nicht, und 1 später abziehen. Andernfalls funktioniert Ihr Algorithmus nicht für Zahlen, die kleiner als eins sind.

    var fullRange = Math.abs(maxRound - minRound);
    var tickSize = Math.ceil(fullRange / (this.XTickCount - 1));

    //You can set Nice looking ticks if you want
    //You can find exemplary method below 
    tickSize = this.NiceLookingTick(tickSize);

    //Here you can write a method to determine if you need zero tick
    //You can find exemplary method below
    var isZeroNeeded = this.HasZeroTick(maxRound, minRound, tickSize);

Ich verwende "schön aussehende Zecken", um Zecken wie 7, 13, 17 usw. zu vermeiden. Die hier verwendete Methode ist ziemlich einfach. Es ist auch schön, bei Bedarf ZeroTick zu haben. Plot sieht auf diese Weise viel professioneller aus. Am Ende dieser Antwort finden Sie alle Methoden. 

Jetzt müssen Sie die Ober- und Untergrenze berechnen. Mit einem Null-Tick ist dies sehr einfach, in anderen Fällen ist jedoch etwas mehr Aufwand erforderlich. Warum? Weil wir die Handlung innerhalb der oberen und unteren Grenze schön zentrieren wollen. Schau dir meinen Code an. Einige der Variablen sind außerhalb dieses Bereichs definiert, und einige von ihnen sind Eigenschaften eines Objekts, in dem der gesamte präsentierte Code gespeichert wird. 

    if (isZeroNeeded) {

        var positiveTicksCount = 0;
        var negativeTickCount = 0;

        if (maxRound != 0) {

            positiveTicksCount = Math.ceil(maxRound / tickSize);
            XUpperBound = tickSize * positiveTicksCount * power10;
        }

        if (minRound != 0) {
            negativeTickCount = Math.floor(minRound / tickSize);
            XLowerBound = tickSize * negativeTickCount * power10;
        }

        XTickRange = tickSize * power10;
        this.XTickCount = positiveTicksCount - negativeTickCount + 1;
    }
    else {
        var delta = (tickSize * (this.XTickCount - 1) - fullRange) / 2.0;

        if (delta % 1 == 0) {
            XUpperBound = maxRound + delta;
            XLowerBound = minRound - delta;
        }
        else {
            XUpperBound =  maxRound + Math.ceil(delta);
            XLowerBound =  minRound - Math.floor(delta);
        }

        XTickRange = tickSize * power10;
        XUpperBound = XUpperBound * power10;
        XLowerBound = XLowerBound * power10;
    }

Und hier sind Methoden, die ich zuvor erwähnt habe, die Sie selbst schreiben können, aber Sie können auch meine verwenden

this.NiceLookingTick = function (tickSize) {

    var NiceArray = [1, 2, 2.5, 3, 4, 5, 10];

    var tickOrder = Math.floor(Math.log10(tickSize));
    var power10 = Math.pow(10, tickOrder);
    tickSize = tickSize / power10;

    var niceTick;
    var minDistance = 10;
    var index = 0;

    for (var i = 0; i < NiceArray.length; i++) {
        var dist = Math.abs(NiceArray[i] - tickSize);
        if (dist < minDistance) {
            minDistance = dist;
            index = i;
        }
    }

    return NiceArray[index] * power10;
}

this.HasZeroTick = function (maxRound, minRound, tickSize) {

    if (maxRound * minRound < 0)
    {
        return true;
    }
    else if (Math.abs(maxRound) < tickSize || Math.round(minRound) < tickSize) {

        return true;
    }
    else {

        return false;
    }
}

Es gibt nur noch eine Sache, die hier nicht enthalten ist. Dies ist die "schön aussehende Grenze". Hierbei handelt es sich um Untergrenzen, die Zahlen ähneln, die den Zahlen in "Schön aussehende Ticks" entsprechen. Zum Beispiel ist es besser, die untere Grenze beginnend bei 5 mit der Tickgröße 5 zu haben, als eine Grafik, die bei 6 mit der gleichen Tickgröße beginnt. Aber dies ist meine Entlassung. Ich überlasse es Ihnen.

Ich hoffe es hilft. Prost!

3
Arthur

dies funktioniert wie ein Zauber, wenn Sie 10 Schritte + Null wollen

//get proper scale for y
$maximoyi_temp= max($institucion); //get max value from data array
 for ($i=10; $i< $maximoyi_temp; $i=($i*10)) {   
    if (($divisor = ($maximoyi_temp / $i)) < 2) break; //get which divisor will give a number between 1-2    
 } 
 $factor_d = $maximoyi_temp / $i;
 $factor_d = ceil($factor_d); //round up number to 2
 $maximoyi = $factor_d * $i; //get new max value for y
 if ( ($maximoyi/ $maximoyi_temp) > 2) $maximoyi = $maximoyi /2; //check if max value is too big, then split by 2
1
mario

Konvertiert diese Antwort als Swift 4

extension Int {

    static func makeYaxis(yMin: Int, yMax: Int, ticks: Int = 10) -> [Int] {
        var yMin = yMin
        var yMax = yMax
        var ticks = ticks
        // This routine creates the Y axis values for a graph.
        //
        // Calculate Min AMD Max graphical labels and graph
        // increments.  The number of ticks defaults to
        // 10 which is the SUGGESTED value.  Any tick value
        // entered is used as a suggested value which is
        // adjusted to be a 'pretty' value.
        //
        // Output will be an array of the Y axis values that
        // encompass the Y values.
        var result = [Int]()
        // If yMin and yMax are identical, then
        // adjust the yMin and yMax values to actually
        // make a graph. Also avoids division by zero errors.
        if yMin == yMax {
            yMin -= ticks   // some small value
            yMax += ticks   // some small value
        }
        // Determine Range
        let range = yMax - yMin
        // Adjust ticks if needed
        if ticks < 2 { ticks = 2 }
        else if ticks > 2 { ticks -= 2 }

        // Get raw step value
        let tempStep: CGFloat = CGFloat(range) / CGFloat(ticks)
        // Calculate pretty step value
        let mag = floor(log10(tempStep))
        let magPow = pow(10,mag)
        let magMsd = Int(tempStep / magPow + 0.5)
        let stepSize = magMsd * Int(magPow)

        // build Y label array.
        // Lower and upper bounds calculations
        let lb = stepSize * Int(yMin/stepSize)
        let ub = stepSize * Int(ceil(CGFloat(yMax)/CGFloat(stepSize)))
        // Build array
        var val = lb
        while true {
            result.append(val)
            val += stepSize
            if val > ub { break }
        }
        return result
    }

}
0
Petr Syrov

Für alle, die dies in ES5 Javascript benötigen, hat ein bisschen gerungen, aber hier ist es:

var min=52;
var max=173;
var actualHeight=500; // 500 pixels high graph

var tickCount =Math.round(actualHeight/100); 
// we want lines about every 100 pixels.

if(tickCount <3) tickCount =3; 
var range=Math.abs(max-min);
var unroundedTickSize = range/(tickCount-1);
var x = Math.ceil(Math.log10(unroundedTickSize)-1);
var pow10x = Math.pow(10, x);
var roundedTickRange = Math.ceil(unroundedTickSize / pow10x) * pow10x;
var min_rounded=roundedTickRange * Math.floor(min/roundedTickRange);
var max_rounded= roundedTickRange * Math.ceil(max/roundedTickRange);
var nr=tickCount;
var str="";
for(var x=min_rounded;x<=max_rounded;x+=roundedTickRange)
{
    str+=x+", ";
}
console.log("Nice Y axis "+str);    

Basierend auf der ausgezeichneten Antwort von Toon Krijtje.

0
Hjalmar Snoep

Die obigen Algorithmen berücksichtigen nicht den Fall, wenn der Bereich zwischen dem minimalen und dem maximalen Wert zu klein ist. Und was ist, wenn diese Werte viel höher als Null sind? Dann haben wir die Möglichkeit, die y-Achse mit einem Wert größer als Null zu starten. Um zu vermeiden, dass sich unsere Linie vollständig auf der oberen oder der unteren Seite der Grafik befindet, müssen wir etwas "Luft zum Atmen" geben. 

Um diese Fälle abzudecken, habe ich (über PHP) den obigen Code geschrieben:

function calculateStartingPoint($min, $ticks, $times, $scale) {

    $starting_point = $min - floor((($ticks - $times) * $scale)/2);

    if ($starting_point < 0) {
        $starting_point = 0;
    } else {
        $starting_point = floor($starting_point / $scale) * $scale;
        $starting_point = ceil($starting_point / $scale) * $scale;
        $starting_point = round($starting_point / $scale) * $scale;
    }
    return $starting_point;
}

function calculateYaxis($min, $max, $ticks = 7)
{
    print "Min = " . $min . "\n";
    print "Max = " . $max . "\n";

    $range = $max - $min;
    $step = floor($range/$ticks);
    print "First step is " . $step . "\n";
    $available_steps = array(5, 10, 20, 25, 30, 40, 50, 100, 150, 200, 300, 400, 500);
    $distance = 1000;
    $scale = 0;

    foreach ($available_steps as $i) {
        if (($i - $step < $distance) && ($i - $step > 0)) {
            $distance = $i - $step;
            $scale = $i;
        }
    }

    print "Final scale step is " . $scale . "\n";

    $times = floor($range/$scale);
    print "range/scale = " . $times . "\n";

    print "floor(times/2) = " . floor($times/2) . "\n";

    $starting_point = calculateStartingPoint($min, $ticks, $times, $scale);

    if ($starting_point + ($ticks * $scale) < $max) {
        $ticks += 1;
    }

    print "starting_point = " . $starting_point . "\n";

    // result calculation
    $result = [];
    for ($x = 0; $x <= $ticks; $x++) {
        $result[] = $starting_point + ($x * $scale);
    }
    return $result;
}
0
panos

Basierend auf dem @ Gamecat-Algorithmus habe ich die folgende Hilfsklasse erstellt

public struct Interval
{
    public readonly double Min, Max, TickRange;

    public static Interval Find(double min, double max, int tickCount, double padding = 0.05)
    {
        double range = max - min;
        max += range*padding;
        min -= range*padding;

        var attempts = new List<Interval>();
        for (int i = tickCount; i > tickCount / 2; --i)
            attempts.Add(new Interval(min, max, i));

        return attempts.MinBy(a => a.Max - a.Min);
    }

    private Interval(double min, double max, int tickCount)
    {
        var candidates = (min <= 0 && max >= 0 && tickCount <= 8) ? new[] {2, 2.5, 3, 4, 5, 7.5, 10} : new[] {2, 2.5, 5, 10};

        double unroundedTickSize = (max - min) / (tickCount - 1);
        double x = Math.Ceiling(Math.Log10(unroundedTickSize) - 1);
        double pow10X = Math.Pow(10, x);
        TickRange = RoundUp(unroundedTickSize/pow10X, candidates) * pow10X;
        Min = TickRange * Math.Floor(min / TickRange);
        Max = TickRange * Math.Ceiling(max / TickRange);
    }

    // 1 < scaled <= 10
    private static double RoundUp(double scaled, IEnumerable<double> candidates)
    {
        return candidates.First(candidate => scaled <= candidate);
    }
}
0
Neil

Danke für die Frage und Antwort, sehr hilfreich. Gamecat, ich frage mich, wie Sie bestimmen, worauf der Tick-Bereich gerundet werden soll. 

tick-Bereich = 21,9. Dies sollte 25,0 sein

Um dies algorithmisch zu tun, müsste man dem obigen Algorithmus Logik hinzufügen, um diese Skala für größere Zahlen gut zu machen. Wenn der Bereich beispielsweise bei 10 Ticks 3346 ist, würde der Tick-Bereich 334,6 sein, und eine Rundung auf die nächsten 10 würde 340 ergeben, wenn 350 wahrscheinlich netter ist.

Was denkst du?

0
theringostarrs