I am trying to update Z values of polygon features with point features. The code is (found on GIS) working good if no 'interor ring' or 'multipart' features are present in the polygon features. The polygon is large data set with several 'interor rings' or 'multiparts'. I have no idea how to solve it. I have understood that 'NoneType' AttributeError refers to 'multipart' or 'inner rings' issue.
My code is :
import os
import arcpy
arcpy.env.workspace = r"D:\acrpy\VV_test\scripts\map1"
point_fc = r"D:\acrpy\VV_test\scripts\map1\VRTX_ZM_KAD_test.shp"
polygon_fc = r"\acrpy\VV_test\scripts\map1\ZM_KAD__test.shp"
my_field = "SHAPE@"
my_field_pnt = "SHAPE@XYZ"
with arcpy.da.UpdateCursor(polygon_fc, my_field) as myUpdtCur:
for row in myUpdtCur:
geom = row[0]
arr_pol = arcpy.Array()
for part in geom:
arr_part = arcpy.Array()
pnt_count = 0
for pnt in part:
with arcpy.da.SearchCursor(point_fc, my_field_pnt) as mySrcCur:
for srcPnt in mySrcCur:
if int(pnt.X) == int(srcPnt[0][0]) and int(pnt.Y) == int(srcPnt[0][1]):
updZpnt=srcPnt[0][2]
del mySrcCur
pnt_count += 1
print pnt_count
myXYZPoint = arcpy.Point(pnt.X, pnt.Y, updZpnt)
arr_part.add(myXYZPoint)
arr_pol.add(arr_part)
polygon = arcpy.Polygon(arr_pol,None, True)
row[0] = polygon
myUpdtCur.updateRow(row)
del myUpdtCur
got the error:
76
77
78
79
80
81
82
Traceback (most recent call last):
File "D:\acrpy\VV_test\scripts_OK\GIS_stackexcahnge\test_update Z values from point vertices to polygon vertices .py", line 21, in
if int(pnt.X) == int(srcPnt[0][0]) and int(pnt.Y) == int(srcPnt[0][1]):
AttributeError: 'NoneType' object has no attribute 'X'
>>>
Answer
The Reading geometries documentation shows the proper processing procedure for sub-parts in polygons:
for row in arcpy.da.SearchCursor(infc, ["OID@", "SHAPE@"]):
# Print the current multipoint's ID
#
print("Feature {}:".format(row[0]))
partnum = 0
# Step through each part of the feature
#
for part in row[1]:
# Print the part number
#
print("Part {}:".format(partnum))
# Step through each vertex in the feature
#
for pnt in part:
if pnt:
# Print x,y coordinates of current point
#
print("{}, {}".format(pnt.X, pnt.Y))
else:
# If pnt is None, this represents an interior ring
#
print("Interior Ring:")
partnum += 1
Note the if pnt
test, with the comment
If pnt is None, this represents an interior ring
Some comments:
Your inner loop is so inefficient, I can't copy it in good conscience. This should be a simple matrix or sparse dictionary of arrays, populated once above the top of the code.
It should be a crime (misdemeanor data abuse) to not use the
spatial_reference
parameter in thearcpy.Polygon
constructor -- failure to do so will truncate your coordinates to the third decimal place.The
with
construct deletes variables, so yourdel
statements were no-op.
And the corrected code block:
desc = arcpy.Describe(polygon_fc)
sr = desc.spatialReference
with arcpy.da.UpdateCursor(polygon_fc, my_field) as myUpdtCur:
for row in myUpdtCur:
geom = row[0]
arr_pol = arcpy.Array()
for part in geom:
arr_part = arcpy.Array()
pnt_count = 0
for pnt in part:
if not pnt:
arr_part.add(None) # Close previous subpart
continue # <-- Skips hole markers
## assign updZpnt here
pnt_count += 1
print pnt_count
myXYZPoint = arcpy.Point(pnt.X, pnt.Y, updZpnt)
arr_part.add(myXYZPoint)
arr_pol.add(arr_part)
row[0] = arcpy.Polygon(arr_pol,sr, True)
myUpdtCur.updateRow(row)
No comments:
Post a Comment