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

📄 xgraphdataserie.cpp

📁 Displaying large amounts of technical data in a chart can be a frustrating task. You can find tons o
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// XGraphDataSerie.cpp: Implementierung der Klasse CXGraphDataSerie.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "XGraphDataSerie.h"
#include "XGraph.h"
#include "GfxUtils.h"
#include "math.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

IMPLEMENT_SERIAL( CXGraphDataSerie, CXGraphObject, 1 )

//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////

CXGraphDataSerie::CXGraphDataSerie()
{
	m_bAutoDelete = false;
	m_bVisible = true;
	m_bShowMarker = false;
	m_bFillBeneath = false;
	m_bFillTransparent = true;
	m_pGraph   = NULL;
	m_pData    = NULL;
	m_nLineStyle = PS_SOLID;
	m_nFillStyle = 6;
	m_nLineSize = 1;
	m_gtType = gtLine;
	m_nFirstVisible = 0;
	m_nLastVisible  = 0;
	m_cLabel = _T(" ");
	m_nMarkerType = 0;
	m_nMarker = 0;
	m_nMarkerSize = 10;
	m_nXAxis  = 0;
	m_nYAxis  = 0;
	m_crColor = 0L;
	m_nCount  = 0; 
	m_nIndex  = 0;
	m_nFillCurve = 1;
	m_crFillColor = RGB(255, 255, 255);

}

CXGraphDataSerie::CXGraphDataSerie(const CXGraphDataSerie& copy)
{
	m_pData  = NULL;
	*this = copy;
}

CXGraphDataSerie& CXGraphDataSerie::operator =(const CXGraphDataSerie& copy)
{
	m_bVisible			= copy.m_bVisible;
	m_bShowMarker		= copy.m_bShowMarker;
	m_bFillBeneath		= copy.m_bFillBeneath;
	m_pGraph			= copy.m_pGraph;
	m_nLineStyle		= copy.m_nLineStyle;
	m_nLineSize			= copy.m_nLineSize; 
	m_gtType			= copy.m_gtType;  
	m_nXAxis			= copy.m_nXAxis;
	m_nYAxis			= copy.m_nYAxis;
	m_crColor			= copy.m_crColor;
	m_nFillStyle		= copy.m_nFillStyle;
	m_nFirstVisible		= copy.m_nFirstVisible;
	m_nLastVisible		= copy.m_nLastVisible;
	m_bFillTransparent  = copy.m_bFillTransparent;
	m_CurveRegions      = copy.m_CurveRegions;
	m_nMarkerType	    = copy.m_nMarkerType;
	m_nMarker           = copy.m_nMarker;
	m_nMarkerSize		= copy.m_nMarkerSize;
	m_bAutoDelete		= copy.m_bAutoDelete;
	m_nCount			= copy.m_nCount; 
	m_nIndex            = copy.m_nIndex;
	m_cLabel		    = copy.m_cLabel;
	m_PS                = copy.m_PS;
	m_nFillCurve		= copy.m_nFillCurve;
	m_crFillColor       = copy.m_crFillColor;

	if (copy.m_bAutoDelete && copy.m_pData)
	{
		m_pData = new TDataPoint[copy.m_nCount];
		memcpy(m_pData, copy.m_pData, sizeof(TDataPoint) * copy.m_nCount);
	}
	else
		m_pData	= copy.m_pData;
		
	return *this;
}

CXGraphDataSerie::~CXGraphDataSerie()
{
	if (m_bAutoDelete)
		delete[] m_pData;
}

void CXGraphDataSerie::PrepareClipboard(CFDATASERIE& serie)
{
	serie.nCount = m_nCount;
	serie.nFirstVisible = m_nFirstVisible;
	serie.nLastVisible = m_nLastVisible;
	serie.nXAxis = m_nXAxis;
	serie.nYAxis = m_nYAxis;
	serie.nIndex = m_nIndex;
	serie.nLineSize = m_nLineSize;
	serie.nFillStyle = m_nFillStyle;
	serie.nMarkerType = m_nMarkerType;
	serie.nMarker = m_nMarker;
	serie.nMarkerSize = m_nMarkerSize;
	serie.nLineStyle = m_nLineStyle;
	serie.bAutoDelete = true;
	serie.bShowMarker = m_bShowMarker;
	serie.bFillBeneath = m_bFillBeneath;
	serie.nFillCurve = m_nFillCurve;
	serie.bFillTransparent = m_bFillTransparent;
	serie.crFillColor = m_crFillColor;

	serie.gtType = m_gtType;
#ifndef _WIN32_WCE
	_tcscpy(serie.cLabel, m_cLabel);
#else
	strcpy(serie.cLabel, (const char*)(LPCTSTR) m_cLabel);
#endif

}

