From 77347d2c7564999e44ad8d83bd30c3e69147990a Mon Sep 17 00:00:00 2001 From: Jeff Kruys <146253146+jkruys-bcgov@users.noreply.github.com> Date: Wed, 4 Sep 2024 16:24:47 -0700 Subject: [PATCH] Pull request to add Add_Geomark_URLs to gis-pantry/tools (#178) * Uploaded files Uploaded code files and toolbox files for Add Geomark URLs tools * Uploaded readme template Uploaded readme template to be edited in github web interface * Delete tools/Add_Geomark_URLs/readme.md * Create readme.md * Update readme.md Updated readme.md with text * Update readme.md --- .../Add_Geomark_URLs_ArcGISDesktop.tbx | Bin 0 -> 8192 bytes .../ArcGISDesktop/add_geomark_py2.py | 100 ++++++++++++++++++ .../ArcGISPro/Add_Geomark_URLs_ArcGISPro.atbx | Bin 0 -> 2541 bytes .../ArcGISPro/add_geomark_py3.py | 83 +++++++++++++++ tools/Add_Geomark_URLs/readme.md | 53 ++++++++++ 5 files changed, 236 insertions(+) create mode 100644 tools/Add_Geomark_URLs/ArcGISDesktop/Add_Geomark_URLs_ArcGISDesktop.tbx create mode 100644 tools/Add_Geomark_URLs/ArcGISDesktop/add_geomark_py2.py create mode 100644 tools/Add_Geomark_URLs/ArcGISPro/Add_Geomark_URLs_ArcGISPro.atbx create mode 100644 tools/Add_Geomark_URLs/ArcGISPro/add_geomark_py3.py create mode 100644 tools/Add_Geomark_URLs/readme.md diff --git a/tools/Add_Geomark_URLs/ArcGISDesktop/Add_Geomark_URLs_ArcGISDesktop.tbx b/tools/Add_Geomark_URLs/ArcGISDesktop/Add_Geomark_URLs_ArcGISDesktop.tbx new file mode 100644 index 0000000000000000000000000000000000000000..9e14d110a3c5446e04f36986edf2f25e39ecbcd4 GIT binary patch literal 8192 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 aj2nI&_O*^b?riJjnNPc8HwgTYHT)O)xdveX literal 0 HcmV?d00001 diff --git a/tools/Add_Geomark_URLs/ArcGISDesktop/add_geomark_py2.py b/tools/Add_Geomark_URLs/ArcGISDesktop/add_geomark_py2.py new file mode 100644 index 0000000..e7a95bd --- /dev/null +++ b/tools/Add_Geomark_URLs/ArcGISDesktop/add_geomark_py2.py @@ -0,0 +1,100 @@ +r""" + +Original Author: jeff.kruys@gov.bc.ca (FIRB) + +Created on: +2024-08-13 + +Purpose: +This script creates Geomark URLs for each feature in an input dataset, and +writes them to a new field named Geomark_URL. It can be run at the command +prompt on a system with ArcGIS Pro installed, or directly in ArcGIS Desktop +10.x in a script tool named Add_Geomark_URL in a toolbox named +Add_Geomark_URL.tbx. + +Usage: +add_geomark_py2.py lyr + +Positional Arguments: + lyr Input layer + +Requirements: +ArcGIS Pro + +Optional Arguments: + -h, --help show this help message and exit + -l, --level log level messages to display; Default: 20 - INFO + -ld, --log_dir path to directory for output log file + +Example Input: +X:\fullpath\add_geomark_py2.py Y:\fullpath\lyr + +History +2024-08-13 (JK): Created script. +""" + +import arcpy, urllib2, time, sys +from urllib import urlencode + +def add_geomark_url(in_fc): + + # Get the spatial reference of the input dataset + srid = arcpy.Describe(in_fc).spatialReference.factoryCode + arcpy.AddMessage(time.strftime("%Y-%m-%d %H:%M:%S : ") + "Spatial reference code of input dataset: " + str(srid)) + + # Add Geomark_URL field if it doesn't already exist + flist = [f.name for f in arcpy.ListFields(in_fc)] + if "Geomark_URL" not in flist: + try: + arcpy.AddField_management(in_table=in_fc, field_name="Geomark_URL", field_type="TEXT", field_length=100) + except: + arcpy.AddError(time.strftime("%Y-%m-%d %H:%M:%S : ") + "Unable to add field to input dataset. Exiting.") + sys.exit() + arcpy.AddMessage(time.strftime("%Y-%m-%d %H:%M:%S : ") + "Added Geomark_URL field to input layer") + else: + arcpy.AddMessage(time.strftime("%Y-%m-%d %H:%M:%S : ") + "Geomark_URL field already exists in input layer") + + # Read each record, send request to create Geomark URL, write the returned URL to the Geomark_URL field + row_total = int(arcpy.GetCount_management(in_fc).getOutput(0)) + read_count = 0 + update_count = 0 + arcpy.AddMessage(time.strftime("%Y-%m-%d %H:%M:%S : ") + "Processing " + str(row_total) + " feature(s) of input " + "dataset") + with arcpy.da.UpdateCursor(in_fc, ["Geomark_URL", "SHAPE@"]) as cursor: + for row in cursor: + read_count += 1 + exist_url = row[0] + if exist_url is None: + geom = row[1] + if geom is None: + row[0] = "Null geometry" + else: + geom_wkt = geom.WKT + post_url = "https://apps.gov.bc.ca/pub/geomark/geomarks/new" + payload = {"bufferSegments": 8, "body": geom_wkt, "bufferMetres": 0, "callback": None, + "failureRedirectUrl": None, "bufferJoin": "ROUND", "bufferMitreLimit": 5, + "bufferCap": "ROUND", "redirectUrl": None, "resultFormat": None, "format": "wkt", + "srid": srid, "allowOverlap": "false"} + post = urlencode(payload) + req = urllib2.Request(post_url, post) + response = urllib2.urlopen(req) + if response.code == 200: + r = response.read() + out_url = r.split('"url":"')[1].split('"')[0] + if out_url == "https://apps.gov.bc.ca/pub/geomark/geomarks/new": + row[0] = "Could not create Geomark URL for this geometry" + else: + row[0] = out_url + update_count += 1 + else: + row[0] = "Error response code " + str(response.code) + cursor.updateRow(row) + + if read_count % 10 == 0 or read_count == row_total: + arcpy.AddMessage(time.strftime("%Y-%m-%d %H:%M:%S : ") + "Processed " + str(read_count) + " of " + + str(row_total) + " feature(s) and added Geomark URL to " + str(update_count) + + " feature(s)") + +if __name__ == "__main__": + in_fc = arcpy.GetParameterAsText(0) + add_geomark_url(in_fc) diff --git a/tools/Add_Geomark_URLs/ArcGISPro/Add_Geomark_URLs_ArcGISPro.atbx b/tools/Add_Geomark_URLs/ArcGISPro/Add_Geomark_URLs_ArcGISPro.atbx new file mode 100644 index 0000000000000000000000000000000000000000..c4161ef5c99bf322b4c8adb0374780d9e9a1c99a GIT binary patch literal 2541 zcmai0dpy&7AOBg+wOA?^$#o88tCP_o*R+EPGv&ApV=h^2#vF{tt(05rAPylaX+o?< zq{pRHLq&&`~7);KHtyp^ZQ_|Hf`Pkd|tjb zGmc+2UvJw5Pg5^1b8m8hN6@Jg*kcGPne4wG^A#Za1@KGUC5^jcgh<`*Ut(qY==UKQlVS-HNO|?fzo9tXVKeX z%v#J`bWZLLUJA^rqhy&H26q}{t&eKP9q6HblG*zlB$y-i6eQV=pvpX zKb%C9$Q)Yac;NvV`h>Oy-9BL3RpAO#Ua2}H?~a)q&;z<$d!ZoT#}TyaO(8`x{wU03 zUb+Pv_^Y8&GAC1MLQY+@y1S7*Z%S%SKeg>dcjnI6&c-JAZV$0wOKoWH^60;$5oJOQ z1xhhyOQR#?xu*@0!wG;0ox9FTORk9Jo(IZluQ9*`M7be6(}wu$zOp zJYVf&W~3&uc(2W^{f7@k&KQUokc(9bviWb!W(Ss{KyB?OBe$C?-}Q3ZWz`tq1{cQ9 zxtve!2Q0FnD3An~S60rm%-{yQ;EL;r!fWcw?2S%ZL5 zYqmE$ZL^;nbS|+OX`z6`Yo{pH zii^3fJB3djFXET;dM=P|ycVU;BL=z#AJS5ANY@TeQW-SH44wrZHa&Fj)@ywc$VZRI zwB+M1=bMKjh|x7*buQDV;5X$8B`|~01C5BI`V*~t^{WG-9@t-<&n?ZR-H#f9lkKu1 zf-F3s6+Cocvw3y{1}WP;%FXMtzvHeP<(QgKFhzc8D{nbbn{t-=5;xp7UfKgWgJ|G^ zdxRD!0r^$un>O7E&#av0zvT|U-}eVgs^4_a$sYFbR9kLs+Vn_?`9Em|&76lWkHv;Y z4V<+bcImS27%;gQ3lYWhGisCk4{p7DMH0W}AgC#0Iso0jrQwM9G@<-B-h?SpjjDH2 zPqXuycTtR3)%mov^3tZRwM@%L`*JHxM5MkHSMLm$ETsi?NXCqn9PaqZ_b!+pf3SaH zAwrjt40;Q*xt~c8tKSV=gjV6%;)M-jUW#-rn#ydpP-Wge9nRugo=-{LQx9-y?v} z$H=-3us=4*t!Q{!Li0D_ahlr3tEmn;5b=uL%yR?m&67+~g5ul3gQKT03_tlwpV5oC z&t<1bLxxO1{_ybeyINb?k?~hJfuSE43A_{V7S;*d=WI{wkK3I-AY-0j^>tb9R$Je4 z`-}YO?kSflSgSW{;rZoGtCsbh*K73Cjjd&q<(sQ=7RqvJf=fr5ZQNg@O5N#4&-|TCWPZJ< zC83w;4a?SV>l+mf_F_>Alw1SbtkiC+hQ^0R(RJr36Q%Mi5)$8b-5q`PnhZg=wGaXT z#sAZF31kx0n?wzvTT8^5K+ev7O7fWeo!KYNidKq~G#wxWE>ymGRGAu^uxg02pYI45 z4Uxh?B@{~E;P^~wG-E-}U z9$wS8FWt1-=W0&-aV=X)sgfZvq#FxoajX2#oHZJab=^nYMS2x)cjFz|Tz0vIYa6xT zdWt?5@xJ=?xMKDaGH3*v<)3u+WP*{=w_!S1Vy5tc!ZtzDKY|v20_)wL`VI$<@ z5=XJJYgsq4Bmm%BEhRw-+ED@x9RiaQ*yq2RCpir9HN{^Y@3n&OecJxao{7aA?9#?O zk4;b?_fnTR{a_i}X2zcnPUr8#V>NSHzyd+xiM0$R@Lm+#;ft;Vi|NbDdBa`O^ciBM zsAJbP4daFflBg|3&TO=@915y6_IvtpLGGoCj+qK_qgT$TC`wGcjB{e)Sh)3C&l_&u zju2?n6`1t*S~twoe{&PX7!y}sT-38%+=<3dI#)Ogm@rmCAOQI5F+t$tf7XUW!+!`i z9vjxsKMJ-R5Ntd|tm*nU?fUOxjkZKEqx==^*CSj{w!Zq-$Wn#>mQ0Z2^?d6qXpK)! i%91HLO literal 0 HcmV?d00001 diff --git a/tools/Add_Geomark_URLs/ArcGISPro/add_geomark_py3.py b/tools/Add_Geomark_URLs/ArcGISPro/add_geomark_py3.py new file mode 100644 index 0000000..d726b4f --- /dev/null +++ b/tools/Add_Geomark_URLs/ArcGISPro/add_geomark_py3.py @@ -0,0 +1,83 @@ +r""" + +Original Author: jeff.kruys@gov.bc.ca (FIRB) + +Created on: +2024-08-12 + +Purpose: +This script creates Geomark URLs for each feature in an input dataset, and +writes them to a new field named Geomark_URL. It can be run at the command +prompt on a system with ArcGIS Pro installed, or directly in ArcGIS Pro in a +script tool named Add_Geomark_URL in a toolbox named Add_Geomark_URL.atbx. + +Usage: +add_geomark_py3.py lyr + +Positional Arguments: + lyr Input layer + +Requirements: +ArcGIS Pro + +Example Input: +X:\fullpath\add_geomark_py3.py Y:\fullpath\lyr + +History +2024-08-12 (JK): Created script. +""" + +import arcpy, requests, time + +def add_geomark_url(in_fc): + + # Get the spatial reference of the input dataset + srid = arcpy.da.Describe(in_fc)["spatialReference"].factoryCode + arcpy.AddMessage(time.strftime('%Y-%m-%d %H:%M:%S : ') + f"Spatial reference code of input dataset: {srid}") + + # Add Geomark_URL field if it doesn't already exist + flist = [f.name for f in arcpy.ListFields(in_fc)] + if "Geomark_URL" not in flist: + arcpy.management.AddField(in_table=in_fc, field_name="Geomark_URL", field_type="TEXT", field_length=100) + arcpy.AddMessage(time.strftime('%Y-%m-%d %H:%M:%S : ') + "Added Geomark_URL field to input layer") + else: + arcpy.AddMessage(time.strftime('%Y-%m-%d %H:%M:%S : ') + "Geomark_URL field already exists in input layer") + + # Read each record, send request to create Geomark URL, write the returned URL to the Geomark_URL field + row_total = int(arcpy.GetCount_management(in_fc).getOutput(0)) + read_count = 0 + update_count = 0 + arcpy.AddMessage(time.strftime('%Y-%m-%d %H:%M:%S : ') + f"Processing {row_total} feature(s) of input dataset") + session = requests.Session() + with arcpy.da.UpdateCursor(in_fc, ["Geomark_URL", "SHAPE@"]) as cursor: + for row in cursor: + read_count += 1 + exist_url = row[0] + if exist_url is None: + geom = row[1] + if geom is None: + row[0] = "Null geometry" + else: + geom_wkt = geom.WKT + post_url = "https://apps.gov.bc.ca/pub/geomark/geomarks/new" + payload = {"bufferSegments": 8, "body": geom_wkt, "bufferMetres": None, "callback": None, + "failureRedirectUrl": None, "bufferJoin": "ROUND", "bufferMitreLimit": 5, + "bufferCap": "ROUND", "redirectUrl": None, "resultFormat": None, "format": "wkt", + "srid": srid, "allowOverlap": "false"} + r = session.post(post_url, data=payload, timeout=5) + if r.status_code == 200: + out_url = r.url + if out_url == "https://apps.gov.bc.ca/pub/geomark/geomarks/new": + row[0] = "Could not create Geomark URL for this geometry" + else: + row[0] = out_url + update_count += 1 + cursor.updateRow(row) + + if read_count % 10 == 0 or read_count == row_total: + arcpy.AddMessage(time.strftime('%Y-%m-%d %H:%M:%S : ') + f"Processed {read_count} of {row_total} " + f"feature(s) and added Geomark URL to {update_count} feature(s)") + +if __name__ == "__main__": + in_fc = arcpy.GetParameterAsText(0) + add_geomark_url(in_fc) diff --git a/tools/Add_Geomark_URLs/readme.md b/tools/Add_Geomark_URLs/readme.md new file mode 100644 index 0000000..287728f --- /dev/null +++ b/tools/Add_Geomark_URLs/readme.md @@ -0,0 +1,53 @@ +# Name + +Add_Geomark_URLs + +# Author + +Jeff Kruys, jeff.kruys@gov.bc.ca, Spatial Data Analyst, Forest Investment and Reporting Branch, Ministry of Forests + +# Description + +The Geomark Web Service takes a feature geometry as input and assigns it a unique URL. This URL can then be sent to another party as a representation of the geometry. + +This script tool will add a field named Geomark_URL to a spatial dataset that you select (FGDB feature class, shapefile etc.) and populate the field with a Geomark URL for each feature. There is one tool designed to work in ArcGIS Desktop 10.x (ArcCatalog or ArcMap), and another tool designed to work within ArcGIS Pro 3.x. + +# Usage + +To use the tool in ArcGIS Desktop, download the two files in the ArcGISDesktop folder above, and save them together in a folder on your local drive or a network drive that you have write access to. In ArcMap, open the Catalog pane (in the Windows menu and select Catalog), browse to the folder where you saved the files, and expand the toolbox item named Add_Geomark_URLs_ArcGISDesktop.tbx. You should see a script tool named Add Geomark URL. Double-click this tool to run it. You will be prompted to select a map layer; select one and click OK to run. + +To use the tool in ArcGIS Pro, download the file Add_Geomark_URLs_ArcGISPro.atbx in the ArcGISPro folder above, and save it in a folder on your local drive or a network drive that you have write access to. (This file has the Python code embedded in it, so you do not need to download the other file, add_geomark_py3.py - it is only provided for reference.) In an ArcGIS Pro project, in the Catalog pane under the Project tab, connect to the folder where you saved the file, then browse to that folder and expand the file. You should see a script tool named Add_Geomark_URLs. Double-click that tool to start it. You will be prompted to select a map layer; select one and click OK to run. + +After running, if no error messages are received, open the attribute table of the layer you specified (or if you already had it open, close it and open it again). You should see a newly-added field named Geomark_URL and it should contain a URL for each feature. + +If a feature has null geometry, the field will contain the text "Null geometry" instead of a URL. If any other problem occurred, you may see the text "Could not create Geomark URL for this geometry"; if you see this in the output, please contact the author. + +# Dependencies/Requirements/Environments + +These scripts have been tested in the GTS desktop environments named "Kamloops Desktop - Geospatial" (with ArcGIS Pro 3.2.2) and "Kamloops Desktop - ArcGIS 10-8" (with ArcGIS Desktop 10.8). + +Executing the tool in the ArcGIS Pro environment requires the Python "requests" module, which should have been installed by default with any installation of ArcGIS Pro and Python 3.x. + +Executing the tool in the ArcGIS Desktop environment requires the Python "urllib" and "urllib2" modules, which should have been installed by default with any installation of ArcGIS Desktop 10.8 and Python 2.x. + +If you receive an error such as "ImportError: No module named urllib" when running either of these tools, please contact the author. + +# Known Bugs/Limitations + +This tool is intended to make it easier to generate Geomark URLs more quickly than uploading individual spatial data files for individual features to the Geomark Web Service. + +The ArcGIS Desktop version of the tool runs quickly, creating 10 Geomark URLs in a few seconds. The ArcGIS Pro version of the tool takes a little longer to run - 10 URLs in about 30 seconds. + +Both tools are only intended to be used on datasets with small numbers of records - in the hundreds at most. + +# Credits + +Thanks to the developers of the Geomark Web Service. + +# Update Log + +2024-08-20 (Jeff Kruys): Tools uploaded to GitHub. + +2024-08-13 (Jeff Kruys): Tool completed and tested in ArcGIS Desktop 10.8. + +2024-08-12 (Jeff Kruys): Tool completed and tested in ArcGIS Pro 3.2.2.