更快的图形

Faster Graphics

所以我一直在研究 3D - 2D 矢量变换,并想开始编写一些有趣、简单的程序来与简单的二次曲面等进行交互。我的问题是:

有哪些好方法可以提高我的代码效率?是否有其他基于 C# 的程序可用于图形?

我正在使用 C# 工作(并且绝对想保持这种状态),并且我意识到到目前为止我一直在以一种非常低效的方式来做这件事。

我不知道我是否可以改进我的循环,或者我每次移动相机时都会计算转换的事实,或者什么,但是任何帮助都会很棒!

下面是一些示例代码(绘制图中所示的表面:http://i.imgur.com/ewjTuii.png

void ColorSurface(Point3[] S)
    {
        List<Panel> f = new List<Panel>();
        try
        {
            for (int x = 0; x < 9; x++)
            {
                for (int y = 0; y < 9; y++)
                {
                    f.Add(new Panel(S[(10 * x) + y], S[(10 * x) + y + 1], S[(10 * x) + y + 11], S[(10 * x) + y + 10], View));
                }
            }
        }
        catch { }
        for (int sort = 0; sort < f.Count - 1; sort++)
        {
            Panel temp;
            if (f[sort] > f[sort + 1])
            {
                temp = f[sort + 1];
                f[sort + 1] = f[sort];
                f[sort] = temp;
            }
        }
        using (var g = this.CreateGraphics())
        {
            for (int i = 0; i < f.Count; i++)
            {
                double dev = f[i].PM.Z;
                PointF[] R = new PointF[4];
                R[0] = Transform32(f[i].P1);
                R[1] = Transform32(f[i].P2);
                R[2] = Transform32(f[i].P3);
                R[3] = Transform32(f[i].P4);
                try
                {
                    SolidBrush G = new SolidBrush(Color.FromArgb(235, (int)(((255 / Math.PI) * (Math.Atan((dev / 10) + 0.2) + (Math.PI / 2)))), 0, 255 - (int)(((255 / Math.PI) * (Math.Atan((dev / 10) + 0.2) + (Math.PI / 2))))));
                    g.FillPolygon(G, R);
                    g.DrawPolygon(new Pen(Color.Black, 1), R);
                    DrawPoint(f[i].PM, new Pen(Color.Black, 3));
                }
                 catch { }
            }
            }

    }

一些快速提高效率的技巧:

  1. 我在这里所说的一切都适用:。特别是,您没有在 OnPaint 中进行绘图。不要使用 CreateGraphics。这不是坏事,你只是没有正确地构建你的代码,它会让以后的事情变得更加困难。

  2. 您在每次循环迭代中访问 List.Count。这通常会添加一个您希望避免的 non-inlined 方法调用(通常,在我之后重复 "the JIT is not very smart" :))。推荐一种形式,例如 for (int sort = 0, count = f.Count; sort < count - 1; sort++) 等。如果您的代码通过从另一个区域移交的 IList<T> 引用(例如作为函数参数)进行访问,这一点尤为重要。是的,现在 CPU 有很好的分支预测。然而,这仍然是在热路径上绝对应该避免的低效率。

  3. 您在每次循环迭代中分配一个全新的 PointF[]。在循环外创建一次并重复使用它。

  4. 更糟糕的是,您在每次循环迭代时都会创建一个全新的 SolidBrush而且 你没有在上面调用 Dispose!至少你需要使用 using,例如using (SolidBrush G = new SolidBrush(...)) { ... }.

  5. 您还在每次循环迭代中创建了两个全新的 Pen,即使它们始终相同。创建一次并重复使用。还可以考虑对第一个使用 Pens.Black,这是一个您不必管理的静态缓存。

最后,不要做 catch { } 这样的事情。这通常属于 "worst practices" 样式指南部分 "DO NOT DO THIS EVER OR YOU WILL BE FIRED".