Select to view content in your preferred language

Draw a rectangle by dragging

4558
11
01-25-2013 01:17 PM
babakkasraei
Emerging Contributor
Hi Experts

How can I draw a rectangle on my map by clicking and dragging my cursor click using python codes?

Best Regards
Babak
Tags (2)
0 Kudos
11 Replies
KimOllivier
Honored Contributor
At the start of a script you can use the FeatureSet input type in a dialog.
You need to have a template featureclass to refer to, in this case a polygon, as a layer to define the symbol to draw.

Then when you run the tool you can interactively draw one or more polygons or rectangles just like using the draw tools.

In the script you can pick up the geometry object if it was the first parameter and use it
inRecSet = arcpy.GetParameter(0)

This has been available since 9.3

You would have to run the tool again to repeat.

If you want more control then 10.1 AddIns will give you access to the message queue of mouse clicks, and tracking.
But AddIns are significantly more trouble, so try the featureset first.
0 Kudos
babakkasraei
Emerging Contributor
Thank you Kim for your answer.

Best regards

Babak
0 Kudos
babakkasraei
Emerging Contributor
At the start of a script you can use the FeatureSet input type in a dialog.
You need to have a template featureclass to refer to, in this case a polygon, as a layer to define the symbol to draw.

Then when you run the tool you can interactively draw one or more polygons or rectangles just like using the draw tools.

In the script you can pick up the geometry object if it was the first parameter and use it
inRecSet = arcpy.GetParameter(0)

This has been available since 9.3

You would have to run the tool again to repeat.

If you want more control then 10.1 AddIns will give you access to the message queue of mouse clicks, and tracking.
But AddIns are significantly more trouble, so try the featureset first.



Dear Kim

Your guide is really important. However, I really don't know how to apply it into my codes. I have created codes for my first button in my Tkinter that some parts of it are created with your help. I really thank you.  Following you can see my codes. they don't work, I really appreciate it if you please help me to correct them to be able to be used as a tool to work like select by rectangle tool.



def button1Click(self, selection):
        def __init__(self):
            self.enabled = True
            self.cursor = 1
            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 of the feature

            extent = rectangle_geometry
            mxd=arcpy.mapping.MapDocument("CURRENT")

            # Set the workspace
            #
            env.workspace = mxd
            index = self.listbox.curselection()               
            label = self.listbox.get(index) 

            # Local variables:
            layer = label

            df = arcpy.mapping.ListDataFrames(mxd)[0]
            # Create a search cursor from layer
            #
            sCur = arcpy.SearchCursor(layer, '"CNTY_NAME" = \'Orange\'')
            # Fetch each feature from the cursor and examine the extent properties
            #

            for row in sCur:
                geom = row.shape
                ext = geom.extent # or row.Shape.extent
                # Create an Array object.
                #The DataFrame extent object is converted into a polygon feature so it can be used with the SelectLayerByLocation function.
                dfAsFeature = arcpy.Polygon(arcpy.Array([df.ext.lowerLeft, df.ext.lowerRight, df.ext.upperRight,  df.ext.upperLeft]),df.spatialReference)
            arcpy.SelectLayerByLocation_management(layer, "INTERSECT", dfAsFeature, "", "NEW_SELECTION")



I hope you help me.
Best regards

Babak
0 Kudos
KimOllivier
Honored Contributor
The featureset is part of the ArcGIS toolbox parameters. It does not use TKinter at all.

Your code attempts to use objects only available using a full AddIn.
http://resources.arcgis.com/en/help/main/10.1/index.html#//014p0000001q000000

You can use Tkinter to draw rectangles on a Tkinter window, but not the ArcMap window, so the coordinates will not be transformed to map units. The message queues between ArcGIS and TKinter are also not the same. That is what AddIns are for. Then you do have access to the ArcMap message queue and can detect all the mouse events such as the code you have pasted.

My solution is for the case when you want to select a box interactively at the start and then run a script, not using the AddIn objects. Since you can add a script tool as a button, this is almost equivalent to Avenue tools we were use to, and it is easy to implement.

http://webhelp.esri.com/arcgisdesktop/9.3/index.cfm?TopicName=Feature%20sets%20and%20record%20sets

The Esri example concentrates on modelbuilder, but it can work in simple tools just as well.

Create a tool and add a parameter. Set it to featureset. Set a schema that is a polygon featureclass.
When you run the tool, open the properties to set drawing rectangles
Draw one or more rectangles and start the tool
In your script collect the polygon featureset entered interactively when the tool is run
This is just like an on-the-fly featureclass but in memory

# DemoBox
# draw a box interactively and report extent
import arcpy
fSet = arcpy.GetParameter(0)
desc = arcpy.Describe(fSet)

# print a JSON representation, version 10.1
arcpy.AddMessage(str(desc.pjson))
# print the extent of each box version 9.3+
for row in arcpy.SearchCursor(fSet):
    arcpy.AddMessage(str(row.shape.extent))
0 Kudos
babakkasraei
Emerging Contributor
Dear Kimo

You don't know how much your help is valuable for me. Thank you.

My question

Can I use the last codes you gave me as a solution in my Tkinter because I definitely need a Tkinter widget GUI in my project?

Thank you for your help.

Best Regards

Babak
0 Kudos
babakkasraei
Emerging Contributor
The featureset is part of the ArcGIS toolbox parameters. It does not use TKinter at all.

Your code attempts to use objects only available using a full AddIn.
http://resources.arcgis.com/en/help/main/10.1/index.html#//014p0000001q000000

