sim: hopefully final version of plot axis unit/suffix handling.
This commit is contained in:
parent
01d18bad97
commit
b20f941bd0
|
@ -818,39 +818,21 @@ void mpScaleX::recalculateTicks ( wxDC & dc, mpWindow & w )
|
||||||
updateTickLabels( dc, w );
|
updateTickLabels( dc, w );
|
||||||
}
|
}
|
||||||
|
|
||||||
int countDecimalDigits ( double x )
|
|
||||||
{
|
|
||||||
int k = (int) ( ( x - floor(x)) * 1000000000.0 );
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
while(k && ((k % 10) == 0 || (k % 10) == 9))
|
|
||||||
{
|
|
||||||
k /= 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
|
|
||||||
while (k != 0)
|
|
||||||
{
|
|
||||||
n++;
|
|
||||||
k /= 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
int mpScaleBase::getLabelDecimalDigits(int maxDigits)
|
int mpScaleBase::getLabelDecimalDigits(int maxDigits)
|
||||||
{
|
{
|
||||||
int m = 0;
|
int m = 0;
|
||||||
|
|
||||||
for( auto l: m_tickLabels )
|
for( auto l: m_tickLabels )
|
||||||
{
|
{
|
||||||
m = std::max ( countDecimalDigits ( l.pos ), m );
|
int k = countDecimalDigits ( l.pos );
|
||||||
|
m = std::max ( k, m );
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::min(m, maxDigits);
|
return std::min(m, maxDigits);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void mpScaleBase::computeLabelExtents ( wxDC & dc, mpWindow & w )
|
void mpScaleBase::computeLabelExtents ( wxDC & dc, mpWindow & w )
|
||||||
{
|
{
|
||||||
|
@ -871,25 +853,14 @@ void mpScaleBase::computeLabelExtents ( wxDC & dc, mpWindow & w )
|
||||||
|
|
||||||
void mpScaleBase::updateTickLabels( wxDC & dc, mpWindow & w )
|
void mpScaleBase::updateTickLabels( wxDC & dc, mpWindow & w )
|
||||||
{
|
{
|
||||||
int sigDigits = 0;
|
|
||||||
|
|
||||||
for ( auto l : m_tickLabels )
|
|
||||||
sigDigits = std::max( sigDigits, countDecimalDigits( l.pos ) );
|
|
||||||
|
|
||||||
//printf("sigDigits: %d\n",sigDigits);
|
|
||||||
|
|
||||||
for ( auto &l : m_tickLabels )
|
|
||||||
{
|
|
||||||
l.label = formatLabel ( l.pos, sigDigits );
|
|
||||||
l.visible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
formatLabels();
|
||||||
computeLabelExtents(dc, w);
|
computeLabelExtents(dc, w);
|
||||||
|
|
||||||
int gap = IsHorizontal() ? m_maxLabelWidth + 10 : m_maxLabelHeight + 5;
|
// int gap = IsHorizontal() ? m_maxLabelWidth + 10 : m_maxLabelHeight + 5;
|
||||||
|
|
||||||
if ( m_tickLabels.size() <= 2)
|
//if ( m_tickLabels.size() <= 2)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
fixme!
|
fixme!
|
||||||
|
@ -1006,11 +977,14 @@ void mpScaleY::computeSlaveTicks( mpWindow& w )
|
||||||
|
|
||||||
double m;
|
double m;
|
||||||
|
|
||||||
|
m_absVisibleMaxV = 0;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < m_masterScale->m_tickValues.size(); i++)
|
for (unsigned int i = 0; i < m_masterScale->m_tickValues.size(); i++)
|
||||||
{
|
{
|
||||||
m = TransformFromPlot ( m_masterScale->TransformToPlot(m_masterScale->m_tickValues[i]) );
|
m = TransformFromPlot ( m_masterScale->TransformToPlot(m_masterScale->m_tickValues[i]) );
|
||||||
m_tickValues.push_back(m);
|
m_tickValues.push_back(m);
|
||||||
m_tickLabels.push_back( TickLabel (m) );
|
m_tickLabels.push_back( TickLabel (m) );
|
||||||
|
m_absVisibleMaxV = std::max(m_absVisibleMaxV, fabs(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1035,6 +1009,7 @@ void mpScaleY::recalculateTicks ( wxDC & dc, mpWindow & w )
|
||||||
|
|
||||||
m_absVisibleMaxV = std::max(std::abs(minVvis), std::abs(maxVvis));
|
m_absVisibleMaxV = std::max(std::abs(minVvis), std::abs(maxVvis));
|
||||||
|
|
||||||
|
|
||||||
m_tickValues.clear();
|
m_tickValues.clear();
|
||||||
m_tickLabels.clear();
|
m_tickLabels.clear();
|
||||||
|
|
||||||
|
@ -1412,24 +1387,13 @@ void mpScaleY::Plot(wxDC & dc, mpWindow & w)
|
||||||
// Draw line
|
// Draw line
|
||||||
dc.DrawLine( orgx, minYpx, orgx, maxYpx);
|
dc.DrawLine( orgx, minYpx, orgx, maxYpx);
|
||||||
|
|
||||||
// To cut the axis line when draw outside margin is false, use this code
|
|
||||||
/* if (m_drawOutsideMargins == true)
|
|
||||||
dc.DrawLine( orgx, 0, orgx, extend);
|
|
||||||
else
|
|
||||||
dc.DrawLine( orgx, w.GetMarginTop(), orgx, w.GetScrY() - w.GetMarginBottom()); */
|
|
||||||
|
|
||||||
const double dig = floor( log( 128.0 / w.GetScaleY() ) / mpLN10 );
|
|
||||||
//const double step = exp( mpLN10 * dig);
|
|
||||||
//const double end = w.GetPosY() + (double)extend / w.GetScaleY();
|
|
||||||
|
|
||||||
wxCoord tx, ty;
|
wxCoord tx, ty;
|
||||||
wxString s;
|
wxString s;
|
||||||
wxString fmt;
|
wxString fmt;
|
||||||
int tmp = (int)dig;
|
|
||||||
int n=0;
|
int n=0;
|
||||||
|
|
||||||
|
|
||||||
tmp=65536;
|
|
||||||
int labelW = 0;
|
int labelW = 0;
|
||||||
// Before staring cycle, calculate label height
|
// Before staring cycle, calculate label height
|
||||||
int labelHeigth = 0;
|
int labelHeigth = 0;
|
||||||
|
@ -1724,6 +1688,7 @@ void mpWindow::OnMouseMove(wxMouseEvent &event)
|
||||||
}
|
}
|
||||||
UpdateAll();
|
UpdateAll();
|
||||||
} else {
|
} else {
|
||||||
|
#if 0
|
||||||
wxLayerList::iterator li;
|
wxLayerList::iterator li;
|
||||||
for (li = m_layers.begin(); li != m_layers.end(); li++) {
|
for (li = m_layers.begin(); li != m_layers.end(); li++) {
|
||||||
if ((*li)->IsInfo() && (*li)->IsVisible()) {
|
if ((*li)->IsInfo() && (*li)->IsVisible()) {
|
||||||
|
@ -1733,6 +1698,7 @@ void mpWindow::OnMouseMove(wxMouseEvent &event)
|
||||||
RefreshRect(tmpLyr->GetRectangle());
|
RefreshRect(tmpLyr->GetRectangle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* if (m_coordTooltip) {
|
/* if (m_coordTooltip) {
|
||||||
wxString toolTipContent;
|
wxString toolTipContent;
|
||||||
toolTipContent.Printf(_("X = %f\nY = %f"), p2x(event.GetX()), p2y(event.GetY()));
|
toolTipContent.Printf(_("X = %f\nY = %f"), p2x(event.GetX()), p2y(event.GetY()));
|
||||||
|
|
|
@ -45,10 +45,13 @@ static wxString formatFloat (double x, int nDigits)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static wxString formatSI ( double x, const wxString& unit, int decimalDigits, double maxValue = 0.0, bool lockSuffix = false, char suffix = 0 )
|
static void getSISuffix ( double x, const wxString& unit, int& power, wxString& suffix )
|
||||||
{
|
{
|
||||||
const int n_powers = 11;
|
const int n_powers = 11;
|
||||||
const struct { double exponent; char suffix; } powers[] = {
|
const struct {
|
||||||
|
double exponent;
|
||||||
|
char suffix;
|
||||||
|
} powers[] = {
|
||||||
{-18,'a'},
|
{-18,'a'},
|
||||||
{-15,'f'},
|
{-15,'f'},
|
||||||
{-12,'p'},
|
{-12,'p'},
|
||||||
|
@ -63,62 +66,109 @@ static wxString formatSI ( double x, const wxString& unit, int decimalDigits, do
|
||||||
{15, 'P'}
|
{15, 'P'}
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( x== 0.0)
|
power = 0;
|
||||||
{
|
suffix = unit;
|
||||||
return wxT("0") + unit;
|
|
||||||
}
|
if (x == 0.0)
|
||||||
|
return;
|
||||||
|
|
||||||
for ( int i = 0; i <n_powers - 1;i++)
|
for ( int i = 0; i <n_powers - 1;i++)
|
||||||
{
|
{
|
||||||
double r_cur = pow(10, powers[i].exponent);
|
double r_cur = pow(10, powers[i].exponent);
|
||||||
bool rangeHit;
|
|
||||||
|
|
||||||
if (maxValue != 0.0)
|
if( fabs(x) >= r_cur && fabs(x) < r_cur * 1000.0 )
|
||||||
rangeHit = fabs(maxValue) >= r_cur && fabs(maxValue) < r_cur * 1000.0 ;
|
|
||||||
else
|
|
||||||
rangeHit = fabs(x) >= r_cur && fabs(x) < r_cur * 1000.0 ;
|
|
||||||
|
|
||||||
if( (!lockSuffix && rangeHit) || (lockSuffix && suffix == powers[i].suffix ) )
|
|
||||||
{
|
{
|
||||||
double v = x / r_cur;
|
power = powers[i].exponent;
|
||||||
wxString rv;
|
if ( powers[i].suffix )
|
||||||
|
suffix = wxString(powers[i].suffix) + unit;
|
||||||
rv = formatFloat ( v, decimalDigits );
|
else
|
||||||
|
suffix = unit;
|
||||||
if(powers[i].suffix)
|
return;
|
||||||
rv += powers[i].suffix;
|
|
||||||
rv += unit;
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wxT("?");
|
}
|
||||||
|
|
||||||
|
static int countDecimalDigits ( double x, int maxDigits )
|
||||||
|
{
|
||||||
|
int64_t k = (int) ( ( x - floor(x)) * pow ( 10.0, (double) maxDigits ));
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
while(k && ((k % 10LL) == 0LL || (k % 10LL) == 9LL))
|
||||||
|
{
|
||||||
|
k /= 10LL;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
|
||||||
|
while (k != 0LL)
|
||||||
|
{
|
||||||
|
n++;
|
||||||
|
k /= 10LL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class FREQUENCY_LIN_SCALE : public mpScaleX
|
static void formatSILabels( mpScaleBase *scale, const wxString& aUnit, int nDigits )
|
||||||
{
|
{
|
||||||
public:
|
double maxVis = scale->AbsVisibleMaxValue();
|
||||||
FREQUENCY_LIN_SCALE(wxString name, int flags, bool ticks = false, unsigned int type = 0) :
|
|
||||||
mpScaleX( name, flags, ticks ,type ) {};
|
|
||||||
|
|
||||||
const wxString formatLabel( double value, int nDigits )
|
wxString suffix;
|
||||||
|
int power, digits = 0;
|
||||||
|
|
||||||
|
getSISuffix( maxVis, aUnit, power, suffix);
|
||||||
|
|
||||||
|
double sf = pow(10.0, power);
|
||||||
|
|
||||||
|
for ( auto &l : scale->TickLabels() )
|
||||||
{
|
{
|
||||||
return formatSI ( value, wxT("Hz"), std::min(nDigits, 2) );
|
int k = countDecimalDigits( l.pos / sf, nDigits );
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
digits = std::max(digits, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( auto &l : scale->TickLabels() )
|
||||||
|
{
|
||||||
|
l.label = formatFloat ( l.pos / sf, digits ) + suffix;
|
||||||
|
l.visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class FREQUENCY_LOG_SCALE : public mpScaleXLog
|
class FREQUENCY_LOG_SCALE : public mpScaleXLog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FREQUENCY_LOG_SCALE(wxString name, int flags, bool ticks = false, unsigned int type = 0) :
|
FREQUENCY_LOG_SCALE(wxString name, int flags) :
|
||||||
mpScaleXLog( name, flags, ticks ,type ) {};
|
mpScaleXLog( name, flags ) {};
|
||||||
|
|
||||||
const wxString formatLabel( double value, int nDigits )
|
void formatLabels()
|
||||||
{
|
{
|
||||||
return formatSI ( value, wxT("Hz"), std::min(nDigits, 2) );
|
const wxString unit = wxT("Hz");
|
||||||
|
wxString suffix;
|
||||||
|
int power;
|
||||||
|
|
||||||
|
for ( auto &l : TickLabels() )
|
||||||
|
{
|
||||||
|
getSISuffix( l.pos, unit, power, suffix);
|
||||||
|
double sf = pow(10.0, power);
|
||||||
|
int k = countDecimalDigits( l.pos / sf, 3 );
|
||||||
|
|
||||||
|
l.label = formatFloat ( l.pos / sf, k ) + suffix;
|
||||||
|
l.visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FREQUENCY_LIN_SCALE : public mpScaleX
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FREQUENCY_LIN_SCALE(wxString name, int flags) :
|
||||||
|
mpScaleX( name, flags, false , 0 ) {};
|
||||||
|
|
||||||
|
void formatLabels()
|
||||||
|
{
|
||||||
|
formatSILabels( this, wxT("Hz"), 3 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,72 +176,74 @@ public:
|
||||||
class TIME_SCALE : public mpScaleX
|
class TIME_SCALE : public mpScaleX
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TIME_SCALE(wxString name, int flags, bool ticks = false, unsigned int type = 0) :
|
TIME_SCALE(wxString name, int flags) :
|
||||||
mpScaleX ( name, flags, ticks ,type ) {};
|
mpScaleX ( name, flags, false, 0) {};
|
||||||
|
|
||||||
const wxString formatLabel( double value, int nDigits )
|
void formatLabels()
|
||||||
{
|
{
|
||||||
return formatSI ( value, wxT("s"), std::min(nDigits, 3), AbsVisibleMaxValue() );
|
formatSILabels( this, wxT("s"), 3 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class VOLTAGE_SCALE_X : public mpScaleX
|
class VOLTAGE_SCALE_X : public mpScaleX
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VOLTAGE_SCALE_X(wxString name, int flags, bool ticks = false, unsigned int type = 0) :
|
VOLTAGE_SCALE_X(wxString name, int flags) :
|
||||||
mpScaleX ( name, flags, ticks, type ) {};
|
mpScaleX ( name, flags, false, 0 ) {};
|
||||||
|
|
||||||
const wxString formatLabel( double value, int nDigits )
|
void formatLabels()
|
||||||
{
|
{
|
||||||
return formatSI ( value, wxT("V"), std::min(nDigits, 3), AbsVisibleMaxValue() );
|
formatSILabels( this, wxT("V"), 3 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GAIN_SCALE : public mpScaleY
|
class GAIN_SCALE : public mpScaleY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GAIN_SCALE(wxString name, int flags, bool ticks = false, unsigned int type = 0) :
|
GAIN_SCALE( wxString name, int flags ) :
|
||||||
mpScaleY ( name, flags, ticks ) {};
|
mpScaleY ( name, flags, false) {};
|
||||||
|
|
||||||
const wxString formatLabel( double value, int nDigits )
|
void formatLabels()
|
||||||
{
|
{
|
||||||
return formatSI ( value, wxT("dB"), std::min(nDigits, 1), AbsVisibleMaxValue(), true, 0 );
|
formatSILabels( this, wxT("dB"), 3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PHASE_SCALE : public mpScaleY
|
class PHASE_SCALE : public mpScaleY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PHASE_SCALE(wxString name, int flags, bool ticks = false, unsigned int type = 0) :
|
PHASE_SCALE(wxString name, int flags) :
|
||||||
mpScaleY ( name, flags, ticks ) {};
|
mpScaleY ( name, flags, false ) {};
|
||||||
|
|
||||||
const wxString formatLabel( double value, int nDigits )
|
void formatLabels()
|
||||||
{
|
{
|
||||||
return formatSI ( value, wxT("\u00B0"), std::min(nDigits, 1), AbsVisibleMaxValue(), true, 0 );
|
formatSILabels( this, wxT("\u00B0"), 3 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class VOLTAGE_SCALE_Y : public mpScaleY
|
class VOLTAGE_SCALE_Y : public mpScaleY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VOLTAGE_SCALE_Y(wxString name, int flags, bool ticks = false, unsigned int type = 0) :
|
VOLTAGE_SCALE_Y(wxString name, int flags) :
|
||||||
mpScaleY ( name, flags, ticks ) {};
|
mpScaleY ( name, flags, false ) {};
|
||||||
|
|
||||||
const wxString formatLabel( double value, int nDigits )
|
void formatLabels()
|
||||||
{
|
{
|
||||||
return formatSI ( value, wxT("V"), std::min(nDigits, 3), AbsVisibleMaxValue() );
|
formatSILabels( this, wxT("V"), 3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CURRENT_SCALE : public mpScaleY
|
class CURRENT_SCALE : public mpScaleY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CURRENT_SCALE(wxString name, int flags, bool ticks = false, unsigned int type = 0) :
|
CURRENT_SCALE(wxString name, int flags ) :
|
||||||
mpScaleY ( name, flags, ticks ) {};
|
mpScaleY ( name, flags, false ) {};
|
||||||
|
|
||||||
const wxString formatLabel( double value, int nDigits )
|
void formatLabels()
|
||||||
{
|
{
|
||||||
return formatSI ( value, wxT("A"), std::min(nDigits, 3), AbsVisibleMaxValue() );
|
formatSILabels( this, wxT("A"), 3 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -764,6 +764,18 @@ public:
|
||||||
virtual double TransformToPlot ( double x ) { return 0.0; };
|
virtual double TransformToPlot ( double x ) { return 0.0; };
|
||||||
virtual double TransformFromPlot (double xplot ){ return 0.0; };
|
virtual double TransformFromPlot (double xplot ){ return 0.0; };
|
||||||
|
|
||||||
|
struct TickLabel {
|
||||||
|
TickLabel( double pos_=0.0, const wxString& label_ = wxT("") ) :
|
||||||
|
pos ( pos_ ),
|
||||||
|
label ( label_ ) {};
|
||||||
|
double pos;
|
||||||
|
wxString label;
|
||||||
|
int pixelPos;
|
||||||
|
bool visible;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<TickLabel>& TickLabels() { return m_tickLabels; };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -771,7 +783,7 @@ protected:
|
||||||
void updateTickLabels( wxDC & dc, mpWindow & w );
|
void updateTickLabels( wxDC & dc, mpWindow & w );
|
||||||
void computeLabelExtents ( wxDC & dc, mpWindow & w );
|
void computeLabelExtents ( wxDC & dc, mpWindow & w );
|
||||||
|
|
||||||
virtual int getLabelDecimalDigits(int maxDigits);
|
//virtual int getLabelDecimalDigits(int maxDigits);
|
||||||
virtual void getVisibleDataRange ( mpWindow& w, double &minV, double& maxV) {};
|
virtual void getVisibleDataRange ( mpWindow& w, double &minV, double& maxV) {};
|
||||||
virtual void recalculateTicks ( wxDC & dc, mpWindow & w ) {};
|
virtual void recalculateTicks ( wxDC & dc, mpWindow & w ) {};
|
||||||
|
|
||||||
|
@ -786,6 +798,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const wxString formatLabel( double value, int nDigits ) { return wxT(""); }
|
virtual const wxString formatLabel( double value, int nDigits ) { return wxT(""); }
|
||||||
|
virtual void formatLabels( ) { };
|
||||||
|
|
||||||
virtual double getTickPos( int n )
|
virtual double getTickPos( int n )
|
||||||
{
|
{
|
||||||
|
@ -803,16 +816,6 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct TickLabel {
|
|
||||||
TickLabel( double pos_=0.0, const wxString& label_ = wxT("") ) :
|
|
||||||
pos ( pos_ ),
|
|
||||||
label ( label_ ) {};
|
|
||||||
double pos;
|
|
||||||
wxString label;
|
|
||||||
int pixelPos;
|
|
||||||
bool visible;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<double> m_tickValues;
|
std::vector<double> m_tickValues;
|
||||||
std::vector<TickLabel> m_tickLabels;
|
std::vector<TickLabel> m_tickLabels;
|
||||||
|
|
Loading…
Reference in New Issue