Each part is labelled at the labelpoint rather than the centroid, hence each part gets labelled.

---- An Alternate Geometry Reconstructor ----

---- Poly* to arrays revisited ----

These two scripts help blow poly features into their constituent parts. Initially a null point (np.nan, np.nan) is used to separate the poly features. The location of these insertions is retained and a fr_to index list is maintained so that the resultant 2D points array can be reconstructed or used in other calculations.

The outputs are: a_2d, ids, fr_to, id_fr_to which represent the 2D array, the id values of where one poly feature ends, a from-to list is constructed and a final list with the ids prepended is also included.

defpoly_pnts(in_fc, as_obj=False):"""Poly features to points while maintaining the location of the points in the input features. null points are replaced 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.

Returns ------- False, returns a 2D array of points and the location to split those points should you need to reconstruct the poly feature. A `nan` point separates the parts of the features within the poly feature, so split first. If `as_obj` is True, a list of arrays is returned.

A sample run

Line 1 reads the featureclass, produces the 2D point array and the various indices

In Line 2 and 3, I usually calculate the mean of the point cloud accounting for the null points separating the individual poly features.

A separate object array can be constructed if you have a need to work with the individual poly features at once, otherwise, you can recreate this using the a array and the fr_to indices as shown in line 4.

Line 5 reconstructs the original polygons so that they can be moved back into ArcGIS Pro ... more later

Normally you would 'do stuff' between line 4 and 5 and send back the resultant array, but this is just for illustration

Lines 16-23 are the from-to pairs of points needed to reconstruct the arrays to make polygons.

Line 24- just combines the two previous lists.

Reconstructing the arrays to poly features

The code below does this. A helper function, then the code block that uses a search cursor to reassemble the array to something that arcpy can use. Sadly you have to go from a numpy array, then create points, which are placed in an arcpy Array and from there the arcpy.Arrays are assembled to form polygon or polyline features. And Finally!!! A single-part featureclass is created, then a multipart featureclass, like the original data that went into the whole process.

Complicated? Not really, the real bottleneck is the cursors. You need them going in (regardless of the shroud placed around them) and going out. (ie __geo_interface__, _as_narray, FeatureClassToNumPyArray.

I should point out here that Numpyarraytofeatureclass works with simple geometry to get poly features back, but who works with simple features all the time.

Some Results

So just to compare the geometries, I will compare the areas calculated using arcpy and those calculated using the function below.

polys = fc_shapes(in_fc)

areas =[p.area for p in polys]

areas1 = poly_area(a, ids, fr_to)

areas # [100.0, 78.0, 155.0, 52.0, 36.0]

areas1 # array([100., 78., 155., 52., 36.])

Looks good. The helper function employs my favorite numpy function einsum, to implement the shoelace formula. A tad overkill for these teeny polygons, but it works blazingly fast for huge point arrays representing real world polygons.

I could calculate the area and length properties as I construct the arrays, like cursors do so that the property is readily available. I find if I wanted those properties I would calculate them, and I don't need them floating around unused.

poly_area is only one of my helper functions for calculating poly properties. These will be assembled at some stage and posted on GitHub and the Code Sharing site.

So why the whole exercise of converting the polygons to arrays in the first place.

Remember, the output is a 2D array of points. Shifting, rotating, scaling, thinning, anything-ing is done on the whole array at once, not one point at a time.

Also note, that the Polygon and Polyline classes have properties and methods like intersect, union etc. Simple functions entailing geometry are not shown/available directly from within those classes. How do you shift a polygon by a finite amount using arcpy? Your homework.