Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 提高DrawingContext性能渲染几何体(多边形和多段线)_C#_Wpf_Performance_Drawingcontext - Fatal编程技术网

C# 提高DrawingContext性能渲染几何体(多边形和多段线)

C# 提高DrawingContext性能渲染几何体(多边形和多段线),c#,wpf,performance,drawingcontext,C#,Wpf,Performance,Drawingcontext,这是我的第一个问题,但我是一个长期潜伏者。我将把它分成两部分,一部分解释我在做什么,为什么我认为这是一条路,第二部分是我自己无法解决的实际问题 我在做什么? 我目前正在开发一个框架,用于呈现实时显示的二维特征。您可以在浏览器中想到像Google Maps这样的应用程序,但是该框架旨在呈现所有类型的地理数据(而不仅仅是轴对齐的光栅数据,如Google瓷砖) 该框架将集成到我们(该公司)的最新产品中,该产品是用于台式机和笔记本电脑的WPF应用程序 因此,我选择WPF仅用于实际渲染几何体;可见性和遮挡

这是我的第一个问题,但我是一个长期潜伏者。我将把它分成两部分,一部分解释我在做什么,为什么我认为这是一条路,第二部分是我自己无法解决的实际问题

我在做什么? 我目前正在开发一个框架,用于呈现实时显示的二维特征。您可以在浏览器中想到像Google Maps这样的应用程序,但是该框架旨在呈现所有类型的地理数据(而不仅仅是轴对齐的光栅数据,如Google瓷砖)

该框架将集成到我们(该公司)的最新产品中,该产品是用于台式机和笔记本电脑的WPF应用程序

因此,我选择WPF仅用于实际渲染几何体;可见性和遮挡剔除由我自己完成,以及输入处理(鼠标拾取)、移动相机等

作为一个实时应用程序,它至少需要达到30 FPS。渲染图像时,该框架的性能足够:我可以在每帧中绘制数千个位图,没有问题,但是PolyOne数据是一个主要问题

实际问题 我正在使用WPF渲染大量的多段线和多边形数据,特别是使用DrawingContext和StreamGeometry。到目前为止,我的理解是,如果我需要表现,这是一种方法。然而,我无法实现我期望的结果

这是我用实际数据填充StreamGeometry的方式:

using (StreamGeometryContext ctx = Geometry.Open())
{
        foreach (var segment in segments)
    {
        var first = ToWpf(segment[0]);
        ctx.BeginFigure(first, false, false);

        // Skip the first point, obviously
        List<Point> points = segment.Skip(1).Select(ToWpf).ToList();
        ctx.PolyLineTo(points, true, false);
    }
}
    Geometry.Freeze();
作为测试,我将OpenStreetMap中的ESRI形状加载到我的应用程序中,以测试其性能,但我一点也不满意: 我的测试数据由约3500条线段组成,总共约20k条线段

将每个片段映射到它自己的StreamGeometry执行得非常糟糕,但我已经有点预料到了:渲染大约需要14秒

然后,我尝试使用多个图形将更多段打包到同一个StreamGeometry中: 80 StreamGeometry,渲染大约需要50毫秒

然而,我没有比这更好的结果了。将行数增加到大约100k会使我的应用程序几乎无法使用:渲染需要超过100ms。 在渲染矢量数据时,除了冻结几何体和笔,我还能做什么

我现在更愿意自己使用DirectX,而不是依赖WPF来处理它,因为有些事情似乎出了很大的问题

编辑

为了进一步说明我在做什么:该应用程序实时可视化地理数据,非常像浏览器中的谷歌地图(GoogleMaps)这样的应用程序:但是它应该可视化更多的数据。您可能知道,谷歌地图允许缩放和平移,这需要>25 FPS才能显示为流畅的动画;少一点的感觉都不流利

* 对不起,在实际产品发布之前,我不应该上传视频。但是,您可能会设想像Google Maps这样的东西,但是有大量的矢量数据(多边形和多段线)。 *

有两种解决方案,其中一种经常被提及:

在位图中缓存重型图形

实现似乎有点简单,但我发现这种方法存在一些问题:为了正确实现平移,我需要避免在每帧绘制沉重的内容,因此我可以选择在平移相机时不更新缓存的位图,或者创建一个覆盖比视口更大区域的位图,这样我只需要每隔一段时间更新缓存的位图

第二个“问题”与缩放有关。然而,这更像是一个视觉伪影,而不是一个真正的问题:因为缓存的位图不能以每秒30帧的速度正确更新,所以在缩放时我也需要避免这种情况。我很可能在缩放时缩放位图,仅在缩放结束时创建一个新位图,但是多段线的宽度不会具有恒定的厚度,尽管它们应该具有恒定的厚度

MapInfo似乎确实使用了这种方法,但我不能说我太喜欢它。不过,它似乎是最容易实现的

将几何图形拆分为不同的图形视觉效果

这种方法似乎以不同的方式处理这个问题。我不确定这种方法是否有效:这取决于我是否正确理解WPF在这个领域应该如何工作。 对于所有需要绘制的东西,我不应该使用一个DrawingVisual,而是应该使用多个,这样就不需要渲染每个东西()。我可以简单地更改参数,例如上面示例中的矩阵,以反映相机平移和移动。 然而,我也看到了这种方法的一些问题:平移摄影机将不可避免地将新的几何体带入视口,因此我需要执行与第一种方法类似的操作,实际渲染当前不可见的内容,但可能由于摄影机移动而变为可见的内容;绘制所有内容都是不可能的,因为对于一个相当小的数据量,可能需要花费大量的时间

与这两种方法相关的问题 这两种方法都无法解决的一个大问题是,即使总体帧速率稳定,偶尔也会出现打嗝,无论是在更新缓存位图时(好的,如果缓存位图仅在摄影机不再平移时更新),还是调用RenderOpen绘制可见的几何体块时,这似乎是不可避免的

我目前的想法

由于这是我见过的唯一两个解决这个问题的方法(我已经用谷歌搜索了一年多了),我想目前唯一的方法就是在最强大的GPU上(应该是
_dc.PushTransform(_mercatorToView);
_dc.DrawGeometry(null, _pen, polyline);
_dc.Pop();