📄 clplot.cpp
字号:
#include "stdafx.h"
#include "clPlot.h"
#include "MemDC.h"
#include "malloc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
long clPlot::m_lMaxDataPrSerie; // max allowed data pr. serie.
long clPlot::m_lMaxDataTotal; // max allowed data total.
//*******************************************************************************************************/
//* time axis threshold. contains grid and label intervals to be used within specified
//* seconds pr. pixels thresholds. The array is terminated by a 'bIAmInUse'=FALSE.
//*******************************************************************************************************/
struct{
BOOL bIAmInUse; // indicate valid entry, last=FALSE
long lgridinterval; // grid line interval in seconds
long llabelinterval; // time label interval in seconds
long lmodethreshold; // mode threshold in seconds pr. pixel
}gridsetting[]={
TRUE, 1, 4, 0, // 0: pr. second
FALSE, 1, 1,0, // last entry in table
};
//*******************************************************************************************************/
//* Function: serie::serie
//*******************************************************************************************************/
serie::serie()
{
m_bIAmInUse = FALSE;
m_color = RGB(0,0,0);
m_iLineStyle = PS_SOLID;
m_bRightAxisAlign = FALSE;
m_lNoValues = 0;
m_lbegin = 0;
m_lend = 0;
m_pvalues = NULL;
}
//*******************************************************************************************************/
//* Function: serie::~serie
//*******************************************************************************************************/
serie::~serie()
{
if(m_pvalues !=NULL)
free(m_pvalues);
}
//*******************************************************************************************************/
//* Function: serie::AddPoint
//*
//* Description: AddPoint add new data to the end of a data serie. It will simply append the data,
//* update the list index and get out.
//*
//* This function will also call realloc or malloc to re-size or create the plot array as
//* needed.
//*
//* The nice thing about circular lists is that they are multi thread enabled as is. You
//* must however implement a syncronization mechanism if more than one thread is supposed
//* to enter data into the plot.
//*
//* Parameters: valuetime Time (x value).
//* y y value
//*
//* Return Value: -none-
//*
//* Author: Jan Vidar Berger
//*******************************************************************************************************/
void serie::AddPoint(CTime &valuetime , double &y)
{
if(m_lNoValues > 0)
m_pvalues = (value*)realloc(m_pvalues, (m_lNoValues+1)*sizeof(value));
else
m_pvalues = (value*)malloc((m_lNoValues+1)*sizeof(value));
m_pvalues[m_lend].ValueTime = valuetime;
m_pvalues[m_lend].dValue = y;
m_lNoValues++;
m_lend++;
if(m_lend >= clPlot::m_lMaxDataPrSerie)
m_lend=0;
if(m_lbegin == m_lend){
m_lbegin++;
if(m_lbegin >= clPlot::m_lMaxDataPrSerie)
m_lbegin=0;
}
}
//*******************************************************************************************************/
//* Function: serie::Reset
//*
//* Description: Reset the serie. Remove data and reset indexes and pointers.
//*
//* Parameters: -none-
//*
//* Return Value: -none-
//*
//* Author: Jan Vidar Berger
//*******************************************************************************************************/
void serie::Reset()
{
m_lNoValues=0;
if(m_pvalues !=NULL)
free(m_pvalues);
m_pvalues = NULL;
m_lbegin = 0;
m_lend = 0;
}
//*******************************************************************************************************/
//*******************************************************************************************************/
clPlot::clPlot()
{
m_ctlBkColor = RGB(255,255,255);
m_plotBkColor = RGB(255,255,255);
m_legendBkColor = RGB(255,255,255);
m_gridColor = RGB(127,127,127);
m_bctlBorder = TRUE;
m_bplotBorder = TRUE;
m_blegendBorder = TRUE;
m_bPrimaryLegend = FALSE;
m_bSecondaryLegend = FALSE;
m_bAxisLY = TRUE;
m_bAxisRY = TRUE;
m_bAxisBX = TRUE;
m_bAutoScrollX = FALSE;
m_bSimMode = FALSE;
m_lMaxDataPrSerie = 10000;
m_lMaxDataTotal = 100000;
m_dNoData = 0.0;
m_dzoom = 1.0;
lArraySize = 1000; // only points with differebt x,y will be put into the array
pLineArray = new CPoint[lArraySize];
SetBXRange(CTime::GetCurrentTime()-CTimeSpan(60),CTime::GetCurrentTime());
m_logFont.lfHeight = -13;
m_logFont.lfWidth = 0;
m_logFont.lfEscapement = 0;
m_logFont.lfOrientation = 0;
m_logFont.lfWeight = 400;
m_logFont.lfItalic = FALSE;
m_logFont.lfUnderline = FALSE;
m_logFont.lfStrikeOut = FALSE;
m_logFont.lfCharSet = ANSI_CHARSET;
m_logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
m_logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
m_logFont.lfQuality = PROOF_QUALITY;
m_logFont.lfPitchAndFamily = DEFAULT_PITCH;
strcpy(m_logFont.lfFaceName,"Ariel");
m_zoomFont.lfHeight = -13;
m_zoomFont.lfWidth = 0;
m_zoomFont.lfEscapement = 0;
m_zoomFont.lfOrientation = 0;
m_zoomFont.lfWeight = 400;
m_zoomFont.lfItalic = FALSE;
m_zoomFont.lfUnderline = FALSE;
m_zoomFont.lfStrikeOut = FALSE;
m_zoomFont.lfCharSet = ANSI_CHARSET;
m_zoomFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
m_zoomFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
m_zoomFont.lfQuality = PROOF_QUALITY;
m_zoomFont.lfPitchAndFamily = DEFAULT_PITCH;
strcpy(m_zoomFont.lfFaceName,"Ariel");
m_font.CreateFontIndirect(&m_zoomFont);
}
//*******************************************************************************************************/
//*******************************************************************************************************/
clPlot::~clPlot()
{
delete [] pLineArray;
}
//*******************************************************************************************************/
//*******************************************************************************************************/
BEGIN_MESSAGE_MAP(clPlot, CWnd)
//{{AFX_MSG_MAP(clPlot)
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//*******************************************************************************************************/
//*******************************************************************************************************/
BOOL clPlot::Create(DWORD dwstyle, CRect &rect, CWnd *pParent, UINT id)
{
DWORD style = dwstyle & (~WS_BORDER);
if(dwstyle & WS_BORDER)
m_bctlBorder=TRUE;
else
m_bctlBorder=FALSE;
if(!CWnd::Create(NULL, "", style, rect, pParent, id, NULL))
return FALSE;
m_ctlRect = rect;
pParent->ClientToScreen(m_ctlRect);
ScreenToClient(m_ctlRect);
ComputeRects(TRUE);
return TRUE;
}
//*******************************************************************************************************/
//* Function : clPlot::ComputeRects
//*
//* Description : Compute rects used for internal possitioning of different objects. This function is
//* called when the plot is created or sized.
//*
//* Return type : void
//*
//* Parameter(s) : bInitialization indicate wherever parameters that can be changed abu the user
//* also should be computed.
//*
//* Author : Jan Vidar Berger
//*******************************************************************************************************/
void clPlot::ComputeRects(BOOL bInitialization)
{
// adjust the client rect for borders
//GetClientRect(m_ctlRect);
CClientDC dc(this);
int w = 0;
int n=0;
CSize z=dc.GetTextExtent(CString("A"));
// m_TextHeight = z.cy;
m_dzoom = ((double)m_ctlRect.Height()/(double)z.cy) / 25.0;
m_zoomFont.lfWidth = (int)(m_logFont.lfWidth * m_dzoom);
m_zoomFont.lfHeight = (int)(m_logFont.lfHeight * m_dzoom);
m_font.Detach();
m_font.CreateFontIndirect(&m_zoomFont);
CFont *oFont = dc.SelectObject(&m_font);
// SetFont(&m_font);
z=dc.GetTextExtent(CString("A"));
m_TextHeight = z.cy;
if(m_bctlBorder){
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;
}
if(bInitialization)
{
m_iMtop = m_iMbottom = m_clientRect.Height()/10;
m_iMleft = m_iMright = m_clientRect.Width()/10;
}
// compute plot rect.
m_plotRect.left = m_clientRect.left + m_iMleft;
m_plotRect.right = m_clientRect.right - m_iMright;
m_plotRect.top = m_clientRect.top + m_iMtop;
m_plotRect.bottom = m_clientRect.bottom - m_iMbottom;
// compute default legend possition
if(bInitialization)
{
m_legendRect.left = m_plotRect.left + (m_iMleft/5);
m_legendRect.right = m_plotRect.left + (m_plotRect.Width()/5);
m_legendRect.top = m_plotRect.top - (m_iMtop/2);
m_legendRect.bottom = m_plotRect.top + (m_iMtop);
int w = 0;
int n=0;
for(int x = 0; x< MAXLEGENDS;x++){
if(m_primarylegends[x].m_bIAmInUse){
n++;
z=dc.GetTextExtent(CString(m_primarylegends[x].m_szTitle));
if(z.cx > w )
w=z.cx;
// m_TextHeight = z.cy;
}
}
m_legendRect.right = m_legendRect.left + 40 + w;
m_legendRect.bottom = m_legendRect.top + 10 + (m_TextHeight*n);
}
// compute left axis area
m_axisLYRect.left = m_clientRect.left + (m_iMleft/5);
m_axisLYRect.right = m_plotRect.left;
m_axisLYRect.top = m_plotRect.top;
m_axisLYRect.bottom = m_plotRect.bottom;
// compute right axis area
m_axisRYRect.left = m_plotRect.left;
m_axisRYRect.right = m_clientRect.right - (m_iMright/5);
m_axisRYRect.top = m_plotRect.top;
m_axisRYRect.bottom = m_plotRect.bottom;
// compute bottom axis area
m_axisBXRect.left = m_plotRect.left;
m_axisBXRect.right = m_plotRect.right;
m_axisBXRect.top = m_plotRect.bottom;
m_axisBXRect.bottom = m_clientRect.bottom - (m_iMbottom/5);
// if(bInitialization)
// {
m_timeaxis.m_dSecondsPrPixel = ((double)(m_timeaxis.m_maxtime.GetTime() - m_timeaxis.m_mintime.GetTime())) / (double)m_plotRect.Width();
m_leftaxis.m_dValuePrPixel = ((double)(m_leftaxis.maxrange- m_leftaxis.minrange) / (double)m_plotRect.Height());
m_rightaxis.m_dValuePrPixel = ((double)(m_rightaxis.maxrange- m_rightaxis.minrange) / (double)m_plotRect.Height());
// }
dc.SelectObject(oFont);
}
//*******************************************************************************************************/
//* Function: clPlot::OnPaint
//*
//* Description: This function will create a memory image, call Draw to draw the plot on it, and when
//* copy the image into memory.
//*
//* This is fast and provides flicker free plot update.
//*
//* Author: Jan Vidar Berger
//*******************************************************************************************************/
void clPlot::OnPaint()
{
CPaintDC dc(this); // device context for painting
CMemDC pdc(&dc); // non flickering painting
Draw(&pdc);
// Do not call CWnd::OnPaint() for painting messages
}
BOOL clPlot::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
//*******************************************************************************************************/
//*******************************************************************************************************/
void clPlot::Draw(CDC * dc)
{
CFont *oFont = dc->SelectObject(&m_font);
DrawBasic(dc);
DrawGrid(dc);
DrawPlot(dc);
DrawLegend(dc);
dc->SelectObject(oFont);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -