Select to view content in your preferred language

FeatureSnapAgent problems

1977
11
09-09-2010 06:25 AM
BBulla
by
Regular Contributor
Hi,

I need to be able to snap my custom tool to a few different features in my map.  I am trying to get the tool to snap to my Watermains first, but no luck.  Here is my code I have so far.  I think this is supposed to be setting up the SnapAgents, but something isn't working.  I get no errors, but my cursor for the tool isn't snapping to anything.

ISnapEnvironment snapEnvironment = m_editor as ISnapEnvironment;
snapEnvironment.ClearSnapAgents();

IFeatureSnapAgent featureSnapAgent = new FeatureSnapClass();
while (pLayer != null)
{
      switch (pLayer.Name)
      {
           case "GISADMIN.WaterMain":
           IFeatureLayer featureLayer = (IFeatureLayer)pLayer;
           IFeatureClass featureClass = featureLayer.FeatureClass;
                            
           featureSnapAgent.FeatureClass = featureClass;
           featureSnapAgent.HitType = esriGeometryHitPartType.esriGeometryPartBoundary;
           snapEnvironment.AddSnapAgent(featureSnapAgent);

            break;
       }

       pLayer = (ILayer2)allLayers.Next();
}
0 Kudos
11 Replies
JeffMatson
Frequent Contributor
The snap agents set up what is available for snapping and how they behave.  I'm guessing you want the blue circle of the edit tools to snap when you move the mouse over your features?  Here is a snippet from the MouseMove event of a custom editing tool that may help:


mDisplay = mMxDoc.ActiveView.ScreenDisplay
'get the current mouse point
mMousePnt = mAV.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y)
'use ISnapEnvironment to see if the current mouse point will snap to any snap agents
mSnapEnv.SnapPoint(mMousePnt)
'set the invert agent (blue circle) to the snap point
'if no snap occurs it will stay "under" the cursor
mEditor.InvertAgent(mMousePnt, mEditor.Display.hDC)
'redraw
mDisplay.Invalidate(mAV.Extent.Envelope, True, esriScreenCache.esriNoScreenCache)
0 Kudos
BBulla
by
Regular Contributor
Hi Jeff,

