Friday, October 26, 2012

Creating a Dynamic Fishnet Tool - Python Addin

At 10.1, you can create python add-ins.  These add-ins are very much like add-ins in .NET, but they do not support GUI development.  This means that you can either just call a function after interacting with a map, or you can open an existing tool.

On the resources.arcgis.com page, one example given is the use of fishnet, but the grid sizes are static at 10x10.  This is a basic example,  much like the 'Hello World' examples in most programming languages, but what if you want user inputs into the fishnet tool?  Can it be done?  The answer is yes, but you need more add-in components to do it.

To use the code posted, you must first install the python add-in component for ArcGIS 10.1.  You can find that here.

After that is installed, create a new project, and add a toolbar, a tool, and two combo boxes.
When naming the ID and Class Name, do not use the same name.  This will lead to problem if you have to communicate between controls.
I called my controls the following:

  • toolbar - ID: analysisTB
  • combobox 1: ID: cboRows1, Class Name: cboRows
  • combobox 2: ID cboColumns1, Class Name: cboColumns
  • tool: ID: fishnetTool101 Class Name fishnetTool
The code behind will create multiple classes and events.  Erase the events that are not needed, so the control is not listening to events that are not needed. 


First code the combo box controls.  Here we will set the control values and store the values to a global variable rows and columns:


rows = 0
columns = 0
class cboClassColumns(object):
    """Implementation for fishnet_addin.cboColumns (ComboBox)"""
    def __init__(self):
        self.items = [i for i in xrange(1, 100)]
        self.editable = True
        self.enabled = True
        self.dropdownWidth = 'WWW'
        self.width = 'WWW'
    def onSelChange(self, selection):
        global columns
        columns = int(selection)
    def onEditChange(self, text):
        global columns
        try:
            columns = int(text)
        except:
            columns = 0
            pythonaddins.MessageBox("Please enter a valid integer", "Value Error")

class cboClassRow(object):
    """Implementation for fishnet_addin.cboRows (ComboBox)"""
    def __init__(self):
        self.items = [i for i in xrange(1, 100)]
        self.editable = True
        self.enabled = True
        self.dropdownWidth = 'WWW'
        self.width = 'WWW'
    def onSelChange(self, selection):
        global rows
        rows = int(selection)
    def onEditChange(self, text):
        global rows
        try:
            rows = int(text)
        except:
            rows = 0
            pythonaddins.MessageBox("Please enter a valid integer", "Value Error")

OnSelChange event sets the row or column value, and since I made my control editable, I validate the user's entry on the onEditChange event.

Next is the fishnet function.  This code goes behind button control in this example:


class fishnetClass(object):
    """Implementation for fishnet_addin.fishnetClassID (Tool)"""
    def __init__(self):
        self.enabled = True
        self.shape = "Rectangle"
        self.cursor = 3
    def onRectangle(self, rectangle_geometry):
        """ creates a temp fishnet polygon """
        extent = rectangle_geometry
        fishnet = None
        global rows
        global columns
        fshFC = r"in_memory\fishnet"
        if arcpy.Exists(fshFC):
            arcpy.Delete_management(fshFC)
        try:
            fishnet = arcpy.CreateFishnet_management(fshFC,
                            '%f %f' %(extent.XMin, extent.YMin),
                            '%f %f' %(extent.XMin, extent.YMax),
                            0, 0, int(rows), int(columns),
                            '%f %f' %(extent.XMax, extent.YMax),'NO_LABELS',
                            '%f %f %f %f' %(extent.XMin, extent.YMin, extent.XMax, extent.YMax),
                            'POLYGON')
            arcpy.RefreshActiveView()
            del extent
        except:
            pythonaddins.MessageBox("Cannot Run the Fishnet Tool", "Error Message")
        return fishnet

Run the makefile.py, and install the add in. Now you can create a dynamic fishnet tool using python.