OSCAR-code/Graphs/gXAxis.cpp

191 lines
5.0 KiB
C++

/********************************************************************
gXAxis Implementation
Copyright (c)2011 Mark Watkins <jedimark@users.sourceforge.net>
License: GPL
*********************************************************************/
#include <math.h>
#include "gXAxis.h"
gXAxis::gXAxis(QColor col)
:gLayer(NULL)
{
color.clear();
color.push_back(col);
m_show_major_lines=false;
m_show_minor_lines=false;
m_show_minor_ticks=true;
m_show_major_ticks=true;
}
gXAxis::~gXAxis()
{
}
void gXAxis::Plot(gGraphWindow & w,float scrx,float scry)
{
float px,py;
//int start_px=w.GetLeftMargin();
//int start_py=w.GetTopMargin();
float width=scrx-(w.GetLeftMargin()+w.GetRightMargin());
// float height=scry-(w.GetTopMargin()+w.GetBottomMargin());
double minx;
double maxx;
if (w.BlockZoom()) {
minx=w.rmin_x;
maxx=w.rmax_x;
} else {
minx=w.min_x;
maxx=w.max_x;
}
double xx=maxx-minx;
if (xx<=0) return;
double xmult=width/xx;
QString fd;
if (xx<1.5) {
fd="00:00:00:0000";
} else {
fd="XXX";
}
float x,y;
GetTextExtent(fd,x,y);
assert(x>0);
double max_ticks=(x+25.0)/width; // y+50 for rotated text
double jj=1/max_ticks;
double minor_tick=max_ticks*xx;
double st2=minx; //double(int(frac*1440.0))/1440.0;
double st,q;
bool show_seconds=false;
bool show_milliseconds=false;
bool show_time=true;
double min_tick;
if (xx<1.5) {
int rounding[16]={12,24,48,72,96,144,288,720,1440,2880,5760,8640,17280,86400,172800,345600}; // time rounding
int ri;
for (ri=0;ri<16;ri++) {
st=round(st2*rounding[ri])/rounding[ri];
min_tick=round(minor_tick*rounding[ri])/rounding[ri];
q=xx/min_tick; // number of ticks that fits in range
if (q<=jj) break; // compared to number of ticks that fit on screen.
}
if (ri>8) show_seconds=true;
if (ri>=14) show_milliseconds=true;
if (min_tick<=0.25/86400.0)
min_tick=0.25/86400;
} else { // Day ticks..
show_time=false;
st=st2;
min_tick=1.0;
double mtiks=(x+20.0)/width;
double mt=mtiks*xx;
min_tick=mt;
//if (min_tick<1.0) min_tick=1.0;
//if (min_tick>10) min_tick=10;
}
if (min_tick<=0) {
assert(min_tick>0);
}
double st3=st;
while (st3>minx) {
st3-=min_tick/10.0;
}
st3+=min_tick/10.0;
py=w.GetBottomMargin();
qint32 vertcnt=0;
GLshort * vertarray=vertex_array[0];
assert(vertarray!=NULL);
if (m_show_minor_ticks) {
for (double i=st3; i<=maxx; i+=min_tick/10.0) {
if (i<minx) continue;
px=(i-minx)*xmult+w.GetLeftMargin();
vertarray[vertcnt++]=px;
vertarray[vertcnt++]=py;
vertarray[vertcnt++]=px;
vertarray[vertcnt++]=py-4;
assert(vertcnt<maxverts);
}
}
while (st<minx) {
st+=min_tick; //10.0; // mucking with this changes the scrollyness of the ticker.
}
int hour,minute,second,millisecond;
QDateTime d;
// Need to use Qpainter clipping..
// messy. :(
glScissor(w.GetLeftMargin()-20,0,width+20,w.GetBottomMargin());
glEnable(GL_SCISSOR_TEST);
//const double extra=min_tick/10.0;
const double extra=0;
for (double i=st; i<=maxx+extra; i+=min_tick) {
d=QDateTime::fromMSecsSinceEpoch(i*86400000.0);
if (show_time) {
minute=d.time().minute();
hour=d.time().hour();
second=d.time().second();
millisecond=d.time().msec();
if (show_milliseconds) {
fd.sprintf("%02i:%02i:%02i:%04i",hour,minute,second,millisecond);
} else if (show_seconds) {
fd.sprintf("%02i:%02i:%02i",hour,minute,second);
} else {
fd.sprintf("%02i:%02i",hour,minute);
}
} else {
fd=d.toString("dd MMM");
}
px=(i-minx)*xmult+w.GetLeftMargin();
if ((i>=st && i<=maxx) && (m_show_major_ticks)) {
vertarray[vertcnt++]=px;
vertarray[vertcnt++]=py;
vertarray[vertcnt++]=px;
vertarray[vertcnt++]=py-6;
assert(vertcnt<maxverts);
}
GetTextExtent(fd,x,y);
//glColor3ub(0,0,0);
if (!show_time) {
DrawText(w,fd, px+y, scry-(py-(x/2)-8), 90.0);
//w.renderText(px-(y/2)+2, scry-(py-(x/2)-20), 90.0,fd);
} else {
DrawText(w,fd, px-(x/2), scry-(py-8-y));
//w.renderText(px-(x/2), scry-(py-(y/2)-20), fd);
}
}
// Draw the little ticks.
assert(vertcnt<maxverts);
glLineWidth(1);
glColor3f(0,0,0);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_SHORT, 0, vertarray);
glDrawArrays(GL_LINES, 0, vertcnt>>1);
glDisableClientState(GL_VERTEX_ARRAY); // deactivate vertex arrays after drawing
glDisable(GL_SCISSOR_TEST);
}