# Python Script: Create a rectangle using coordinates, width and height atributes from DBF

13515
19
Jump to solution
01-11-2017 09:01 AM New Contributor II

Dear Xander,

I wonder if it is possible to take width and length of the rectangle from a dbf table.. I have 24 rows with different length and width values, and hence I want to create 24 rectangles with different sizes according to width and length from the dbf table.

Best,

Tim

Tags (7)
1 Solution

Accepted Solutions by Esri Esteemed Contributor

Yes, Blake Terhune  was completely right! Those were errors indeed. Find below the corrected (and tested) code:

``import arcpydef main():    import os    arcpy.env.overwriteOutput = True    # input dbf file, edit this !!!    tbl = r'D:\Xander\GeoNet\DBF2Rectangles\testdata.dbf'    # edit these field names !!!    fld_oid_in = 'OID@'    fld_X = 'X'    fld_Y = 'Y'    fld_width = 'Width'    fld_height = 'Height'    fld_oid_out = 'OID_DBF'    # output feature class    fc_out = r'D:\Xander\GeoNet\DBF2Rectangles\test.gdb\rectangles' # edit this !!!    # define a spatial reference, edit this !!!    sr = arcpy.SpatialReference(3857)  # example for WGS_1984_Web_Mercator_Auxiliary_Sphere    # create output featureclass    fc_ws, fc_name = os.path.split(fc_out)    arcpy.CreateFeatureclass_management(fc_ws, fc_name, "POLYGON", None, None, None, sr)    # add field OID DBF    AddField(fc_out, fld_oid_out, "LONG", None)    # insert cursor to store the results    flds_out = ('SHAPE@', fld_oid_out)    with arcpy.da.InsertCursor(fc_out, flds_out) as curs_out:        # loop over dbf file        flds = (fld_oid_in, fld_X, fld_Y, fld_width, fld_height)        with arcpy.da.SearchCursor(tbl, flds) as curs:            for row in curs:                oid = row                x = row                y = row                w = row                h = row                polygon = createRectangle(x, y, w, h, sr)                curs_out.insertRow((polygon, oid, ))def AddField(fc, fld_name, fld_type, fld_length):    if len(arcpy.ListFields(fc, fld_name)) == 0:        arcpy.AddField_management(fc, fld_name, fld_type, None, None, fld_length)def createRectangle(x, y, w, h, sr):    xmin = float(x) - float(w) / 2.0    xmax = float(x) + float(w) / 2.0    ymin = float(y) - float(h) / 2.0    ymax = float(y) + float(h) / 2.0    lst_pnts = []    lst_pnts.append(arcpy.Point(xmin, ymin))    lst_pnts.append(arcpy.Point(xmin, ymax))    lst_pnts.append(arcpy.Point(xmax, ymax))    lst_pnts.append(arcpy.Point(xmax, ymin))    lst_pnts.append(lst_pnts)    return arcpy.Polygon(arcpy.Array(lst_pnts), sr)if __name__ == '__main__':    main()‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍``

And the result for some random data: 19 Replies by Esri Esteemed Contributor

Question branched from this thread: https://community.esri.com/thread/84853 by xander_bakker by Esri Esteemed Contributor

Hi Tim Gattinger , I branched your question to a new thread.

Yes it is possible to adapt the script to read width and height attributes from attributes in a DBF. What was not clear to me is if that DBF is a stand alone table or not. In case it is look at the example below.

This will take a DBF (specified on row 7) with the attributes defined on lines 11 to 14 and create a new output featureclass (defined at line 18) that will hold the polygons of the rectangles by reading XY attributes (is this the case?) and the width and height defined in attributes. Important is to specify a relevant (projected) coordinate system on line 21 in which X, Y, width and height are expressed:

