mathplot: various improvements, added log scale [wip]

This commit is contained in:
Tomasz Wlostowski 2016-08-11 14:41:48 +02:00 committed by Maciej Suminski
parent d869771f04
commit d2f4d5c2fb
2 changed files with 727 additions and 192 deletions

View File

@ -83,7 +83,7 @@ mpLayer::mpLayer() : m_type(mpLAYER_UNDEF)
SetFont((wxFont&) *wxNORMAL_FONT);
m_continuous = FALSE; // Default
m_showName = TRUE; // Default
m_drawOutsideMargins = TRUE;
m_drawOutsideMargins = FALSE;
m_visible = true;
}
@ -221,9 +221,9 @@ void mpInfoCoords::UpdateInfo(mpWindow& w, wxEvent& event)
wxGTK instead works perfectly with it.
Info on wxForum: http://wxforum.shadonet.com/viewtopic.php?t=3451&highlight=drawtext+eol */
#ifdef _WINDOWS
m_content.Printf(wxT("x = %f y = %f"), w.p2x(mouseX), w.p2y(mouseY));
// FIXME m_content.Printf(wxT("x = %f y = %f"), XScale().P2x(w, mouseX), YScale().P2x(w, mouseY));
#else
m_content.Printf(wxT("x = %f\ny = %f"), w.p2x(mouseX), w.p2y(mouseY));
// FIXME m_content.Printf(wxT("x = %f\ny = %f"), XScale().P2x(w, mouseX), YScale().P2x(w, mouseY));
#endif
}
}
@ -360,6 +360,39 @@ void mpInfoLegend::Plot(wxDC & dc, mpWindow & w)
}
}
#if 0
double mpScaleXLog::X2p( mpWindow &w, double x )
{
return ( x - w.GetPosX() ) * w.GetScaleX();
}
double mpScaleXLog::P2x( mpWindow &w, double x )
{
return w.GetPosX() + x / w.GetScaleX();
}
double mpScaleX::X2p( mpWindow &w, double x )
{
return ( x - w.GetPosX() ) * w.GetScaleX();
}
double mpScaleX::P2x( mpWindow &w, double x )
{
return w.GetPosX() + x / w.GetScaleX();
}
double mpScaleY::X2p( mpWindow &w, double x )
{
return ( w.GetPosY() - x ) * w.GetScaleY();
}
double mpScaleY::P2x( mpWindow &w, double x )
{
return w.GetPosY() - x/w.GetScaleY();
}
#endif
//-----------------------------------------------------------------------------
@ -404,7 +437,7 @@ void mpFX::Plot(wxDC & dc, mpWindow & w)
// Draw the point only if you can draw outside margins or if the point is inside margins
if (m_drawOutsideMargins || ((iy >= minYpx) && (iy <= maxYpx)))
dc.DrawLine( i, iy, i, iy);
// wxCoord c = w.y2p( GetY(w.p2x(i)) ); //(wxCoord) ((w.GetPosY() - GetY( (double)i / w.GetScaleX() + w.GetPosX()) ) * w.GetScaleY());
// wxCoord c = YScale().X2p( GetY(XScale().P2x(i)) ); //(wxCoord) ((w.GetPosY() - GetY( (double)i / w.GetScaleX() + w.GetPosX()) ) * w.GetScaleY());
}
}
@ -429,7 +462,7 @@ void mpFX::Plot(wxDC & dc, mpWindow & w)
tx = ((w.GetScrX() - w.GetMarginRight() - w.GetMarginLeft() - tx) / 2) + w.GetMarginLeft();
else
tx = w.GetMarginLeft() + 8;
dc.DrawText( m_name, tx, w.y2p(GetY(w.p2x(tx))) ); // (wxCoord) ((w.GetPosY() - GetY( (double)tx / w.GetScaleX() + w.GetPosX())) * w.GetScaleY()) );
dc.DrawText( m_name, tx, w.y2p(GetY(w.p2x(tx))) );
}
}
}
@ -469,9 +502,10 @@ void mpFY::Plot(wxDC & dc, mpWindow & w)
for (i=0;i< w.GetScrY(); ++i)
{
ix = w.x2p(GetX(w.p2y(i)));
if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx)))
dc.DrawLine(ix, i, ix, i);
// wxCoord c = w.x2p(GetX(w.p2y(i))); //(wxCoord) ((GetX( (double)i / w.GetScaleY() + w.GetPosY()) - w.GetPosX()) * w.GetScaleX());
// wxCoord c = XScale().X2p(GetX(YScale().P2x(i))); //(wxCoord) ((GetX( (double)i / w.GetScaleY() + w.GetPosY()) - w.GetPosX()) * w.GetScaleX());
// dc.DrawLine(c, i, c, i);
}
}
@ -541,8 +575,12 @@ void mpFXY::Plot(wxDC & dc, mpWindow & w)
{
while (GetNextXY(x, y))
{
ix = w.x2p(x);
iy = w.y2p(y);
double px = m_scaleX->TransformToPlot(x);
double py = m_scaleY->TransformToPlot(y);
ix = w.x2p(px);
iy = w.y2p(py);
if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx) && (iy >= minYpx) && (iy <= maxYpx))) {
dc.DrawPoint(ix, iy);
UpdateViewBoundary(ix, iy);
@ -553,8 +591,12 @@ void mpFXY::Plot(wxDC & dc, mpWindow & w)
{
while (GetNextXY(x, y))
{
ix = w.x2p(x);
iy = w.y2p(y);
double px = m_scaleX->TransformToPlot(x);
double py = m_scaleY->TransformToPlot(y);
ix = w.x2p(px);
iy = w.y2p(py);
if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx) && (iy >= minYpx) && (iy <= maxYpx))) {
dc.DrawLine(ix, iy, ix, iy);
UpdateViewBoundary(ix, iy);
@ -570,8 +612,17 @@ void mpFXY::Plot(wxDC & dc, mpWindow & w)
bool first = TRUE;
while (GetNextXY(x, y))
{
wxCoord x1 = w.x2p(x); // (wxCoord) ((x - w.GetPosX()) * w.GetScaleX());
wxCoord c1 = w.y2p(y); // (wxCoord) ((w.GetPosY() - y) * w.GetScaleY());
double px = m_scaleX->TransformToPlot(x);
double py = m_scaleY->TransformToPlot(y);
wxCoord x1 = w.x2p(px);
wxCoord c1 = w.y2p(py);
//printf("px %.10f py %.10f c1 %d\n", px, py, c1);
//wxCoord x1 = XScale().X2p(w,x); // (wxCoord) ((x - w.GetPosX()) * w.GetScaleX());
//wxCoord c1 = YScale().X2p(w,y); // (wxCoord) ((w.GetPosY() - y) * w.GetScaleY());
if (first)
{
first=FALSE;
@ -688,22 +739,322 @@ void mpProfile::Plot(wxDC & dc, mpWindow & w)
#define mpLN10 2.3025850929940456840179914546844
IMPLEMENT_DYNAMIC_CLASS(mpScaleX, mpLayer)
void mpScaleX::recalculateTicks ( wxDC & dc, mpWindow & w )
{
const int extend = w.GetScrX(); // /2;
mpScaleX::mpScaleX(wxString name, int flags, bool ticks, unsigned int type)
dig = floor( log( 128.0 / w.GetScaleX() ) / mpLN10 );
step = exp( mpLN10 * dig);
end = w.GetPosX() + (double)extend / w.GetScaleX();
n0 = floor( (w.GetPosX() ) / step ) * step ;
printf("%.10f %.10f %.10f", n0, step, end);
computeLabelExtents( dc, w );
labelStep = ceil(((double) m_maxLabelWidth + mpMIN_X_AXIS_LABEL_SEPARATION)/(w.GetScaleX()*step))*step;
}
void mpScaleX::computeLabelExtents ( wxDC & dc, mpWindow & w )
{
m_maxLabelHeight = 0;
m_maxLabelWidth = 0;
for (int n = 0; n < labelCount(); n++)
{
int tx, ty;
const wxString s = getLabel( n );
dc.GetTextExtent(s, &tx, &ty);
m_maxLabelHeight = std::max( ty, m_maxLabelHeight );
m_maxLabelWidth = std::max( tx, m_maxLabelWidth );
}
}
int mpScaleX::tickCount() const
{
return (int) floor( ( end - n0 ) / step );
}
int mpScaleX::labelCount() const
{
return (int) floor( ( end - n0 ) / labelStep );
}
const wxString mpScaleX::getLabel( int n )
{
return wxT("L");
}
double mpScaleX::getTickPos( int n )
{
return n0 + (double) n * step;
}
double mpScaleX::getLabelPos( int n )
{
return n0 + (double) n * labelStep;
}
void mpScaleY::getVisibleDataRange ( mpWindow& w, double &minV, double& maxV)
{
wxCoord minYpx = m_drawOutsideMargins ? 0 : w.GetMarginTop();
wxCoord maxYpx = m_drawOutsideMargins ? w.GetScrY() : w.GetScrY() - w.GetMarginBottom();
double pymin = w.p2y(minYpx);
double pymax = w.p2y(maxYpx);
printf("PYmin %.3f PYmax %.3f\n", pymin, pymax);
minV = TransformFromPlot(pymax);
maxV = TransformFromPlot(pymin);
}
void mpScaleY::recalculateTicks ( wxDC & dc, mpWindow & w )
{
const int extend = w.GetScrX(); // /2;
//dig = floor( log( 128.0 / w.GetScaleY() ) / mpLN10 );
//step = exp( mpLN10 * dig);
//end = w.GetPosX() + (double)extend / w.GetScaleY();
double minV, maxV, minVvis, maxVvis;
GetDataRange ( minV, maxV );
getVisibleDataRange ( w, minVvis, maxVvis );
m_tickValues.clear();
m_labeledTicks.clear();
double minErr = 1000000000000.0;
double bestStep;
int bestCount;
for(int i = 10; i <= 20; i+=2)
{
double step = fabs(maxVvis - minVvis) / (double) i;
double base = pow(10, floor(log10(step)));
//printf("base %.3f\n", base);
double stepInt = floor(step / base) * base;
double err = fabs(step - stepInt);
if(err< minErr)
{
minErr = err;
bestStep = stepInt;
bestCount = i;
}
//printf("step %d %.3f %.3f best %.3f\n",i, step, stepInt, bestStep);
}
double v = floor(minVvis / bestStep) * bestStep;
double zeroOffset = 100000000.0;
printf("maxVVis %.3f\n", maxVvis);
while ( v < maxVvis )
{
m_tickValues.push_back(v);
if (fabs(v) < zeroOffset)
zeroOffset = fabs(v);
printf("tick %.3f\n", v);
v+=bestStep;
}
if ( zeroOffset <= bestStep )
{
for( double& t: m_tickValues )
t -= zeroOffset;
}
for( double t: m_tickValues )
m_labeledTicks.push_back(t);
//n0 = floor(minVvis / bestStep) * bestStep;
//end = n0 +
//n0 = floor( (w.GetPosX() ) / step ) * step ;
printf("zeroOffset:%.3f tickjs : %d\n", zeroOffset, m_tickValues.size());
computeLabelExtents( dc, w );
//labelStep = ceil(((double) m_maxLabelWidth + mpMIN_X_AXIS_LABEL_SEPARATION)/(w.GetScaleX()*step))*step;
}
void mpScaleY::computeLabelExtents ( wxDC & dc, mpWindow & w )
{
m_maxLabelHeight = 0;
m_maxLabelWidth = 0;
for (int n = 0; n < labelCount(); n++)
{
int tx, ty;
printf("***********GetLabel %d\n", n);
const wxString s = getLabel( n );
dc.GetTextExtent(s, &tx, &ty);
m_maxLabelHeight = std::max( ty, m_maxLabelHeight );
m_maxLabelWidth = std::max( tx, m_maxLabelWidth );
}
}
int mpScaleY::tickCount() const
{
return m_tickValues.size();
}
int mpScaleY::labelCount() const
{
return m_labeledTicks.size();
}
const wxString mpScaleY::getLabel( int n )
{
return wxT("L");
}
double mpScaleY::getTickPos( int n )
{
return m_tickValues[n];
}
double mpScaleY::getLabelPos( int n )
{
return m_labeledTicks[n];
}
void mpScaleXBase::getVisibleDataRange ( mpWindow& w, double &minV, double& maxV)
{
wxCoord startPx = m_drawOutsideMargins ? 0 : w.GetMarginLeft();
wxCoord endPx = m_drawOutsideMargins ? w.GetScrX() : w.GetScrX() - w.GetMarginRight();
//printf("getVisibleDataRange\n");
double pxmin = w.p2x(startPx);
double pxmax = w.p2x(endPx);
minV = TransformFromPlot(pxmin);
maxV = TransformFromPlot(pxmax);
}
void mpScaleXLog::recalculateTicks ( wxDC & dc, mpWindow & w )
{
double minV, maxV, minVvis, maxVvis;
GetDataRange ( minV, maxV );
getVisibleDataRange ( w, minVvis, maxVvis );
double decades = log( maxV / minV ) / log(10);
double minDecade = pow(10, floor(log10(minV)));
double maxDecade = pow(10, ceil(log10(maxV)));
double visibleDecades = log( maxVvis / minVvis ) / log(10);
printf("visibleD %.1f %.1f %.1f\n", visibleDecades, maxVvis, minVvis);
double d;
m_ticks.clear();
m_labeledTicks.clear();
for ( d= minDecade; d<=maxDecade; d *= 10.0)
{
printf("d %.1f\n",d );
m_labeledTicks.push_back( d );
for(double dd = d; dd < d * 10; dd += d)
{
if(visibleDecades < 2)
m_labeledTicks.push_back(dd);
//printf("dd %.1f\n",dd);
m_ticks.push_back(dd);
}
}
computeLabelExtents( dc, w );
printf("labeled ticks : %d\n", m_labeledTicks.size());
labelStep = ceil(((double) m_maxLabelWidth + mpMIN_X_AXIS_LABEL_SEPARATION)/(w.GetScaleX()*step))*step;
}
void mpScaleXLog::computeLabelExtents ( wxDC & dc, mpWindow & w )
{
m_maxLabelHeight = 0;
m_maxLabelWidth = 0;
for (int n = 0; n < labelCount(); n++)
{
int tx, ty;
const wxString s = getLabel( n );
dc.GetTextExtent(s, &tx, &ty);
m_maxLabelHeight = std::max( ty, m_maxLabelHeight );
m_maxLabelWidth = std::max( tx, m_maxLabelWidth );
}
}
int mpScaleXLog::tickCount() const
{
return m_ticks.size();
}
int mpScaleXLog::labelCount() const
{
return m_labeledTicks.size();
// return (int) floor( ( end - n0 ) / labelStep );
}
const wxString mpScaleXLog::getLabel( int n )
{
return wxT("L");
}
double mpScaleXLog::getTickPos( int n )
{
return m_ticks[n]; //n0 + (double) n * step;
}
double mpScaleXLog::getLabelPos( int n )
{
return m_labeledTicks[n];
}
IMPLEMENT_ABSTRACT_CLASS(mpScaleXBase, mpLayer)
IMPLEMENT_DYNAMIC_CLASS(mpScaleX, mpScaleXBase)
IMPLEMENT_DYNAMIC_CLASS(mpScaleXLog, mpScaleXBase)
mpScaleXBase::mpScaleXBase(wxString name, int flags, bool ticks, unsigned int type)
{
SetName(name);
SetFont( (wxFont&) *wxSMALL_FONT);
SetPen( (wxPen&) *wxGREY_PEN);
m_flags = flags;
m_ticks = ticks;
m_labelType = type;
//m_labelType = type;
m_type = mpLAYER_AXIS;
m_labelFormat = wxT("");
//m_labelFormat = wxT("");
}
void mpScaleX::Plot(wxDC & dc, mpWindow & w)
mpScaleX::mpScaleX(wxString name, int flags, bool ticks, unsigned int type) :
mpScaleXBase ( name, flags, ticks ,type ) {};
mpScaleXLog::mpScaleXLog(wxString name, int flags, bool ticks, unsigned int type) :
mpScaleXBase ( name, flags, ticks ,type ) {};
void mpScaleXBase::Plot(wxDC & dc, mpWindow & w)
{
int tx, ty;
recalculateTicks( dc, w );
if (m_visible) {
dc.SetPen( m_pen);
dc.SetFont( m_font);
@ -711,7 +1062,7 @@ void mpScaleX::Plot(wxDC & dc, mpWindow & w)
const int extend = w.GetScrX(); // /2;
if (m_flags == mpALIGN_CENTER)
orgy = w.y2p(0); //(int)(w.GetPosY() * w.GetScaleY());
orgy = w.y2p(0); //(int)(w.GetPosY() * w.GetScaleY());
if (m_flags == mpALIGN_TOP) {
if (m_drawOutsideMargins)
orgy = X_BORDER_SEPARATION;
@ -729,49 +1080,8 @@ void mpScaleX::Plot(wxDC & dc, mpWindow & w)
if (m_flags == mpALIGN_BORDER_TOP )
orgy = 1;//-dc.LogicalToDeviceY(0);
dc.DrawLine( 0, orgy, w.GetScrX(), orgy);
// dc.DrawLine( 0, orgy, w.GetScrX(), orgy);
// To cut the axis line when draw outside margin is false, use this code
/*if (m_drawOutsideMargins == true)
dc.DrawLine( 0, orgy, w.GetScrX(), orgy);
else
dc.DrawLine( w.GetMarginLeft(), orgy, w.GetScrX() - w.GetMarginRight(), orgy); */
const double dig = floor( log( 128.0 / w.GetScaleX() ) / mpLN10 );
const double step = exp( mpLN10 * dig);
const double end = w.GetPosX() + (double)extend / w.GetScaleX();
wxCoord tx, ty;
wxString s;
wxString fmt;
int tmp = (int)dig;
if (m_labelType == mpX_NORMAL) {
if (!m_labelFormat.IsEmpty()) {
fmt = m_labelFormat;
} else {
if (tmp>=1) {
fmt = wxT("%.f");
} else {
tmp=8-tmp;
fmt.Printf(wxT("%%.%df"), tmp >= -1 ? 2 : -tmp);
}
}
} else {
// Date and/or time axis representation
if (m_labelType == mpX_DATETIME) {
fmt = (wxT("%04.0f-%02.0f-%02.0fT%02.0f:%02.0f:%02.0f"));
} else if (m_labelType == mpX_DATE) {
fmt = (wxT("%04.0f-%02.0f-%02.0f"));
} else if ((m_labelType == mpX_TIME) && (end/60 < 2)) {
fmt = (wxT("%02.0f:%02.3f"));
} else {
fmt = (wxT("%02.0f:%02.0f:%02.0f"));
}
}
//double n = floor( (w.GetPosX() - (double)extend / w.GetScaleX()) / step ) * step ;
double n0 = floor( (w.GetPosX() /* - (double)(extend - w.GetMarginLeft() - w.GetMarginRight())/ w.GetScaleX() */) / step ) * step ;
double n = 0;
#ifdef MATHPLOT_DO_LOGGING
wxLogMessage(wxT("mpScaleX::Plot: dig: %f , step: %f, end: %f, n: %f"), dig, step, end, n0);
#endif
@ -780,11 +1090,23 @@ void mpScaleX::Plot(wxDC & dc, mpWindow & w)
wxCoord minYpx = m_drawOutsideMargins ? 0 : w.GetMarginTop();
wxCoord maxYpx = m_drawOutsideMargins ? w.GetScrY() : w.GetScrY() - w.GetMarginBottom();
tmp=-65535;
int labelH = 0; // Control labels heigth to decide where to put axis name (below labels or on top of axis)
int maxExtent = 0;
for (n = n0; n < end; n += step) {
const int p = (int)((n - w.GetPosX()) * w.GetScaleX());
printf("StartPx %d endPx %d ordy %d maxy %d\n", startPx, endPx, orgy, maxYpx);
int tmp=-65535;
int labelH = m_maxLabelHeight; // Control labels heigth to decide where to put axis name (below labels or on top of axis)
//int maxExtent = tc.MaxLabelWidth();
printf("Ticks : %d\n",labelCount());
for (int n = 0; n < tickCount(); n++)
{
double tp = getTickPos(n);
//double xlogmin = log10 ( m_minV );
//double xlogmax = log10 ( m_maxV );
double px = TransformToPlot ( tp ); //( log10 ( tp ) - xlogmin) / (xlogmax - xlogmin);
const int p = (int)(( px - w.GetPosX()) * w.GetScaleX());
#ifdef MATHPLOT_DO_LOGGING
wxLogMessage(wxT("mpScaleX::Plot: n: %f -> p = %d"), n, p);
#endif
@ -798,89 +1120,54 @@ void mpScaleX::Plot(wxDC & dc, mpWindow & w)
m_pen.SetStyle(wxDOT);
dc.SetPen(m_pen);
if ((m_flags == mpALIGN_BOTTOM) && !m_drawOutsideMargins) {
//printf("d1");
m_pen.SetStyle(wxDOT);
dc.SetPen(m_pen);
dc.DrawLine( p, orgy+4, p, minYpx );
m_pen.SetStyle(wxSOLID);
dc.SetPen(m_pen);
dc.DrawLine( p, orgy+4, p, orgy-4 );
} else {
if ((m_flags == mpALIGN_TOP) && !m_drawOutsideMargins) {
//printf("d2");
dc.DrawLine( p, orgy-4, p, maxYpx );
} else {
dc.DrawLine( p, 0/*-w.GetScrY()*/, p, w.GetScrY() );
//printf("d3");
dc.DrawLine( p, minYpx, p, maxYpx ); //0/*-w.GetScrY()*/, p, w.GetScrY() );
}
}
m_pen.SetStyle(wxSOLID);
dc.SetPen(m_pen);
}
// Write ticks labels in s string
if (m_labelType == mpX_NORMAL)
s.Printf(fmt, n);
else if (m_labelType == mpX_DATETIME) {
time_t when = (time_t)n;
struct tm tm = *localtime(&when);
s.Printf(fmt, (double)tm.tm_year+1900, (double)tm.tm_mon+1, (double)tm.tm_mday, (double)tm.tm_hour, (double)tm.tm_min, (double)tm.tm_sec);
} else if (m_labelType == mpX_DATE) {
time_t when = (time_t)n;
struct tm tm = *localtime(&when);
s.Printf(fmt, (double)tm.tm_year+1900, (double)tm.tm_mon+1, (double)tm.tm_mday);
} else if ((m_labelType == mpX_TIME) || (m_labelType == mpX_HOURS)) {
double modulus = fabs(n);
double sign = n/modulus;
double hh = floor(modulus/3600);
double mm = floor((modulus - hh*3600)/60);
double ss = modulus - hh*3600 - mm*60;
#ifdef MATHPLOT_DO_LOGGING
wxLogMessage(wxT("%02.0f Hours, %02.0f minutes, %02.0f seconds"), sign*hh, mm, ss);
#endif // MATHPLOT_DO_LOGGING
if (fmt.Len() == 20) // Format with hours has 11 chars
s.Printf(fmt, sign*hh, mm, floor(ss));
else
s.Printf(fmt, sign*mm, ss);
}
dc.GetTextExtent(s, &tx, &ty);
labelH = (labelH <= ty) ? ty : labelH;
/* if ((p-tx/2-tmp) > 64) { // Problem about non-regular axis labels
if ((m_flags == mpALIGN_BORDER_BOTTOM) || (m_flags == mpALIGN_TOP)) {
dc.DrawText( s, p-tx/2, orgy-4-ty);
} else {
dc.DrawText( s, p-tx/2, orgy+4);
}
tmp=p+tx/2;
}
*/
maxExtent = (tx > maxExtent) ? tx : maxExtent; // Keep in mind max label width
}
}
m_pen.SetStyle(wxSOLID);
dc.SetPen(m_pen);
dc.DrawLine( startPx, minYpx, endPx, minYpx );
dc.DrawLine( startPx, maxYpx, endPx, maxYpx );
printf("Labels : %d\n",labelCount());
// Actually draw labels, taking care of not overlapping them, and distributing them regularly
double labelStep = ceil((maxExtent + mpMIN_X_AXIS_LABEL_SEPARATION)/(w.GetScaleX()*step))*step;
for (n = n0; n < end; n += labelStep) {
const int p = (int)((n - w.GetPosX()) * w.GetScaleX());
for (int n = 0; n < labelCount(); n++)
{
double tp = getLabelPos(n);
//double xlogmin = log10 ( m_minV );
//double xlogmax = log10 ( m_maxV );
double px = TransformToPlot ( tp ); //( log10 ( tp ) - xlogmin) / (xlogmax - xlogmin);
const int p = (int)((px- w.GetPosX()) * w.GetScaleX());
printf("p %d %.1f\n", p, px);
#ifdef MATHPLOT_DO_LOGGING
wxLogMessage(wxT("mpScaleX::Plot: n_label = %f -> p_label = %d"), n, p);
#endif
if ((p >= startPx) && (p <= endPx)) {
// Write ticks labels in s string
if (m_labelType == mpX_NORMAL)
s.Printf(fmt, n);
else if (m_labelType == mpX_DATETIME) {
time_t when = (time_t)n;
struct tm tm = *localtime(&when);
s.Printf(fmt, (double)tm.tm_year+1900, (double)tm.tm_mon+1, (double)tm.tm_mday, (double)tm.tm_hour, (double)tm.tm_min, (double)tm.tm_sec);
} else if (m_labelType == mpX_DATE) {
time_t when = (time_t)n;
struct tm tm = *localtime(&when);
s.Printf(fmt, (double)tm.tm_year+1900, (double)tm.tm_mon+1, (double)tm.tm_mday);
} else if ((m_labelType == mpX_TIME) || (m_labelType == mpX_HOURS)) {
double modulus = fabs(n);
double sign = n/modulus;
double hh = floor(modulus/3600);
double mm = floor((modulus - hh*3600)/60);
double ss = modulus - hh*3600 - mm*60;
#ifdef MATHPLOT_DO_LOGGING
wxLogMessage(wxT("%02.0f Hours, %02.0f minutes, %02.0f seconds"), sign*hh, mm, ss);
#endif // MATHPLOT_DO_LOGGING
if (fmt.Len() == 20) // Format with hours has 11 chars
s.Printf(fmt, sign*hh, mm, floor(ss));
else
s.Printf(fmt, sign*mm, ss);
}
wxString s = getLabel ( n );
dc.GetTextExtent(s, &tx, &ty);
if ((m_flags == mpALIGN_BORDER_BOTTOM) || (m_flags == mpALIGN_TOP)) {
dc.DrawText( s, p-tx/2, orgy-4-ty);
@ -930,6 +1217,9 @@ void mpScaleX::Plot(wxDC & dc, mpWindow & w)
}; */
}
IMPLEMENT_DYNAMIC_CLASS(mpScaleY, mpLayer)
mpScaleY::mpScaleY(wxString name, int flags, bool ticks)
@ -940,11 +1230,14 @@ mpScaleY::mpScaleY(wxString name, int flags, bool ticks)
m_flags = flags;
m_ticks = ticks;
m_type = mpLAYER_AXIS;
m_labelFormat = wxT("");
//m_labelFormat = wxT("");
}
void mpScaleY::Plot(wxDC & dc, mpWindow & w)
{
printf("Plot Y-scale\n");
recalculateTicks(dc, w);
if (m_visible) {
dc.SetPen( m_pen);
dc.SetFont( m_font);
@ -970,9 +1263,11 @@ void mpScaleY::Plot(wxDC & dc, mpWindow & w)
if (m_flags == mpALIGN_BORDER_LEFT )
orgx = 1; //-dc.LogicalToDeviceX(0);
wxCoord endPx = m_drawOutsideMargins ? w.GetScrX() : w.GetScrX() - w.GetMarginRight();
wxCoord minYpx = m_drawOutsideMargins ? 0 : w.GetMarginTop();
wxCoord maxYpx = m_drawOutsideMargins ? w.GetScrY() : w.GetScrY() - w.GetMarginBottom();
// Draw line
dc.DrawLine( orgx, 0, orgx, extend);
dc.DrawLine( orgx, minYpx, orgx, maxYpx);
// To cut the axis line when draw outside margin is false, use this code
/* if (m_drawOutsideMargins == true)
@ -991,14 +1286,14 @@ void mpScaleY::Plot(wxDC & dc, mpWindow & w)
double maxScaleAbs = fabs(w.GetDesiredYmax());
double minScaleAbs = fabs(w.GetDesiredYmin());
double endscale = (maxScaleAbs > minScaleAbs) ? maxScaleAbs : minScaleAbs;
if (m_labelFormat.IsEmpty()) {
/* if (m_labelFormat.IsEmpty()) {
if ((endscale < 1e4) && (endscale > 1e-3))
fmt = wxT("%.2f");
else
fmt = wxT("%.1e");
} else {
fmt = m_labelFormat;
}
}*/
/* if (tmp>=1)
{*/
// fmt = wxT("%7.5g");
@ -1009,12 +1304,11 @@ void mpScaleY::Plot(wxDC & dc, mpWindow & w)
// fmt.Printf(wxT("%%.%dg"), (tmp >= -1) ? 2 : -tmp);
// }
double n = floor( (w.GetPosY() - (double)(extend - w.GetMarginTop() - w.GetMarginBottom())/ w.GetScaleY()) / step ) * step ;
int n;
// double n = floor( (w.GetPosY() - (double)(extend - w.GetMarginTop() - w.GetMarginBottom())/ w.GetScaleY()) / step ) * step ;
/* wxCoord startPx = m_drawOutsideMargins ? 0 : w.GetMarginLeft(); */
wxCoord endPx = m_drawOutsideMargins ? w.GetScrX() : w.GetScrX() - w.GetMarginRight();
wxCoord minYpx = m_drawOutsideMargins ? 0 : w.GetMarginTop();
wxCoord maxYpx = m_drawOutsideMargins ? w.GetScrY() : w.GetScrY() - w.GetMarginBottom();
tmp=65536;
int labelW = 0;
@ -1022,8 +1316,15 @@ void mpScaleY::Plot(wxDC & dc, mpWindow & w)
int labelHeigth = 0;
s.Printf(fmt,n);
dc.GetTextExtent(s, &tx, &labelHeigth);
for (;n < end; n += step) {
const int p = (int)((w.GetPosY() - n) * w.GetScaleY());
for (n = 0; n < tickCount(); n++ ) {
printf("Tick %d\n", n);
double tp = getTickPos(n);
double py = TransformToPlot ( tp ); //( log10 ( tp ) - xlogmin) / (xlogmax - xlogmin);
const int p = (int)(( w.GetPosY() - py ) * w.GetScaleY());
if ((p >= minYpx) && (p <= maxYpx)) {
if (m_ticks) { // Draw axis ticks
if (m_flags == mpALIGN_BORDER_LEFT) {
@ -1047,7 +1348,8 @@ void mpScaleY::Plot(wxDC & dc, mpWindow & w)
dc.SetPen( m_pen);
}
// Print ticks labels
s.Printf(fmt, n);
s=getLabel(n);
dc.GetTextExtent(s, &tx, &ty);
#ifdef MATHPLOT_DO_LOGGING
if (ty != labelHeigth) wxLogMessage(wxT("mpScaleY::Plot: ty(%f) and labelHeigth(%f) differ!"), ty, labelHeigth);
@ -1141,6 +1443,7 @@ END_EVENT_TABLE()
mpWindow::mpWindow( wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long flag )
: wxWindow( parent, id, pos, size, flag, wxT("mathplot") )
{
m_zooming = false;
m_scaleX = m_scaleY = 1.0;
m_posX = m_posY = 0;
m_desiredXmin=m_desiredYmin=0;
@ -1277,13 +1580,15 @@ void mpWindow::OnMouseMove(wxMouseEvent &event)
if (event.m_leftDown) {
if (m_movingInfoLayer == NULL) {
wxClientDC dc(this);
wxPen pen(*wxBLACK, 1, wxDOT);
wxPen pen(m_fgColour, 1, wxDOT);
dc.SetPen(pen);
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawRectangle(m_mouseLClick.x, m_mouseLClick.y, event.GetX() - m_mouseLClick.x, event.GetY() - m_mouseLClick.y);
m_zooming = true;
} else {
wxPoint moveVector(event.GetX() - m_mouseLClick.x, event.GetY() - m_mouseLClick.y);
m_movingInfoLayer->Move(moveVector);
m_zooming = false;
}
UpdateAll();
} else {
@ -1313,6 +1618,7 @@ void mpWindow::OnMouseLeftDown (wxMouseEvent &event)
{
m_mouseLClick.x = event.GetX();
m_mouseLClick.y = event.GetY();
m_zooming = true;
#ifdef MATHPLOT_DO_LOGGING
wxLogMessage(_("mpWindow::OnMouseLeftDown() X = %d , Y = %d"), event.GetX(), event.GetY());/*m_mouseLClick.x, m_mouseLClick.y);*/
#endif
@ -1330,6 +1636,8 @@ void mpWindow::OnMouseLeftRelease (wxMouseEvent &event)
{
wxPoint release(event.GetX(), event.GetY());
wxPoint press(m_mouseLClick.x, m_mouseLClick.y);
m_zooming = false;
if (m_movingInfoLayer != NULL) {
m_movingInfoLayer->UpdateReference();
m_movingInfoLayer = NULL;
@ -1357,9 +1665,22 @@ void mpWindow::Fit()
// JL
void mpWindow::Fit(double xMin, double xMax, double yMin, double yMax, wxCoord *printSizeX,wxCoord *printSizeY)
{
double xExtra = fabs(xMax - xMin) * 0.00;
double yExtra = fabs(yMax - yMin) * 0.03;
xMin -= xExtra;
xMax += xExtra;
yMin -= yExtra;
yMax += yExtra;
//printf(" ******************Fit: %.3f %.3f", xMin, xMax);
// Save desired borders:
m_desiredXmin=xMin; m_desiredXmax=xMax;
m_desiredYmin=yMin; m_desiredYmax=yMax;
// printf("minx %.1f miny %.1f maxx %.1f maxy %.1f\n", xMin, yMin, xMax, yMax);
if (printSizeX!=NULL && printSizeY!=NULL)
{
@ -1577,9 +1898,13 @@ void mpWindow::ZoomOut(const wxPoint& centerPoint )
m_desiredYmax = m_posY;
m_desiredYmin = m_posY - (m_scrY - m_marginTop - m_marginBottom) / m_scaleY; // m_desiredYmin = m_posY - m_scrY / m_scaleY;
//printf("desired xmin %.1f ymin %.1f xmax %.1f ymax %.1f l %d\n", m_desiredXmin, m_desiredYmin, m_desiredXmax, m_desiredYmax, !!m_enableLimitedView);
//printf("current xmin %.1f ymin %.1f xmax %.1f ymax %.1f\n", m_minX, m_minY, m_maxX, m_maxY);
if(m_enableLimitedView && (m_desiredXmin < m_minX || m_desiredXmin < m_minX
|| m_desiredXmax > m_maxX || m_desiredXmax > m_maxX))
{
//printf("call fit()\n");
Fit();
}
@ -1907,6 +2232,16 @@ bool mpWindow::UpdateBBox()
{
bool first = TRUE;
m_minX = 0.0;
m_maxX = 1.0;
m_minY = 0.0;
m_maxY = 1.0;
return true;
#if 0
for (wxLayerList::iterator li = m_layers.begin(); li != m_layers.end(); li++)
{
mpLayer* f = *li;
@ -1936,6 +2271,9 @@ bool mpWindow::UpdateBBox()
}
//node = node->GetNext();
}
#endif
#ifdef MATHPLOT_DO_LOGGING
wxLogDebug(wxT("[mpWindow::UpdateBBox] Bounding box: Xmin = %f, Xmax = %f, Ymin = %f, YMax = %f"), m_minX, m_maxX, m_minY, m_maxY);
#endif // MATHPLOT_DO_LOGGING
@ -2384,6 +2722,57 @@ mpFXYVector::mpFXYVector(wxString name, int flags ) : mpFXY(name,flags)
m_type = mpLAYER_PLOT;
}
double mpScaleX::TransformToPlot ( double x )
{
return (x - m_minV) / (m_maxV - m_minV);
}
double mpScaleX::TransformFromPlot ( double xplot )
{
return xplot * (m_maxV - m_minV) + m_minV;
}
double mpScaleY::TransformToPlot ( double x )
{
return (x - m_minV) / (m_maxV - m_minV);
}
double mpScaleY::TransformFromPlot ( double xplot )
{
return xplot * (m_maxV - m_minV) + m_minV;
}
double mpScaleXLog::TransformToPlot ( double x )
{
double xlogmin = log10 ( m_minV );
double xlogmax = log10 ( m_maxV );
return ( log10 ( x ) - xlogmin) / (xlogmax - xlogmin);
}
double mpScaleXLog::TransformFromPlot ( double xplot )
{
double xlogmin = log10 ( m_minV );
double xlogmax = log10 ( m_maxV );
return pow(10.0, xplot * (xlogmax - xlogmin) + xlogmin );
}
double log10( double x)
{
return log(x)/log(10.0);
}
mpFSemiLogXVector::mpFSemiLogXVector(wxString name, int flags ) :
mpFXYVector ( name, flags )
{}
IMPLEMENT_DYNAMIC_CLASS(mpFSemiLogXVector, mpFXYVector)
void mpFXYVector::Rewind()
{
m_index = 0;

View File

@ -140,6 +140,8 @@ typedef enum __mp_Layer_Type {
continuity set to false (draw separate points).
These may or may not be used by implementations.
*/
class mpScaleBase;
class WXDLLIMPEXP_MATHPLOT mpLayer : public wxObject
{
public:
@ -305,6 +307,7 @@ class WXDLLIMPEXP_MATHPLOT mpLayer : public wxObject
void SetBrush(wxBrush brush) { m_brush = brush; };
protected:
wxFont m_font; //!< Layer's font
wxPen m_pen; //!< Layer's pen
wxBrush m_brush; //!< Layer's brush
@ -580,6 +583,8 @@ class WXDLLIMPEXP_MATHPLOT mpFY : public mpLayer
Optionally implement a constructor and pass a name (label) and a label alignment
to the constructor mpFXY::mpFXY. If the layer name is empty, no label will be plotted.
*/
class mpScaleBase;
class WXDLLIMPEXP_MATHPLOT mpFXY : public mpLayer
{
public:
@ -606,6 +611,12 @@ class WXDLLIMPEXP_MATHPLOT mpFXY : public mpLayer
*/
virtual void Plot(wxDC & dc, mpWindow & w);
virtual void SetScale ( mpScaleBase *scaleX, mpScaleBase *scaleY )
{
m_scaleX = scaleX;
m_scaleY = scaleY;
}
protected:
int m_flags; //!< Holds label alignment
@ -613,6 +624,7 @@ class WXDLLIMPEXP_MATHPLOT mpFXY : public mpLayer
// Data to calculate label positioning
wxCoord maxDrawX, minDrawX, maxDrawY, minDrawY;
//int drawnPoints;
mpScaleBase *m_scaleX, *m_scaleY;
/** Update label positioning data
@param xnew New x coordinate
@ -670,7 +682,90 @@ class WXDLLIMPEXP_MATHPLOT mpProfile : public mpLayer
the bottom-right hand of the ruler. The scale numbering automatically
adjusts to view and zoom factor.
*/
class WXDLLIMPEXP_MATHPLOT mpScaleX : public mpLayer
class WXDLLIMPEXP_MATHPLOT mpScaleBase : public mpLayer
{
public:
mpScaleBase () {};
virtual ~mpScaleBase () {};
bool HasBBox() { return FALSE; }
/** Set X axis alignment.
@param align alignment (choose between mpALIGN_BORDER_BOTTOM, mpALIGN_BOTTOM, mpALIGN_CENTER, mpALIGN_TOP, mpALIGN_BORDER_TOP */
void SetAlign(int align) { m_flags = align; };
/** Set X axis ticks or grid
@param ticks TRUE to plot axis ticks, FALSE to plot grid. */
void SetTicks(bool enable) { m_ticks = enable; };
/** Get X axis ticks or grid
@return TRUE if plot is drawing axis ticks, FALSE if the grid is active. */
bool GetTicks() { return m_ticks; };
//virtual double X2p( mpWindow &w, double x ) = 0;
//virtual double P2x( mpWindow &w, double x ) = 0;
void SetDataRange ( double minV, double maxV )
{
m_minV = minV;
m_maxV = maxV;
}
void GetDataRange ( double &minV, double& maxV)
{
minV = m_minV;
maxV = m_maxV;
}
virtual double TransformToPlot ( double x ) { return 0.0; };
virtual double TransformFromPlot (double xplot ){ return 0.0; };
protected:
virtual void getVisibleDataRange ( mpWindow& w, double &minV, double& maxV) {};
virtual void recalculateTicks ( wxDC & dc, mpWindow & w ) {};
virtual int tickCount() const { return 0; }
virtual int labelCount() const { return 0; }
virtual const wxString getLabel( int n ) { return wxT(""); }
virtual double getTickPos( int n ) { return 0.0; }
virtual double getLabelPos( int n ) { return 0.0; }
int m_flags; //!< Flag for axis alignment
bool m_ticks; //!< Flag to toggle between ticks or grid
double m_minV, m_maxV;
int m_maxLabelHeight;
int m_maxLabelWidth;
};
class WXDLLIMPEXP_MATHPLOT mpScaleXBase : public mpScaleBase
{
public:
/** Full constructor.
@param name Label to plot by the ruler
@param flags Set the position of the scale with respect to the window.
@param ticks Select ticks or grid. Give TRUE (default) for drawing axis ticks, FALSE for drawing the grid.
@param type mpX_NORMAL for normal labels, mpX_TIME for time axis in hours, minutes, seconds. */
mpScaleXBase(wxString name = wxT("X"), int flags = mpALIGN_CENTER, bool ticks = true, unsigned int type = mpX_NORMAL);
virtual ~mpScaleXBase () {};
/** Layer plot handler.
This implementation will plot the ruler adjusted to the visible area. */
virtual void Plot(wxDC & dc, mpWindow & w);
virtual void getVisibleDataRange ( mpWindow& w, double &minV, double& maxV);
// unsigned int m_labelType; //!< Select labels mode: mpX_NORMAL for normal labels, mpX_TIME for time axis in hours, minutes, seconds
// wxString m_labelFormat; //!< Format string used to print labels
DECLARE_DYNAMIC_CLASS(mpScaleXBase)
};
class WXDLLIMPEXP_MATHPLOT mpScaleX : public mpScaleXBase
{
public:
/** Full constructor.
@ -682,56 +777,73 @@ class WXDLLIMPEXP_MATHPLOT mpScaleX : public mpLayer
/** Layer plot handler.
This implementation will plot the ruler adjusted to the visible area. */
virtual void Plot(wxDC & dc, mpWindow & w);
/** Check whether this layer has a bounding box.
This implementation returns \a FALSE thus making the ruler invisible
to the plot layer bounding box calculation by mpWindow. */
virtual bool HasBBox() { return FALSE; }
/** Set X axis alignment.
@param align alignment (choose between mpALIGN_BORDER_BOTTOM, mpALIGN_BOTTOM, mpALIGN_CENTER, mpALIGN_TOP, mpALIGN_BORDER_TOP */
void SetAlign(int align) { m_flags = align; };
/** Set X axis ticks or grid
@param ticks TRUE to plot axis ticks, FALSE to plot grid. */
void SetTicks(bool ticks) { m_ticks = ticks; };
/** Get X axis ticks or grid
@return TRUE if plot is drawing axis ticks, FALSE if the grid is active. */
bool GetTicks() { return m_ticks; };
/** Get X axis label view mode.
@return mpX_NORMAL for normal labels, mpX_TIME for time axis in hours, minutes, seconds. */
unsigned int GetLabelMode() { return m_labelType; };
/** Set X axis label view mode.
@param mode mpX_NORMAL for normal labels, mpX_TIME for time axis in hours, minutes, seconds. */
void SetLabelMode(unsigned int mode) { m_labelType = mode; };
/** Set X axis Label format (used for mpX_NORMAL draw mode).
@param format The format string */
void SetLabelFormat(const wxString& format) { m_labelFormat = format; };
/** Get X axis Label format (used for mpX_NORMAL draw mode).
@return The format string */
const wxString& GetLabelFormat() { return m_labelFormat; };
//virtual void Plot(wxDC & dc, mpWindow & w);
//virtual double X2p( mpWindow &w, double x );
//virtual double P2x( mpWindow &w, double x );
virtual double TransformToPlot ( double x );
virtual double TransformFromPlot (double xplot );
protected:
int m_flags; //!< Flag for axis alignment
bool m_ticks; //!< Flag to toggle between ticks or grid
unsigned int m_labelType; //!< Select labels mode: mpX_NORMAL for normal labels, mpX_TIME for time axis in hours, minutes, seconds
wxString m_labelFormat; //!< Format string used to print labels
void computeLabelExtents ( wxDC & dc, mpWindow & w );
virtual void recalculateTicks ( wxDC & dc, mpWindow & w );
virtual int tickCount() const;
virtual int labelCount() const;
virtual const wxString getLabel( int n );
virtual double getTickPos( int n );
virtual double getLabelPos( int n );
double n0, dig, step, labelStep, end;
DECLARE_DYNAMIC_CLASS(mpScaleX)
};
class WXDLLIMPEXP_MATHPLOT mpScaleXLog : public mpScaleXBase
{
public:
/** Full constructor.
@param name Label to plot by the ruler
@param flags Set the position of the scale with respect to the window.
@param ticks Select ticks or grid. Give TRUE (default) for drawing axis ticks, FALSE for drawing the grid.
@param type mpX_NORMAL for normal labels, mpX_TIME for time axis in hours, minutes, seconds. */
mpScaleXLog(wxString name = wxT("log(X)"), int flags = mpALIGN_CENTER, bool ticks = true, unsigned int type = mpX_NORMAL);
virtual double TransformToPlot ( double x );
virtual double TransformFromPlot (double xplot );
/** Layer plot handler.
This implementation will plot the ruler adjusted to the visible area. */
//virtual double X2p( mpWindow &w, double x );
//virtual double P2x( mpWindow &w, double x );
protected:
void recalculateTicks ( wxDC & dc, mpWindow & w );
int tickCount() const;
int labelCount() const;
const wxString getLabel( int n );
double getTickPos( int n );
double getLabelPos( int n );
void computeLabelExtents ( wxDC & dc, mpWindow & w );
std::vector<double> m_ticks;
std::vector<double> m_labeledTicks;
double dig, step, end, n0, labelStep;
DECLARE_DYNAMIC_CLASS(mpScaleXLog)
};
/** Plot layer implementing a y-scale ruler.
If align is set to mpALIGN_CENTER, the ruler is fixed at X=0 in the coordinate system. If the align is set to mpALIGN_TOP or mpALIGN_BOTTOM, the axis is always drawn respectively at top or bottom of the window. A label is plotted at
the top-right hand of the ruler. The scale numbering automatically
adjusts to view and zoom factor.
*/
class WXDLLIMPEXP_MATHPLOT mpScaleY : public mpLayer
class WXDLLIMPEXP_MATHPLOT mpScaleY : public mpScaleBase
{
public:
/** @param name Label to plot by the ruler
@ -762,18 +874,29 @@ class WXDLLIMPEXP_MATHPLOT mpScaleY : public mpLayer
@return TRUE if plot is drawing axis ticks, FALSE if the grid is active. */
bool GetTicks() { return m_ticks; };
/** Set Y axis Label format.
@param format The format string */
void SetLabelFormat(const wxString& format) { m_labelFormat = format; };
/** Get Y axis Label format.
@return The format string */
const wxString& GetLabelFormat() { return m_labelFormat; };
virtual double TransformToPlot ( double x );
virtual double TransformFromPlot (double xplot );
protected:
virtual void getVisibleDataRange ( mpWindow& w, double &minV, double& maxV);
virtual void recalculateTicks ( wxDC & dc, mpWindow & w );
virtual int tickCount() const;
virtual int labelCount() const;
virtual const wxString getLabel( int n );
virtual double getTickPos( int n );
virtual double getLabelPos( int n );
void computeLabelExtents ( wxDC & dc, mpWindow & w );
// double m_minV, m_maxV;
int m_maxLabelHeight;
int m_maxLabelWidth;
std::vector<double> m_tickValues;
std::vector<double> m_labeledTicks;
int m_flags; //!< Flag for axis alignment
bool m_ticks; //!< Flag to toggle between ticks or grid
wxString m_labelFormat; //!< Format string used to print labels
//wxString m_labelFormat; //!< Format string used to print labels
double dig, step, end, n0, labelStep;
DECLARE_DYNAMIC_CLASS(mpScaleY)
};
@ -971,6 +1094,8 @@ class WXDLLIMPEXP_MATHPLOT mpWindow : public wxWindow
inline wxCoord y2p(double y) { return (wxCoord) ( (m_posY-y) * m_scaleY); }
/** Enable/disable the double-buffering of the window, eliminating the flicker (default=disabled).
*/
void EnableDoubleBuffer( bool enabled ) { m_enableDoubleBuffer = enabled; }
@ -1246,7 +1371,7 @@ class WXDLLIMPEXP_MATHPLOT mpWindow : public wxWindow
bool m_enableScrollBars;
wxPoint m_scroll;
mpInfoLayer* m_movingInfoLayer; //!< For moving info layers over the window area
bool m_zooming;
DECLARE_DYNAMIC_CLASS(mpWindow)
DECLARE_EVENT_TABLE()
};
@ -1320,6 +1445,7 @@ class WXDLLIMPEXP_MATHPLOT mpFXYVector : public mpFXY
*/
bool GetNextXY(double & x, double & y);
public:
/** Returns the actual minimum X data (loaded in SetData).
*/
double GetMinX() { return m_minX; }
@ -1336,11 +1462,31 @@ class WXDLLIMPEXP_MATHPLOT mpFXYVector : public mpFXY
*/
double GetMaxY() { return m_maxY; }
protected:
int m_flags; //!< Holds label alignment
DECLARE_DYNAMIC_CLASS(mpFXYVector)
};
class WXDLLIMPEXP_MATHPLOT mpFSemiLogXVector : public mpFXYVector
{
public:
/** @param name Label
@param flags Label alignment, pass one of #mpALIGN_NE, #mpALIGN_NW, #mpALIGN_SW, #mpALIGN_SE.
*/
mpFSemiLogXVector(wxString name = wxEmptyString, int flags = mpALIGN_NE);
virtual ~mpFSemiLogXVector() {}
/** Changes the internal data: the set of points to draw.
Both vectors MUST be of the same length. This method DOES NOT refresh the mpWindow; do it manually.
* @sa Clear
*/
DECLARE_DYNAMIC_CLASS(mpFSemiLogXVector)
};
//-----------------------------------------------------------------------------
// mpText - provided by Val Greene
//-----------------------------------------------------------------------------