Select to view content in your preferred language

Select a Feature by Rectangle( Better code display)

2802
2
01-12-2013 03:20 AM
babakkasraei
Emerging Contributor
Hi

I have created a Python Tekinter GUI with a listbox to show the map layers and some button widgets.
I have to bind a "Select Features by Rectangle" function to the "Select Feature button "Button 1" to be able to select some parts of a layer which is inside or intersect with rectangle.
My Problem
If I wanted to use "Select a Layer by Location", it would be easy, but for "Select Features by Rectangle" tool I couldn't find a Python function. I may do three things.
1. Use the Python function for it.
2. Write codes to create a tracker rectangle on the map.
3. Find a way to turn the tool on in ArcMAP by Python codes and use it on the map.
I tried all of these ways but I was not successful.
I appreciate it, if somebody finds a solution for this question.
Following this message you can see my script. It works with any maps. You need to add it as a tool in ArcMap to read the current map.
Best Regards
Babak Kasraei


# Import modules
import sys,os,math,string,arcpy

# Import Tkinter modules
from Tkinter import *
import tkMessageBox

# This class will create a tekinter GUI with widgets
class ScrolledList(Frame):
    def __init__(self, options, parent=None):
        Frame.__init__(self, parent)
        self.pack(expand=YES, fill=BOTH)                  
        
        self.myParent=self
        sbar = Scrollbar(self)

        # This button is for exit
        self.button5 = Button(self, text="exit",background="gray")
        self.button5.pack(side=BOTTOM, padx=100, pady=10)
        self.button5.bind("<Button-1>", self.button5Click)

        # This button will show only the selected features
        self.button3 = Button(self, text=" Show only Selected features",background="yellow")
        self.button3.pack(side = BOTTOM, padx=100, pady=10)
        
        
        # This button will show all features
        self.button4 = Button(self, text=" Show All Features", background="BROWN")
        self.button4.pack(side=BOTTOM, padx=100,pady=10)
        
        
        # This button will clear selection
        self.button2 = Button(self, text=" Clear selection", background="red")
        self.button2.pack(side=BOTTOM, padx=100, pady=10)
        
        
        # This button will pick features with drawing a rectangle on the map view 
        self.button1 = Button(self, text=" Pick Features",background="green")
        self.button1.pack(side = BOTTOM, padx=100, pady=10)
        self.button1.bind("<Button-1>", self.button1Click)

        # This listBox will show the contents of TOC and map layers
        list = Listbox(self, relief=SUNKEN)
        sbar.config(command=list.yview)                   
        list.config(yscrollcommand=sbar.set)              
        sbar.pack(side=RIGHT, fill=Y)                     
        list.pack(side=LEFT, expand=YES, fill=BOTH)

        # Read from current map
        mxd=arcpy.mapping.MapDocument("CURRENT")
        options = arcpy.mapping.ListLayers(mxd)

        # This loop will go through each item in the TOC to list them
        count = 0
        for label in options:                             
            list.insert(count, label)                      
            count += 1
        list.bind('<Double-1>', self.handleList)          
        self.listbox = list
        # This function will create a selection
    def handleList(self, event):
        
        index = self.listbox.curselection()               
        label = self.listbox.get(index)                   
        self.runCommand(label)
        

        # This function will add a label to the Tekinter GUI to show what is selected
                           
    def runCommand(self, selection):                      
        Label(text="You selected : "+selection).pack(side=BOTTOM,padx=10,pady=10)

        # This function will choose some part of a layer using a rectangle
    
    def button1Click(self, selection):
        
        index = self.listbox.curselection()               
        label = self.listbox.get(index) 

        # Local variables:
        layer = label

        # Process: Select Layer By Location
        arcpy.SelectLayerByLocation_management(layer, "", "", "", "NEW_SELECTION")


        # This function will close the GUI
    def button5Click(self, event):
        root.destroy()
        
        
root = Tk()
# Title of the tekinter

root.title('Theme Management')

# Label of the listbox
Label(text="Select and Unselect TOC features").pack(side=TOP,padx=10,pady=10)
options = map((lambda x: str(x)), range(20))
ScrolledList(options).mainloop()



 



The most important part for this question is using button one by which I have to draw a rectangle on the current map and select parts of it as follows.


     
        # This button will pick features with drawing a rectangle on the map view 
        self.button1 = Button(self, text=" Pick Features",background="green")
        self.button1.pack(side = BOTTOM, padx=100, pady=10)
        self.button1.bind("<Button-1>", self.button1Click)
    
    def button1Click(self, selection):
        
        index = self.listbox.curselection()               
        label = self.listbox.get(index) 

        # Local variables:
        layer = label

        # Process: Select Layer By Location
        arcpy.SelectLayerByLocation_management(layer, "", "", "", "NEW_SELECTION")

Tags (2)
0 Kudos
2 Replies
CarlSunderman
Frequent Contributor
the answer to this can be found here

http://support.esri.com/en/knowledgebase/techarticles/detail/40730

import arcpy

import pythonaddins



class MC(object):

    """Implementation for MouseClickSample_addin.MCtool (Tool)"""

    def __init__(self):

        self.enabled = True

        self.shape = "NONE" # Can set to "Line", "Circle" or "Rectangle" for interactive shape drawing and to activate the onLine/Polygon/Circle event sinks.

    def onMouseDownMap(self, x, y, button, shift):

        pass


then you can convert the rectangle extent to a FC with this
boxAsFeature = arcpy.Polygon(arcpy.Array([yourMouseclickRectangleExtent]),df.spatialReference
)
0 Kudos
babakkasraei
Emerging Contributor
the answer to this can be found here

http://support.esri.com/en/knowledgebase/techarticles/detail/40730

import arcpy

import pythonaddins



class MC(object):

    """Implementation for MouseClickSample_addin.MCtool (Tool)"""

    def __init__(self):

        self.enabled = True

        self.shape = "NONE" # Can set to "Line", "Circle" or "Rectangle" for interactive shape drawing and to activate the onLine/Polygon/Circle event sinks.

    def onMouseDownMap(self, x, y, button, shift):

        pass


then you can convert the rectangle extent to a FC with this
boxAsFeature = arcpy.Polygon(arcpy.Array([yourMouseclickRectangleExtent]),df.spatialReference
)


Hi

Thank you for the reply.

It is a great help.

I also found some codes that are pretty similar to your codes except for the class that this one doesn't have it.


def __init__(self):
    self.enabled = True
    self.cursor = 3
    self.shape = 'Rectangle'
    
def onRectangle(self, rectangle_geometry):
    """Occurs when the rectangle is drawn and the mouse button is released.
    The rectangle is a extent object."""

    extent = rectangle_geometry
    # After you get your extent, to select the features in a layer named 'Stands' intersecting the extent rectangle, do this:
    mxd = arcpy.mapping.MapDocument('CURRENT')
    df = mxd.activeDataFrame
    ext = df.extent
    lyrs = arcpy.mapping.ListLayers(mxd, "Stands", df)
    if lyrs:
        lyr = lyrs[0]
    else:
        return

    a = arcpy.Array()
    a.add(ext.lowerLeft)
    a.add(ext.lowerRight)
    a.add(ext.upperRight)
    a.add(ext.upperLeft)
    a.add(ext.lowerLeft)
    thepoly = arcpy.Polygon(a)

    arcpy.SelectLayerByLocation_management('Stands', 'Intersect', thepoly, 0, 'New_Selection')

0 Kudos