Wednesday, March 27, 2013

Creating Data Frame Extents (ArcPy 10.1)

I read your comments, and thank you for posting them.  I was asked how do you clip all layers in a map document by the current data frame's extent.

In a previous post, I discussed how to create extent polygons for feature classes and individual features.  The same method applies for creating an extent polygon using data frames.

The data frame object has a whole host of properties and methods which can be found here.  To get the extent of a data frame, just reference the extent property to obtain the data frame's current extent.  Create the extent polygon or feature class, and clip by the extent geometry.

# Clip layers by extent of data frame (assuming in arcmap session)
import os
import arcpy
from arcpy import env
from arcpy import mapping
mxd = mapping.MapDocument("CURRENT")
df = mxd.activeDataFrame
extent = df.extent
array = arcpy.Array()
array.add(extent.lowerLeft)
array.add(extent.lowerRight)
array.add(extent.upperRight)
array.add(extent.upperLeft)
array.add(extent.lowerLeft)
polygon = arcpy.Polygon(array, df.spatialReference)
array.removeAll()
del array
for layer in mapping.ListLayers(mxd, data_frame=df):
    clipped_fc = env.scratchGDB + os.sep + layer.datasetName + "_clipped"
    arcpy.Clip_analysis(in_features=layer, 
                        clip_features=polygon,
                        out_feature_class=clipped_fc)
    del layer
del mxd
del df
del extent

This code is just a quick re-hash of old concepts applied to a new method. The extent object creates a polygon, which is used to clip the layers in that data frame.

6 comments:

Stefan O. said...

I think this code does not work because the variable array is not initialised before calling array.add(extent.lowerLeft)

Andrew said...

fixed

Anonymous said...

Excellent post! Thank you very much!
For me (total newbie in Python), in order to get it to work I had to define the path to scratchGDB:
arcpy.env.scratchWorkspace="c:/Temp".

I don't know if it was the right thing to do, but hey, it worked! ;)

Now, could this be extended to also deal with rasters and annotations? I guess it could, but I do not have a clue of where to begin...

Anyway, thanks again!

/Richard

R-dogg said...

Thank you so much for this post! This is exactly what I'm looking to do, but when I try running it with Python 2.7, I get a "TypeError: Abstract Class" message on the arcpy.Array() line.

Any suggestions as to how to get around that or what I might be doing wrong?

Thanks!

wank1 said...

I'm getting "TypeError: Abstract Class" in python (when running inside 10.2.2) as a tool. This happens when ever I try to define a array with

myarray = arcpy.Array()

did you solve this issue?

Andrew said...

Sorry, I cannot reproduce your issue. Does array = arcpy.Array() work in the python window in ArcMap?

In addition, the script would have to be modified if running from python outside of the ArcMap session because you cannot get the extent of an ArcMap session using current, you would have to pass in the full path to the saved arcmap document.

Change: mxd = mapping.MapDocument("CURRENT")
to mxd = mapping.MapDocument(r"my full path to mxd")