Page 1 of 1
Accumulation mode
Posted: Mon May 21, 2012 9:02 am
by 15661458
Hello Steema,
I am drawing an oscilloscope in realtime using FastLine series. I also need a special "accumulation" mode to visualize signal noise by drawing each incoming data set *without* removing any of the previous data already visible. Adding a new series each time my data (8K point set) changes is not an option in a realtime scenario. I tried the Error series, but it does not exactly give me the result I need. Do you have any ideas?
Thanks in advance
Philipp
P.S.
Another small question... How can I convert a mouse client coordinate inside the chart area (not series) to the corresponding chart view position? I need to position the cursor tool to the mouse click position...
Re: Accumulation mode
Posted: Mon May 21, 2012 2:41 pm
by 10050769
Hello Philipp,
I am drawing an oscilloscope in realtime using FastLine series. I also need a special "accumulation" mode to visualize signal noise by drawing each incoming data set *without* removing any of the previous data already visible. Adding a new series each time my data (8K point set) changes is not an option in a realtime scenario. I tried the Error series, but it does not exactly give me the result I need. Do you have any ideas?
Can you please send us a simple code with your data so we can try to find a solution for you? Also, I recommend you take a look in demo project,concretely, in All Features\Welcome !\Functions where there are a examples of function that can helpful for you.
P.S.
Another small question... How can I convert a mouse client coordinate inside the chart area (not series) to the corresponding chart view position? I need to position the cursor tool to the mouse click position...
I recommend you use method CalcPosPoint(int value) of axes that returns the corresponding value of a Screen position.
Thanks,
Re: Accumulation mode
Posted: Mon May 21, 2012 3:57 pm
by 15661458
Hello Sandra,
thanks for your quick reply. I could not find sth. suitable in the demo projects. Here is some code, that should give you the basic idea:
Code: Select all
// Methods gets called whenever data is available
public void UpdateChannelData(string seriesName, double[] data)
{
var series = _oscilloscopeDataSeries[seriesName];
if (this.EnableAccumulation)
{
// TODO: I want to draw the new set of data while keeping all past series data visualized in the chart.
// I do not need the complete data and properties of all last series in memory, but just the graphics...
// Since this method gets called very often (every 30ms) I can not add a new series with approx. 8000 values
// each time. Is there some way to draw the updated series, without erasing the old series?
}
else
{
// simple: just reset old values and update the series with incoming data
series.Delete(0, series.Count);
series.Add(data);
}
Your second tip worked great
Thanks
Re: Accumulation mode
Posted: Mon May 21, 2012 5:48 pm
by 15661458
I figured out how to do it, but it is rather cumbersome...
Code: Select all
void OnAfterDraw(object sender, Graphics3D g)
{
if (_enableAccumulationMode)
{
// 1) render current frame to accumulation buffer
using (Graphics gfx = Graphics.FromImage(_accumulationBuffer[0]))
{
g.BackBuffer.Render(gfx);
}
// 2) combine current frame with accumulation buffer
unsafe
{
int width = _accumulationBuffer[0].Width;
int height = _accumulationBuffer[0].Height;
var srcData =
_accumulationBuffer[0].LockBits(Rectangle.FromLTRB(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
var dstData =
_accumulationBuffer[1].LockBits(Rectangle.FromLTRB(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
int* srcPtr = (int*)srcData.Scan0;
int* dstPtr = (int*)dstData.Scan0;
HashSet<int> colorLut = new HashSet<int>();
foreach (var series in _osciDataChannels.Values)
{
colorLut.Add(series.Color.ToArgb());
}
for (int idx = 0; idx < height * width; idx++, srcPtr++, dstPtr++)
{
int srcValue = *srcPtr;
if (colorLut.Contains(srcValue))
{
*dstPtr = srcValue;
}
}
_accumulationBuffer[0].UnlockBits(srcData);
_accumulationBuffer[1].UnlockBits(dstData);
}
// 3) draw combined frame on top
g.Draw(0, 0, _accumulationBuffer[1]);
}
}
_accumulationBuffer must be the size of the chart area and updated /reset if scroll or zoom changes or chart size... And yes, this also comes with a performance penalty, but is a lot faster and memory friendly than adding a new series each time
the data changes...
If there is a more elegant / faster way please help me out
Thanks
Philipp
Re: Accumulation mode
Posted: Wed May 23, 2012 2:28 pm
by 10050769
Hello Philipp,
Thanks for your code and your solution. I am glad that you have found a solution for your problem. On the other hand, to try to optimize your code would be very helpful for us if you can send your project.
Thanks,