我写了一张显示财务数据的图表。当我使用PathGeometry
以及PathFigure
和LineSegment
来绘制不到10.000点作为连线时,表现很好。但是现在我需要同时显示多达100.000点(没有滚动),而且已经非常慢,只有50.000点。我在考虑StreamGeometry
,但我不确定,因为它基本上与PathGeometry
将信息作为字节流进行处理相同。有没有人有想法让这更高效,或者有人甚至做过类似的事情?
编辑:这些数据点一旦绘制就不会改变,所以如果有潜在的优化,请告诉我(线段现在被冻结)。
编辑:我试过StreamGeometry。由于某种原因,创建图形的时间更长,但这不是问题。绘制所有点后在图表上绘制仍然与前一个方法一样慢。我认为WPF处理的数据点太多了。 编辑:我已经进行了一些实验,我注意到通过将先前为double的坐标转换为int来改善性能,以防止WPF抗锯齿子像素线。编辑:感谢所有建议减少线段数量的回复。对于阶梯线,我将它们降低到最多两倍的水平分辨率,对于简单的线条,最多是水平分辨率,现在性能相当不错。
答案 0 :(得分:16)
我会考虑对您尝试渲染的点数进行下采样。您可能拥有50,000点数据,但您不太可能将它们全部放在屏幕上;即使你在一个显示器中绘制每一个点,你也需要100,000像素的水平分辨率来绘制它们!即使在D3D中也有很多东西需要绘制。
由于您更有可能拥有2,048像素的像素,因此您可以减少绘图点并绘制适合屏幕的近似曲线,并且只有几千个顶点。例如,如果用户绘制包括10000个点的时间帧,则在绘图之前将那些10000点下采样到1000。您可以尝试多种技术,从简单平均到中间邻居到高斯卷积再到(我的建议)bicubic interpolation。 Drawing any number of points greater than 1/2 the screen resolution will simply be a waste
当用户放大图形的一部分时,您可以重新采样以获得更高的分辨率和更准确的曲线拟合。
答案 1 :(得分:6)
当您开始处理几何体中数十万个不同的顶点和向量时,您应该考虑将图形代码迁移到使用图形框架而不是依赖于WPF(它建立在Direct3D之上,因此能够非常有效的矢量图形渲染,有很多额外的开销正在阻碍它的效率)。可以在WPF中托管Direct3D和OpenGL图形渲染窗口 - 我建议移动该方向,而不是继续仅在WPF中工作。
(编辑:在“Direct3D”的原始答案中更改了“DirectX”)
答案 2 :(得分:5)
另一个想法是使用Image控件,并将Source属性设置为您动态创建的DrawingImage。
根据WPF Control Development Unleashed中的Pavan Podila所说,当您拥有成千上万的不需要任何交互性的视觉效果时,这种方法非常有用。查看他的书的第25页了解更多信息。
这是一个旧线程,但我认为值得一提的是,您可以通过使用MouseUp()事件与上述方法实现交互。您知道图像视口的大小,图像的分辨率和鼠标的位置。例如,您可以通过附加到UserControl_SizeChanged事件的计时器维护集合actualScreenPoints:
double xworth = viewport.ActualWidth / (XEnd - XStart);
double xworth = viewport.ActualHeight / (YEnd - YStart);
List<Point> actualScreenPoints = new List<Point>();
for (var i = 0; i < points.Count; i++)
{
double posX = points[i].X * xworth;
double posY = points[i].Y * yworth;
actualScreenPoints.Add(posX, posY);
}
然后当您的MouseUp()事件触发时,检查集合中的任何点是否在+ -2px范围内。在给定的点上有你的MouseUp。
答案 3 :(得分:4)
我不知道它的扩展程度如何,但我在WPF中使用ZedGraph取得了一些成功(WindowsFormsPresenter中的WinForms控件)。我很惊讶没有人提到它。即使您没有计划将其用于当前项目,也值得一看。
祝你好运!答案 4 :(得分:4)
刚开始讨论这个问题,但正如我在this帖子中所提到的,最有效的方法可能就是针对WPF的可视化层进行编程。
WPF中的所有Visual视频最终都与这一层相悖......所以它是所有这些中最轻量级的方法。
有关详细信息,请参阅this和this。马修麦克唐纳的 Pro WPF in C# 2008 书的第14章也有一个很好的部分。
作为另一个参考......参见Pavan Podila的书 WPF Control Development Unleashed 的第2章。在第13页,他讨论了DrawingVisuals如何成为图表组件的绝佳选择。
最后,我刚刚注意到Charles Petzold写了一篇MSDN杂志article,其中最好的整体(高性能)解决方案(散点图)是DrawingVisual方法。
答案 5 :(得分:3)
我相信保留在WPF框架中的唯一方法可能是在自定义控件中覆盖OnRender。然后,您可以将几何体直接渲染到持久场景,剔除视图之外的任何内容。如果用户一次只能看到一小部分数据集,那么剔除就足够了。
有了这么多数据点,当整个数据集在视图中时,用户不太可能看到完整的细节。因此,考虑简化整个视图的数据集,然后在放大时显示更详细的视图也是值得的。
编辑:另外,给StreamGeometry一个镜头。它存在的全部原因是性能,直到你尝试才会知道。
答案 6 :(得分:1)
这是一个非常好的问题,并且它的核心问题是“任何用户都可以从包含100,000个离散点的屏幕中实际使用或做出商业决策吗?”。
遵循GUI设计philosphy的最佳实践,答案应该是否,这将使我质疑是否有不同的方式来满足应用程序的要求。
如果真的有一个真正的案例,在屏幕上显示100,000点,没有滚动,那么使用离屏缓冲区是可行的方法。将图像合成到位图,而不是根据需要将位图打到窗口/页面上。这样,繁重的工作只进行一次,之后每次需要绘制窗口时都可以使用硬件加速。
希望这有帮助。
答案 7 :(得分:0)
我没有使用WPF(免责声明),但我怀疑你的性能问题是因为你的代码试图在所有数据中拟合一条平滑的曲线,并且所需的时间增加了几何(或更糟)数据点的数量。
我不知道这是否可以在外观上接受,但尝试通过用直线将每个点连接到最后一个来绘制数据。这应该使得时间 - 图表与数据点的数量成比例,并且使用尽可能多的点,图表可能最终看起来完全相同。
答案 8 :(得分:0)
另一个想法是使用Image控件,并将Source属性设置为您动态创建的DrawingImage。
根据Pavan Podila中的WPF Control Development Unleashed,当您拥有成千上万的不需要任何交互性的视觉效果时,这种方法非常有用。查看他的书的第25页了解更多信息。