所以我一直在研究三维-二维矢量变换,并想开始编写一些有趣、简单的程序来与简单的二次曲面等进行交互。我的问题是:
有哪些好方法可以提高代码的效率?还有其他基于C#的程序可以用于图形吗?
我在C#工作(我肯定想保持这种状态),我意识到到到目前为止我一直在以一种非常低效的方式做这件事。
我不知道我是否可以改进我的循环,或者我每次移动相机时都会计算变换,或者其他什么,但任何帮助都会很棒!
以下是一些示例代码(绘制如图所示的表面:https://i.stack.imgur.com/zi1ZQ.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 { }
}
}
}
一些快速高效的提示:
-
我在这里所说的一切都适用:https://stackoverflow.com/a/11025428/1191082。特别是,您不是在
OnPaint
中进行绘图。不要使用CreateGraphics
。这并不邪恶,你只是没有正确地构建你的代码,这会让以后的事情变得更加困难 -
您在每次循环迭代中都访问
List.Count
。这通常会添加一个您希望避免的非内联方法调用(通常,在我之后重复,"JIT不是很聪明":)。推荐一个表单,如for (int sort = 0, count = f.Count; sort < count - 1; sort++)
等。如果您的代码是通过从另一个区域移交的IList<T>
引用访问的(如作为函数参数),则这一点尤为重要。是的,CPU现在有很好的分支预测。然而,这仍然是一种效率低下的情况,在热路径上应该绝对避免。 -
在每个循环迭代中分配一个全新的
PointF[]
。在循环外创建一次并重复使用。 -
更糟糕的是,您在每个循环迭代中都创建了一个全新的
SolidBrush
而且你没有在上面调用Dispose
!至少您需要使用using
,例如using (SolidBrush G = new SolidBrush(...)) { ... }
。 -
您还在每个循环迭代中创建两个全新的
Pen
,尽管它们总是相同的。创建一次并重用它。还可以考虑使用Pens.Black
作为第一个缓存,这是一个不需要管理的静态缓存。
最后,不要做catch { }
这样的事情。这通常属于风格指南的"最坏做法"部分,其中有"永远不要这样做,否则你会被解雇"。