📄 xgraphaxis.cpp
字号:
}
if (bFound == TRUE)
break;
}
m_fCurMin = pow(10.0,floor(log10(m_fCurMin)));
m_fCurMax = pow(10.0,ceil(log10(m_fCurMax)));
return;
}
int nScaleTicks;
if (m_AxisKind == yAxis)
{
m_fSpareRange = (2 * m_nArcSize);
m_fMarkerSpareSize = DrawCurveMarkers(pDC, false);
int nTop = m_pGraph->m_clInnerRect.top + m_fSpareRange + m_fMarkerSpareSize;
int nBottom = m_pGraph->m_clInnerRect.bottom;
int nHeight = GetMaxLabelHeight(pDC);
int nRange = nBottom - nTop;
nScaleTicks = max(2, (int)((double) nRange / (double) nHeight));
}
else
{
m_fSpareRange = (4 * m_nArcSize);
m_fMarkerSpareSize = DrawCurveMarkers(pDC, false);
int nLeft = m_pGraph->m_clInnerRect.left;
int nRight = m_pGraph->m_clInnerRect.right - m_fSpareRange - m_fMarkerSpareSize;
int nWidth = GetMaxLabelWidth(pDC);
int nRange = nRight - nLeft;
nScaleTicks = max(2, (int)((double) nRange / (double) nWidth));
}
double fStep;
if (m_bDateTime)
{
FitTimeScale(&fStep, nScaleTicks, m_fCurMin, m_fCurMax);
if (fStep > 0.0)
{
m_fStep = fStep;
AdaptTimeAxis(&m_fCurMin, &m_fCurMax, m_fStep);
}
}
else
{
FitScale(&fStep, nScaleTicks, m_fCurMin, m_fCurMax);
if (fStep > 0.0)
{
m_fStep = fStep;
AdaptAxis(&m_fCurMin, &m_fCurMax, m_fStep);
}
}
}
double CXGraphAxis::GetValueForPos(int nPos)
{
if (m_AxisType == atLog)
{
double fVal = 0.0;
double fRange = log10(m_fCurMax) - log10(m_fCurMin);
if (m_AxisKind == yAxis)
fVal = pow(10.0,-(nPos-m_pGraph->m_clInnerRect.bottom)/(double)m_nRange *fRange + log10(m_fCurMin));
else
fVal = pow(10.0, (nPos-m_pGraph->m_clInnerRect.left)/(double)m_nRange * fRange + log10(m_fCurMin));
return fVal;
}
double fVal;
m_fRange = m_fCurMax - m_fCurMin;
if (m_AxisKind == yAxis)
fVal = (-(nPos - m_pGraph->m_clInnerRect.bottom)) / ((double) m_nRange / m_fRange) + m_fCurMin;
else
fVal = (nPos - m_pGraph->m_clInnerRect.left) / ((double) m_nRange / m_fRange) + m_fCurMin;
return fVal;
}
CPoint CXGraphAxis::GetPointForValue(TDataPoint* point)
{
if (m_AxisType == atLog)
{
CPoint res = CPoint(0,0);
m_fRange = m_fCurMax - m_fCurMin;
double ratio = 0.0;
if (m_AxisKind == yAxis)
{
ratio = (log10(point->fYVal) - log10(m_fCurMin))/(log10(m_fCurMax)-log10(m_fCurMin));
res.y = m_pGraph->m_clInnerRect.bottom - ratio * (double) m_nRange;
}
else
{
ratio = (log10(point->fXVal) - log10(m_fCurMin))/(log10(m_fCurMax)-log10(m_fCurMin));
res.x = m_pGraph->m_clInnerRect.left + ratio * (double) m_nRange;
}
return res;
}
CPoint res;
m_fRange = m_fCurMax - m_fCurMin;
if (m_AxisKind == yAxis)
res.y = m_pGraph->m_clInnerRect.bottom - ((point->fYVal - m_fCurMin) * ((double) m_nRange / m_fRange));
else
res.x = m_pGraph->m_clInnerRect.left + ((point->fXVal - m_fCurMin) * ((double) m_nRange / m_fRange));
return res;
}
void CXGraphAxis::GetRange(double&fMin, double& fMax, double& fStep)
{
fMin = m_fCurMin;
fMax = m_fCurMax;
fStep = m_fStep;
}
void CXGraphAxis::Scale(double fFactor)
{
if (!m_bDateTime)
SetCurrentRange(m_fCurMin / fFactor, m_fCurMax / fFactor);
else
{
COleDateTimeSpan range (m_fCurMax - m_fCurMin);
int nSeconds = range.GetTotalSeconds () / fFactor;
m_fCurMin += COleDateTimeSpan(0,0,0, nSeconds);
m_fCurMax -= COleDateTimeSpan(0,0,0, nSeconds);
}
}
void CXGraphAxis::GetIndexByXVal(long& nIndex, double x, int nCurve)
{
double dStep;
dStep = fabs(m_pGraph->m_Data[nCurve].m_pData[1].fXVal - m_pGraph->m_Data[nCurve].m_pData[0].fXVal);
nIndex = (long)((x - m_pGraph->m_Data[nCurve].m_pData[0].fXVal) / dStep);
if (nIndex < 0)
nIndex = 0;
if (nIndex >= m_pGraph->m_Data[nCurve].m_nCount)
nIndex = m_pGraph->m_Data[nCurve].m_nCount - 1;
if (m_pGraph->m_Data[nCurve].m_pData[nIndex].fXVal > x)
{
while (nIndex > 0 && m_pGraph->m_Data[nCurve].m_pData[nIndex].fXVal > x)
nIndex --;
}
else
{
while (nIndex < m_pGraph->m_Data[nCurve].m_nCount && m_pGraph->m_Data[nCurve].m_pData[nIndex].fXVal <= x)
nIndex ++;
}
}
double CXGraphAxis::RoundDouble(double doValue, int nPrecision)
{
static const double doBase = 10.0f;
double doComplete5, doComplete5i;
doComplete5 = doValue * pow(doBase, (double) (nPrecision + 1));
if(doValue < 0.0f)
doComplete5 -= 5.0f;
else
doComplete5 += 5.0f;
doComplete5 /= doBase;
modf(doComplete5, &doComplete5i);
return doComplete5i / pow(doBase, (double) nPrecision);
}
// bypass that silly fmod problem (results unexpected due to binary representation)
// saveFmod(1.0,0.2) correctly returns 0.0 instead of 0.2
// complexity is O(x/y)
double saveFmod(double x, double y)
{
double fRes = 0.0;
while ((fRes+y) <= fabs(x))
fRes += y;
if (x < 0.0)
return x + fRes;
else
return x - fRes;
}
void CXGraphAxis::AdaptAxis(double* fStart, double* fEnd, double fStep)
{
double fRemainder;
fRemainder = saveFmod(*fStart-fStep, fStep);
if (fRemainder != 0.0)
*fStart -= fRemainder + fStep;
fRemainder = saveFmod(*fEnd+fStep, fStep);
if (fRemainder != 0.0)
*fEnd -= fRemainder - fStep;
}
void CXGraphAxis::AdaptTimeAxis(double * pfStart, double * pfEnd, double fStep)
{
double fDummy;
unsigned long iDummy;
int iModulo = 0;
COleDateTimeSpan cSpan;
COleDateTime cOffset,
cStart,
cEnd;
double lSeconds;
cOffset.SetDateTime (1970, 1, 1, 0, 0, 0);
// Get Step in seconds
fStep *= 24 * 3600;
cStart = *pfStart;
cSpan = cStart - cOffset;
lSeconds = cSpan.GetTotalSeconds ();
if (fStep > 0.0)
iModulo = ((long) lSeconds - (long) fStep) % (long)fStep;
if (iModulo != 0)
{
iDummy = (unsigned long) lSeconds / (unsigned long) fStep;
fDummy = (double) ((iDummy) * (unsigned long)fStep);
*pfStart = (DATE)(COleDateTime(fDummy / 24.0 / 3600.0)) + cOffset ;
}
CString ccStart = COleDateTime(*pfStart).Format ();
cEnd = *pfEnd;
cSpan = cEnd - cOffset;
lSeconds = cSpan.GetTotalSeconds ();
if (fStep > 0.0)
iModulo = ((long) lSeconds - (long) fStep) % (long)fStep;
if (iModulo != 0)
{
iDummy = (unsigned long) lSeconds / (unsigned long) fStep;
fDummy = (double) ((iDummy+1) * (unsigned long)fStep);
CString ccEnd = COleDateTime(*pfEnd).Format ();
*pfEnd = (DATE)(COleDateTime(fDummy / 24.0 / 3600.0)) + cOffset ;
}
CString ccEnd = COleDateTime(*pfEnd).Format ();
}
void CXGraphAxis::FitTimeScale(double *fStepWidth, int nBestCount, double fStart, double fEnd)
{
COleDateTime cStart, cEnd;
COleDateTimeSpan cSpan;
double fStep;
double fSpan;
cStart = fStart;
cEnd = fEnd;
cSpan = cEnd - cStart;
fSpan = cSpan.GetTotalSeconds ();
if(nBestCount > 0)
fStep = fSpan / (double)nBestCount;
else
fStep = 0;
for (int i = 1; TimeStepTable[i] != -1; i++)
{
if (fStep > TimeStepTable[i-1] && fStep <= TimeStepTable[i])
{
fStep = TimeStepTable[i];
break;
}
}
*fStepWidth = fStep;
*fStepWidth /= 24.0 * 3600;
}
void CXGraphAxis::FitScale (double *fStepWidth, int nBestCount, double fStart, double fEnd)
{
double fSize;
double fStep;
double fDivider;
int nDecimalCount = 0;
fSize = fEnd - fStart;
fStep = fSize / (double) nBestCount;
if (fStep == 0.0)
return;
if (fStep < 1.0 && (int)fStep == 0)
fDivider = 10.0;
else
fDivider = 0.1;
if (fStep >= 1.0)
{
for (nDecimalCount = 0; fStep >= 1.0; fStep *= fDivider, nDecimalCount++);
fStep = fStep * (double)10.0;
nDecimalCount--;
}
else
{
for (nDecimalCount = 0; fStep < 1.0; fStep *= fDivider, nDecimalCount--);
}
if (fStep > 0.0f && fStep <= 1.0)
fStep = 1.0;
if (fStep > 1.0f && fStep <= 2.0)
fStep = 2.0;
if (fStep > 2.0f && fStep <= 5.0)
fStep = 5.0;
if (fStep > 5.0f && fStep <= 10.0)
fStep = 10.0;
*fStepWidth = (double)((int)fStep * pow (10.0, (double)nDecimalCount));
if (*fStepWidth == 0.0)
*fStepWidth = 0.1;
}
void CXGraphAxis::Serialize( CArchive& archive )
{
LOGFONT font;
int nHelper;
CObject::Serialize (archive);
if( archive.IsStoring() )
{
archive << m_bAutoScale;
archive << m_bVisible;
archive << m_bShowGrid;
archive << m_cDisplayFmt;
archive << m_cLabel;
archive << m_fMax;
archive << m_fMin;
archive << m_fCurMax;
archive << m_fCurMin;
archive << m_fStep;
archive << m_nTop;
archive << m_nLeft;
nHelper = (int) m_AxisKind;
archive << nHelper;
archive << m_nArcSize;
archive << m_nTickSize;
archive << m_crColor;
archive << m_crGridColor;
archive << m_nGridStyle;
archive << m_fSpareRange;
archive << m_bDateTime;
archive << m_fMarkerSpareSize;
archive << m_fRange;
archive << m_nRange;
archive << m_nMarkerSize;
nHelper = (int) m_Placement;
archive << nHelper;
archive << m_bShowMarker;
archive << m_ColorRanges.size();
for (int i = 0; i < m_ColorRanges.size(); i++)
archive.Write(&m_ColorRanges[i], sizeof(COLORRANGE));
archive << m_AxisMarkers.size();
for (i = 0; i < m_AxisMarkers.size(); i++)
archive.Write(&m_AxisMarkers[i], sizeof(AXISMARKER));
m_Font.GetLogFont (&font);
archive.Write(&font, sizeof(LOGFONT));
m_TitleFont.GetLogFont (&font);
archive.Write(&font, sizeof(LOGFONT));
}
else
{
archive >> m_bAutoScale;
archive >> m_bVisible;
archive >> m_bShowGrid;
archive >> m_cDisplayFmt;
archive >> m_cLabel;
archive >> m_fMax;
archive >> m_fMin;
archive >> m_fCurMax;
archive >> m_fCurMin;
archive >> m_fStep;
archive >> m_nTop;
archive >> m_nLeft;
archive >> nHelper;
m_AxisKind = (EAxisKind) nHelper;
archive >> m_nArcSize;
archive >> m_nTickSize;
archive >> m_crColor;
archive >> m_crGridColor;
archive >> m_nGridStyle;
archive >> m_fSpareRange;
archive >> m_bDateTime;
archive >> m_fMarkerSpareSize;
archive >> m_fRange;
archive >> m_nRange;
archive >> m_nMarkerSize;
archive >> nHelper;
m_Placement = (EAxisPlacement) nHelper;
archive >> m_bShowMarker;
archive >> nHelper;
for (int i = 0; i < nHelper; i++)
{
COLORRANGE range;
archive.Read(&range, sizeof(COLORRANGE));
m_ColorRanges.push_back (range);
}
archive >> nHelper;
for (i = 0; i < nHelper; i++)
{
AXISMARKER marker;
archive.Read(&marker, sizeof(AXISMARKER));
m_AxisMarkers.push_back (marker);
}
if (m_Font.m_hObject != NULL)
m_Font.DeleteObject ();
if (m_TitleFont.m_hObject != NULL)
m_TitleFont.DeleteObject ();
archive.Read(&font, sizeof(LOGFONT));
m_Font.CreateFontIndirect (&font);
archive.Read(&font, sizeof(LOGFONT));
m_TitleFont.CreateFontIndirect (&font);
}
}
#pragma warning (default : 4244)
#pragma warning (default : 4800)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -