8

I'm trying to add a tool to an add-in toobar to select features from an existing feature class and copy them across to another feature class. I need two tools, one for a point and one for a rectangle. Add-in tools only handle rectangles, so I'm trying to generate the point coordinate off the onMouseDown event and simply use the X and Y feedback I get. The problem is that I can't seem to pass these coordinates to anything usefull to extract the features. I've tried using Environment extents and then doing a simple CopyFeatures, but that's not working as it copies the entire fc and doesn't seem to honour the environment settings I set.

Can I pass coordinates to the Select by Location tool somehow or is there another way of passing coordinates to something to extract by that extent?

This is what I have now:

import arcpy
import pythonaddins
arcpy.overWriteOutput = True

# Replace this with the SDE layer once it's available.
global ELAtemplate, fc
ELAtemplate = r'C:\Data\nsw_map_units.shp'
fc = ""

class DefineUnitsbyPoint(object):
    """Implementation for DefineUnitsbyPoint.tool (Tool)"""
    def __init__(self):
        self.enabled = True
        self.shape = "Rectangle" # Use onMouseDown to get initial extent of the rectangle.
    def onMouseDownMap(self, x, y, button, shift):
        # fc can be assigned from a combo box selection in another class
        global ELAtemplate, fc
        if fc == "":
            pythonaddins.MessageBox('Choose a layer to select from.', 'Choose a Layer', 0)
        else:
            mxd = arcpy.mapping.MapDocument("CURRENT")
            pointGeom = arcpy.PointGeometry(arcpy.Point(x,y), mxd.activeDataFrame.spatialReference)
            arcpy.SelectLayerByLocation_management(ELAtemplate, "INTERSECT", pointGeom, "", "ADD_TO_SELECTION")
            arcpy.CopyFeatures(ELAtemplate, fc)
7
  • 1
    Post the complete code, not just a snippet. Also to easily format the code correctly, select it in the question body editor and hit Ctrl-K.
    – blah238
    Commented Feb 13, 2013 at 2:29
  • Where is fc set? It's not set to anything but an empty string in this code. Also the input to SelectLayerByLocation must be a reference to a Layer object or the name of a feature layer in the current map document. ELAtemplate is a string pointing to a shapefile.
    – blah238
    Commented Feb 13, 2013 at 4:14
  • 1
    fc is set from a combo box selection. So I've made that global. ELAtemplate is a shapefile here, but I've tried running this in the Python window as a layer, shapefile or dragged from the TOC and none of them work.
    – MierMoto
    Commented Feb 13, 2013 at 4:21
  • In the Python window (ArcMap) I've used the following, after creating the geometry in pointGeom: arcpy.MakeFeatureLayer_management("nsw_map_units","unit_layer") where nsw_map_units comes from the TOC. I then use that to run arcpy.SelectLayerByLocation_management('unit_layer',"INTERSECT",pointGeom,"#","ADD_TO_SELECTION") , but I get no selection. I've even tried to physically create a point layer.
    – MierMoto
    Commented Feb 13, 2013 at 4:30
  • I don't know why that wouldn't work unless pointGeom doesn't actually intersect anything in unit_layer. Perhaps you need to just refresh the view?
    – blah238
    Commented Feb 13, 2013 at 4:35

2 Answers 2

4

You will probably want to use onMouseDownMap rather than onMouseDown as this returns the location in map coordinates, not window coordinates.

Additionally, be sure to pass in a valid SpatialReference object to the PointGeometry constructor, otherwise it will most likely not work. In the example below I use the spatial reference of the active data frame.

Lastly you may want to specify a search_distance on your SelectLayerByLocation so that point and line features can be selected without clicking on them exactly. In ArcObjects you would normally use ArcMap's selection tolerance in pixels and expand your point's envelope by that amount in map coordinates. I couldn't find a way to access ArcMap's selection tolerance setting in arcpy, but if you want to go with the default of 3 pixels (or pass in your own), you can pass the output of the function in this answer as a search_distance (in inches) to SelectLayerByLocation.

def onMouseDownMap(self, x, y, button, shift):
    mxd = arcpy.mapping.MapDocument("CURRENT")
    pointGeom = arcpy.PointGeometry(arcpy.Point(x, y), mxd.activeDataFrame.spatialReference)
    searchdistance = getSearchDistanceInches(mxd.activeDataFrame.scale)
    lyr = arcpy.mapping.ListLayers(mxd)[0] # assumes you want to select features from 1st layer in TOC
    arcpy.SelectLayerByLocation_management(lyr, "INTERSECT", pointGeom, "%d INCHES" % searchdistance)
    arcpy.RefreshActiveView()
6
  • I have asked a question about the selection tolerance issue I ran into while formulating this answer, hopefully this is something that can be done without ArcObjects but I have my doubts: How to buffer a point in a Python Add-In by ArcMap's selection tolerance?
    – blah238
    Commented Feb 1, 2013 at 5:41
  • Added a partial solution to the selection tolerance issue.
    – blah238
    Commented Feb 2, 2013 at 23:29
  • Cheers blah238 for the help. I think I'm almost there. I didn't think about creating geometry. I must admit, I'm still getting in the mapping module as I've been working with 9.3.1 until now. I've got it all down, except for the SelectByLocation. It just doesn't select and I think it's the code that's causing my add-in to not display its icons (indicating incorrect code). I'm not using a search distance, as it's an intersect. I'm curious to know why you used a searchdistance. I'm using arcpy.SelectLayerByLocation_management("unit_layer","INTERSECT",pointGeom,,"ADD_TO_SELECTION")
    – MierMoto
    Commented Feb 13, 2013 at 0:37
  • This is what I'm using for the select: ("unit_layer","INTERSECT",pointGeom,"","ADD_‌​TO_SELECTION") Not sure why it's not selecting anything. I checked the point object's properties to make sure its got the corect coordinates and spatial reference and the first input is a feature layer.
    – MierMoto
    Commented Feb 13, 2013 at 0:45
  • Do not use comments to post code. Edit your question to include your current code.
    – blah238
    Commented Feb 13, 2013 at 1:19
1

I am assuming that you are using the techniques described in the Answer to Is it possible to get the coordinates of a user clicked point in a current MXD with ArcGIS 10.0 ArcPy? earlier today or something similar.

Once you are able to create your point or polygon (rectangle) geometry using something like the code below you should be able to use that as your select_features for Select Layer By Location.

pt=arcpy.PointGeometry(arcpy.Point(x,y))

From there Copy Features should get the features you are after.

1
  • Cheers @PolyGeo That's the bit I didn't think of and it's working, but now the script's failing at the selection. I've used the layer either from the TOC or as a feature layer, but no luck. I'm using INTERSECT with "#" as the search distance and ADD_TO_SELECTION. It's just not selecting anything. I'm running it out of the Python window with no joy, but it works from the Toolbox.
    – MierMoto
    Commented Feb 13, 2013 at 1:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.