Monday, March 26, 2012

GraphicsPath.IsVisible() method wont work when using zoom matrix with a big zoom factor in GDI+

When programming for a graphical application, I noticed that the GraphicsPath.IsVisible() method, sometimes,  is not working fine for small path figures when using scale matrix for the Graphics of the object or Control.

I googled for the problem and found a solution in Java. Then I translated the code to C# as an extension method to the GraphicsPath. It works fine now. The translated code is as follows:

/// <summary>
/// Indicates whether the graphics path contains the specified point or not.
/// </summary>
/// <param name="graphicsPath">The graphics path to check if it contains the point.</param>
/// <param name="location">The specified location to check if it is inside the path or not.</param>
/// <returns>True if the point is within the graphics path, otherwise false.</returns>
public static bool Contains(this GraphicsPath graphicsPath, PointF location)
{
    GraphicsPath actualPath = (GraphicsPath)graphicsPath.Clone();
    bool oddTransitions = false;

    actualPath.Flatten(null, .25f);

    for (int i = 0, j = actualPath.PointCount - 1; i < actualPath.PointCount; j = i++)
        if ((actualPath.PathPoints[i].Y < location.Y && actualPath.PathPoints[j].Y >= location.Y) ||
            (actualPath.PathPoints[j].Y < location.Y && actualPath.PathPoints[i].Y >= location.Y))
            if (actualPath.PathPoints[i].X + 
                ((location.Y - actualPath.PathPoints[i].Y) /
                (actualPath.PathPoints[j].Y - actualPath.PathPoints[i].Y) *
                (actualPath.PathPoints[j].X - actualPath.PathPoints[i].X)) < location.X)
                oddTransitions = !oddTransitions;

    return oddTransitions;
}

I cloned and flattened the original path to be sure the result is correct even if it contains Beziers. Hope it can help you.

Enjoy programming.


No comments:

Post a Comment