Wednesday 2 January 2019

Using arcpy AsShape on GeoJSON file?


I'm new to working with GeoJSON and have been reviewing the ArcGIS page for AsShape, but the examples seem a little thin.


I'm currently pulling a WFS from a GeoServer instance in GeoJSON format. I am using pycurl to do this as the service is https and it's easier to do authentication with pycurl. I basically issue my url query and build a file (results.json).



I know how to easily build point feature classes from any text (including json) and build attributes using cursors, but the data I'm working with now has lines and polygons as well.


Could anyone give me some guidance, share a snippet, or something that basically shows me how to get into the .json file with AsShape, or uses AsShape successfully with the json.load command?



Answer



It is pretty simple actually, you just need to iterate through the features of the geojson structure once you have got it in a dictionary format (like from the json.load() function). I don't work with GeoServer WFS services, but I did find a json example online. The first shows just how to iterate through the json and get an arcpy.Geometry object back.


import arcpy
import os
arcpy.env.overwriteOutput = True

geojson = {
"type": "FeatureCollection",

"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [102.0, 0.5]
},
"properties": {
"Name": "aoi",
"Source": "google"
}

}, {
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[102.0, 0.0],
[103.0, 1.0],
[104.0, 0.0],
[105.0, 1.0]
]

},
"properties": {
"Name": "centerline",
"Source": "bing"

}
}, {
"type": "Feature",
"geometry": {
"type": "Polygon",

"coordinates": [
[
[100.0, 0.0],
[101.0, 0.0],
[101.0, 1.0],
[100.0, 1.0],
[100.0, 0.0]
]
]
},

"properties": {
"Name": "parking lot",
"Source": "esri"
}
}]
}

# print type from arcpy.Geometry objects
for ft in geojson['features']:
geom = arcpy.AsShape(ft['geometry'], False)

print geom.type

This example should print the following:


point
line
polygon

Taking a similar json structure for polygon features, you can easily convert it to a feature class by first creating a feature class, adding the necessary fields, then using an Insert Cursor to feed in the values.


import arcpy
import os

arcpy.env.overwriteOutput = True

geojson2 = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[

[300.0, 200.0],
[301.0, 200.0],
[301.0, 201.0],
[300.0, 201.0],
[300.0, 200.0]
]
]
},
"properties": {
"Name": "aoi",

"Source": "google"
}
}, {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[100.0, 0.0],
[101.0, 0.0],

[101.0, 1.0],
[100.0, 1.0],
[100.0, 0.0]
]
]
},
"properties": {
"Name": "centerline",
"Source": "bing"


}
}, {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[400.0, 300.0],
[401.0, 300.0],
[401.0, 301.0],

[400.0, 301.0],
[400.0, 300.0]
]
]
},
"properties": {
"Name": "parking lot",
"Source": "esri"
}
}]

}

# we are working with polygons, so make new polygon fc
fc = r'C:\TEMP\testing.gdb\geojson_test'
sr = arcpy.SpatialReference(26915) # utm 15N

path, name = os.path.split(fc)
arcpy.management.CreateFeatureclass(path, name, 'POLYGON', spatial_reference=sr)

# add fields as listed from the properties of each feature

fields = ['Name', 'Source']
for field in fields:
arcpy.management.AddField(fc, field, 'TEXT')

# insert rows
with arcpy.da.InsertCursor(fc, ['SHAPE@'] + fields) as irows:
for feature in geojson2['features']:
geom = arcpy.AsShape(feature['geometry'], False)
irows.insertRow([geom] + [feature['properties'][f] for f in fields])
print 'done'


I would also recommend having a look at the requests module instead of pycurl, you can get format back as raw json and do not have to worry about working with intermediate .json files. It also supports all kinds of authorization types and passing in arguments is very elegant.


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...