void CXGraphDataSerie::DrawMarker(CDCEx *pDC)
{	
	CPoint point;

	int nWidth = m_pGraph->m_clInnerRect.Width() / m_nMarkerSize / 4;

	int nMarkerCount = 2;
	
	if (nWidth > 0)
		nMarkerCount = m_nCount / nWidth;

	if (nMarkerCount <= 0)
		nMarkerCount = 2;

	if (m_pGraph->m_opOperation == CXGraph::opEditCurve)
		nMarkerCount = 1;


	CXGraphAxis& yaxis = m_pGraph->GetYAxis(m_nYAxis);
	CXGraphAxis& xaxis = m_pGraph->GetXAxis(m_nXAxis);

	for (int i = 0; i < m_nCount; i += nMarkerCount)
	{
		CPoint point;

		point.x = xaxis.GetPointForValue(&m_pData[i]).x - (m_nMarkerSize / 2);
		point.y = yaxis.GetPointForValue(&m_pData[i]).y - (m_nMarkerSize / 2);
	
		int nMarker = m_nMarkerType == 0 ? m_pGraph->GetCurveIndex(this) : m_nMarker;

		yaxis.DrawMarker (pDC, point, nMarker, m_nMarkerSize , pDC->m_bMono ? 0L : m_crColor, m_nMarkerType == 1 );
	}
}

void CXGraphDataSerie::CreateCurveGripRgn(CPoint oldPoint, CPoint point)
{
	HITTEST ht;
	
	ht.p1 = oldPoint;
	ht.p2 = point;

	m_CurveRegions.push_back (ht);
}


void CXGraphDataSerie::Draw(CDCEx *pDC)
{
	static CPoint oldPoint(-1,-1);
	CPoint point;
	int    i = 0;
	POINT* pPoly;
		
	COLORREF crInverted = RGB(255 - GetRValue(m_crColor),
							  255 - GetGValue(m_crColor),
							  255 - GetBValue(m_crColor));

	CPenSelector ps(pDC->m_bMono ? 0L : (m_bSelected ? crInverted : m_crColor), m_nLineSize, pDC, m_nLineStyle); 

	point.x = m_pGraph->GetXAxis(m_nXAxis).GetPointForValue(&m_pData[i]).x;
	point.y = m_pGraph->GetYAxis(m_nYAxis).GetPointForValue(&m_pData[i]).y;


	if (m_bFillBeneath)
	{
		if (m_nFillCurve != -1)
		{
			CXGraphDataSerie& ds = GetGraph()->GetCurve (m_nFillCurve);
			long nCount = ds.GetCount () ;
			pPoly = new POINT[m_nCount + nCount];

		}
		else
		{
			pPoly = new POINT[m_nCount + 2];
		}

		pPoly[0].x = point.x;
		pPoly[0].y = point.y;
		
	}

	oldPoint = point;

	CXGraphAxis& yaxis = m_pGraph->GetYAxis(m_nYAxis);
	CXGraphAxis& xaxis = m_pGraph->GetXAxis(m_nXAxis);

	if (m_gtType == gtLine)
		pDC->MoveTo(point);

	if (m_gtType == gtScatter)
		pDC->Ellipse (point.x-m_nLineSize, point.y-m_nLineSize,point.x+m_nLineSize, point.y+m_nLineSize);

	m_CurveRegions.clear ();
	
	int nPoint = 1;
	
	for (i = 1; i < m_nCount; i++)
	{
		point.x = xaxis.GetPointForValue(&m_pData[i]).x;
		point.y = yaxis.GetPointForValue(&m_pData[i]).y;
					
		if (point.x != oldPoint.x )
		{
			if ((m_pGraph->m_clInnerRect.PtInRect (point) || m_pGraph->m_clInnerRect.PtInRect (oldPoint)))
				CreateCurveGripRgn(oldPoint, point);
			
			if (m_gtType == gtLine)
				pDC->LineTo(point);

			if (m_gtType == gtScatter)
				pDC->Ellipse (point.x-m_nLineSize, point.y-m_nLineSize,point.x+m_nLineSize, point.y+m_nLineSize);

			if (m_bFillBeneath)
			{
				pPoly[nPoint].x = point.x;
				pPoly[nPoint++].y = point.y;
			}
					
			oldPoint = point;
		}
	}

	if (m_bFillBeneath)
	{
		if (m_nFillCurve != -1)
		{
			CXGraphDataSerie& ds = GetGraph()->GetCurve (m_nFillCurve);
			CXGraphAxis& yaxis =  GetGraph()->GetYAxis (ds.GetYAxis());
			CXGraphAxis& xaxis = GetGraph()->GetXAxis (ds.GetXAxis());

			for (long nFC = ds.GetCount () - 1; nFC >= 0; nFC--)
			{
				point.x = xaxis.GetPointForValue(&ds.m_pData[nFC]).x;
				point.y = yaxis.GetPointForValue(&ds.m_pData[nFC]).y;
				pPoly[nPoint].x = point.x;
				pPoly[nPoint++].y = point.y;
			}

		}
		else
		{
			pPoly[nPoint++] = CPoint(oldPoint.x, m_pGraph->m_clInnerRect.bottom) ;
			pPoly[nPoint++] = CPoint(pPoly[0].x, m_pGraph->m_clInnerRect.bottom) ;
		}
		
		int nOldBkMode = pDC->GetBkMode ();

		pDC->SetBkMode(m_bFillTransparent ? TRANSPARENT : OPAQUE);
		
		int nOldROP2 = R2_COPYPEN;
		
		if (m_bFillTransparent)
			nOldROP2 = pDC->SetROP2 (R2_NOTXORPEN);
		
		
		// Make shure the polygon's outline is invisible
		CPenSelector ps(0, 0, pDC, PS_NULL);

		if (m_nFillStyle == HS_SOLID) 
		{
			// Solid
			
			CBrushSelector bs(pDC->m_bMono ? 0L : m_crFillColor, pDC);
			pDC->Polygon (pPoly, nPoint);
		}
#ifndef _WIN32_WCE
		else
		{
			// Hatched
			CBrushSelector bs(pDC->m_bMono ? 0L : m_crFillColor, m_nFillStyle, pDC);
			pDC->Polygon (pPoly, nPoint);
		}
#endif

		pDC->SetBkMode(nOldBkMode);
		pDC->SetROP2 (nOldROP2);

		delete pPoly;
	}

}

