1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
/*
* $Id: tick60.c,v 1.1 2005-09-18 22:04:36 dhmunro Exp $
* Implement base 60 ticks and labels for coordinate systems.
*/
/* Copyright (c) 2005, The Regents of the University of California.
* All rights reserved.
* This file is part of yorick (http://yorick.sourceforge.net).
* Read the accompanying LICENSE file for details.
*/
#include "gist.h"
/* Use sprintf function in labeling functions */
#include <stdio.h>
extern double ceil(double);
/* Here are the possible intervals for a base 60 scale.
The 720 interval is skipped if the 1800 was present, otherwise all
these intervals will be present in the tick hierarchy. */
#define N_CUTS 7
static GpReal cutoffs[N_CUTS]= { 1800., 720., 360., 180., 90., 30., 10. };
int Base60Ticks(GpReal lo, GpReal hi, GpReal nMajor, GpReal nMinor,
GpReal *ticks, int nlevel[TICK_LEVELS])
/* Puts ticks at multiples of 30, failing if lo<-3600 or hi>+3600.
For ticks at multiples of 10 or less, the subdivisions are
identical to the default decimal tick scheme. */
{
GpReal finest= (hi-lo)/nMajor;
GpReal delta= cutoffs[0];
GpReal tick0;
int i0, ntot, nlevs, phase, base, ndivs;
if (lo<-3600. || hi>3600. ||
finest<=cutoffs[N_CUTS-1] || finest>delta) return 1;
for (i0=0 ; i0<N_CUTS && finest<=cutoffs[i0] ; i0++) delta= cutoffs[i0];
tick0= ceil(lo/delta)*delta;
for (ntot=0 ; tick0<=hi ; ntot++,tick0+=delta) ticks[ntot]= tick0;
nlevel[0]= ntot;
nlevs= 1;
finest= (hi-lo)/nMinor;
/* perform base 60 part of subdivision */
for (; i0<N_CUTS && finest<=cutoffs[i0] ; i0++) {
if (i0==1) {
i0++; /* skip 720 starting from 1800 */
if (finest>cutoffs[i0]) break;
ndivs= 5;
} else {
ndivs= i0<5? 2 : 3; /* 90->30 and 30->10 are 3, others all 2 */
}
delta= cutoffs[i0];
tick0= ceil(lo/delta);
phase= (int)(tick0-ceil(tick0/ndivs-.00001)*ndivs);
tick0*= delta;
for ( ; tick0<=hi ; tick0+=delta,phase=(phase+1)%ndivs)
if (phase) ticks[ntot++]= tick0;
nlevel[nlevs]= ntot;
if (++nlevs>=TICK_LEVELS) return 0;
}
if (i0<N_CUTS || finest>5.) return 0;
/* perform base 10 part of subdivision if necessary */
delta= 5.;
base= 5;
ndivs= 2;
for (; nlevs<TICK_LEVELS ; nlevs++) {
tick0= ceil(lo/delta);
phase= (int)(tick0-ceil(tick0/ndivs-.00001)*ndivs);
tick0*= delta;
for ( ; tick0<=hi ; tick0+=delta,phase=(phase+1)%ndivs)
if (phase) ticks[ntot++]= tick0;
nlevel[nlevs]= ntot;
if (base==2) break;
if (base==5) {
delta*= 0.2;
base= 1;
ndivs= 5;
} else if (finest<=0.1*delta) {
delta*= 0.5;
base= 5;
ndivs= 2;
continue;
} else {
delta*= 0.2;
base= 2;
ndivs= 5;
}
if (finest>delta) break;
}
return 0;
}
int DegreeLabels(char *label, GpReal value)
/* Prints (value+180)%360-180 instead of just value. */
{
GpReal dv;
int val;
if (value<-3600. || value>3600.) return 1;
dv= ceil(value-0.00001);
val= (int)dv;
if (dv<value) dv= value-dv;
else dv= dv-value;
if (dv>0.00001) return 1;
if (!label) return 0;
val= (val+180)%360;
if (val<=0) val+= 360;
sprintf(label, "%d", val-180);
return 0;
}
int HourLabels(char *label, GpReal value)
/* Prints hh:mm (or mm:ss) for value 60*hh+mm (or 60*mm+ss). */
{
GpReal dv;
int hh, mm, neg;
if (value<-3600. || value>3600.) return 1;
dv= ceil(value-0.00001);
neg= dv<0.;
if (neg) hh= (int)(-dv);
else hh= (int)dv;
if (dv<value) dv= value-dv;
else dv= dv-value;
if (dv>0.00001) return 1;
if (!label) return 0;
mm= hh%60;
hh/= 60;
sprintf(label, "%s%02d:%02d", (neg?"-":""), hh, mm);
return 0;
}
|