如何处理 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
值,无论缩放到多近或多远,都能保持正确的外观。
我正在 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
值,无论缩放到多近或多远,都能保持正确的外观。