/*
* $Id: tick60.c,v 1.1.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;
}
syntax highlighted by Code2HTML, v. 0.9.1