Select to view content in your preferred language

Identifying the clicked path/ring

586
3
03-07-2011 10:58 PM
BrianBorg
Emerging Contributor
I have a number of polyline/polygon geometries and each contain more than one path/ring. When i capture the mouse click event, it returns the whole feature. Is there a way how I can get the actual path/ring clicked rather than the whole feature?
0 Kudos
3 Replies
DominiqueBroux
Esri Frequent Contributor
Is there a way how I can get the actual path/ring clicked rather than the whole feature?

There is nothing out of the box.
I guess this might be developed by using the Paths and Rings properties of the polyline/polygon but likely not that easy (this would need some geometry calculations).
0 Kudos
DanielWalton
Frequent Contributor
Below is some code to do this. The only gotcha is to somehow make sure that overlapping rings are parsed smallest->biggest, to ensure you get the most accurate result.

        void graphicsLayer_MouseLeftButtonUp(object sender, GraphicMouseButtonEventArgs e)
        {
            var clicked = Map.ScreenToMap(e.GetPosition(Map));
            var polygon = (Polygon)e.Graphic.Geometry;

            foreach(var ring in polygon.Rings)
                if (Intterra.Projection.Utilities.PointIsInGeometry(ring, clicked))
                {
                    //you found the correct ring
                }
        }
        static bool PointIsInGeometry(PointCollection points, MapPoint point)
        {
            int i;
            int j = points.Count - 1;
            bool output = false;

            for (i = 0; i < points.Count; i++)
            {
                if (points.X < point.X && points.X >= point.X || points.X < point.X && points.X >= point.X)
                {
                    if (points.Y + (point.X - points.X) / (points.X - points.X) * (points.Y - points.Y) < point.Y)
                    {
                        output = !output;
                    }
                }
                j = i;
            }
            return output;
        }
0 Kudos
DanielWalton
Frequent Contributor
A better approach would be to split each polygon with multiple rings into multiple graphics, each one having a single ring.

        void Graphics_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action != NotifyCollectionChangedAction.Add) return;
            var gc = (GraphicCollection)sender;

            foreach (var item in e.NewItems)
            {
                var g = (Graphic) item;

                if (!(g.Geometry is Polygon) || ((Polygon) g.Geometry).Rings.Count <= 1) continue;
                var p = (Polygon) g.Geometry;
                Dispatcher.BeginInvoke(() =>
                {
                    foreach (var ring in p.Rings)
                    {
                        var newg = new Graphic {Geometry = new Polygon {SpatialReference = p.SpatialReference}};
                        foreach (var a in g.Attributes) newg.Attributes.Add(a);
                        ((Polygon)newg.Geometry).Rings.Add(ring);
                        gc.Add( newg );
                    }
                    gc.Remove(g);
                });
            }
        }
0 Kudos