可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
A simple XY line graph: The X axis will represent the complete range of possible rating percentages, from 0% on one end to 100% on the other. Specifically, the X value will represent our rating cut-off, or the minimum rating a transaction can have before it is no longer acceptable. The Y axis will show values from 0 to the total number of transactions that have come through. The Y value will represent the total number of transactions that have a rating greater than the current X value (or greater than or equal to the current X value, I haven't decided yet). No transactions will have come through when this graph is first drawn, so the graph will begin at "y=0x".
Let's say the first transaction comes through, with a rating of 40%. The rating of the transaction indicates that this transaction is acceptable if our rating cut-off is less than 40%. (... or less than or equal to 40%. Again, I haven't decided yet).
First, the Y axis will rescale to show the range of 0-1 (since 1 is the total number of transactions). Then the line will be modified to indicate that 0 transactions are acceptable from x=40 or more, and that 1 transaction is acceptable from x=40 or less. This is easy to accomplish in WPF by simply adding two points to the line path - one at (40,0) and the other at (40,1) - and then moving the line's left endpoint to (0,1). The line's right endpoint will remain at (100,0). This process can then be repeated for the second transaction, and so on.
The problem is that we will be dealing with six-digit quantities of transactions. and I want to make sure I am using WPF's hardware accelerated vector drawing capabilities to their fullest extent to ensure the graph doesn’t lag or freeze the rest of the program as it tries to render 300,000 points onto a single line path. Or is WPF supposed to be able to handle numbers like that in a heartbeat? I need to find a way to implement this graph without slowing the application to a halt. I have faith that WPF's vector drawing platform will provide a solution, but I don't know enough about how to exploit WPF to be certain that I am getting the most out of WPF's high-performance rendering capabilities.
回答1:
I just stumbled upon this post and am building a line graph control myself that needs to be very performant as we update the points on our lines in a real-time manner.
If performance and number of Visual(s) are what you are after ... I doubt you will find a more performant approach than programming directly against WPF's Visual layer (links: 1, 2). My initial results from using this approach have been very positive.
This will be even more performant than overriding OnRender as it will encourage you to take advantage of WPF's retained mode drawing subsystem (where all the drawing instructions are cached).
That is, if all you have to update is a point on the line, then updating the point will force the line Visual to update but won't force the rest of the graph (axes, gridlines, ...) to update ... as the drawing instructions for these are retained and will be reused (since they aren't updating).
Chapter 14 in Pro WPF in C# 2008 by Matthew MacDonald has a great section (titled 'Visuals') on programming against WPF's Visual layer. Chapter 2 of WPF Control Development Unleashed also has section on page 13 where he discusses how a DrawingVisual approach would be perfect for a charting component. Finally, Charles Petzold wrote a MSDN Magazine article where the best overall solution to a scatter plot was a DrawingVisual approach.
(Now, I know that your question mentioned the axes will also be updating ... and so my answer is really for the general case ... but I still think that this approach will be the most performant ... as only the things that need updating ... will update.)
回答2:
If you want it to be fast, the best way is to derive from Control and implement OnRender - normally this isn't necessary, but for your application it might be.
Also, let's take a step back - the screen you're rendering to certainly isn't 300k pixels across; before you go to render, reduce the buffer by averaging n nodes into one until you've got something closer to the resolution of the actual device, then draw it on-screen.
回答3:
I do not know the answer, but coding up a quick test shouldn't take much longer than it did for you to post. Also, see this thread for a similar discussion.
回答4:
It might be worth having a look at the WPF DynamicDataDisplay library. I've been using it recently and haven't any problems with large amounts of data. It's only an early version (0.3 in fact) so there's not much documentation, but it does have samples showing how to use it. Hopefully that'll be enough to get you started.
The SimulationSample generates lots of data, so that should be a good place to start.
回答5:
If you aren't using .NET 3.5 SP1 just don't use any of the shader effects. Otherwise there isn't much you need to do as a WPF developer to ensure it uses hardware acceleration.
回答6:
IMHO, Paul seems to be on the right track, check out the sections on map smoothing, some of the examples use results from the Florida 2000 election results (~9M votes 18+M total people) for data sets.
Along the lines of the thread from AgileJon, somewhat, I would use simply manually emit a bitmap if no straight forward technique was available to better depect your data set. I render visualizations of scatter plots that are easially 16 000 000 (16 Million+) in seconds, full 32bit ARGB pallette.
You seem to of remarked "But going back to bitmaps seems like a giant step backwards", I would not be so quick to say that, the universe is bound by physical limits.
I referred another post to this codeproject article, which does many tens of thousands of 3D plots + animation etc...