On a custom control I've a series of LED objects that should be turned on according to a given GraphicsPath
(e.g., see image below). Currently I'm using graphicsPath.IsVisible(ledPoint)
, however since I have many LEDs, the iteration through all of them can be very slow, especially if the path is complex (e.g. the inverse of the path in the example).
Does any of you has an idea toward something more clever to speed up iteration? If it is too complex to make an example, it may work to redirect me toward proper resources. Please consider that the control is in GDI+ an re-engineering into another engine is not an option.
EDIT
on my PC (i7 3.6GHz) when as GraphicsPath
I've just a simple rectangle 100x100 pixels and then I compute the inverse on my Control that is sizing about 500x500 pixels (hence, the resulting GraphicsPath
will be a 500x500 rectangle with an 'hole' of 100x100), to test 6000 LEDs takes about 1.5sec, which will be too much affecting user experience.
Following Matthew Watson reply, I'm detailing more on my example:
//------ Base path test
GraphicsPath path = new GraphicsPath();
path.AddRectangle(new Rectangle(100, 100, 100, 100));
var sw = System.Diagnostics.Stopwatch.StartNew();
for (int x = 0; x < 500; ++x)
for (int y = 0; y < 500; ++y)
path.IsVisible(x, y);
Console.WriteLine(sw.ElapsedMilliseconds);
//------ Inverse path test
GraphicsPath clipRect = new GraphicsPath();
clipRect.AddRectangle(new Rectangle(0, 0, 500, 500));
GraphicsPath inversePath = Utility.CombinePath(path, clipRect, CombineMode.Complement);
sw.Restart();
for (int x = 0; x < 500; ++x)
for (int y = 0; y < 500; ++y)
inversePath.IsVisible(x, y);
Console.WriteLine(sw.ElapsedMilliseconds);
On my PC I have ~725ms on the first test and ~5000ms on the second. And this is just a fairly simple path. The GraphicsPath
is generated by user's mouse movements and the user can perform several paths combinations (inverting, union, intersection,.. I use GPC for this). Hence, testing for inversion by testing the negation of GraphicsPath.IsVisible()
can be tricky.
The inversePath
returned from Utility.CombinePath
is quite simple and has following points (left PathPoints
, right PathTypes
):