0

So I've been messing around with 3D - 2D vector transformations and would like to start writing some fun, simple programs to interact with simple quadric surfaces and such. My question is this:

What are some good ways to make my code more efficient? Are there other C# based programs that I can use for graphics?

I'm working in C# (and definitely want to stay that way), and I realize that I have been doing this in a pretty inefficient way so far.

I don't know if I can improve my looping, or the fact that I calculate the transformations every time I move the camera, or what, but any help would be awesome!

Here is some example code (draws the surface pictured in image: 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 { }
            }
            }

    }
wvn
  • 624
  • 5
  • 12

1 Answers1

3

Some quick efficiency tips:

  1. Everything I said here applies: https://stackoverflow.com/a/11025428/1191082 . In particular, you're not doing your drawing in OnPaint. Do not use CreateGraphics. It's not evil, you're just not structuring your code correctly and it will make things much more difficult later on.

  2. You're accessing List.Count on every loop iteration. This generally adds a non-inlined method call that you will want to avoid (in general, and repeat after me, "the JIT is not very smart" :)). Recommend a form such as, for (int sort = 0, count = f.Count; sort < count - 1; sort++) etc. This is particular important if your code is accessing via an IList<T> reference that was handed over from another area (like as a function parameter). Yes, CPUs have pretty good branch prediction nowadays. However, this is still an inefficiency that should absolutely be avoided on hot paths.

  3. You allocate a brand new PointF[] on every loop iteration. Create it once outside the loop and reuse it.

  4. Even worse, you're creating a brand new SolidBrush on every loop iteration. And you're not calling Dispose on it! At the very least you need to use using, e.g. using (SolidBrush G = new SolidBrush(...)) { ... }.

  5. You're also creating two brand new Pens on every loop iteration, even though they're always the same. Create it once and reuse it. Also consider using Pens.Black for the first one, which is a static cache that you won't have to manage.

And last, don't do stuff like catch { }. That usually goes under "worst practices" sections of style guidelines with "DO NOT DO THIS EVER OR YOU WILL BE FIRED".

Community
  • 1
  • 1
Rick Brewster
  • 3,374
  • 1
  • 17
  • 21