Create fishnet with row iterator - why does extent not update?

8619
10
Jump to solution
03-25-2014 02:04 PM
AlejandroBlei
New Contributor
Hello, I am struggling to solve what should be a simple problem: I want to create fishnets over several squares; each of the squares is 2200 meters by 2200 meters. I am using Model Builder in ArcGIS Desktop 10.1. I would like to use the iterate row selection feature.

Let's say I am dealing with a shapefile that contiains only one square. There is no issue here. I set the extent of the fishnet to match the extent of the file that contains one square only. I specify the numbers of rows and columns and cell size. This is easy.

Now let's say i want to do the same thing but for a file that contains 68 square. Each square corresponds to a row in the attribute table. This is what I mean, one shapefile in the TOC and 68 squares:

[ATTACH=CONFIG]32498[/ATTACH]

The attribute table contains 68 rows where each row corresponds to a square. All quite normal


When I input the 68 row file to the "itereate row selection tool" and connect that to the create fishnet tool, like so (below) I get a pop-up box that wants me to choose between "template extent," "environments," or "precondition." I choose template extent thinking that this means: "treat each feature represented by each of the 68 rows as having unique extents to be used in creating 68 different fishnets."

[ATTACH=CONFIG]32500[/ATTACH]

When I double click on the fishnet box, I see this:

[ATTACH=CONFIG]32501[/ATTACH]

This is where things start to get a little fishy (pardon the pun!), because I would like the have the extent of each fishnet update to reflect each feature in each of the rows. Nevertheless, there are coordinates already entered for the extent of the fishnet. As I have found out, these coordinates correspond to the extent of the data frame - the extent when all 68 households are visible. For example when I hit ok and run the model:

I see this:

[ATTACH=CONFIG]32503[/ATTACH]

There was a fishnet created in the lower left hand corner, it has 22 rows and 22 columns, each 100 x 100 meters, just as i would like. Unfortunately, this location does not correspond to any of the squares in the file. And there is only one fishnet, not 68. This is what it looks like when I zoom to the extent of the fishnet that was created. This fishnet looks alright, the problem is I need 68 of them to match the extents of the 68 squares in the top image.

[ATTACH=CONFIG]32504[/ATTACH]

I have a vague notion of what is going wrong. ArcGIS does not understand, or I am not properly inputting, the fact that one fishnet should be created for each row of the input table. Moreover, the extent each fishnet that is created should match the extent of the feature in each row.

What I would like to have: At the very least, 68 fishnets, each 22 rows by 22 columns, 100 x 100 meter cells. 22 x 22 = 484, so there will be 484 polygons associated with a square. Since there are 68 squares, there should be 484 x 68 = 32,912 rows when all is said in done. This can be in one file with 32,912 rows or each square can be it's own file, meaning there would be 68 files, each with 484 rows.

Any suggestions, tips, solutions, would be immensely appreciated.  My sincere thanks.
0 Kudos
10 Replies
XanderBakker
Esri Esteemed Contributor

If each fishnet should cover each polygon, then the code should be adapted (as far as I can tell). The n_row and n_cols should be calculated for each polygon depending the extent of the polygon.

If this is what you want:

Fishnet.png

Then you should use this code:

import arcpy, os
arcpy.env.overwriteOutput = True

def CreateFishnetsForFeats(in_polys, out_loc, cell_x=0, cell_y=0):
    '''
    in_polys: input polygon feature class
    out_loc: folder location for new file gdb containing fishnet feature class
    cell_x: cell width
    cell_y: cell height
    '''

    # Create file gdb to store data
    gdb = str(arcpy.CreateFileGDB_management(out_loc, 'Fishnets.gdb').getOutput(0))

    # spatial reference
    arcpy.env.outputCoordinateSystem = arcpy.Describe(in_polys).spatialReference

    # Loop thru rows of input polygons
    with arcpy.da.SearchCursor(in_polys, ['SHAPE@', 'OID@']) as rows:
        for row in rows:
            ext = row[0].extent
            st = '%f %f' %(ext.XMin, ext.YMin)
            orien = '%f %f' %(ext.XMin, ext.YMax)

            if cell_y == 0:
                n_rows = 1
                cell_y = ext.height
            else:
                n_rows = int((ext.height - (ext.height % cell_y)) / cell_y) + 1

            if cell_x == 0:
                n_cols = 1
                cell_x = ext.width
            else:
                n_cols = int((ext.width - (ext.width % cell_x)) / cell_x) + 1

            # Create fishnet
            out = os.path.join(gdb, 'fish_{0}'.format(row[1]))
            arcpy.CreateFishnet_management(out, st, orien, cell_x,
                                           cell_y, n_rows, n_cols,
                                           labels='NO_LABELS',
                                           geometry_type='POLYGON')

    # set workspace to new gdb
    arcpy.env.workspace = gdb
    fishnets = arcpy.ListFeatureClasses()
    targ = fishnets[0]
    for i, fish in enumerate(fishnets):

        # Add field for original polygon ID
        fid = fish.split('_')[1]
        arcpy.AddField_management(fish, 'POLY_ID', 'LONG')
        with arcpy.da.UpdateCursor(fish, ['POLY_ID']) as rows:
            for row in rows:
                row[0] = fid
                rows.updateRow(row)

        # append fishnets into one feature class
        if i > 0:
            arcpy.Append_management([fish], targ, 'NO_TEST')
            arcpy.Delete_management(fish)
            print 'Appended: {0}'.format(fish)

    print 'Done'
    return

if __name__ == '__main__':
    polys = r'C:\TEMP\test_polys.shp'
    loc = r'C:\TEMP'

    CreateFishnetsForFeats(polys, loc, 100, 100)