ACM Algorithm 463 fornisce tre funzioni semplici per produrre buoni bilance assi con uscite xminp, xmaxp e dist per i valori minimo e massimo della scala e la distanza tra le tacche sulla scala, data una richiesta di n
intervalli includere i punti dati xmin
e xmax
:
Scale1()
dà una scala lineare con circa n
intervalli e dist
essendo una potenza intera di 10 volte 1, 2 o 5. 012.351.641.061.
Scale2()
fornisce una scala lineare con esattamente gli intervalli n
(il divario tra xminp e xmaxp tende ad essere maggiore dell'intervallo prodotto da Scale1()
).
Scale3()
fornisce una scala logaritmica.
Il documento originale del 1973 è online here, che fornisce ulteriori spiegazioni rispetto al codice collegato sopra.
Il codice è in Fortran ma è solo un insieme di calcoli aritmetici, quindi è molto semplice interpretarlo e convertirlo in altre lingue. Non ho scritto PHP da solo, ma sembra molto simile a C, quindi potresti iniziare eseguendo il codice tramite f2c che dovrebbe darti qualcosa di simile a eseguibile in PHP.
Ci sono funzioni più complicate che forniscono scale più carine (ad esempio quelle in gnuplot
), ma Scale1()
probabilmente farebbe il lavoro per voi con codice minimo.
(Questa risposta si basa sulla mia risposta ad una precedente interrogazione Graph axis calibration in C++)
(EDIT - ho trovato un'implementazione di Scale1()
che ho fatto in Perl):
use strict;
sub scale1 ($$$) {
# from TOMS 463
# returns a suitable scale ($xMinp, $xMaxp, $dist), when called with
# the minimum and maximum x values, and an approximate number of intervals
# to divide into. $dist is the size of each interval that results.
# @vInt is an array of acceptable values for $dist.
# @sqr is an array of geometric means of adjacent values of @vInt, which
# is used as break points to determine which @vInt value to use.
#
my ($xMin, $xMax, $n) = @_;
@vInt = {1, 2, 5, 10};
@sqr = {1.414214, 3.162278, 7.071068 }
if ($xMin > $xMax) {
my ($tmp) = $xMin;
$xMin = $xMax;
$xMax = $tmp;
}
my ($del) = 0.0002; # accounts for computer round-off
my ($fn) = $n;
# find approximate interval size $a
my ($a) = ($xMax - $xMin)/$fn;
my ($al) = log10($a);
my ($nal) = int($al);
if ($a < 1) {
$nal = $nal - 1;
}
# $a is scaled into a variable named $b, between 1 and 10
my ($b) = $a/10^$nal;
# the closest permissable value for $b is found)
my ($i);
for ($i = 0; $i < $_sqr; $i++) {
if ($b < $sqr[$i]) last;
}
# the interval size is computed
$dist = $vInt[$i] * 10^$nal;
$fm1 = $xMin/$dist;
$m1 = int($fm1);
if ($fm1 < 0) $m1--;
if (abs(($m1 + 1.0) - $fm1) < $del) $m1++;
# the new minimum and maximum limits are found
$xMinp = $dist * $m1;
$fm2 = $xMax/$dist;
$m2 = $fm2 + 1;
if ($fm2 < -1) $m2--;
if (abs ($fm2 + 1 - $m2) < $del) $m2--;
$xMaxp = $dist * $m2;
# adjust limits to account for round-off if necessary
if ($xMinp > $xMin) $xMinp = $xMin;
if ($xMaxp < $xMax) $xMaxp = $xMax;
return ($xMinp, $xMaxp, $dist);
}
sub scale1_Test {
$par = (-3.1, 11.1, 5,
5.2, 10.1, 5,
-12000, -100, 9);
print "xMin\txMax\tn\txMinp\txMaxp,dist\n";
for ($i = 0; $i < $_par/3; $i++) {
($xMinp, $xMaxp, $dist) = scale1($par[3*$i+0],
$par[3*$i+1], $par[3*$i+2]);
print "$par[3*$i+0]\t$par[3*$i+1]\t$par[3*$i+2]\t$xMinp\t$xMaxp,$dist\n";
}
}
nessuno? almeno qualche suggerimento? – michi
C'è un certo numero di etichette che vuoi visualizzare per immagine? – Kyle
@Kyle: nessun numero fisso di etichette, deve adattarsi ai valori. Tenendo conto della larghezza di 300 px, esiste una sorta di limite naturale. – michi