- inFc: The input feature class
- eraseFc: The feature class whose features will be erased from the input feature class
- outLoc: The output file geodatabase
- outName: The final name of the output feature class
- workspace: A file geodatabase workspace
- notices: Set to True for printed progress information
The code:
def Erase (inFc, eraseFc, outLoc = "", outName = "", workspace = "in_memory", notices = False):
import os
addToToc = arcpy.env.addOutputsToMap
arcpy.env.addOutputsToMap = False
if not outName:
outName = os.path.basename (inFc) + "_Erase"
if not outLoc:
catPath = arcpy.Describe (inFc).catalogPath
outLoc = os.path.dirname (catPath)
outFc = UniqueFileName (outLoc, outName)
outLoc, outName = os.path.split (outFc)
garbage = []
inType = arcpy.Describe (inFc).shapeType
eraseType = arcpy.Describe (eraseFc).shapeType
#lines and lines
if inType == "Polyline" and eraseType == "Polyline":
#buffer both lines: flat, left
inBuffFc = UniqueFileName (workspace)
arcpy.Buffer_analysis (inFc, inBuffFc, ".01 FEET")
garbage += [inBuffFc]
eraseBuffFc = UniqueFileName (workspace)
arcpy.Buffer_analysis (eraseFc, eraseBuffFc, ".01 FEET")
garbage += [eraseBuffFc]
#union input buffer with erase buffer
unionFc = UniqueFileName (workspace)
arcpy.Union_analysis ([inBuffFc, eraseBuffFc], unionFc)
garbage += [unionFc]
#select union output by erase buffer
unionLyr = UniqueLayerName (unionFc)
garbage += [unionLyr]
arcpy.SelectLayerByLocation_management (unionLyr, "WITHIN", eraseBuffFc)
#switch union selection
arcpy.SelectLayerByAttribute_management (unionLyr, "SWITCH_SELECTION")
#check for selection
if not arcpy.Describe (unionLyr).FIDSet:
arcpy.CreateFeatureclass_management (outLoc, outName, "POLYLINE", inFc, "", "", inFc)
for trash in garbage:
arcpy.Delete_management (trash)
return outFc
#clip line
arcpy.env.addOutputsToMap = addToToc
arcpy.Clip_analysis (inFc, unionLyr, outFc)
#lines and polygons
elif inType == "Polyline" and eraseType == "Polygon":
#buffer both lines: flat, left
inBuffFc = UniqueFileName (workspace)
arcpy.Buffer_analysis (inFc, inBuffFc, ".01 FEET")
garbage += [inBuffFc]
#union input buffer with erase buffer
unionFc = UniqueFileName (workspace)
arcpy.Union_analysis ([inBuffFc, eraseFc], unionFc)
garbage += [unionFc]
#select union output by erase buffer
unionLyr = UniqueLayerName (unionFc)
garbage += [unionLyr]
arcpy.SelectLayerByLocation_management (unionLyr, "WITHIN", eraseFc)
#switch union selection
arcpy.SelectLayerByAttribute_management (unionLyr, "SWITCH_SELECTION")
#check for selection
if not arcpy.Describe (unionLyr).FIDSet:
arcpy.CreateFeatureclass_management (outLoc, outName, "POLYLINE", inFc, "", "", inFc)
for trash in garbage:
arcpy.Delete_management (trash)
return outFc
#clip line
arcpy.env.addOutputsToMap = addToToc
arcpy.Clip_analysis (inFc, unionLyr, outFc)
#polygons and polygons
elif inType == "Polygon" and eraseType == "Polygon":
unionFc = UniqueFileName (outLoc, outName)
arcpy.env.addOutputsToMap = addToToc
arcpy.Union_analysis ([inFc, eraseFc], unionFc, "NO_FID")
arcpy.env.addOutputsToMap = False
unionLyr = UniqueLayerName (unionFc)
garbage += [unionLyr]
arcpy.SelectLayerByLocation_management (unionLyr, "WITHIN", eraseFc)
arcpy.DeleteFeatures_management (unionLyr)
inFlds = [f.name for f in arcpy.ListFields (inFc)]
delFlds = [f.name for f in arcpy.ListFields (unionLyr) if not f.name in inFlds and not
f.type in ("Geometry", "OID") and f.required == False]
arcpy.DeleteField_management (unionLyr, delFlds)
arcpy.env.addOutputsToMap = addToToc
for trash in garbage:
arcpy.Delete_management (trash)
return outFc
def UniqueFileName(Location = "in_memory", Name = "file", Extension = ""):
"""
returns an unused file name
'Location' will be the file folder
'Name' will be the file name plus numeric extension if needed
'Extension' is the file extension
similar to arcpy.CreateUniqueName
"""
import arcpy
import os
if Extension:
outName = os.path.join (Location, Name + "." + Extension)
else:
outName = os.path.join (Location, Name)
i = 0
while arcpy.Exists (outName):
i += 1
if Extension:
outName = os.path.join (Location, Name + "_" + str(i) + "." + Extension)
else:
outName = os.path.join (Location, Name + "_" + str(i))
return outName
def UniqueLayerName(inFC = None, sql = None):
"""
returns an unused feature layer name
"""
import arcpy
import os
lyrName = os.path.join ("lyr0")
i = 0
while arcpy.Exists (lyrName):
i += 1
lyrName = "lyr" + str(i)
if inFC:
arcpy.MakeFeatureLayer_management (inFC, lyrName, sql)
return lyrName
This comment has been removed by a blog administrator.
ReplyDeleteHi,
ReplyDeleteThank a lot for sharing the code! I think the variable "fcName" in Line 10 should be "outName". Cheers~~
Thanks, you were right. I've fixed the code. Good catch.
DeleteThis works well, however since I didn't have an advanced licence, I had to change the buffer parameters from "Left" to "Full" and from "Flat" to "Round". Since those with an advance licence would simply use the Erase tool, it would make no sense to keep the advanced licence parameters.
ReplyDeleteIt would be helpful if there were a script that would call the Erase Function, for those who are not arcpy proficient.
Good point. I've updated the code accordingly.
DeleteI thought you could use arcpy functions outside of arcmap without license?
ReplyDelete