void CXGraphDataSerie::ResetVisibleRange()
{
	m_nFirstVisible = 0;
	m_nLastVisible  = m_nCount - 1;
}


TDataPoint* CXGraphDataSerie::GetLinearTrend(long nPoints)
{
	TDataPoint* pData;
	
	pData = new TDataPoint[m_nCount + nPoints];

	double fYSum  = 0.0,
		   fTYSum = 0.0,
		   fTSum  = 0.0,
		   fT2Sum = 0.0;
			
	for (long i = 0; i < m_nCount; i ++)
	{
		fYSum += m_pData[i].fYVal;
		fTYSum += (m_pData[i].fYVal * (i+1));
		fTSum += (i+1);
		fT2Sum += ((i+1)*(i+1));
	}

	double fDiff = m_pData[1].fXVal - m_pData[0].fXVal;

	for (i = 0; i < (m_nCount + nPoints); i ++)
	{
		if (i < m_nCount)
			pData[i].fXVal = m_pData[i].fXVal;
		else
			pData[i].fXVal = pData[i-1].fXVal + fDiff;

		double fB = (m_nCount * fTYSum - fTSum * fYSum) / (m_nCount * fT2Sum - (fTSum * fTSum));
		double fA = (fYSum - fB * fTSum) / m_nCount;
		pData[i].fYVal = fA + fB * (i+1);
	}

	return pData;
}

TDataPoint* CXGraphDataSerie::GetCubicTrend(long nPoints)
{
	TDataPoint* pData;
	
	pData = new TDataPoint[m_nCount + nPoints];

	double fTY3Sum = 0.0,
		   fT6Sum = 0.0;
			
	for (long i = 0; i < m_nCount; i ++)
	{
		fTY3Sum += (m_pData[i].fYVal * pow(i+1, 3));
		fT6Sum  += (pow (i+1, 6));
	}

	double fDiff = m_pData[1].fXVal - m_pData[0].fXVal;

	for (i = 0; i < (m_nCount + nPoints); i ++)
	{
		if (i < m_nCount)
			pData[i].fXVal = m_pData[i].fXVal;
		else
			pData[i].fXVal = pData[i-1].fXVal + fDiff;
	
		pData[i].fYVal = (fTY3Sum/fT6Sum) * pow (i+1,3);
	}

	return pData;
}



TDataPoint* CXGraphDataSerie::GetPolynomialTrend(int nDegree, int nPoints)
{
    TDataPoint* pData;
	
	pData = new TDataPoint[m_nCount + nPoints];

	m_PS.m_nGlobalO = nDegree;
	
	if (!m_PS.Polyfit (m_nCount, nDegree, m_pData))
	{
		delete pData;
		return NULL;
	}

	for ( int i = 0; i < (m_nCount + nPoints); i++ )
	{
		if (i < m_nCount)
			pData[i].fXVal = m_pData[i].fXVal;
		else
			pData[i].fXVal = pData[i-1].fXVal + (pData[i-1].fXVal - pData[i-2].fXVal);

		pData[i].fYVal = m_PS.GetValue (pData[i].fXVal);
	}

    return pData;
}


TDataPoint* CXGraphDataSerie::GetSimpleMovingAverage(int span)
{
    int	   p;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -