OnToolMouseDown click point

1090
6
08-07-2020 06:53 AM
BrianBulla
Occasional Contributor III

Hi,

I'm creating a MapTool to help with creating a fully digitized sewer connection.  It works by sketching a line on the map;  the first click creates the connection to the sewer, the last click the 'end' of the line, and everything in between is the actual sewer connection.

Currently I check for the first click to be intersecting the gravityMainLayer in the OnSketchCompleteAsync.  It works, and I've created some IntersectsLayer code to determine an intersection of the first point.

        protected override Task<bool> OnSketchCompleteAsync(Geometry geometry)
        {
            var pointCollection = ((Multipart)geometry).Points;
            MapPoint connectionPoint = pointCollection[0];
            MapPoint plugPoint = pointCollection[pointCollection.Count - 1];

            

            QueuedTask.Run(() =>
            {
                if (IntersectsLayer(connectionPoint, gravityMainLayer) == false)
                {
                    ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("The starting point must intersect the GravitySewer layer.", "Error");
                    return;
                }                

                .....
                    
                blah, blah, blah,

                .....
    

            return base.OnSketchCompleteAsync(geometry);
        }


        public bool IntersectsLayer(MapPoint point, FeatureLayer layer)
        {
            try
            {   
                SpatialQueryFilter spatialFilter = new SpatialQueryFilter();
                spatialFilter.FilterGeometry = point;
                spatialFilter.SpatialRelationship = SpatialRelationship.Intersects;
                
                RowCursor theCursor = layer.Search(spatialFilter);
                Feature feature;
                while (theCursor.MoveNext())
                {
                    using (feature = (Feature)theCursor.Current)
                    {
                        return true;
                    }
                }

                return false;                
            }
            catch (Exception ex)
            {
                ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(ex.ToString());
            }

            return false;
        }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

To make things work better for the user, I am trying to have it check for the intersection after the first mouse click, to avoid the user making more clicks when not necessary.  So I am using the OnToolMouseDown to capture the first click, and the look for the intersection.  The problem is that each time the IntersectLayer always returns false, even though I am for sure clicking a point that is intersecting the gravityMainLayer.  As soon as I comment out the OnToolMouseDown code, everything works fine again.

So my question is should the OnToolMouseDown event return the same MapPoint as the OnSketchCompleteAsync event??  From stepping through the code, it looks like a valid point, but I don't understand why it is never intersecting.

        protected override void OnToolMouseDown(MapViewMouseButtonEventArgs e)
        {
            if (e.ChangedButton == System.Windows.Input.MouseButton.Left)
            {
                clickCount++;
                e.Handled = true; //Handle the event args to get the call to the corresponding async method
            }
            //base.OnToolMouseDown(e);
        }

        protected override Task HandleMouseDownAsync(MapViewMouseButtonEventArgs e)
        {
            if (clickCount == 1)
            {
                QueuedTask.Run(() =>
                {
                    var mapPoint = MapView.Active.ClientToMap(e.ClientPoint);
                    if (IntersectsLayer(mapPoint, gravityMainLayer) == false)
                    {
                        ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("The starting point must intersect the GravitySewer layer.", "Error");
                        clickCount = 0;
                    }
                });
            }

            return base.HandleMouseDownAsync(e);
        }
0 Kudos
6 Replies
by Anonymous User
Not applicable

Hey Brian,

Ive had more success with 'ScreenToMap' than Client when using a mouse point. You may also want to expand the point into a small circle or square to help searching rather than relying on an exact point/line intersect.

0 Kudos
BrianBulla
Occasional Contributor III

Hi Sean Jones.  I've modified to use ScreenToMap, but no difference.  Calling my IntersectsLayer code from OnToolMouseDown just doesn't seem to work.  But calling it from OnSketchComplete does.  Very strange considering both methods should be using the same information.

0 Kudos
by Anonymous User
Not applicable

Hey Brian,

Take a look at the xy coords returned from the mouse generated map point too. See if its close to what is returned from the sketchcomplete geometry (which is going to be the correct one). You may have to project the mouse map point into the spatial reference of the map for the intersect to work.

0 Kudos
BrianBulla
Occasional Contributor III

Hi Sean Jones‌.  You are correct.  The same mouse click is producing two different points, but they both have the same Spatial Reference.  How can that be??

0 Kudos
KrisCulin
Occasional Contributor

Hi Brian,

When I was working on similar layout functionality, I found that using OnSketchModifiedAsync was better than OnSketchCompleteAsync().  Now you need to realize that this method gets called every time the user clicks in the map as that is when the sketch is modified.  But by using some internal flags to know when the first click was made and when the last click was made, it worked out.

I also had to watch out for re-entries as well.  So I have an "IsExecuting" flag that is initially set to true and then set to false once the QueuedTask is completed (which is awaited).  This way if IsExecuting is true on the re-entry, then I short-circuit and exit the method.

In this case, you would need to use the GetCurrentSketchAsync() method to get the geometry of the current sketch.  On the first click, it should return just one point.  Then you'd have to determine what you would consider the "last" click and then handle the creation of the feature at that point.  At the end, be sure you call FinishSketchAsync() to finish the sketch and deactivate the tool.

I hope this information helps you.

Kris

0 Kudos
DavidMrázek
Occasional Contributor II

Hi, I wonder if you solved this problem?

0 Kudos