Skip to content

Commit fb69dc6

Browse files
committed
Initial Commit
1 parent cd951f5 commit fb69dc6

File tree

3 files changed

+130
-1
lines changed

3 files changed

+130
-1
lines changed

Plus Code.tbx

14 KB
Binary file not shown.

README.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,32 @@
1-
# arcgis-plus-code-generator
1+
# arcgis-plus-code-generator
2+
3+
4+
# Description
5+
6+
This tool exposes the open location code API create by google and uses it to generate Plus Codes on ArcGIS feature classes. The API documentation is there: https://github.com/google/open-location-code
7+
8+
Detailed information about Plus Codes and the KML Service that Google Provides can be found there: https://grid.plus.codes/
9+
10+
This tool is a side effect of a project I have done for work. I have explored different solutions with FME and QGIS, but this was by far the fastest solution. It can generate plus code on points, and polygon feature classes.
11+
12+
# System Requirements
13+
14+
This tool is developed and tested for ArcGIS Pro. I have tested for ArcGIS Pro 2.7.
15+
16+
Your python environment must be of 3.x (tested with 3.7, but I assume it work with 3.6 too).
17+
18+
The open location code library for Python must be installed in your python environment. In short
19+
`pip install openlocationcode`. For detailed instructions: https://github.com/google/open-location-code/tree/master/python
20+
21+
# How to use
22+
23+
Use the tool box in ArcGIS Pro. There is built in help in the tool metadata, and the tool is configured to guide you and minimize input errors.
24+
25+
# How to contribute
26+
27+
This tool has been done in rush. Though is works, it does not match my standards or the industry standards in terms of unit testing or documentation.
28+
If you want to help, or have any suggestion, log an issue, and a pull request if you feel bold enough.
29+
30+
31+
32+
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import arcpy
2+
from openlocationcode import openlocationcode as olc
3+
4+
# https://github.com/google/open-location-code/blob/master/python/openlocationcode_test.py
5+
6+
7+
def check_spatial_reference(feature_class):
8+
sr = arcpy.Describe(feature_class).spatialReference
9+
if sr.factoryCode != 4326:
10+
raise ValueError('The input feature class must be in WHS84 (WKID 4326)')
11+
12+
13+
def validate_plus_code_length(code):
14+
15+
# Those are the number of digit required from the specifications.
16+
valid_codes_length = [
17+
2, # Level 0
18+
4, # Level 1
19+
6, # Level 2
20+
8, # Level 3
21+
10, # Level 4
22+
11, # Level 5
23+
12 # Level 6
24+
]
25+
26+
if code not in valid_codes_length:
27+
raise ValueError('Valid Plus Code must be one of the following value: {}'.format(
28+
', '.join([str(code) for code in valid_codes_length])
29+
))
30+
31+
32+
def validate_code_field_length(feature_class, plus_code_field, code_length):
33+
fields = [field for field in arcpy.ListFields(feature_class) if field.name.lower() == plus_code_field.lower()]
34+
if fields is None or len(fields) == 0:
35+
raise Exception('The field {} does not exist'.format(plus_code_field))
36+
37+
field = fields[0]
38+
if field.type != 'String':
39+
raise Exception('The field for plus code must be of type String')
40+
if field.length < (code_length + 1):
41+
raise Exception('The field {} is not long enough. Field Length: {} - Plus Code Length: {} - Plus Code Length Required: {}'.format(
42+
field.name,
43+
field.length,
44+
code_length,
45+
code_length + 1
46+
))
47+
48+
49+
def generate_plus_code(feature_class, plus_code_field, code_length):
50+
"""
51+
Generate the plus code based on a input feature class. The centroid of the geometry is used.
52+
53+
:param feature_class: The input feature class. The EPSG must be 4326
54+
:param plus_code_field: The field that will contain the plus codes.
55+
:param code_length: The maximum length for the plus code.
56+
:return:
57+
"""
58+
59+
# Make sure that the input feature class is in the appropriate format.
60+
check_spatial_reference(feature_class)
61+
62+
# Validate that the plus code is a valid value
63+
validate_plus_code_length(code_length)
64+
65+
# Validate the field is long enough to accomodate the code.
66+
validate_code_field_length(feature_class, plus_code_field, code_length)
67+
68+
count = 0
69+
with arcpy.da.UpdateCursor(feature_class, ['SHAPE@XY', plus_code_field, 'OID@']) as input_cursor:
70+
for input_row in input_cursor:
71+
72+
oid = input_row[-1]
73+
count += 1
74+
75+
if count % 100000 == 0:
76+
arcpy.AddMessage('Processed {} rows so far ...'.format(count))
77+
78+
try:
79+
longitude = input_row[0][0]
80+
latitude = input_row[0][1]
81+
plus_code = olc.encode(latitude, longitude, code_length)
82+
input_row[1] = plus_code
83+
input_cursor.updateRow(input_row)
84+
except Exception as ex:
85+
arcpy.AddWarning(
86+
'Something went wrong with feature OID: {} - Error Message: {}'.format(oid, ex.message)
87+
)
88+
89+
90+
if __name__ == '__main__':
91+
input_feature_class = arcpy.GetParameterAsText(0)
92+
output_plus_code_field = arcpy.GetParameterAsText(1)
93+
output_code_length = int(arcpy.GetParameterAsText(2))
94+
try:
95+
generate_plus_code(input_feature_class, output_plus_code_field, output_code_length)
96+
except Exception as ex:
97+
arcpy.AddError(ex)
98+

0 commit comments

Comments
 (0)