|
Packit Service |
0e769b |
#include <stdio.h>
|
|
Packit Service |
0e769b |
#include <math.h>
|
|
Packit Service |
0e769b |
#include <stdlib.h>
|
|
Packit Service |
0e769b |
#include <string.h>
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
/*
|
|
Packit Service |
0e769b |
* adapted from Paul Heckbert's algorithm on p 657-659 of
|
|
Packit Service |
0e769b |
* Andrew S. Glassner's book, "Graphics Gems"
|
|
Packit Service |
0e769b |
* ISBN 0-12-286166-3
|
|
Packit Service |
0e769b |
*
|
|
Packit Service |
0e769b |
*/
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
#include "tickmarks.h"
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
#define MAX(a, b) (((a) < (b)) ? (b) : (a))
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
static double nicenum(double x, int round)
|
|
Packit Service |
0e769b |
{
|
|
Packit Service |
0e769b |
int exp; /* exponent of x */
|
|
Packit Service |
0e769b |
double f; /* fractional part of x */
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
exp = floor(log10(x));
|
|
Packit Service |
0e769b |
f = x / pow(10.0, exp);
|
|
Packit Service |
0e769b |
if (round) {
|
|
Packit Service |
0e769b |
if (f < 1.5)
|
|
Packit Service |
0e769b |
return 1.0 * pow(10.0, exp);
|
|
Packit Service |
0e769b |
if (f < 3.0)
|
|
Packit Service |
0e769b |
return 2.0 * pow(10.0, exp);
|
|
Packit Service |
0e769b |
if (f < 7.0)
|
|
Packit Service |
0e769b |
return 5.0 * pow(10.0, exp);
|
|
Packit Service |
0e769b |
return 10.0 * pow(10.0, exp);
|
|
Packit Service |
0e769b |
}
|
|
Packit Service |
0e769b |
if (f <= 1.0)
|
|
Packit Service |
0e769b |
return 1.0 * pow(10.0, exp);
|
|
Packit Service |
0e769b |
if (f <= 2.0)
|
|
Packit Service |
0e769b |
return 2.0 * pow(10.0, exp);
|
|
Packit Service |
0e769b |
if (f <= 5.0)
|
|
Packit Service |
0e769b |
return 5.0 * pow(10.0, exp);
|
|
Packit Service |
0e769b |
return 10.0 * pow(10.0, exp);
|
|
Packit Service |
0e769b |
}
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
static void shorten(struct tickmark *tm, int nticks, int *power_of_ten,
|
|
Packit Service |
0e769b |
int use_KMG_symbols, int base_offset)
|
|
Packit Service |
0e769b |
{
|
|
Packit Service |
0e769b |
const char shorten_chr[] = { 0, 'K', 'M', 'G', 'P', 'E', 0 };
|
|
Packit Service |
0e769b |
int i, l, minshorten, shorten_idx = 0;
|
|
Packit Service |
0e769b |
char *str;
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
minshorten = 100;
|
|
Packit Service |
0e769b |
for (i = 0; i < nticks; i++) {
|
|
Packit Service |
0e769b |
str = tm[i].string;
|
|
Packit Service |
0e769b |
l = strlen(str);
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
if (strcmp(str, "0") == 0)
|
|
Packit Service |
0e769b |
continue;
|
|
Packit Service |
0e769b |
if (l > 9 && strcmp(&str[l - 9], "000000000") == 0) {
|
|
Packit Service |
0e769b |
*power_of_ten = 9;
|
|
Packit Service |
0e769b |
shorten_idx = 3;
|
|
Packit Service |
0e769b |
} else if (6 < minshorten && l > 6 &&
|
|
Packit Service |
0e769b |
strcmp(&str[l - 6], "000000") == 0) {
|
|
Packit Service |
0e769b |
*power_of_ten = 6;
|
|
Packit Service |
0e769b |
shorten_idx = 2;
|
|
Packit Service |
0e769b |
} else if (l > 3 && strcmp(&str[l - 3], "000") == 0) {
|
|
Packit Service |
0e769b |
*power_of_ten = 3;
|
|
Packit Service |
0e769b |
shorten_idx = 1;
|
|
Packit Service |
0e769b |
} else {
|
|
Packit Service |
0e769b |
*power_of_ten = 0;
|
|
Packit Service |
0e769b |
}
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
if (*power_of_ten < minshorten)
|
|
Packit Service |
0e769b |
minshorten = *power_of_ten;
|
|
Packit Service |
0e769b |
}
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
if (minshorten == 0)
|
|
Packit Service |
0e769b |
return;
|
|
Packit Service |
0e769b |
if (!use_KMG_symbols)
|
|
Packit Service |
0e769b |
shorten_idx = 0;
|
|
Packit Service |
0e769b |
else if (base_offset)
|
|
Packit Service |
0e769b |
shorten_idx += base_offset;
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
for (i = 0; i < nticks; i++) {
|
|
Packit Service |
0e769b |
str = tm[i].string;
|
|
Packit Service |
0e769b |
l = strlen(str);
|
|
Packit Service |
0e769b |
str[l - minshorten] = shorten_chr[shorten_idx];
|
|
Packit Service |
0e769b |
if (shorten_idx)
|
|
Packit Service |
0e769b |
str[l - minshorten + 1] = '\0';
|
|
Packit Service |
0e769b |
}
|
|
Packit Service |
0e769b |
}
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
int calc_tickmarks(double min, double max, int nticks, struct tickmark **tm,
|
|
Packit Service |
0e769b |
int *power_of_ten, int use_KMG_symbols, int base_offset)
|
|
Packit Service |
0e769b |
{
|
|
Packit Service |
0e769b |
char str[100];
|
|
Packit Service |
0e769b |
int nfrac;
|
|
Packit Service |
0e769b |
double d; /* tick mark spacing */
|
|
Packit Service |
0e769b |
double graphmin, graphmax; /* graph range min and max */
|
|
Packit Service |
0e769b |
double range, x;
|
|
Packit Service |
0e769b |
int count, i;
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
/* we expect min != max */
|
|
Packit Service |
0e769b |
range = nicenum(max - min, 0);
|
|
Packit Service |
0e769b |
d = nicenum(range / (nticks - 1), 1);
|
|
Packit Service |
0e769b |
graphmin = floor(min / d) * d;
|
|
Packit Service |
0e769b |
graphmax = ceil(max / d) * d;
|
|
Packit Service |
0e769b |
nfrac = MAX(-floor(log10(d)), 0);
|
|
Packit Service |
0e769b |
snprintf(str, sizeof(str)-1, "%%.%df", nfrac);
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
count = ((graphmax + 0.5 * d) - graphmin) / d + 1;
|
|
Packit Service |
0e769b |
*tm = malloc(sizeof(**tm) * count);
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
i = 0;
|
|
Packit Service |
0e769b |
for (x = graphmin; x < graphmax + 0.5 * d; x += d) {
|
|
Packit Service |
0e769b |
(*tm)[i].value = x;
|
|
Packit Service |
0e769b |
sprintf((*tm)[i].string, str, x);
|
|
Packit Service |
0e769b |
i++;
|
|
Packit Service |
0e769b |
}
|
|
Packit Service |
0e769b |
shorten(*tm, i, power_of_ten, use_KMG_symbols, base_offset);
|
|
Packit Service |
0e769b |
return i;
|
|
Packit Service |
0e769b |
}
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
#if 0
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
static void test_range(double x, double y)
|
|
Packit Service |
0e769b |
{
|
|
Packit Service |
0e769b |
int nticks, i;
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
struct tickmark *tm = NULL;
|
|
Packit Service |
0e769b |
printf("Testing range %g - %g\n", x, y);
|
|
Packit Service |
0e769b |
nticks = calc_tickmarks(x, y, 10, &tm;;
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
for (i = 0; i < nticks; i++)
|
|
Packit Service |
0e769b |
printf(" (%s) %g\n", tm[i].string, tm[i].value);
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
printf("\n\n");
|
|
Packit Service |
0e769b |
free(tm);
|
|
Packit Service |
0e769b |
}
|
|
Packit Service |
0e769b |
|
|
Packit Service |
0e769b |
int main(int argc, char *argv[])
|
|
Packit Service |
0e769b |
{
|
|
Packit Service |
0e769b |
test_range(0.0005, 0.008);
|
|
Packit Service |
0e769b |
test_range(0.5, 0.8);
|
|
Packit Service |
0e769b |
test_range(5.5, 8.8);
|
|
Packit Service |
0e769b |
test_range(50.5, 80.8);
|
|
Packit Service |
0e769b |
test_range(-20, 20.8);
|
|
Packit Service |
0e769b |
test_range(-30, 700.8);
|
|
Packit Service |
0e769b |
}
|
|
Packit Service |
0e769b |
#endif
|