ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Plot (Draw) many point in one second
Posted by Alex on Sep-24-2016 21:34
Hello

I have array with 100000 elements that will be update every second.(in c++)
I want to plot all points (element) in one second before the new array will create.
is it possible to draw 100000 point in real time method in one second?
(I want to use MFC real time example ).

  Re: Plot (Draw) many point in one second
Posted by Peter Kwan on Sep-25-2016 18:44
Hi Alex,

Yes, it should be possible to draw 100000 points per second. If you are plotting a line chart, please remember to use the "Fast Line Mode". See:

http://www.chartdir.com/forum/download_thread.php?site=chartdir&bn=chartdir_support&thread=1474067384#N1474619441

Regards
Peter Kwan

  Re: Plot (Draw) many point in one second
Posted by Alex on Sep-25-2016 20:25
Hi Peter

Thanks for your answer.
I saw your MFC projects and chose  "Real_time_chart" but this project draw point by point in unit of time. I want to draw 100000 point in that unit (unit means in my mind  :every point draw in fraction of second in your codes) .

Beside I checked your project code and saw your recommended command "Fast Line Mode" , it was written .



Peter Kwan wrote:

Hi Alex,

Yes, it should be possible to draw 100000 points per second. If you are plotting a line chart, please remember to use the "Fast Line Mode". See:

http://www.chartdir.com/forum/download_thread.php?site=chartdir&bn=chartdir_support&thread=1474067384#N1474619441

Regards
Peter Kwan

  Re: Plot (Draw) many point in one second
Posted by Alex on Sep-28-2016 13:55
Hi
Dear Peter Can you help us?

Alex wrote:

Hi Peter

Thanks for your answer.
I saw your MFC projects and chose  "Real_time_chart" but this project draw point by point in unit of time. I want to draw 100000 point in that unit (unit means in my mind  :every point draw in fraction of second in your codes) .

Beside I checked your project code and saw your recommended command "Fast Line Mode" , it was written .



Peter Kwan wrote:

Hi Alex,

Yes, it should be possible to draw 100000 points per second. If you are plotting a line chart, please remember to use the "Fast Line Mode". See:

http://www.chartdir.com/forum/download_thread.php?site=chartdir&bn=chartdir_support&thread=1474067384#N1474619441

Regards
Peter Kwan

  Re: Plot (Draw) many point in one second
Posted by Peter Kwan on Sep-28-2016 19:29
Attachments:
Hi Alex,

In the Realtime Chart sample code, there is a random number generator that updates the data by appending one data point per unit time. However, the chart is always drawn with all the data points.

In your real code, instead of using the random number generator to append one data point per unit time, you can always change 100000 points per unit time. The chart will still update correct as it is always drawing all the points.

I have modified the "mfcdemo/realtimedemo" sample code so that it now updates 100000 data points every second and use the points for a line chart. To try the sample code, please download the attached "realtimedemoDlg.cpp" and "realtimedemoDlg.h", and copy it to the "mfcdemorealtimedemo" subdirectory, overwriting the existing sample code there. Then please compile and run the code for testing. In my own machine, it consumes around 2% CPU only for plotting 100000 points per second.

Hope this can help.

Regards
Peter Kwan
realtimedemoDlg.cpp
// realtimedemoDlg.cpp : implementation file
//

#include "stdafx.h"
#include "realtimedemo.h"
#include "realtimedemoDlg.h"
#include <math.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

/////////////////////////////////////////////////////////////////////////////
// CRealtimedemoDlg dialog

static const int DataRateTimer = 1;
static const int ChartUpdateTimer = 2;
static const int DataInterval = 1000;

//
// Constructor
//
CRealtimedemoDlg::CRealtimedemoDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CRealtimedemoDlg::IDD, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_dataSeriesA = new double[sampleSize];
	memset(m_dataSeriesA, 0, sampleSize * sizeof(m_dataSeriesA[0]));
}

CRealtimedemoDlg::~CRealtimedemoDlg()
{
	delete[] m_dataSeriesA;
}

void CRealtimedemoDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CRealtimedemoDlg)
    DDX_Control(pDX, IDC_GammaValue, m_ValueC);
    DDX_Control(pDX, IDC_BetaValue, m_ValueB);
    DDX_Control(pDX, IDC_AlphaValue, m_ValueA);
    DDX_Control(pDX, IDC_ChartViewer, m_ChartViewer);
    DDX_Control(pDX, IDC_RunPB, m_RunPB);
    DDX_Control(pDX, IDC_UpdatePeriod, m_UpdatePeriod);
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CRealtimedemoDlg, CDialog)
    //{{AFX_MSG_MAP(CRealtimedemoDlg)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_TIMER()
    ON_WM_DESTROY()
    ON_BN_CLICKED(IDC_RunPB, OnRunPB)
    ON_BN_CLICKED(IDC_FreezePB, OnFreezePB)
    ON_CBN_SELCHANGE(IDC_UpdatePeriod, OnSelchangeUpdatePeriod)
    ON_CONTROL(CVN_ViewPortChanged, IDC_ChartViewer, OnViewPortChanged)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRealtimedemoDlg message handlers

