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

📄 chart.cpp

📁 vc代用matcom编程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Chart.cpp : implementation file
// Originator : Kris Jearakul  tuktun@hotmail.com
//				http://krisj.iwarp.com
// Comment	  : Use with your own risk !!

#include "stdafx.h"
#include "Chart.h"
#include "math.h"

#include "Resource.h"

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

/////////////////////////////////////////////////////////////////////////////
// CChart

CChart::CChart()
{
	SetRange(-10,10,-10,10);
	strChartTitle = "Untitled Chart" ;
	strLabelX = "x" ;
	strLabelY = "y" ;
	iChartType = 2 ;
	nGridX = 10 ;
	nGridY = 10 ;
	bIsSerieAllocated = FALSE ;
	bLogScale = FALSE ;
	bFontIsCreate = FALSE ;
	bBkNeedToUpdate = TRUE ;
	nPlotIndex = 0 ;
	nPointCount = 0 ;
	nSerieCount = 5 ;

	m_BGColor = RGB(192,192,192);
	m_ABGColor= RGB(0,0,0);
	m_AxisColor = RGB(50,50,50);
	m_GridColor = RGB(50,50,50);
	m_num=1;
 
	m_PenBrightLine.CreatePen(PS_SOLID,0,RGB(0xff,0xff,0xff));
	m_PenDarkLine.CreatePen(PS_SOLID,0,RGB(0x55,0x55,0x55));
	Is_GetData=FALSE;
}

CChart::~CChart()
{

	for( int i = 0  ; i < nSerieCount ; i++)
	{
		mpSerie[i].FreeSerie() ;
		mpSerieB[i].FreeSerie() ;
		mpSerieC[i].FreeSerie() ;
		mpSerieD[i].FreeSerie() ;
	}
	if(memBkDC.GetSafeHdc() != NULL)
	   memBkDC.SelectObject(m_pOldBkBitmap);
	if( bFontIsCreate ) {
		delete pLegendFontY ;
		delete pLegendFontX ;
		delete pTitleFont ;
	}
}


BEGIN_MESSAGE_MAP(CChart, CWnd)
	//{{AFX_MSG_MAP(CChart)
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_RBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_CONTEXTMENU()
	ON_WM_SETCURSOR()
	ON_COMMAND(IDR_READ_PONIT, OnReadPoint)
	ON_COMMAND(ID_CHART_BACK, OnBack)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CChart message handlers


BOOL CChart::Create(DWORD dwStyle, CRect &rect, CWnd *pParent, UINT id)
{
	//DWORD style = dwStyle & ( ~WS_BORDER ) ;
	//static CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW);
	BOOL result ;
	
	result = CWnd::CreateEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE, 
                          NULL, NULL, dwStyle, 
                          rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
                          pParent->GetSafeHwnd(), (HMENU)id) ;
	if( !result )
		AfxMessageBox("Error creating window");
	m_ctlRect = rect ;
	pParent->ClientToScreen(m_ctlRect) ;
	ScreenToClient(m_ctlRect) ;
	CreateFont(); // Get system font for label draw 
	bFontIsCreate = TRUE ;
	CalcRect() ; // Compute rectangle 
	ResCalc(); // Compute resolution per dot .

	return result ;
}

void CChart::CalcRect()
{
	int offsetX , offsetY ;

	if(m_ctlRect)
	{
		m_clientRect.left  = m_ctlRect.left+2 ;
		m_clientRect.right = m_ctlRect.right-2 ;
		m_clientRect.top   = m_ctlRect.top+2 ;
		m_clientRect.bottom = m_ctlRect.bottom-2;
	} else {
		m_clientRect = m_ctlRect ;
		}

	//Calculate offset of window to be 4/5 of its window .

	offsetY   = m_clientRect.Height()/10 ;
	offsetX   = m_clientRect.Width()/10 ;
	m_axisRect.left = m_clientRect.left + (offsetX)-10 ;
	m_axisRect.right = m_clientRect.right - (offsetX)+15;
	m_axisRect.top = m_clientRect.top + (offsetY)+5;
	m_axisRect.bottom = m_clientRect.bottom - (offsetY)-20 ;
}

