Search code examples
c#.netgdi+regionhittest

GraphicsPath.IsVisible() doesn't match up with actual path?


I'm experiencing a discrepancy between a GraphicsPath drawn in World coordinates on a UserControl and the results of GraphicsPath.IsVisible() to Hit Test the shape with the mouse.

I performed a little test that made a map of where IsVisible() returned true, relative to the GraphicsPath shape that was drawn. The results show a very "low resolution" version of the shape I'm drawing.

Link to shared Google Drive image showing the results: http://goo.gl/zd6xiM

Is there something I'm doing or not doing correctly that's causing this?

Thanks!

Here's the majority of my OnMouseMove() event handler:

protected override void OnMouseMove(MouseEventArgs e)
{
    //base.OnMouseMove(e);

    debugPixel = Point.Empty;

    PointF worldPosition = ScreenToWorld(PointToClient(Cursor.Position));

    if (_mouseStart == Point.Empty) // Just moving mouse around, no buttons pressed
    {
        _objectUnderMouse = null;

        // Hit test mouse position against each canvas object to see if we're overtop of anything
        for (int index = 0; index < _canvasObjects.Count; index++) // Uses front to back order
        {
            NPCanvasObject canvasObject = _canvasObjects[index];
            if (canvasObject is NPCanvasPart)
            {
                NPCanvasPart canvasPart = (canvasObject as NPCanvasPart);
                NPPart part = canvasPart.Part;
                GraphicsPath gp = canvasPart.GraphicsPath;

                // Set the object under the mouse cursor, and move it to the "front" so it draws on top of everythign else
                if (gp.IsVisible(worldPosition))
                {
                    // DEBUG
                    debugPixel.X = e.X;
                    debugPixel.Y = e.Y;

                    _objectUnderMouse = canvasObject;
                    _canvasObjects.MoveItemAtIndexToFront(_canvasObjects.IndexOf(canvasObject));

                    break; // Since we're modifying the collection we're iterating through, we can't reliably continue past this point
                }
            }
        }
    }
    else
    {
        ...
    }
}

Later in my drawing code I draw a pixel whenever debugPixel != Point.Empty . I temporarily suppressed clearing before drawing so I could see them all.

Some other info that may be asked, or could be helpful to troubleshoot:

  • I've tried different Graphics.InterpolationMode settings but that doesn't seem to have any effect
  • I've applied a TranslateTransform and ScaleTransform to the main drawing Graphics but the underlying HitTest map seems to scale and translate equal to the GraphicsPath
  • For my main drawing canvas, Graphics.PageUnit = GraphicsUnit.Inch, except when I'm doing pixel-based overlay stuff

Solution

  • I thought I had researched this thoroughly enough, but apparently not. Shortly after posting this question I did another search with slightly different terms and found this:

    http://vbcity.com/forums/t/72877.aspx

    ...which was enough to clue me in that the GraphicsPath and my main drawing Graphics were not the same. Using the overloaded GraphicsPath.IsVisible(PointF, Graphics) solved this problem very nicely.

    Essentially it was trying to check against a very aliased (pixelated) version of my shape that had been scaled to the same size but not smoothed.