如何处理WPF绘​​图中的大量几何数据?

时间:2018-01-29 21:56:27

标签: c# wpf vector-graphics

我正在尝试使用WPF UI中的DrawingGroup绘制一些项目,代码看起来有点像这样:

foreach( var path in allRoads ) 
{
    var wpfPen = new Pen(brush, penSize);
    GeometryDrawing geometry = new GeometryDrawing();
    geometry.Pen = wpfPen;
    geometry.Geometry = GetPathGeometry(path);
    drawingGroup.Children.Add(geometry);
}

当我绘制我正在渲染的各种几何项目时,我会反复调用它(我将它们添加到DrawingGroup然后要求DrawingContext之后绘制它)但它会遇到麻烦并崩溃输出以下消息:

  

线程0x3228已退出,代码为0(0x0)。抛出异常:   PresentationCore.dll中的“System.OverflowException”未处理   发生在'System.OverflowException'类型的异常   PresentationCore.dll图像数据在生成期间产生溢出   处理

崩溃似乎发生在第38000个几何项目(所有这些多点路径,有些可能很长,因为这是GIS数据)被添加到DrawingGroup.Children集合中。

我猜这可能会推动系统超越它的设计目标 - 在WPF中有更好的方法来处理这个问题吗?它可以处理大量的几何数据,如果没有,下落就是限制吗?

1 个答案:

答案 0 :(得分:1)

在尝试渲染点之前,您可以使用Non-parametric Ramer-Douglas-Peucker算法简化点的集合。这将保持相同的基本形状,但大大减少细节(在您正在谈论的缩放级别甚至可以看到的细节)。

来自维基百科的伪代码:

function DouglasPeucker(PointList[], epsilon)
    // Find the point with the maximum distance
    dmax = 0
    index = 0
    end = length(PointList)
    for i = 2 to ( end - 1) {
        d = perpendicularDistance(PointList[i], Line(PointList[1], PointList[end])) 
        if ( d > dmax ) {
            index = i
            dmax = d
        }
    }
    // If max distance is greater than epsilon, recursively simplify
    if ( dmax > epsilon ) {
        // Recursive call
        recResults1[] = DouglasPeucker(PointList[1...index], epsilon)
        recResults2[] = DouglasPeucker(PointList[index...end], epsilon)

        // Build the result list
        ResultList[] = {recResults1[1...length(recResults1)-1], recResults2[1...length(recResults2)]}
    } else {
        ResultList[] = {PointList[1], PointList[end]}
    }
    // Return the result
    return ResultList[]
end

以下是C# implementation的链接。

您可以根据缩放级别动态调整epsilon值,无论您缩放的距离有多近,都可以保持正确。