``import arcpydef main():    import os    # input dbf file, edit this !!!    tbl = r'D:\Folder\SubFolder\NameOfYour.dbf'    # edit these field names !!!    fld_oid_in = 'OID@'    fld_X = 'X'    fld_Y = 'Y'    fld_width = 'Width'    fld_height = 'Height'    fld_oid_out = 'OID_DBF'    # output feature class    fc_out = r'D:\Folder\SubFolder\NameOfWorkspace.gdb\rectangles' # edit this !!!    # define a spatial reference, edit this !!!    sr = arcpy.SpatialReference(3857)  # example for WGS_1984_Web_Mercator_Auxiliary_Sphere    # create output featureclass    fc_ws, fc_name = os.path.split(fc_out)    arcpy.CreateFeatureclass_management(fc_ws, fc_name, "POLYGON", None, None, None, sr)    # add field OID DBF    AddField(fc_out, fld_oid_out, "LONG", None)    # insert cursor to store the results    flds_out = ('SHAPE@', fld_oid_out)    with arcpy.da.InsertCursor(fc_out, flds_out) as curs_out:        # loop over dbf file        flds = (fld_oid, fld_X, fld_Y, fld_width, fld_height)        with arcpy.da.SearchCursor(fc, flds) as curs:            for row in curs:                oid = row                x = row                y = row                w = row                h = row                polygon = createRectangle(x, y, w, h, sr)                curs_out.insertRow((polygon, oid, ))def AddField(fc, fld_name, fld_type, fld_length):    if len(arcpy.ListFields(fc, fld_name)) == 0:        arcpy.AddField_management(fc, fld_name, fld_type, None, None, fld_length)def createRectangle(x, y, w, h, sr):    xmin = float(x) - float(w) / 2.0    xmax = float(x) + float(w) / 2.0    ymin = float(y) - float(h) / 2.0    ymax = float(y) + float(h) / 2.0    lst_pnts = []    lst_pnts.append(arcpy.Point(xmin, ymin))    lst_pnts.append(arcpy.Point(xmin, ymax))    lst_pnts.append(arcpy.Point(xmax, ymax))    lst_pnts.append(arcpy.Point(xmax, ymin))    lst_pnts.append(lst_pnts)    return arcpy.Polygon(arcpy.Array(lst_pnts), sr)if __name__ == '__main__':    main()‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍`` by Esri Esteemed Contributor

Oops, just noticed I made an mistake on line 43 - 44. It should be replaced by:

``                polygon = createRectangle(x, y, w, h, sr)‍‍‍``

New: just updated code in post above... by MVP Esteemed Contributor

Can you update your original code as well (maybe you did and I am missing the obvious)? New Contributor II

Thanks, it looks great I'll try the code as soon as possible.. I just didnt understand where the X,Y coordinates come from...I created center points from an underlying shapefile, can I e.g. take the coordiunates form these points and just add them to the dbf and go on with the script you just wrote?

So..in your code are the X,Y coordinates meant to be the starting point for each rectangle, or sth like that?

Best, Tim New Contributor II

After the adaptions I made, it still says 'global name 'fc' not defined'..do you have an idea?! Im quite new to the programming stuff btw.. by MVP Regular Contributor

In line 36 of Xander's code where the SearchCursor is created, I think fc should be changed to tbl. However, it also looks like fld_oid is undefined on line 35; maybe should be fld_oid_in? by Esri Esteemed Contributor

Very valid comments Blake Terhune  (+1)... will generate a dummy table with some random data and test the code, to see what needs to be changed. by Esri Esteemed Contributor

Yes, Blake Terhune  was completely right! Those were errors indeed. Find below the corrected (and tested) code:

``import arcpydef main():    import os    arcpy.env.overwriteOutput = True    # input dbf file, edit this !!!    tbl = r'D:\Xander\GeoNet\DBF2Rectangles\testdata.dbf'    # edit these field names !!!    fld_oid_in = 'OID@'    fld_X = 'X'    fld_Y = 'Y'    fld_width = 'Width'    fld_height = 'Height'    fld_oid_out = 'OID_DBF'    # output feature class    fc_out = r'D:\Xander\GeoNet\DBF2Rectangles\test.gdb\rectangles' # edit this !!!    # define a spatial reference, edit this !!!    sr = arcpy.SpatialReference(3857)  # example for WGS_1984_Web_Mercator_Auxiliary_Sphere    # create output featureclass    fc_ws, fc_name = os.path.split(fc_out)    arcpy.CreateFeatureclass_management(fc_ws, fc_name, "POLYGON", None, None, None, sr)    # add field OID DBF    AddField(fc_out, fld_oid_out, "LONG", None)    # insert cursor to store the results    flds_out = ('SHAPE@', fld_oid_out)    with arcpy.da.InsertCursor(fc_out, flds_out) as curs_out:        # loop over dbf file        flds = (fld_oid_in, fld_X, fld_Y, fld_width, fld_height)        with arcpy.da.SearchCursor(tbl, flds) as curs:            for row in curs:                oid = row                x = row                y = row                w = row                h = row                polygon = createRectangle(x, y, w, h, sr)                curs_out.insertRow((polygon, oid, ))def AddField(fc, fld_name, fld_type, fld_length):    if len(arcpy.ListFields(fc, fld_name)) == 0:        arcpy.AddField_management(fc, fld_name, fld_type, None, None, fld_length)def createRectangle(x, y, w, h, sr):    xmin = float(x) - float(w) / 2.0    xmax = float(x) + float(w) / 2.0    ymin = float(y) - float(h) / 2.0    ymax = float(y) + float(h) / 2.0    lst_pnts = []    lst_pnts.append(arcpy.Point(xmin, ymin))    lst_pnts.append(arcpy.Point(xmin, ymax))    lst_pnts.append(arcpy.Point(xmax, ymax))    lst_pnts.append(arcpy.Point(xmax, ymin))    lst_pnts.append(lst_pnts)    return arcpy.Polygon(arcpy.Array(lst_pnts), sr)if __name__ == '__main__':    main()‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍``

And the result for some random data:  