I am writing a script that can take a .txt file as input and as output has a shapefile containing polygons to be used in ArcMap. My input looks like this with points at each vertex of a polygon, and the opening and closing point at the same location:
0,1013757671.0,1,557286.0000000,6349610.0000000 ...
With the order being: FID, ID, POINT, X, Y this has slightly changed to FID, ID, X, Y, ID as integer starting at '1'
I am able to make a list containing this information as separate elements like below and with their respective type (like integer, float etc):
[[0, 1013757671.0, 1, 557286.0, 6349610.0, 1], ...
Then I create a new shapefile that is to contain the polygons with an existing spatial reference taken from another file:
sr = arcpy.Describe(r"C:\Users\B026349\Documents\data\export\Site_101231911.shp").spatialReference
arcpy.CreateFeatureclass_management(outPath, outFile, "POLYGON", "", "DISABLED", "DISABLED", sr)...
However, I am stuck with writing the polygons to this new shapefile, since one polygon needs to be created per ID (the second number in each row of the list of elements).
I tried the following code based on the documentation on writing geometries (link), but I get a shapefile in which all columns are filled with a 0 and there are no polygons:
cur = arcpy.da.InsertCursor(outFile, ["SHAPE@"])
array = arcpy.Array()
ID = 1013757671.0 #starting ID
for row in splitData: #list containing the data
if ID == 1013757671.0:
ID = row[1] #ID field, when this changes it should create a new polygon
if ID != row[1]:
cur.insertRow([arcpy.Polygon(array)])
array.removeAll()
array.add(arcpy.Point(row[3], row[4], ID=row[1]))
ID = row[1]
cur.insertRow([arcpy.Polygon(array)])
if cur:
del cur
How can I make it function?
Based on the comments I have made some changes to the code above but my results are the following:
I mapped the points and color coded them to indicate which should be connected to form a polygon, but as can be seen this doesn't happen very well.
I tried both methods posted as answers. The first changed my code to the following to match my data stream (which has slightly changed into: [[0, 1013757671.0, 557286.0, 6349610.0, 1] or respectively, FID, ID, X, Y and ID as a sequence of integers)
file = "C:\Users\B026349\Documents\scripts\Points.csv"
sr = arcpy.Describe(r"C:\Users\B026349\Documents\data\export\Site_101231911.shp").spatialReference #ETRS_1989_UTM_Zone_32N
arcpy.CreateFeatureclass_management(outPath, outFile, "POLYGON", "", "DISABLED", "DISABLED", sr)
ddict = defaultdict(list)
with open(file) as reader:
for fi,i,x,y,l in csv.reader(reader): #'l' are the ID's (i) reduced to a numerical sequence, for example: 1, 1, 1, 2, 2, 3, 3, 3
ddict[int(l)].append(arcpy.Point(X=float(x),Y=float(y)))
with arcpy.da.InsertCursor(outFile, "SHAPE@") as iCursor:
for key,verts in ddict.items():
iCursor.insertRow([arcpy.Polygon(arcpy.Array(verts))])
My results have improved, but there are still issues and they look like the following now:
With the second suggested method my code looks like this:
sr = arcpy.Describe(r"C:\Users\B026349\Documents\data\export\Site_101231911.shp").spatialReference #ETRS_1989_UTM_Zone_32N
arcpy.CreateFeatureclass_management(outPath, outFile, "POLYGON", "", "DISABLED", "DISABLED", sr)
id = splitData[0][4]
array = arcpy.Array()
with arcpy.da.InsertCursor(outFile, ['ID', 'SHAPE@']) as ic:
for k, row in enumerate(splitData):
if row[4] == id:
array.append(arcpy.Point(row[2], row[3]))
else:
poly = arcpy.Polygon(array)
ic.insertRow([id, poly])
array.removeAll()
id = row[4]
array.append(arcpy.Point(row[2], row[3]))
if k == len(splitData):
poly = arcpy.Polygon(array)
ic.insertRow([id, poly])
This code gives me this result:
I guess im getting closer but there is still something wrong.
I fixed the problem, the issue was that the coordinates were calculated without added precision behind the dot. Therefore, some coordinates where on the same location giving weird polygon results. The code block that uses a 'dictionary approach' with input as a csv gives the expected result. The other suggested method does not attach the last polygon and im not sure why.
My datastream:
[0, 557285.65, 6349611.13, 1] equal to FID (int), X(float), Y(float), POLYGON ID(int)