//
// Initialization
//
BOOL CRealtimedemoDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // *** code automatically generated by VC++ MFC AppWizard ***
    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);         // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon
    
    //
    // Initialize member variables
    //
    m_extBgColor = getDefaultBgColor();     // Default background color

    // The random number seed.
    m_seed = 0;

    //
    // Initialize controls
    //

    // Set up the data acquisition mechanism. In this demo, we just use a timer to get a 
    // sample every 250ms.
    SetTimer(DataRateTimer, DataInterval, 0);

    // The chart update rate (in ms)
    m_UpdatePeriod.SelectString(0, _T("1000"));
    
    // Load icons for the Run/Freeze buttons
    loadButtonIcon(IDC_RunPB, IDI_RunPB, 100, 20);
    loadButtonIcon(IDC_FreezePB, IDI_FreezePB, 100, 20);

    // Initially set the Run mode
    m_RunPB.SetCheck(1);
    OnRunPB();

    return TRUE;
}

// *** code automatically generated by VC++ MFC AppWizard ***
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon.  For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CRealtimedemoDlg::OnPaint() 
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();
    }
}

// *** code automatically generated by VC++ MFC AppWizard ***
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CRealtimedemoDlg::OnQueryDragIcon()
{
    return (HCURSOR) m_hIcon;
}

//
// User clicks on the Run pushbutton
//
void CRealtimedemoDlg::OnRunPB() 
{
    // Enable chart update timer
    CString s;
    m_UpdatePeriod.GetLBText(m_UpdatePeriod.GetCurSel(), s);
    SetTimer(ChartUpdateTimer, _tcstol(s, 0, 0), 0);
}

//
// User clicks on the Freeze pushbutton
//
void CRealtimedemoDlg::OnFreezePB() 
{
    // Disable chart update timer
    KillTimer(ChartUpdateTimer);    
}

//
// Handles timer events
//
void CRealtimedemoDlg::OnTimer(UINT_PTR nIDEvent) 
{
    switch (nIDEvent)
    {
    case DataRateTimer:
        // Is data acquisition timer - get a new data sample
        getData();
        break;
    case ChartUpdateTimer:
        // Is chart update timer - request chart update
        m_ChartViewer.updateViewPort(true, false);      
        break;
    }
    
    CDialog::OnTimer(nIDEvent);
}

//
// View port changed event
//
void CRealtimedemoDlg::OnViewPortChanged()
{
    drawChart(&m_ChartViewer);
}

//
// User changes the chart update period
//
void CRealtimedemoDlg::OnSelchangeUpdatePeriod() 
{
    if (m_RunPB.GetCheck())
    {
        // Call freeze then run to use the new chart update period
        OnFreezePB();
        OnRunPB();
    }   
}

/////////////////////////////////////////////////////////////////////////////
// CRealtimedemoDlg methods

//
// A utility to shift a new data value into a data array
//
static void shiftData(double *data, int len, double newValue)
{
    memmove(data, data + 1, sizeof(*data) * (len - 1));
    data[len - 1] = newValue;
}

//
// The data acquisition routine. In this demo, this is invoked every 250ms.
//
void CRealtimedemoDlg::getData()
{
    // The current time in millisecond resolution
	RanSeries r(m_seed++);
	DoubleArray randomSeries = r.getSeries(sampleSize, 100, -2, 2, 0);
	memcpy(m_dataSeriesA, randomSeries.data, sampleSize * sizeof(m_dataSeriesA[0]));
}

//
// Draw the chart and display it in the given viewer
//
void CRealtimedemoDlg::drawChart(CChartViewer *viewer)
{
    // Create an XYChart object 600 x 270 pixels in size, with light grey (f4f4f4) 
    // background, black (000000) border, 1 pixel raised effect, and with a rounded frame.
    XYChart *c = new XYChart(600, 270, 0xf4f4f4, 0x000000, 1);
    c->setRoundedFrame(m_extBgColor);
    
    // Set the plotarea at (30, 62) and of size 550 x 175 pixels. Use white (ffffff) 
    // background. Enable both horizontal and vertical grids by setting their colors to 
    // grey (cccccc). Set clipping mode to clip the data lines to the plot area.
    c->setPlotArea(30, 62, 550, 175, 0xffffff, -1, -1, 0xcccccc, 0xcccccc);
    c->setClipping();

    // Add a title to the chart using 15 pts Times New Roman Bold Italic font, with a light
    // grey (dddddd) background, black (000000) border, and a glass like raised effect.
    c->addTitle("Field Intensity at Observation Satellite", "timesbi.ttf", 15
        )->setBackground(0xdddddd, 0x000000, Chart::glassEffect());
            
    // Configure the y-axis with a 10pts Arial Bold axis title
    c->yAxis()->setTitle("Intensity (V/m)", "arialbd.ttf", 10);

    // Configure the x-axis to auto-scale with at least 75 pixels between major tick and 
    // 15  pixels between minor ticks. This shows more minor grid lines on the chart.
    c->xAxis()->setTickDensity(75, 15);

    // Set the axes width to 2 pixels
    c->xAxis()->setWidth(2);
    c->yAxis()->setWidth(2);

    // Create a line layer to plot the lines
    LineLayer *layer = c->addLineLayer(DoubleArray(m_dataSeriesA, sampleSize), 0x0000ff);
	layer->setFastLineMode();

    // Set the chart image to the WinChartViewer
    viewer->setChart(c);
    delete c;
}