//////////////////////////////////////////////////////////
// Draw box and fill color inside it .
void CChart::DrawBorder(CDC *pDC)
{
	CBrush brushCtl;//(m_BGColor);
	brushCtl.CreateSolidBrush(m_BGColor); 	
	pDC->FillRect(m_ctlRect,&brushCtl);//填充曲线面板

    CBrush bbrushCtl;//(m_BGColor);
	bbrushCtl.CreateSolidBrush(m_ABGColor); 	
	pDC->FillRect(m_axisRect,&bbrushCtl);//填充曲线面板

	CPen *pOldPen;
	pOldPen = pDC->SelectObject(&m_PenBrightLine);//设置当前默认画笔为m_PenBrightLine
	pDC->MoveTo(m_ctlRect.left,m_ctlRect.top);
	pDC->LineTo(m_ctlRect.left,m_ctlRect.bottom);
	pDC->MoveTo(m_ctlRect.left,m_ctlRect.top);
	pDC->LineTo(m_ctlRect.right,m_ctlRect.top);
/////////////////////用明线勾画出面板的明暗对比效果
	pDC->SelectObject(&m_PenDarkLine);//设置当前默认画笔为m_PenDarkLine
	pDC->MoveTo(m_clientRect.right,m_clientRect.top);
	pDC->LineTo(m_clientRect.right,m_clientRect.bottom);
	pDC->MoveTo(m_clientRect.left,m_clientRect.bottom);
	pDC->LineTo(m_clientRect.right,m_clientRect.bottom);	
	
	pDC->SelectObject(pOldPen);
}

void CChart::DrawAxis(CDC *pDC)
{
	CPen *old , pen(PS_SOLID, 2, m_AxisColor) ;
	old = pDC->SelectObject(&pen) ;
	double dcenter ;
	switch( iChartType ) {
	
	case 0:
		pDC->MoveTo(Corrdinate(dRangeX[MIN],dRangeY[MIN]));
		pDC->LineTo(Corrdinate(dRangeX[MAX],dRangeY[MIN]));
		pDC->MoveTo(Corrdinate(dRangeX[MIN],dRangeY[MIN]));
		pDC->LineTo(Corrdinate(dRangeX[MIN],dRangeY[MAX]));
		break;
	
	case 1:
		dcenter = (dRangeY[MAX] + dRangeY[MIN]) / 2 ;
		pDC->MoveTo(Corrdinate(dRangeX[MIN],dcenter));
		pDC->LineTo(Corrdinate(dRangeX[MAX],dcenter));
		pDC->MoveTo(Corrdinate(dRangeX[MIN],dRangeY[MIN]));
		pDC->LineTo(Corrdinate(dRangeX[MIN],dRangeY[MAX]));
		break;

	case 2:
		//draw vertical axis
		dcenter = (dRangeX[MAX] + dRangeX[MIN]) /2 ;
		pDC->MoveTo(Corrdinate(dcenter,dRangeY[MIN]));
		pDC->LineTo(Corrdinate(dcenter,dRangeY[MAX]));
		
		//draw horizontal axis
		dcenter = (dRangeY[MAX] + dRangeY[MIN]) /2 ;
		pDC->MoveTo(Corrdinate(dRangeX[MIN],dcenter));
		pDC->LineTo(Corrdinate(dRangeX[MAX],dcenter));
		break;

	}	
	
	pDC->SelectObject(old) ;
	
}

CPoint CChart::Corrdinate(double x, double y)
{
	double rx , ry ;
	int xPixel , yPixel ;
	CPoint retPt ;

	rx = x - dRangeX[MIN] ; // Calculate horizontal offset from origin
	ry = y - dRangeY[MIN] ; // Calculate vertical offset from origin .

	// Convert offset to be number of pixel on screen .
	xPixel = (int)(rx / dResX) ; 
	yPixel = (int)(ry / dResY) ;

	//Calulate point to be drawn .
	retPt.x= xPixel + m_axisRect.left;
	retPt.y= m_axisRect.bottom - yPixel; 
	return retPt ;
}

void CChart::PlotA(CDC *pDC)
{
	
	// If there is no data available for plot then return .
	if ( !nPlotIndex ) return ;
		
	CPen *old , *pen ;

	
	CPoint pt ;
	int i;
	
	for( i = 0 ; i < nSerieCount ; i++) {
		// Create the new pen as the color of serie 
		pen = new CPen(PS_SOLID,0,mpSerie[i].m_plotColor);
		old = pDC->SelectObject(pen);
		// calculate the corrdinate of ploting point.
		pt = Corrdinate(mpSerie[i].dValueX[0],mpSerie[i].dValueY[0]) ;
		pDC->MoveTo(pt);
		//Start plot all available data .
		for(int index = 1 ; index <= nPlotIndex ; index++){
			pt = Corrdinate(mpSerie[i].dValueX[index],
						mpSerie[i].dValueY[index]) ;
		pDC->LineTo(pt) ;		
		}
		pDC->SelectObject(old);
		delete pen ;
	}
	
}
void CChart::PlotB(CDC *pDC)
{
	
	// If there is no data available for plot then return .
	if ( !nPlotIndex ) return ;
		
	CPen *old , *pen ;

	
	CPoint pt ;
	int i;
	
	for( i = 0 ; i < nSerieCount ; i++) {
		// Create the new pen as the color of serie 
		pen = new CPen(PS_SOLID,0,mpSerieB[i].m_plotColor);
		old = pDC->SelectObject(pen);
		// calculate the corrdinate of ploting point.
		pt = Corrdinate(mpSerieB[i].dValueX[0],mpSerieB[i].dValueY[0]) ;
		pDC->MoveTo(pt);
		//Start plot all available data .
		for(int index = 1 ; index <= nPlotIndex ; index++){
			pt = Corrdinate(mpSerieB[i].dValueX[index],
						mpSerieB[i].dValueY[index]) ;
		pDC->LineTo(pt) ;		
		}
		pDC->SelectObject(old);
		delete pen ;
	}
}

void CChart::DrawChartTitle(CDC *pDC)
{
	int x , y ;
	int oldbkmode ;
	CFont *old ;


	old = pDC->SelectObject(pTitleFont);
	oldbkmode = pDC->SetBkMode(TRANSPARENT) ;

	CSize textSize = pDC->GetTextExtent(strChartTitle,
		strChartTitle.GetLength()) ;

	//Calculate centre window corrdinate of text ;
	pDC->SetTextAlign(TA_LEFT);
	y = m_ctlRect.top + (textSize.cy/2) ;
	x = m_clientRect.left + 
		(m_clientRect.Width()/2) - (textSize.cx/2) ;

	pDC->TextOut(x,y,strChartTitle) ;
	pDC->SetBkMode(oldbkmode);
	pDC->SelectObject(old);
}

void CChart::DrawGrid(CDC *pDC)
{
	CPen *old , pen(PS_SOLID, 0, m_GridColor),pen1(PS_SOLID, 0, RGB(192,192,192));
	CPoint m_start, m_stop ;
	int i  ;
	double x ,y ;
	double step ;
    CString strpoint;
	old = pDC->SelectObject(&pen);
	
	// Draw vertical grid 

	step = (dRangeX[MAX] - dRangeX[MIN]) / (double)nGridX ;
	for( i = 0 ; i <= nGridX ; i++ )
	{
		x = dRangeX[MIN] + (step * (double)i) ;
		m_start = Corrdinate(x,dRangeY[MIN]);
		m_stop  = Corrdinate(x,dRangeY[MAX]);
		pDC->MoveTo(m_start);
		pDC->LineTo(m_stop);
	}
	
	// Draw horizontal grid.

	step = (dRangeY[MAX] - dRangeY[MIN]) / (double)nGridY ;
	for( i = 0 ; i <= nGridY ; i++ )
	{
		y = dRangeY[MIN] + (step * (double)i) ;
		m_start = Corrdinate(dRangeX[MIN],y) ;
		m_stop  = Corrdinate(dRangeX[MAX],y) ;
		pDC->MoveTo(m_start);
		pDC->LineTo(m_stop);
	}	
	if (Is_GetData&&m_axisRect.left<=m_Point.x&&m_axisRect.right>=m_Point.x&&m_axisRect.top<=m_Point.y&&m_axisRect.bottom>=m_Point.y)
	{
		pDC->SelectObject(&pen1);
		pDC->MoveTo(m_Point.x,m_axisRect.top);
		pDC->LineTo(m_Point.x,m_axisRect.bottom);
		pDC->MoveTo(m_axisRect.left,m_Point.y);
		pDC->LineTo(m_axisRect.right,m_Point.y);	
		strpoint.Format("(%5.2f,%5.2f)",(double)(dRangeX[MIN]+(m_PointX-m_axisRect.left)*((dRangeX[MAX]-dRangeX[MIN]))/(double)(m_axisRect.Width())),(double)(dRangeY[MIN]+(m_axisRect.bottom-m_PointY)*((dRangeY[MAX]-dRangeY[MIN])/m_axisRect.Height())));
		pDC->TextOut(m_Point.x,m_Point.y,strpoint);
	}
	pDC->SelectObject(old);
}

BOOL CChart::SetRange(double dMinX, double dMaxX, 
					   double dMinY,double dMaxY)
{

	bBkNeedToUpdate = TRUE ; // Background need to be re-draw
	dRangeY[MIN] = dMinY ;
	dRangeY[MAX] = dMaxY ;
	dRangeX[MAX] = dMaxX ;
	dRangeX[MIN] = dMinX ;
    ResCalc();
	return TRUE ;	
}

