Hit Testing Polygons in a GraphicsOverlay

2173
3
02-01-2017 09:15 AM
KevinSayer
New Contributor III

We've been having problems with the Quartz SDK whilst hit testing polygons in a GraphicsOverlay.  We are calling IdentifyGraphicsOverlayAsync on the MapView and setting the tolerance parameter to 0 for precise selection and the maximumResults parameter to 1.  The IdentifyGraphicsOverlayResult.Graphics collection seems to intermittently contain no graphics.

We've played around with the parameters and either setting the tolerance to at least 3 or the maximumResults to 10 (arbitrarliy selected), seems to fix this.  Is this expected and explainable behaviour or is there a bug in the implementation?  Intuitively, neither of the parameters mentioned seem as though they should make any difference to the behaviour.

This problem is easily reproducible in the ArcGIS Runtime SDK for .Net Samples by changing the OnMapTapped implementation in the IdentifyGraphics example to the following:

        private async void OnMapViewTapped(object sender, GeoViewInputEventArgs e)
        {
            var tolerance = 0d; // Use larger tolerance for touch
            var maximumResults = 1; // Only return one graphic  
            var onlyReturnPopups = false; // Return more than popups

            // Use the following method to identify graphics in a specific graphics overlay
           IdentifyGraphicsOverlayResult identifyResults = await MyMapView.IdentifyGraphicsOverlayAsync(
                _polygonOverlay,
                e.Position,
                tolerance,
                onlyReturnPopups,
                maximumResults);

            // Check if we got results

            if (identifyResults.Graphics.Count > 0)
            {
                foreach (var graphic in identifyResults.Graphics)
                {
                    graphic.IsSelected = true;
                }
            }
            else
            {
                foreach (var graphic in _polygonOverlay.Graphics)
                {
                    graphic.IsSelected = false;
                }
            }
        }

0 Kudos
3 Replies
JenniferNery
Esri Regular Contributor

Are you using a touch or mouse device? Identify with zero tolerance from a tapped event seem difficult to do. It may appear you hit the border of geometry but it may not be the case too. You can use GeometryEngine.Intersects(graphic.Geometry, mapPoint) to troubleshoot. If this returns true and graphic is not selected, then maybe Identify has an issue with zero tolerance.

However, I just tried to test zero tolerance identify and it consistently selected the graphic. I am using one of the points in the polygon.

        public MainWindow()
        {
            InitializeComponent();
            var geometry = Esri.ArcGISRuntime.Geometry.Geometry.FromJson("{\"rings\":[[[-13631102.181532314,4549468.2923788792],[-13630332.658191375,4548355.2318321653],[-13631871.704873253,4548355.2318321653],[-13631102.181532314,4549468.2923788792]]],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}");
            MyMapView.Map = new Map(Basemap.CreateImagery()) { InitialViewpoint = new Viewpoint(geometry) };
            var symbol = new SimpleFillSymbol(SimpleFillSymbolStyle.Solid, Colors.Red, null);
            var overlay = new GraphicsOverlay();
            overlay.Graphics.Add(new Graphic(geometry, symbol));
            MyMapView.GraphicsOverlays.Add(overlay);
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            var overlay = MyMapView.GraphicsOverlays[0];
            var graphic = overlay.Graphics[0];
            graphic.IsSelected = false;
            var mapPoint = (graphic.Geometry as Polygon)?.Parts?.FirstOrDefault()?.StartPoint;
            if (mapPoint != null)
            {
                var screenPoint = MyMapView.LocationToScreen(mapPoint);
                var result = await MyMapView.IdentifyGraphicsOverlayAsync(overlay, screenPoint, 0, false);
                graphic = result?.Graphics?.FirstOrDefault();
                if (graphic != null)
                    graphic.IsSelected = true;
            }
        }
0 Kudos
KevinSayer
New Contributor III

Hi Jennifer,

Thanks for your response.

The code that you sent works fine for me too but unfortunately it's not representative of what we are doing.

The code I pasted into the initial question is what we need to do and is lifted from your own examples on GitHub.

To answer your question, yes we are using the mouse and we do require accurate hit testing, hence the low tolerance.  The hit testing fails even when clicking on a point well within the polygon however.  I can choose a point roughly in the centre of your triangle and still get intermittent failures.  I've even tried hard coding the centre point in the mouse event handler and that fails intermittently too.

I tried your suggestion regarding the geometry engine by the way and that seems to confirm the bug.  It always finds an intersection when clicking within the graphic, even when the IdentifyGraphicsOverlayAsync method returns no results.

Regards,

Kevin

0 Kudos
JenniferNery
Esri Regular Contributor

Thanks, Kevin for clarifying this. I'm also able to reproduce the issue of clicking within the geometry may intermittently return empty. We'll work on getting this fixed in future releases of the API.

For the meantime, if you use the other IdentifyGraphicsOverlay override with maximumResults other than 1.

var results = await MyMapView.IdentifyGraphicsOverlaysAsync(e.Position, 0, false, 2);

or 

foreach(var overlay in MyMapView.GraphicsOverlays)
{
    var overlayResult = await MyMapView.IdentifyGraphicsOverlayAsync(overlay, e.Position, 0, false, 2);
}

Either one of these return the expected graphic consistently. The other overload where there is no maximumResults seem to work more consistently when GraphicsOverlay.RenderingMode is Static. By default, if you had not set this - it's Dynamic. The issue seems to be with Dynamic mode and when result is expected to return just one.

Thanks, we'll look into this.

0 Kudos