Thanks for responding.  I've implemented your idea, but still no luck.  Again, no errors, just nothing happening.  In my OnMouseMove event for the tool, this is what I've got:

           
        public override void OnMouseMove(int Button, int Shift, int X, int Y)
        {
            try
            {
                IMxDocument pMxDoc = (IMxDocument)m_application.Document;
                IActiveView pActiveView = pMxDoc.ActiveView;

                ESRI.ArcGIS.Display.IScreenDisplay pScreenDisplay = pActiveView.ScreenDisplay;
                ESRI.ArcGIS.Display.IDisplayTransformation pDisplayTransformation = pScreenDisplay.DisplayTransformation;
                IPoint mousePoint = pDisplayTransformation.ToMapPoint(X, Y);

                snapEnvironment.SnapPoint(mousePoint);
                m_editor.InvertAgent(mousePoint, m_editor.Display.hDC);
                pScreenDisplay.Invalidate(pActiveView.Extent.Envelope, true, (short)esriScreenCache.esriNoScreenCache);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }



Basically the same as yours.  What I'm trying to do is to get the default cursor for my custom tool to snap to a feature called Watermain.  I'm not really sure where I am going wrong, as everything appears to compile and run with no errors.

From my first post am I missing something like setting the SnapAgent to snap to the 'Edge' or something like that??  I've been looking for that, but can't find a way to do it.
0 Kudos
JeffMatson
Frequent Contributor
A few questions:

Does the invert agent show up while you are moving the mouse, but won't snap?  Or does it not show up at all?

If you open the Snapping Window, does the snap agent you created show up, and is it checked?  What's your snap tolerance and is it set to pixels or map units?
0 Kudos
BBulla
by
Regular Contributor
Hi Jeff,

While it's hard to see, I do believe the blue dot is there (I am just using the default cursor for a new ArcMap tool).  If I use a different cursor, would it be easier to see??

When I go to the Snapping window, I can see that the snapping is set for the map.  But, because of the work we do here (ie. editing all the time), the snapping is always set.  I'm not sure the code I am running from the first post is the reason why the snapping is set.  Even though I am running .ClearSnapAgents, and then I am creating one, I have all the snapping set that is always there normally.

If the users are setting the snapping up manually, do I even need the bit of code I am showing in my first post??

As for the blue dot when using my tool, it is not snapping to anything.  But if I go to the standard Create New Feature tool, it is snapping.

Any ideas??
0 Kudos
BBulla
by
Regular Contributor
OK, I modified my OnMouseMove code so that I can see the InvertAgent.  I can now confirm that the agent is there and it is snapping.  I think what my problem now is that when I create my feature on the MouseDown event, I am using the X,Y of the mouse and not of the InvertAgent to create the point feature.

How do I get the X,Y of the InvertAgent?

When I run this line:

m_editor.InvertAgent(mousePoint,0);

is the IPoint (mousePoint) variable getting updated to the actual point of the 'snap'??  It doesn't seem like it is unless I am doing something wrong.

Thanks,
0 Kudos
JeffMatson
Frequent Contributor
Hi Brian

You are correct, if your users are setting up snapping manually you won't need your code to set up a snap agent.  Setting the ISnapEnvironment to the IEditor should allow your tool's snapping to behave however the snapping window is set up.  Are you using the Editor's edit session, or starting one from scratch on the workspace of your feature class?   

As for moving the cursor instead of the invert agent, you might try using IDisplayTransformation.FromMapPoint and pass in the resulting X and Y values:
http://msdn.microsoft.com/en-us/library/system.windows.forms.cursor.position(ide).aspx
0 Kudos
BBulla
by
Regular Contributor
Thanks Jeff,

Yes, I am just using the Edit Session started by the user (the tool is disabled until an edit session is started).

Do you know how I would set the location of the base.m_cursor??  There is no property of m_cursor.X or m_cursor.Y.

Or even better would be how do I get the coordinate that the InvertAgent has snapped to??  I can see it has snapped, but when I create my new feature based on the mousePoint, it is not snapped.
0 Kudos
JeffMatson
Frequent Contributor

Or even better would be how do I get the coordinate that the InvertAgent has snapped to?? I can see it has snapped, but when I create my new feature based on the mousePoint, it is not snapped.



ISnapEnvironment.SnapPoint will change the coordinates of the point you pass in, if it has successfully snapped.  Is 'mousePoint' is a modular level variable so you can use this point in another procedure such as _OnMouseUp or wherever your feature is being created?
0 Kudos
BBulla
by
Regular Contributor
Hi Jeff,

I declare mousePoint at the beginning of my class like so:

public sealed class ServiceConnectionTool : BaseTool
{
     private IPoint mousePoint;


     //in here I have all my other methods including the mouse down and mouse move events

    public override void OnMouseDown(int Button, int Shift, int X, int Y)
    {
    }

}



So, yes, I can access the mousePoint from pretty much anywhere in my code.  After the InvertAgent uses the mousePoint to snap to the nearest line (if within the tolerance) is it supposed to update the value of mousePoint to be the same as the snapped coordinate??  If so, it doens't appear to be doing that and the point feature I am creating (using mousePoint) is not snapped to the line the InvertAgent is snapping to.


To create the feature this is my code, using the mousePoint:
                        points[0] = mousePoint;

                        //For GeoFeature Classes
                        UID pID = new UID();
                        pID.Value = "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}";

                        IMap pMap = pMxDoc.FocusMap;
                        IEnumLayer allLayers;
                        allLayers = pMap.get_Layers(pID, true);

                        ILayer2 pLayer;
                        pLayer = (ILayer2)allLayers.Next();

                        while (pLayer.Name != "GISADMIN.WAT_Fitting")
                            pLayer = (ILayer2)allLayers.Next();

                        if (pLayer.Name == "GISADMIN.WAT_Fitting")
                        {

                            IFeatureLayer featureLayer = (IFeatureLayer)pLayer;
                            IFeatureClass featureClass = featureLayer.FeatureClass;

                            watFittingSelections = (IFeatureSelection)featureLayer;

                            m_editor.StartOperation();
                            CreateWaterServiceConnection(featureClass, point1);
                            m_editor.StopOperation("Create new Service Connection");
                        }
0 Kudos