---- Poly* Features to Points ----This one may seem a bit odd, so I will explain it abit.Returns - Line 13, gets the spatial reference for the featureclass
- A null point is created on line 16... none of this None stuff or a
Line 17, your familiar SearchCursor is used to pull the geometry object out for further work. (I use an enumerator since I use 'i' in a different incarnation of the script...more in a different blog) Line 21 pulls our arcpy Point coordinates unless 'None' is found. If it is, then it is replaced with my null_pnt. Line 24 records the number of points in the shape. This value is used later for poly* reconstruction and is returned is 'as_obj' is False. Line 26 produces a numpy array from the coordinates and null_pnts. Line 27 does a cumulative sum of the points in each shape. This is a key... 'c' allows us to split a 2D array of points into subgroups. A subgroup may contain a null_pnt which further allows one to split the points into parts whether they be interior rings and/or array parts. And the final lines. If 'as_obj' is True a list of arrays is returned. The arrays may be conventional 2D arrays, 3D arrays or object arrays. Not for you to worry though. If 'as_obj' is false, then a 2D list of points is returned as well as the 'c' array should you need to split it later.
Why the difference- With the 2D array of points, it is blooming easy to determine the parameters for the whole array dataset multiple times without having to repeat things. For example, means, std deviations.
- The 2D array allows you to do things that you can't do easily. Every tried to rotate polygons about an origin point? How about a tiny shift in the coordinates. A quick densification but you only have a Standard license? Think of something that you can't do easily with the plain arcpy geometry objects... they are easy in array format.
- With the object array option, you can pick and choose which geometry objects to operate on and you don't need to reconstruct them prior to sending them back to arcpy geometries.
==================================================================================== The Scriptdef poly_pnts(in_fc, as_obj=False):
"""Poly features to points while maintaining the location of the points in
the input features. null points are replaces with their numpy equivalent.
Parameters
----------
in_fc : text
Full path to the featureclass.
as_obj : boolean
True returns a list of arrays of the shapes. The array types may be
mixed. False, returns a 2D array of points and an array of indices.
"""
SR = getSR(in_fc)
out = []
c = []
null_pnt = (np.nan, np.nan)
with arcpy.da.SearchCursor(in_fc, 'SHAPE@', spatial_reference=SR) as cur:
for i, row in enumerate(cur):
sub = []
poly = row[0]
pnts = [[pt.X, pt.Y] if pt else null_pnt
for arr in poly for pt in arr]
sub.extend(pnts)
c.append(len(pnts))
out.extend(sub)
out = np.asarray(out)
c = np.cumsum(c)
if as_obj:
return np.split(out, c)[:-1]
return out, c
---- Results .... a, c = poly_pnts(in_fc, as_obj=False)
a.shape
a
array([[ 300010., 5000000.],
[ 300000., 5000000.],
[ 300000., 5000010.],
[ 300010., 5000010.],
[ 300010., 5000000.],
[ 300010., 5000020.],
[ 300010., 5000010.],
[ 300000., 5000010.],
[ 300000., 5000020.],
[ 300010., 5000020.],
[ nan, nan],
.... big snip
c
array([ 5, 21, 41, 50, 58], dtype=int32)
|