I'm kind of at my wits' end here.
My insert cursor is not letting me use a polygon object for input into my SHAPE@ for a polygon feature class.
The workflow is: get a layer from a source using OGR, then, for each feature in the layer, grab its geometry as JSON, feed that into an array, create an arcpy.Polygon object from it, and feed it into the SHAPE@ of my polygon feature class.
I have tried arcpy.AsShape() in the following ways:
Since they all failed, I'm trying to create a Polygon object directly and feed that in instead.
I'm doing this because ogr2ogr produces a broken feature class in the desired location.
from osgeo import ogr
import json
tbl =r"...\Default.gdb\work"
source = r"filepath"
spat_ref = arcpy.SpatialReference(102962)
in_ds = ogr.Open(source)
lay = in_ds.ExecuteSQL("select * from Townships")
with arcpy.da.InsertCursor(tbl, ["SHAPE@"]) as cursor:
for l in lay:
gJSON = json.loads(l.GetGeometryRef().ExportToJson())
coors = arcpy.Array()
for cor in gJSON["coordinates"][0][0]:
coors.append(arcpy.Point(cor[0], cor[1]))
coors = arcpy.Polygon(coors, spat_ref)
cursor.insertRow(tuple(coors))
Traceback (most recent call last):
File "<string>", line 15, in <module>
TypeError: cannot read geometry sequence. expected list of floats
Here's the thing.
I'm getting valid coordinates from the JSON. I can plot them manually and verify that they are what they're supposed to be.
I have done a similar workflow before, where I fed a geometry object into the SHAPE@ with no problem. I have even tried actually feeding Pro a Geometry object instead of a Polygon object, and it crashed instantly.
Here's the JSON exactly as given in line11 for the first polygon.
What is going on?
Thanks!
AsShape—ArcGIS Pro | Documentation
your coordinate system and the one expected for geojson differ,which should produce the error.
and the help examples seem to add to the confusion as to whether all types require one
The spatial reference of a geometry object created from GeoJSON will be WGS 1984.
But it returns a list of list of lists expecting multipart shapes for actual shape
# --- via shortcuts
pth = r"C:\arcpro_npg\data\json\poly_a.geojson"
with open(pth) as f:
data = json.load(f)
type_key = pth.split(".")[-1]
keys = list(data.keys())
if 'features' in keys:
shapes = data['features']
coord_key = ['rings', 'coordinates'][type_key == 'geojson']
coords = [s['geometry'][coord_key] for s in shapes] # 'rings'
type_key
'geojson'
# --- or as a func
def _json_geom_(pth):
"""Return polygon/polyline geometry from a geoJSON or JSON file.
Parameters
----------
pth : text
The file path to the json or geojson file. The file extension is key.
Notes
-----
No error checking is done to ensure that the file provided to the function
complies with the structure required. It is a convenience function.
"""
import json
json_type = pth.split(".")[-1]
with open(pth) as f:
data = json.load(f) # kys = data.keys()
if json_type == 'geojson':
a = [i['geometry']['coordinates'] for i in data['features']]
elif json_type == 'json':
as_type = 'rings' if "Polygon" in data['geometryType'] else 'paths'
a = [i['geometry'][as_type] for i in data['features']]
else:
print("json file must end in `geojson` or `json` file extension.")
return a
a = _json_geom_(pth)
clean = [i[0] for i in a] # -- clean it up before `arcpying` it
clean
[[[300022.82380000036, 5000018.7291],
[300023.75989999995, 5000021.7301],
[300019.0992999999, 5000023.1839000005],
[300018.1632000003, 5000020.1828000005],
[300022.82380000036, 5000018.7291]],
[[300021.27770000044, 5000018.5285],
[300021.3431000002, 5000017.9504],
[300022.17009999976, 5000018.044],
[300022.1047, 5000018.622099999],
[300021.27770000044, 5000018.5285]],
[[300022.42509999964, 5000018.3925],
[300022.1776999999, 5000017.876499999],
[300022.69710000046, 5000017.6274999995],
[300022.9445000002, 5000018.1435],
[300022.42509999964, 5000018.3925]],
[[300021.1076999996, 5000017.653000001],
[300021.2898000004, 5000017.0383],
[300021.87260000035, 5000017.210999999],
[300021.69049999956, 5000017.8257],
[300021.1076999996, 5000017.653000001]],
[[300022.18709999975, 5000017.619000001],
[300022.40770000033, 5000016.850199999],
[300023.48759999964, 5000017.16],
[300023.26690000016, 5000017.9289],
[300022.18709999975, 5000017.619000001]],
[[300012.00459999964, 5000015.468699999],
[300011.9464999996, 5000015.1555],
[300013.37310000043, 5000014.890699999],
[300013.43120000046, 5000015.2038],
[300012.00459999964, 5000015.468699999]]]
image created outside of the arcpy environment, but you have some numbers that you can test. A geojson is in the zip
Well, that does explain the AsShape issue, but the Polygon and Geometry objects' problems remain a mystery.
I got around this by still using ogr2ogr after all.
I had been copying everything to a geopackage (long story), then doing stuff to it.
I was able to copy everything to a file gdb instead, and the problem geometry came along with no issues.
Unfortunately, not everything made it to the file gdb, so what I really ended up doing was copying everything to a geopackage AND the file gdb, then copying everything from the geopackage to the file gdb and skipping anything that failed.
Gross, probably pretty inefficient, and ultimately one step forward and one step back, but it does work now.
Have you tried re-building the geometry with the spatial reference after getting the WGS84 AsShape result?
from osgeo import ogr
import json
tbl =r"...\Default.gdb\work"
source = r"filepath"
spat_ref = arcpy.SpatialReference(102962)
in_ds = ogr.Open(source)
lay = in_ds.ExecuteSQL("select * from Townships")
# Do the risky processing outside the cursor so
# if something goes wrong, you wont have a partial insert
to_insert = []
for l in lay:
# Load Geojson
gJSON = json.loads(l.GetGeometryRef().ExportToJson())
# Get as ESRI shape
shape = arcpy.AsShape(gJSON)
# Re-build shape with correct spatial reference
proj_shape = arcpy.Polygon(arcpy.Array(part for part in shape), spat_ref)
# Add shape to insert list
to_insert.append(proj_shape)
with arcpy.da.InsertCursor(tbl, ["SHAPE@"]) as cursor:
for proj_shape in to_insert:
cursor.insertRow([proj_shape])
When I test this with your sample geojson, I get this:
So it seems to be properly re-building the shape.
It is "Esri JSON," no 'geo' prefix, and "GeoJSON," no 'Esri' or 'general' qualifier.
I took the GeoJSON shared in the question and tested it at GeoJSON Viewer & Validator, it fails with:
Line 1: Polygons and MultiPolygons should follow the right-hand rule