c# - 在WinForms应用程序中绘制数千条线的最快方法是什么

标签 c# winforms performance graphics

我有 WinForms 应用程序。我制作了一个用户控件,它根据大约 10k 行的坐标绘制 map 。实际上,并非所有直线都是直线,但是本地图完全缩小时 - 贝塞尔曲线不再相关,而是被直线取代。

本地图缩放时,我的直线和曲线数量较少,因此绘图速度足够快(低于15毫秒)。但是当它完全缩小时 - 我需要绘制所有线条(因为所有线条都适合视口(viewport))。这速度慢得令人痛苦。在我的速度非常快的机器上,大约需要 1000 毫秒,因此在速度较慢的机器上,这将是一个过大的杀伤力。

有没有一种简单的方法可以加快绘图速度? 我使用 Graphics 对象进行绘图,并将 Graphics.Scale 属性设置为适合我的控件的 map 。 这会减慢速度吗? 我使用 Graphics.TranslateTransform() 来确保整个 map 可见。 缩放和平移仅在 OnPaint() 事件处理程序中设置一次。

然后有一个循环绘制大约 10k 行。我只是看到他们在屏幕上画画。

也许 WPF 容器会有所帮助?

嗯,我可能可以简化 map 以合并一些线,但我想知道这是否值得。它会使代码变得非常复杂,会引入更多的计算,使用额外的内存,我不知道最终它是否会更快。

顺便说一句,我测试了在我的机器上处理所有行(通过一些额外的计算从一种结构转换为另一种结构)大约需要 10 毫秒。因此 - 仅绘图就花费了 100 倍的时间。

编辑: 现在新问题来了。我已经打开双缓冲:

SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);

这是我困惑的 OnPaint() 处理程序:

protected override void OnPaint(PaintEventArgs e) {
    base.OnPaint(e);
    if (Splines == null) return;

    var pens = new[] {
        new Pen(TrackColor),
        new Pen(TrackColor),
        new Pen(RoadColor),
        new Pen(RiverColor),
        new Pen(CrossColor)
    };

    var b = Splines.Bounds;
    Graphics g = e.Graphics;

    g.PageScale = _CurrentScale;
    g.TranslateTransform(-b.Left, -b.Top);
    int i = 0;
    foreach (var s in Splines) {
        g.DrawLine(pens[s.T], s.A, s.D);
        if (++i > 100) break;
        //if (s.L) g.DrawLine(pens[s.T], s.A, s.D);
        //else g.DrawBezier(pens[s.T], s.A, s.B, s.C, s.D);
    }

    foreach (var p in pens) p.Dispose();
}

相信我的话,如果我只从样式中删除 OptimizedDoubleBuffer ,代码就可以工作。当处理程序正确执行双缓冲时,每个 DrawLine 都会使用正确的参数执行。但图形不显示。调整大小期间的 CPU 使用率接近于零。就像所有 DrawLine 调用都被忽略一样。这里发生了什么?

最佳答案

在我最近看到但找不到的相关帖子中,OP 声称在将其控制切换到使用双缓冲时看到了很大的加速。显然,在屏幕上绘制东西很受欢迎。

您可以尝试的另一件事是在缩小时减少绘制的线条中的点列表。您可以在每次更改缩放比例时只执行一次,而不是每帧都进行抽取。

关于c# - 在WinForms应用程序中绘制数千条线的最快方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27892059/

相关文章:

vb.net - 如何在 vb.net 中更改 DateTimePicker 的日期格式

winforms - 避免处理系统定义的 Pen 和 Brush 实例

c# - 为什么在模态对话框中调用 Hide() 时 FormClosing 会触发两次?

c# - EF 5 更新超时;可能是由于死锁

c# - 模型未在 ASP.NET MVC 3 中传递

java - Tomcat Web 应用程序线程转储

python - 在 Python 中高效创建(播种)大型字典

python - 找到两个字符串之间交集的最佳方法是什么?

c# - LogParser 访问被拒绝错误

c# - 自定义订单,可以吗?