////////////////////////////////////////////////////////
//Calculate resolution per dot
void CChart::ResCalc()
{
	double dpixelx, dpixely ;
	
	dpixelx = (double)m_axisRect.Width() ;
	dpixely = (double)m_axisRect.Height() ;
	dResY = (dRangeY[MAX] - dRangeY[MIN]) / dpixely ;
	dResX = (dRangeX[MAX] - dRangeX[MIN]) / dpixelx ;
}

///////////////////////////////////////////////////////
// Set Axis style 
//
void CChart::SetAxisStyle(int iStyle)
{
	if( (iStyle > 2) || (iStyle < 0) ) return ;
	iChartType = iStyle ;
}

////////////////////////////////////////////////////////
// Draw 1/5 fine scale in log mode
// in order to implement log grid set bLogScale = TRUE
void CChart::DrawLogGrid(CDC *pDC)
{
	// Change this number for changing number of fine scales.
	const int FINE_SCALE = 5 ; 
	CPen *old , pen(PS_SOLID, 0, RGB(192,192,192)) ;
	CPoint m_start, m_stop ;
	int i  ;
	int j ;
	double y ;
	double step ;
	double Ymax , Ymin ;

	Ymax = dRangeY[MAX] ;
	Ymin = dRangeY[MIN] ;
	//Remap scale to 0 - nGridY
	SetRange(dRangeX[MIN],dRangeX[MAX],0,nGridY);
	old = pDC->SelectObject(&pen);
	for( j = (int)dRangeY[MIN] ; j < (int)dRangeY[MAX] ; j ++) {
	   y = (double)j;
	   step = (pow(10,y+1) - pow(10,y)) /(double)FINE_SCALE ;
		for(i = 0 ; i < FINE_SCALE ; i++ )
		{
		
			y = log10(pow(10,y) + step) ;
			m_start = Corrdinate(dRangeX[MIN],y) ;
			m_stop  = Corrdinate(dRangeX[MAX],y) ;
			pDC->MoveTo(m_start);
			pDC->LineTo(m_stop);

		}
	}
	SetRange(dRangeX[MIN],dRangeX[MAX],Ymin,Ymax ) ;
	pDC->SelectObject(old);
	
}

////////////////////////////////////////
// Allocate memory for plotting 
BOOL CChart::AllocSerie(int nSerie)
{
	
	if( !bIsSerieAllocated )
	{
		for(int i = 0 ; i < nSerieCount ; i++ ) 
		{
			if ( !mpSerie[i].AllocSerie(nSerie)) 
			{
				AfxMessageBox("Can not allocate serie") ;
				return FALSE ;
			}
			if ( !mpSerieB[i].AllocSerie(nSerie))
			{
				AfxMessageBox("Can not allocate serie") ;
				return FALSE ;
			}
			if ( !mpSerieC[i].AllocSerie(nSerie))
			{
				AfxMessageBox("Can not allocate serie") ;
				return FALSE ;
			}
			if ( !mpSerieD[i].AllocSerie(nSerie))
			{
				AfxMessageBox("Can not allocate serie") ;
				return FALSE ;
			}
		}
	}
	
	nPointCount = nSerie ;
	bIsSerieAllocated = TRUE ;
	return TRUE ;

}

BOOL CChart::SetXYValueA(double x, double y, int index, int iSerieIdx)
{
	if(!bIsSerieAllocated ) return FALSE ;
	if (iSerieIdx > (nSerieCount-1)) return FALSE ;

	// Prevent writting to unallocated buffer 
	if(index >= nPointCount ) return FALSE ;
	
	// Clip the ploting area if it exceed ranged .
	if(x > dRangeX[MAX] ) x = dRangeX[MAX] ;
	if(x < dRangeX[MIN] ) x = dRangeX[MIN] ;
	if(y > dRangeY[MAX] ) y = dRangeY[MAX] ;
	if(y < dRangeY[MIN] ) y = dRangeY[MIN];
  
	
	for( int i = 0  ; i < iSerieIdx ; i++)
	{	
		mpSerieB[i].FreeSerie() ;
		mpSerieC[i].FreeSerie() ;
		mpSerieD[i].FreeSerie() ;
	}
	
	mpSerie[iSerieIdx].dValueX[index] = x ;
	mpSerie[iSerieIdx].dValueY[index] = y ;
	mpSerie[iSerieIdx].bIsPlotAvailable = TRUE ;

	nPlotIndex = index ;

⌨️ 快捷键说明

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