/////////////////////////////////////////////////////////////////////////////
// General utilities

//
// Get the default background color
//
int CRealtimedemoDlg::getDefaultBgColor()
{
    LOGBRUSH LogBrush; 
    HBRUSH hBrush = (HBRUSH)SendMessage(WM_CTLCOLORDLG, (WPARAM)CClientDC(this).m_hDC, 
        (LPARAM)m_hWnd); 
    ::GetObject(hBrush, sizeof(LOGBRUSH), &LogBrush); 
    int ret = LogBrush.lbColor;
    return ((ret & 0xff) << 16) | (ret & 0xff00) | ((ret & 0xff0000) >> 16);
}

//
// Load an icon resource into a button
//
void CRealtimedemoDlg::loadButtonIcon(int buttonId, int iconId, int width, int height)
{
    GetDlgItem(buttonId)->SendMessage(BM_SETIMAGE, IMAGE_ICON, (LPARAM)::LoadImage(
        AfxGetResourceHandle(), MAKEINTRESOURCE(iconId), IMAGE_ICON, width, height, 
        LR_DEFAULTCOLOR));  
}
realtimedemoDlg.h
// realtimedemoDlg.h : header file
//

#pragma once

#include "ChartViewer.h"
#include <afxmt.h>


// The number of samples per data series used in this demo
const int sampleSize = 100000;


// CRealtimedemoDlg dialog
class CRealtimedemoDlg : public CDialog
{
// Construction
public:
	CRealtimedemoDlg(CWnd* pParent = NULL);	// standard constructor
	~CRealtimedemoDlg();

// Dialog Data
	enum { IDD = IDD_REALTIMEDEMO_DIALOG };
	CStatic	m_ValueC;
	CStatic	m_ValueB;
	CStatic	m_ValueA;
	CChartViewer m_ChartViewer;
	CButton	m_RunPB;
	CSpinButtonCtrl	m_AlarmSpin;
	CComboBox	m_UpdatePeriod;

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support


// Implementation
protected:
	HICON m_hIcon;

	// Generated message map functions
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	afx_msg void OnTimer(UINT_PTR nIDEvent);
	afx_msg void OnRunPB();
	afx_msg void OnFreezePB();
	afx_msg void OnSelchangeUpdatePeriod();
	afx_msg void OnViewPortChanged();
	DECLARE_MESSAGE_MAP()


private:
	double *m_dataSeriesA;	// The values for the data series A

	double m_seed;			// Used by the random number generator to generate real time data.
	int m_extBgColor;		// The default background color.

	// Shift new data values into the real time data series 
	void getData();
	
	// Draw chart
	void drawChart(CChartViewer *viewer);

	// utility to get default background color
	int getDefaultBgColor();
	// utility to load icon resource to a button
	void loadButtonIcon(int buttonId, int iconId, int width, int height);
};

  Re: Plot (Draw) many point in one second
Posted by Alex on Oct-02-2016 19:58
Dear Peter

I saw your files. My problem resolved (thank you very very much) but i have a small question. :)
You update chart after one second but, if i want to update the chart after my array was created and  finished what shall we do?(I knew that i have  to modify switch case section) can you help me how ?

Best Regards
Alex
Section Of Your Code:

void CRealtimedemoDlg::OnTimer(UINT_PTR nIDEvent)
{
    switch (nIDEvent)
    {
    case DataRateTimer:
        // Is data acquisition timer - get a new data sample
        getData();
        break;
    case ChartUpdateTimer:
        // Is chart update timer - request chart update
        m_ChartViewer.updateViewPort(true, false);
        break;
    }

    CDialog::OnTimer(nIDEvent);
}

  Re: Plot (Draw) many point in one second
Posted by Peter Kwan on Oct-03-2016 23:39
Hi Alex,

In the example, the data are generated using a random number generator in the main thread. The data are generated periodically using a timer.

I am not exactly sure how your data are read into C++ array variables. If the data are read into C++ in the main thread (the same thread that the GUI is created), then you just need to call "m_ChartViewer.updateViewPort(true, false);" after getting the data. For example:

//function to get the data
getData();
m_ChartViewer.updateViewPort(true, false);

You probably already know that all MFC controls can only be called in the GUI thread. (It is because the MFC controls are constantly processing various Windows event in the GUI thread, such as the mouse events, paint events, etc. If it is also called by another thread, it would mean uncoordinated concurrent access, and would frequency lead to unpredictable strange problems.) So if your data are read in using another thread, you would need to post a message to the Form to inform it to update the chart.

Hope this can help.

Regards
Peter Kwan