📄 chartaxis.cpp
字号:
CSize TextSize = pDC->GetTextExtent(szBuff);
if (!m_bIsSecondary)
pDC->ExtTextOut(HorizPos-TextSize.cx/2,m_ObjectRect.top+5,ETO_CLIPPED|ETO_OPAQUE,NULL,szBuff,NULL);
else
pDC->ExtTextOut(HorizPos-TextSize.cx/2,m_ObjectRect.bottom-5-TextSize.cy,ETO_CLIPPED|ETO_OPAQUE,NULL,szBuff,NULL);
if (!m_bIsLogarithmic)
TickValue += m_TickIncrement;
else
TickValue *= m_TickIncrement;
TickCount++;
}
}
else
{
if (!m_bIsSecondary)
{
pDC->MoveTo(m_ObjectRect.right-1,m_StartPos);
pDC->LineTo(m_ObjectRect.right-1,m_EndPos);
}
else
{
pDC->MoveTo(m_ObjectRect.left+1,m_StartPos);
pDC->LineTo(m_ObjectRect.left+1,m_EndPos);
}
if (m_MinValue == m_MaxValue)
{
int VertPos = m_EndPos + (int)fabs((m_EndPos-m_StartPos)/2.0);
if (!m_bIsSecondary)
{
pDC->MoveTo(m_ObjectRect.right-1,VertPos);
pDC->LineTo(m_ObjectRect.right-4,VertPos);
}
else
{
pDC->MoveTo(m_ObjectRect.left+1,VertPos);
pDC->LineTo(m_ObjectRect.left+4,VertPos);
}
if (!m_bIsLogarithmic)
{
szBuff.Format(_T("%.*f"),m_DecCount,TickValue);
}
else
{
int LogDecCount = (int)(log10(TickValue));
szBuff.Format(_T("%.*f"),LogDecCount,TickValue);
}
CSize TextSize = pDC->GetTextExtent(szBuff);
if (!m_bIsSecondary)
pDC->ExtTextOut(LabelSize.cx+m_ObjectRect.left+2,VertPos-TextSize.cy/2,ETO_CLIPPED|ETO_OPAQUE,NULL,szBuff,NULL);
else
pDC->ExtTextOut(m_ObjectRect.left+6,VertPos-TextSize.cy/2,ETO_CLIPPED|ETO_OPAQUE,NULL,szBuff,NULL);
}
else while ( (TickValue<=m_MaxValue) || (TickValue-m_MaxValue < 0.0000001) )
{
int VertPos = ValueToScreen(TickValue);
if (!m_bIsInverted)
FirstTickPos = VertPos;
if (!m_bIsSecondary)
{
pDC->MoveTo(m_ObjectRect.right-1,VertPos);
pDC->LineTo(m_ObjectRect.right-4,VertPos);
}
else
{
pDC->MoveTo(m_ObjectRect.left+1,VertPos);
pDC->LineTo(m_ObjectRect.left+4,VertPos);
}
if (!m_bIsLogarithmic)
{
szBuff.Format(_T("%.*f"),m_DecCount,TickValue);
}
else
{
int LogDecCount = (int)(log10(TickValue));
if (LogDecCount<0)
LogDecCount = (int)fabs(LogDecCount*1.0)+1;
else
LogDecCount = 0;
szBuff.Format(_T("%.*f"),LogDecCount,TickValue);
}
CSize TextSize = pDC->GetTextExtent(szBuff);
if(!m_bIsSecondary)
pDC->ExtTextOut(m_ObjectRect.left+LabelSize.cx+4,VertPos-TextSize.cy/2,ETO_CLIPPED|ETO_OPAQUE,NULL,szBuff,NULL);
else
pDC->ExtTextOut(m_ObjectRect.left+6,VertPos-TextSize.cy/2,ETO_CLIPPED|ETO_OPAQUE,NULL,szBuff,NULL);
if (!m_bIsLogarithmic)
TickValue += m_TickIncrement;
else
TickValue *= m_TickIncrement;
TickCount++;
}
}
CRect Size = m_pParent->GetPlottingRect();
m_pAxisGrid->SetRect(Size);
double TickSpace = 0;
if (m_bIsLogarithmic)
{
m_TickIncrement = 10;
TickSpace = log10(m_TickIncrement) * GetAxisLenght()/(log10(m_MaxValue)-log10(m_MinValue));
}
else
TickSpace = m_TickIncrement * GetAxisLenght()/(m_MaxValue-m_MinValue);
m_pAxisGrid->SetTicksCount(TickCount);
m_pAxisGrid->Draw(pDC);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldFont);
}
void CChartAxis::SetMinMax(double Minimum, double Maximum)
{
if (Minimum > Maximum)
{
TRACE(_T("Maximum axis value must be > minimum axis value"));
return;
}
m_MinValue = m_UnzoomMin = Minimum;
m_MaxValue = m_UnzoomMax = Maximum;
}
void CChartAxis::SetInverted(bool bNewValue)
{
m_bIsInverted = bNewValue;
}
int CChartAxis::GetAxisLenght() const
{
int Length = (int)fabs( (m_EndPos-m_StartPos) * 1.0);
return Length;
}
void CChartAxis::CalculateTicksIncrement()
{
if (!m_bAutoTicks)
{
CalculateFirstTick();
return;
}
//Calculate the appropriate TickSpace (1 tick every 30 pixel +/-)
if (m_bIsLogarithmic)
m_TickIncrement = 10;
else
{
int PixelSpace;
if (m_bIsHorizontal)
PixelSpace = 25;
else
PixelSpace = 20;
int MaxTickNumber = (int)fabs((m_EndPos-m_StartPos)/PixelSpace * 1.0);
//Best Tick Space
double TempTickSpace = (m_MaxValue-m_MinValue)/MaxTickNumber;
// Calculate appropriate tickSpace (not rounded on 'strange values' but
// on something like 1, 2 or 5*10^X where X is optimalized for showing the most
// significant digits)
int Zeros = (int)floor(log10(TempTickSpace));
double MinTickSpace = pow(10.0,Zeros);
int Digits = 0;
if (Zeros<0) //must set digits
{
Digits = (int)fabs(Zeros*1.0);
}
if (MinTickSpace>=TempTickSpace)
{
m_TickIncrement = MinTickSpace;
SetDecimals(Digits);
}
else if (MinTickSpace*2>=TempTickSpace)
{
m_TickIncrement = MinTickSpace*2;
SetDecimals(Digits);
}
else if (MinTickSpace*5>=TempTickSpace)
{
m_TickIncrement = MinTickSpace*5;
SetDecimals(Digits);
}
else if (MinTickSpace*10>=TempTickSpace)
{
m_TickIncrement = MinTickSpace*10;
if (Digits)
SetDecimals(Digits-1);
else
SetDecimals(Digits);
}
}
CalculateFirstTick();
}
void CChartAxis::CalculateFirstTick()
{
if (m_bIsLogarithmic)
{
int LogBase = (int)log10(m_MinValue);
m_FirstTickVal = pow(10.0,LogBase);
}
else
{
m_FirstTickVal = 0;
if (m_TickIncrement!=0)
{
if (m_MinValue == 0)
m_FirstTickVal = 0;
else if (m_MinValue>0)
{
m_FirstTickVal = (int)(m_MinValue/m_TickIncrement) * m_TickIncrement;
while (m_FirstTickVal<m_MinValue)
m_FirstTickVal += m_TickIncrement;
}
else
{
m_FirstTickVal = (int)(m_MinValue/m_TickIncrement) * m_TickIncrement;
while (m_FirstTickVal>m_MinValue)
m_FirstTickVal -= m_TickIncrement;
if (!(m_FirstTickVal == m_MinValue))
m_FirstTickVal += m_TickIncrement;
}
}
}
}
long CChartAxis::GetTickScreenPos(int TickIndex) const
{
double TickVal = 0;
if (!m_bIsLogarithmic)
TickVal = m_FirstTickVal + TickIndex * m_TickIncrement;
else
TickVal = m_FirstTickVal * pow(m_TickIncrement,TickIndex);
return ValueToScreen(TickVal);
}
long CChartAxis::ValueToScreen(double Value) const
{
long Offset = 0;
if (m_bIsLogarithmic)
Offset = (int)floor((log10(Value)-log10(m_MinValue)) * GetAxisLenght()/(log10(m_MaxValue)-log10(m_MinValue)) );
else
{
Offset = (int)floor( (Value - m_MinValue) * GetAxisLenght()/(m_MaxValue-m_MinValue) );
}
if (m_bIsHorizontal)
{
if (!m_bIsInverted)
return (m_StartPos + Offset);
else
return (m_EndPos - Offset);
}
else
{
if (!m_bIsInverted)
return (m_StartPos - Offset);
else
return (m_EndPos + Offset);
}
}
double CChartAxis::ScreenToValue(long ScreenVal) const
{
int AxisOffset = 0;
if (!m_bIsHorizontal)
{
if (m_bIsInverted)
AxisOffset = ScreenVal - m_EndPos;
else
AxisOffset = m_StartPos - ScreenVal;
}
else
{
if (!m_bIsInverted)
AxisOffset = ScreenVal - m_StartPos;
else
AxisOffset = m_EndPos - ScreenVal;
}
if (!m_bIsLogarithmic)
return ( (AxisOffset * 1.0 / GetAxisLenght()*(m_MaxValue-m_MinValue)) + m_MinValue);
else
return (pow(10.0,(AxisOffset *1.0 / GetAxisLenght()*(log10(m_MaxValue)-log10(m_MinValue)) ) + log10(m_MinValue)) );
}
void CChartAxis::PanAxis(long PanStart, long PanEnd)
{
double StartVal = ScreenToValue(PanStart);
double EndVal = ScreenToValue(PanEnd);
if (!m_bIsLogarithmic)
{
double Shift = StartVal - EndVal;
SetZoomMinMax(m_MinValue+Shift,m_MaxValue+Shift);
}
else
{
double Factor = StartVal/EndVal;
SetZoomMinMax(m_MinValue*Factor,m_MaxValue*Factor);
}
}
void CChartAxis::SetZoomMinMax(double Minimum, double Maximum)
{
if (Minimum > Maximum)
{
TRACE(_T("Maximum axis value must be > minimum axis value"));
return;
}
m_MinValue = Minimum;
m_MaxValue = Maximum;
}
void CChartAxis::UndoZoom()
{
SetMinMax(m_UnzoomMin,m_UnzoomMax);
}
void CChartAxis::RegisterSeries(CChartSerie* pSeries)
{
// First check if the series is already present in the list
SeriesList::iterator iter = m_pRelatedSeries.begin();
for (iter; iter!=m_pRelatedSeries.end(); iter++)
{
if ( (*iter) == pSeries)
return;
}
m_pRelatedSeries.push_back(pSeries);
}
void CChartAxis::UnregisterSeries(CChartSerie* pSeries)
{
SeriesList::iterator iter = m_pRelatedSeries.begin();
for (iter; iter!=m_pRelatedSeries.end(); iter++)
{
if ( (*iter) == pSeries)
{
m_pRelatedSeries.erase(iter);
return;
}
}
}
void CChartAxis::RefreshAutoAxis()
{
if (!m_bIsAutomatic)
return;
double SeriesMin = 0;
double SeriesMax = 0;
double TempMin = 0;
double TempMax = 0;
SeriesList::iterator iter = m_pRelatedSeries.begin();
if (iter != m_pRelatedSeries.end())
{
if (m_bIsHorizontal)
(*iter)->GetSerieXMinMax(SeriesMin,SeriesMax);
else
(*iter)->GetSerieYMinMax(SeriesMin,SeriesMax);
}
for (iter; iter!=m_pRelatedSeries.end(); iter++)
{
if (m_bIsHorizontal)
(*iter)->GetSerieXMinMax(TempMin,TempMax);
else
(*iter)->GetSerieYMinMax(TempMin,TempMax);
if (TempMin < SeriesMin)
SeriesMin = TempMin;
if (TempMax > SeriesMax)
SeriesMax = TempMax;
}
if ( (SeriesMax>m_MaxValue) || (SeriesMin<m_MinValue) )
{
SetMinMax(SeriesMin,SeriesMax);
m_pParent->RefreshCtrl();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -