⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xgraphaxis.cpp

📁 Displaying large amounts of technical data in a chart can be a frustrating task. You can find tons o
💻 CPP
📖 第 1 页 / 共 4 页
字号:
			}
			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 + -