As before, the inputs----The polygons that I will be using are shown to the right.
- A square, 5 points, first and last duplicates
- A lake on an island in a lake...
- A multipart with a two different shaped donut holes
- The letter 'C'
- The letter 'V'
|---- 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.
A sample run
Normally you would 'do stuff' between line 4 and 5 and send back the resultant array, but this is just for illustration
Line 15 shows that poly features 1 and 2 have 2 parts.
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.
So just to compare the geometries, I will compare the areas calculated using arcpy and those calculated using the function below.
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.
The pesky attributes