You can use Tkinter to draw rectangles on a Tkinter window, but not the ArcMap window, so the coordinates will not be transformed to map units. The message queues between ArcGIS and TKinter are also not the same. That is what AddIns are for. Then you do have access to the ArcMap message queue and can detect all the mouse events such as the code you have pasted.

My solution is for the case when you want to select a box interactively at the start and then run a script, not using the AddIn objects. Since you can add a script tool as a button, this is almost equivalent to Avenue tools we were use to, and it is easy to implement.

http://webhelp.esri.com/arcgisdesktop/9.3/index.cfm?TopicName=Feature%20sets%20and%20record%20sets

The Esri example concentrates on modelbuilder, but it can work in simple tools just as well.

Create a tool and add a parameter. Set it to featureset. Set a schema that is a polygon featureclass.
When you run the tool, open the properties to set drawing rectangles
Draw one or more rectangles and start the tool
In your script collect the polygon featureset entered interactively when the tool is run
This is just like an on-the-fly featureclass but in memory

# DemoBox
# draw a box interactively and report extent
import arcpy
fSet = arcpy.GetParameter(0)
desc = arcpy.Describe(fSet)

# print a JSON representation, version 10.1
arcpy.AddMessage(str(desc.pjson))
# print the extent of each box version 9.3+
for row in arcpy.SearchCursor(fSet):
    arcpy.AddMessage(str(row.shape.extent))


Dear Kim

I tried the steps you have written. I created a model in my toolbox with Select by location tool.

I created a variable then I set it to feature set in my model. Then I added a schema to it which is a polygon feature set that I had been already created. finally I connected it to the selection tool.

Now as you wrote I need to run the tool and open the properties to set a rectangle drawing and draw some rectangles.

your words

When you run the tool, open the properties to set drawing rectangles

I don't understand this step. How does it happen because my tool still needs a layer?

If I run the tool where will be the properties option?

Which properties do you mean? Properties of tool, model or variable. Where is the draw a rectangle option.

Next you have written



In your script collect the polygon featureset entered interactively when the tool is run



Do you mean that I collect extent features by drawing a rectangle on my layer?

I really appreciate your clarification.

Best regards

Babak
0 Kudos
KimOllivier
Honored Contributor
Don't use a model, just create a script tool.

You set a schema to define the featureclass and fields in the dialog wizard when adding the parameters to the tool.
It uses that schema to create a polygon when you draw interactively. It has to exist, you are not defining a new featureclass.

After you open the tool there is a hidden property to change the drawing style by right-clicking the input in the tool dialog for the template properties.

It defaults to drawing a polygon, but you can change it to draw a box. It requires a line and then drag which is a bit strange but it enables you to draw a box at any angle. But you can right click again and set a horizontal property.

You would use the feature to select other layers directly, I only printed the json dump and the extent to demonstrate that it is a polygon feature that can be used in other tools or in Python.
0 Kudos
babakkasraei
Emerging Contributor
Dear Kim

I did it successfully. I put my parameter as Feature set. When the Schema appeared I gave it an empty shape file.

So as soon as I open the dialogue my cursor starts drawing a rectangle.

Now I have two problems.

1- I need my rectangle to be hollow, because when draw the rectangle, it covers the other layers.

2- I want to embed these codes into my Tkinter to work by pushing button1 click. I found the following codes for entering the schema into python codes


  from json_schema import Schema, AnyInteger

  my_schema = Schema([u"set-temp", {u"degrees": AnyInteger}]) 

  if my_schema.validate([u"set-temp", {u"degrees": 10}]):
    print "Valid!"
 

Do you think it is possible? How?

I hope you help me.

Best regards

Babak
0 Kudos
babakkasraei
Emerging Contributor
Don't use a model, just create a script tool.

You set a schema to define the featureclass and fields in the dialog wizard when adding the parameters to the tool.
It uses that schema to create a polygon when you draw interactively. It has to exist, you are not defining a new featureclass.

After you open the tool there is a hidden property to change the drawing style by right-clicking the input in the tool dialog for the template properties.

It defaults to drawing a polygon, but you can change it to draw a box. It requires a line and then drag which is a bit strange but it enables you to draw a box at any angle. But you can right click again and set a horizontal property.

You would use the feature to select other layers directly, I only printed the json dump and the extent to demonstrate that it is a polygon feature that can be used in other tools or in Python.


Hi Kim

I created the following codes in my Tkinter for button1 function. It works; however, I still have problem because I have to create a feature set parameter by a schema and then draw my rectangle before running the tool. After running the tool when I select a layer from the list and push button1 the place that I have selected get highlight, so it works, but I want it to work when I push the button not before it. following you can see my button1 codes.


def button1Click(self, selection):
        
            
        # Import arcpy module
        import arcpy
        index = self.listbox.curselection()               
        label = self.listbox.get(index) 

        # Local variables:
        layer = label

        # Script arguments
        Feature_Set = arcpy.GetParameterAsText(0)
        if Feature_Set == '#' or not Feature_Set:
           Feature_Set = "in_memory\\{EDD8060B-E74A-42D1-93A5-7CB08285BA52}" # provide a default value if unspecified

        # Local variables:
        CHS_Chart_Extents__3_ = Feature_Set
        CHS_Chart_Extents = layer

        # Process: Select Layer By Location
        arcpy.SelectLayerByLocation_management(CHS_Chart_Extents, "WITHIN", Feature_Set, "", "NEW_SELECTION")
        arcpy.RefreshActiveView()



I appreciate your help

Best regards

Babak
0 Kudos