I am trying to plot data on a PDA that is being collected in real time via the bluetooth serial port using c# and windows mobile 5. I am having trouble plotting the data in such a way that it appears smooth. I have tried drawing a line from an array of points which worked but only really displayed discrete chunks of data. I found a similar solution on this forum in reference to ECG data, which also worked but again it showed some amount of data and then very visibly refreshed. I have tried drawing the points onto a bitmap and then painting the bitmap to make it smoother but again it isn't really fast enough.
What I would like to end up with is something that behaves like the CPU usage history graph in the windows task manager. A data point starts on the right hand side of the plot and moves smoothly across to the left. Is there a standard approach to a problem like this? I apologise if the question is a little vague but I don't want to spend ages trying different things if its a problem with a well known general solution.
It kind of depends on how you want it to work visually. The CPU usage in Task Manager scrolls the entire chart right to left, and it is not at all smooth. It's refreshing (for me anyway) about once a second and when it refreshes, then entire chart "bumps" to the side.
I did something in the CF back in the 1.0 days as a test, and I opted to have the chart remain static and have the data lines continuually drawn left to right and when it reached the right edge, it would start drawing again back on the left, erasing the oldest chart data as it progressed (like an ECG does).
For that scenario, your bitmap is remaining largely unchanged, so you shouldn't be redrawing the entire thing. I did this by using a clipping resion that was basically a "vertical band" or rectangle the height of the chart but only, say, 10px wide. I redrew that band with the updated axis values so the only bits actually being redrawn is that small band. It also had the added benefit of doing the visible "erasing" the oldest data once I wrapped back to the start of the chart.
Related
I am currently working on a C# winforms graphing application. To get right to the point, the Paint event handler for my graphing control has to plot thousands of points which can take several seconds. During this time the application is frozen. My goal is the following: if the user changed what data to be plotted while the older data is being plotted then it would stop in the middle of drawing the older data and start drawing the new the data. What is the proper way to do this or is this something else I am total missing? I tried to make my question as clear as possible.
The answer to you question lies in double buffering. You don't need to know all the details about double buffering to use it. Simply set the property to true like below to enable it within a control.
MyGraphPanelControl.DoubleBuffered = true;
The obvious draw back is memory usage but it will greatly increase the "speed" of things drawn on the panel. Like a lot of things in Computer Science, you trade memory for speed and visa versa.
Also, reading this from Microsoft will give you more insight in how to use Double Buffering.
Hello: I am trying to create an app which will display a moving sphere. App will vary speed and direction. I've tried Adobe Flash but cannot get it smooth. Smoothness is essential in this case. So I am trying C#.
Initially, I can see that this can be implemented by:
1) Creating a PictureBox of a sphere, and using a Timer, change its coordinates. or
2) Using the this.paint function to draw a filled circle, and somehow, with a timer, erasing and redrawing it.
Can someone recommend the best path to take? I'll have a main menu where the user will chose speed/direction/how many etc... and then simply show the "game window" with the moving spheres. Any guidance would be much appreciated.
This is to be displayed on a PC only.
Thanks
-Ed
I just answered a similar question here.
NOTE: Depending on your needs, it is possible to achieve smooth animations under winforms (under certain conditions) though you are responsible for everything. wpf provides an animation framework but wpf is perhaps a milestone harder.
It probably does not matter should you pursue winforms first or WPF. You arguably could learn the basics under winforms then move over to wpf. wpf may require you to learn quite a bit before you can do anything.
Summary
Essentially what this does is to create an offscreen bitmap that we will draw into first. It is the same size as the UserControl. The control's OnPaint calls DrawOffscreen passing in the Graphics that is attached to the offscreen bitmap. Here we loop around just rendering the tiles/sky that are visible and ignoring others so as to improve performance.
Once it's all done we zap the entire offscreen bitmap to the display in one operation. This serves to eliminate:
Flicker
Tearing effects (typically associated with lateral movement)
There is a Timer that is scheduled to update the positions of all the tiles based on the time since the last update. This allows for a more realistic movement and avoids speed-ups and slow-downs under load. Tiles are moved in the OnUpdate method.
If you note in the code for Timer1OnTick I call Invalidate(Bounds); after animating everything. This does not cause an immediate paint rather Windows will queue a paint operation to be done at a later time. Consecutive pending operations will be fused into one. This means that we can be animating positions more frequently than painting during heavy load. Animation mechanic is independent of paint. That's a good thing, you don't want to be waiting for paints to occur. xna does a similar thing
Please refer to my full SO answer complete with sample code
Here are a few hints to get you going:
First you will need to come to a decision about which platform to target: WPF or Winforms.
Then you should know what to move across what; a nice Bitmap or just a circle across an empty background or a Bitmap or a Form with controls on it.
In Winforms both your approaches will work, esp. if you set a circular region see here for an example of that. (The part in the fun comment!)
And yes, a Timer is the way to animate the sphere. Btw, a Panel or even a Label can display an Bitmap just as well as a PictureBox.
For smooth movements make sure to set the Form.Doublebuffered=true, if you move across a Form. If you move across any other control (except a PictureBox or a Label) you will need to subclass it to get access to the DoubleBuffered property!
It is often also a good idea to keep the Location of a moving item in a variable as a PointF and use floats for its speed because this way you can fine grain the speed and Location changes and also the Timer Intervals!
In my WinRT app I need to draw about 3000 objects on a canvas, where I can translate and zoom the view. Unfortunatley, after adding about 1500 lines to my canvas my Windows 8 App always crashes. What could be the best practice to achieve this?
One solution could be rendering everything on an image (how do I do this?). But then I loose comfort of easy access and editing of every element.
Also my scale and translate is very slow. But since I also need a big overview, it makes no sense to put only the objects of the visible area in the canvas, since on minimum zoom it's still everything and zoomed it's still very laggy cause of add and remove operations.
There are a couple of different things you should employ to have a smooth UX:
Use a Quadtree, whenever you add a shape to your canvas you also put it on your Quadtree. This will be helpful when you will zoom on a portion of the image: you will know what objects are in this portion of the image; you will render them again (against using a cached/pixellated version).
To overcome the potentially lengthy drawing process you could do the following:
display the portion of the cached image overview at the right scale
use a progress indicator to let know the user that the program is working render this portion
when the faint rendering is done, blit it on the screen
A concrete example: Google Maps does that.
My Scenario:
I have a camera focused at a white screen, which is taking a live feed and displaying that feed in a picture box by virtue of a FrameReceived event.
I need to kick off a process to crop the image if something is inserted between the camera and the screen.
This process needs to start when the image first changes so I need to compare one frame with another to see if anything has changed.
My Efforts
I have tried hashing the images and comparing them, which doesnt work as the frames are never exactly the same
I have tried to loop through each pixel, comparing different values such as brightness, hue etc but this is too slow
I have tried looping through with a sub sample but it is either too slow or too unreliable.
I even tried what I like to call the "Twisted Pair Solution" where I inverted one then added them together and checking the result but this was far too complex and slow.
My Environment
Visual Studio 2012 (2010 if neccessary is available)
Ueye camera
C#
The images are of type System.Drawing.Bitmap
Notes
The biggest problem seems to be that to reliably get this result, it takes longer than we have for a reasonable frame rate, meaning that the calculation is not finished before a new frame comes in, which means that whatever variable I use to store the previous image is being overwritten before it can stop being used, and there appears to be thread after thread building up and it causes a whole lotta shakin.
I would recommend using some sort of image processing library , because the default .Net image processing tools are limited ,you can use an image processing library like http://www.aforgenet.com/framework/.
Than you can for example subtract image 1 from image 2, and sum the differences. If they are below a threshold (you choose the on the fits your need) they are identical.
or you can deep deeper and try this http://thecsharper.com/?p=94
I have an application which runs fullscreen on a high resolution display (1920x1080).
About 25% of the screen is a StackPanel that scrolls images across the screen.
(the X position is animated with double animation)
The scroll is very laggy and jumpy, and with visible tearing.
This is running on a brand new high-end gaming laptop, running Win7 64bit.
I don't understand why the performance is so poor. Am I doing something wrong? Does this kind of animation run on the CPU or GPU? Is there a smarter way to scroll images across the screen?
WPF can be hardware-accelerated, but only on newer video card drivers. Some of the onboard, out of box drivers, will default back to software rendering, which can feel really slow and clunky. As for the tearing, that's a normal video card setting, called V-Sync. I would try updating the video card drivers to a proprietary driver (nVidia, AMD, etc.), and enabling vertical sync on the card.
You can check to see if it falls into software, or hardware rendering using the methods explained here.
If that doesn't resolve the issue, the only other possibility I can think of is your animation/rendering is not synced to the GUI.
See this msdn article for more details.
A trick that I've seen that can get around this issue is to place a 3D object on your page, view it side on and rotate it e.g. for 4 images have a cube with an image set to each side.
Yes the rotation still requires GPU and processor time but it is taken care of internally by the WPF animation and so doesn't require interaction with code behind once set rolling.