sim: hopefully final version of plot axis unit/suffix handling.

This commit is contained in:
Tomasz Wlostowski 2016-08-11 14:42:10 +02:00 committed by Maciej Suminski
parent 01d18bad97
commit b20f941bd0
3 changed files with 141 additions and 120 deletions

View File

@ -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()));

View File

@ -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 );
} }
}; };

View File

@ -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;