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

How to handle a large amount of geometry data in a WPF drawing?

我正在 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 稍后绘制它),它会被重复调用,但它遇到了麻烦并崩溃并显示以下消息:

The thread 0x3228 has exited with code 0 (0x0). Exception thrown: 'System.OverflowException' in PresentationCore.dll An unhandled exception of type 'System.OverflowException' occurred in PresentationCore.dll The image data generated an overflow during processing.

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

我猜这可能会使系统超出其设计目标 - 是否有更好的方法在 WPF 中处理此问题?它可以处理大量几何数据吗?如果不能,限制在哪里?

您可以使用 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

这是一个link到一个C# implementation

您可以根据缩放级别动态调整 epsilon 值,无论缩放到多近或多远,都能保持正确的外观。