The fishnet tool is basically a way to make a polygon layer that looks like, well, a fishnet that has adjacent rectangualr (or square) polygons (like a checkerboard). I do a lot of large-dataset processing in Python, and the Fishnet tool is always my step #1 in being able to break up large datasets to get them to work with the ESRI tools.For example:# Description
# -----------
# This creates an area of interest feature class, a few buffers of the area of interest, and a fishnet polygon to use for tile-by-tile psudo-parallel processing.
# Written for Python version: 2.5.1 (PythonWin)
# Written for ArcGIS version: 9.3.1 (should be forward compatible).
# Author: Chris Snyder, WA Department of Natural Resources, chris.snyder(at)wadnr.gov
# Date created:
# Last Updated: 20090923, csny490
try:
#Import system modules and creates the Geoprocessor object (the v9.2 way)
import sys, string, os, glob, shutil, time, traceback, arcgisscripting
gp = arcgisscripting.create(9.3)
#Defines some functions
def showGpMessage():
try:
print >> open(logFile, 'a'), "\n" + gp.GetMessages() + "\n"
print "\n" + gp.GetMessages() + "\n"
except:
pass
def showPyMessage():
try:
print >> open(logFile, 'a'), str(time.ctime()) + " - " + str(message)
print str(time.ctime()) + " - " + str(message)
except:
pass
#Sets a date/time stamp variable in the format yyyymmddhhmmss (example: 20060330132345)
dateTimeStamp = time.strftime('%Y%m%d%H%M%S')
#Specifies the root variable, makes the logFile variable, and does some error checking...
root = sys.argv[1]
if os.path.exists(root)== False:
print "Specified root directory: " + root + " does not exist... Bailing out!"
sys.exit()
scriptName = sys.argv[0].split("\\")[len(sys.argv[0].split("\\")) - 1][0:-3] #Gets the name of the script without the .py extension
logFile = root + "\\log_files\\" + scriptName + "_" + dateTimeStamp[:8] + ".log" #Creates the logFile variable
if os.path.exists(root + "\\log_files") == False:
os.mkdir(root + "\\log_files")
if os.path.exists(logFile)== True:
os.remove(logFile)
message = "Deleting log file with the same name and datestamp... Recreating " + logFile; showPyMessage()
workspaceDir = "overlay_index"
if os.path.exists(root + "\\" + workspaceDir)== False:
message = "Creating layer directory: " + root + "\\" + workspaceDir; showPyMessage()
os.mkdir(root + "\\" + workspaceDir)
#Attempts to check out the highest grade license available...
if gp.CheckProduct("ArcInfo") == "Available":
gp.SetProduct("ArcInfo")
elif gp.CheckProduct("ArcEditor") == "Available":
gp.SetProduct("ArcEditor")
elif gp.CheckProduct("ArcView") == "Available":
gp.SetProduct("ArcView")
else:
messsage = "No ArcGis licesnses are available... Exiting script!"; showPyMessage(); sys.exit()
message = "Selected an " + gp.ProductInfo() + " license"; showPyMessage()
#Sets some environment variables
gp.overwriteoutput = True
gp.loghistory = False
sr = 'PROJCS["NAD_1983_HARN_StatePlane_Washington_South_FIPS_4602_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",45.83333333333334],PARAMETER["Standard_Parallel_2",47.33333333333334],PARAMETER["Latitude_Of_Origin",45.33333333333334],UNIT["Foot_US",0.3048006096012192]]'
gp.OutputCoordinateSystem = sr
gp.XYTolerance = "0.001 METERS"
gp.XYResolution = "0.0005 METERS"
gp.workspace = root + "\\" + workspaceDir
#Process: Creates a FGDB to hold all the spatial layers
fgdbName = "overlay_index"
fgdbPath = gp.workspace + "\\" + fgdbName + ".gdb"
gp.CreateFileGDB_management(gp.workspace, fgdbName); showGpMessage()
#Process: Makes a FC of the PLS polys we want
plsFC = root + "\\gis_layers\\pls.gdb\\pls"
plsFL = "pls_feature_layer"
gp.MakeFeatureLayer_management(plsFC, plsFL, "SUR_OWN_CD > 0 OR TIM_OWN_CD > 0", "", ""); showGpMessage()
dnrMgmtAllFC = fgdbPath + "\\dnr_mgmt_all"
gp.Dissolve_management(plsFL, dnrMgmtAllFC, "", "", "SINGLE_PART"); showGpMessage()
#Process: Creates a fishnet layer (the basis of the index polygons)
fishnetLine1FC = fgdbPath + "\\fishnet_line1"
dsc = gp.describe(dnrMgmtAllFC)
xMin = dsc.extent.xmin
yMin = dsc.extent.ymin
xMax = dsc.extent.xmax
yMax = dsc.extent.ymax
bufferWidth = 1 #Buffer width expands the the extent of the fishnet by that many map units (to make sure it extends past DNR lands a bit)
numberOfRows = 6
numberOfColumns = 6
gp.CreateFishnet_management(fishnetLine1FC, str(xMin - bufferWidth) + " " + str(yMin - bufferWidth), str(xMin - bufferWidth) + " " + str(yMin), "0", "0", numberOfRows, numberOfColumns, str(xMax + bufferWidth) + " " + str(yMax + bufferWidth), "NO_LABELS", ""); showGpMessage()
fishnet1FC = fgdbPath + "\\fishnet_poly1"
gp.FeatureToPolygon_management(fishnetLine1FC, fishnet1FC, "", "", ""); showGpMessage()
gp.Delete_management(fishnetLine1FC, ""); showGpMessage()
#Process: Creates a 2nd fishnet layer (that is more dense than the original)
fishnetLine2FC = fgdbPath + "\\fishnet_line2"
densificationFactor = 12 #this densification factor ABSOLUTELY NEEDS to be a multiple of 2 (e.g. 2,4,6,8,etc)
gp.CreateFishnet_management(fishnetLine2FC, str(xMin - bufferWidth) + " " + str(yMin - bufferWidth), str(xMin - bufferWidth) + " " + str(yMin), "0", "0", str(numberOfRows * densificationFactor), str(numberOfColumns * densificationFactor), str(xMax + bufferWidth) + " " + str(yMax + bufferWidth), "NO_LABELS", ""); showGpMessage()
fishnet2FC = fgdbPath + "\\fishnet_poly2"
gp.FeatureToPolygon_management(fishnetLine2FC, fishnet2FC, "", "", ""); showGpMessage()
gp.Delete_management(fishnetLine2FC, ""); showGpMessage()
#Process: Updates fishnet1FC with fishnet2FC for specified areas
hcpUnitFC = root + "\\gis_layers\\hcpunit.gdb\\hcpunit"
oesfFC = fgdbPath + "\\oesf"
gp.Select_analysis(hcpUnitFC, oesfFC, "HCPUNIT_ID = 1", "", ""); showGpMessage()
fishnet1FL = "fishnet_1_feature_layer"
gp.MakeFeatureLayer_management(fishnet1FC, fishnet1FL, "", "", ""); showGpMessage()
gp.SelectLayerByLocation_management(fishnet1FL, "INTERSECT", oesfFC, "", "NEW_SELECTION"); showGpMessage()
fishnet2FL = "fishnet_2_feature_layer"
gp.MakeFeatureLayer_management(fishnet2FC, fishnet2FL, "", "", ""); showGpMessage()
gp.SelectLayerByLocation_management(fishnet2FL, "HAVE_THEIR_CENTER_IN", fishnet1FL, "", "NEW_SELECTION"); showGpMessage()
gp.Delete_management(oesfFC, ""); showGpMessage()
fishnetFC = fgdbPath + "\\fishnet_poly"
gp.Update_analysis(fishnet1FC, fishnet2FL, fishnetFC, "BORDERS", ""); showGpMessage()
#Process: Make a line FC version of fishnetFC
fishnetLineFC = fgdbPath + "\\fishnet_lines"
gp.FeatureToLine_management(fishnetFC, fishnetLineFC, "", "NO_ATTRIBUTES"); showGpMessage()
#Process: Unions everything together
union1FC = fgdbPath + "\\union1"
gp.Union_analysis(fishnetFC + ";" + dnrMgmtAllFC, union1FC, "ONLY_FID", "", "GAPS"); showGpMessage()
#BLAH BLAH BLAH - I had to trim this part out to post it to the forum (stupid 10,000 charater limit!!!)
#Process: Compacts the PGDB
gp.Compact_management(fgdbPath); showGpMessage()
#Process: Creates a .txt file that indicates to other scripts how many tiles there are (this is used so that the run_union_master script doesn't have to use the gp and waste memory)
print >> open(root + "\\log_files\\" + "therearethismanytiles_" + str(numberOfTiles) + ".txt", 'a'), "therearethismanytiles_" + str(numberOfTiles)
message = "ALL DONE!"; showPyMessage()
print >> open(root + "\\log_files\\" + scriptName + "_isalldone.txt", 'a'), scriptName + "_isalldone.txt"
except:
print >> open(root + "\\log_files\\" + scriptName + "_bombed.txt", 'a'), scriptName + "_bombed.txt"
message = "\n*** LAST GEOPROCESSOR MESSAGE (may not be source of the error)***"; showPyMessage()
showGpMessage()
message = "\n*** PYTHON ERRORS *** "; showPyMessage()
message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
message = "Python Error Info: " + str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()
message = "\n*** PYTHON LOCAL VARIABLE LIST ***"; showPyMessage()
variableCounter = 0
while variableCounter < len(locals()):
message = str(list(locals())[variableCounter]) + " = " + str(locals()[list(locals())[variableCounter]]); showPyMessage()
variableCounter = variableCounter + 1
showPyMessage()