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
Solved! Go to Solution.
Yes, Blake Terhune was completely right! Those were errors indeed. Find below the corrected (and tested) code:
import arcpy
def 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[0]
x = row[1]
y = row[2]
w = row[3]
h = row[4]
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[0])
return arcpy.Polygon(arcpy.Array(lst_pnts), sr)
if __name__ == '__main__':
main()
And the result for some random data:
Question branched from this thread: https://community.esri.com/thread/84853 by xander_bakker
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 arcpy
def 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[0]
x = row[1]
y = row[2]
w = row[3]
h = row[4]
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[0])
return arcpy.Polygon(arcpy.Array(lst_pnts), sr)
if __name__ == '__main__':
main()
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...
Can you update your original code as well (maybe you did and I am missing the obvious)?
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
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..
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?
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.
Yes, Blake Terhune was completely right! Those were errors indeed. Find below the corrected (and tested) code:
import arcpy
def 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[0]
x = row[1]
y = row[2]
w = row[3]
h = row[4]
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[0])
return arcpy.Polygon(arcpy.Array(lst_pnts), sr)
if __name__ == '__main__':
main()
And the result for some random data: