Last active
February 12, 2018 10:35
-
-
Save TimSC/2b22f9f41a4d86978501c7cc9b82b224 to your computer and use it in GitHub Desktop.
Test OSM bbox functionality
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import print_function | |
import sys | |
import requests | |
from requests.auth import HTTPBasicAuth | |
import xml.etree.ElementTree as ET | |
PY3 = sys.version_info > (3, 0) | |
if PY3: | |
raw_input = input | |
def GetChangesetBbox(cid): | |
response = requests.get(baseurl+"/0.6/changeset/"+str(cid)) | |
xml = ET.fromstring(response.text) | |
changesetEl = xml.find("changeset") | |
bbox = (changesetEl.attrib["min_lon"], changesetEl.attrib["min_lat"], | |
changesetEl.attrib["max_lon"], changesetEl.attrib["max_lat"]) | |
return list(map(float, bbox)) | |
def CreateChangeset(userpass, verbose=0): | |
#Create a changeset | |
createChangeset = "<?xml version='1.0' encoding='UTF-8'?>\n" +\ | |
"<osm version='0.6' generator='JOSM'>\n" +\ | |
" <changeset id='0' open='false'>\n" +\ | |
" <tag k='comment' v='python test function' />\n" +\ | |
" <tag k='created_by' v='JOSM/1.5 (3592 en_GB)' />\n" +\ | |
" </changeset>\n" +\ | |
"</osm>\n" | |
response = requests.put(baseurl+"/0.6/changeset/create",data=createChangeset,auth=userpass) | |
if verbose: print(response.text) | |
cid = int(response.text) | |
if response.status_code != 200: return (0,"Error creating changeset") | |
return (1, cid) | |
def CloseChangeset(userpass, cid, verbose=0): | |
#Close the changeset | |
url = baseurl+"/0.6/changeset/"+str(cid)+"/close" | |
response = requests.put(url,data="",auth=userpass) | |
if verbose: print(response.text) | |
if response.status_code != 200: return (0,"Error closing changeset") | |
def PtsToBbox(posLi, bboxIn = None): | |
if bboxIn is None: | |
bbox = [None, None, None, None] | |
else: | |
bbox = bboxIn[:] | |
for pos in posLi: | |
if bbox[0] is None or pos[1] < bbox[0]: | |
bbox[0] = pos[1] | |
if bbox[1] is None or pos[0] < bbox[1]: | |
bbox[1] = pos[0] | |
if bbox[2] is None or pos[1] > bbox[2]: | |
bbox[2] = pos[1] | |
if bbox[3] is None or pos[0] > bbox[3]: | |
bbox[3] = pos[0] | |
return bbox | |
def CompareBboxes(bbox1, bbox2): | |
errVal = None | |
for v1, v2 in zip(bbox1, bbox2): | |
ev = abs(v1 - v2) | |
if errVal is None or ev > errVal: | |
errVal = ev | |
return errVal | |
def ParseDiff(xml): | |
diff = ET.fromstring(xml) | |
out = {"node": {}, "way": {}, "relation": {}} | |
for ch in diff: | |
out[ch.tag][int(ch.attrib['old_id'])] = (int(ch.attrib['new_id']), int(ch.attrib['new_version'])) | |
return out | |
def TestCreateWayWithNodes(userpass, verbose=0): | |
ok, cid = CreateChangeset(userpass) | |
posLi = [(51.25022331526812, -0.6042092878597837), (51.2419166618214, -0.5910182209303836)] | |
#Create a way between two nodes | |
create = "<?xml version='1.0' encoding='UTF-8'?>\n" +\ | |
"<osmChange version='0.6' generator='JOSM'>\n" +\ | |
"<create version='0.6' generator='JOSM'>\n" +\ | |
" <node id='-289' changeset='{}' lat='{}' lon='{}' />\n".format(cid, posLi[0][0], posLi[0][1]) +\ | |
" <node id='-2008' changeset='{}' lat='{}' lon='{}' />\n".format(cid, posLi[1][0], posLi[1][1]) +\ | |
" <way id='-2010' changeset='"+str(cid)+"'>\n"+\ | |
" <nd ref='-289' />\n"+\ | |
" <nd ref='-2008' />\n"+\ | |
" </way>\n"+\ | |
"</create>\n" +\ | |
"</osmChange>\n" | |
response = requests.post(baseurl+"/0.6/changeset/"+str(cid)+"/upload",data=create,auth=userpass) | |
if verbose: print (response.text) | |
if response.status_code != 200: return (0,"Error creating node") | |
diffMapping = ParseDiff(response.text) | |
wayIdVer = diffMapping["way"][-2010] | |
chkBbox = GetChangesetBbox(cid) | |
expectedBbox = PtsToBbox(posLi) #All created nodes used to specify bbox | |
maxErr = CompareBboxes(chkBbox, expectedBbox) | |
if maxErr > 1e-6: | |
print ("Bbox don't match expected", chkBbox) | |
print ("Expected: ", expectedBbox) | |
CloseChangeset(userpass, cid, verbose) | |
chkBbox = GetChangesetBbox(cid) | |
maxErr = CompareBboxes(chkBbox, expectedBbox) | |
if maxErr > 1e-6: | |
print ("Bbox don't match expected", chkBbox) | |
print ("Expected: ", expectedBbox) | |
ok, cid = CreateChangeset(userpass) | |
#Modify way tags | |
modifyWay = '<osmChange version="0.6" generator="JOSM">'+"\n"+\ | |
"<modify>\n"+\ | |
" <way id='{}' version='{}' changeset='{}'>\n".format(wayIdVer[0], wayIdVer[1], cid)+\ | |
" <nd ref='{}' />\n".format(diffMapping['node'][-289][0])+\ | |
" <nd ref='{}' />\n".format(diffMapping['node'][-2008][0])+\ | |
" <tag k='comment' v='python test function' />\n" +\ | |
" </way>\n"+\ | |
"</modify>\n"+\ | |
"</osmChange>\n" | |
response = requests.post(baseurl+"/0.6/changeset/"+str(cid)+"/upload",data=modifyWay,auth=userpass) | |
if verbose: print (response.text) | |
if response.status_code != 200: return (0,"Error deleting node") | |
diffMapping2 = ParseDiff(response.text) | |
CloseChangeset(userpass, cid, verbose) | |
chkBbox = GetChangesetBbox(cid) | |
expectedBbox = PtsToBbox(posLi) #All nodes in modified way used to specify bbox | |
maxErr = CompareBboxes(chkBbox, expectedBbox) | |
if maxErr > 1e-6: | |
print ("Bbox don't match expected", chkBbox) | |
print ("Expected: ", expectedBbox) | |
ok, cid = CreateChangeset(userpass) | |
#Move node in way | |
nodeIdVer = diffMapping['node'][-289] | |
newPos = (51.253, -0.596) | |
modifyNode = '<osmChange version="0.6" generator="JOSM">'+"\n"+\ | |
"<modify>\n"+\ | |
" <node id='{}' version='{}' changeset='{}' lat='{}' lon='{}' />\n".format(nodeIdVer[0], nodeIdVer[1], cid, newPos[0], newPos[1])+\ | |
"</modify>\n"+\ | |
"</osmChange>\n" | |
response = requests.post(baseurl+"/0.6/changeset/"+str(cid)+"/upload",data=modifyNode,auth=userpass) | |
if verbose: print (response.text) | |
if response.status_code != 200: return (0,"Error moving node") | |
chkBbox = GetChangesetBbox(cid) | |
expectedBbox = PtsToBbox([posLi[0], newPos]) #Only the affect node (new and old position) is used to define bbox | |
maxErr = CompareBboxes(chkBbox, expectedBbox) | |
if maxErr > 1e-6: | |
print ("Bbox don't match expected", chkBbox) | |
print ("Expected: ", expectedBbox) | |
#Add node to way | |
newPos2 = (51.250, -0.606) | |
create = "<?xml version='1.0' encoding='UTF-8'?>\n" +\ | |
"<osmChange version='0.6' generator='JOSM'>\n" +\ | |
"<create version='0.6' generator='JOSM'>\n" +\ | |
" <node id='-559' changeset='{}' lat='{}' lon='{}' />\n".format(cid, newPos2[0], newPos2[1]) +\ | |
"</create>\n" +\ | |
"</osmChange>\n" | |
response = requests.post(baseurl+"/0.6/changeset/"+str(cid)+"/upload",data=create,auth=userpass) | |
if verbose: print (response.text) | |
if response.status_code != 200: return (0,"Error creating node") | |
diffMapping3 = ParseDiff(response.text) | |
newNodeIdVer = diffMapping3["node"][-559] | |
CloseChangeset(userpass, cid, verbose) | |
ok, cid = CreateChangeset(userpass) | |
modifyWay = '<osmChange version="0.6" generator="JOSM">'+"\n"+\ | |
"<modify>\n"+\ | |
" <way id='{}' version='{}' changeset='{}'>\n".format(wayIdVer[0], diffMapping2['way'][wayIdVer[0]][1], cid)+\ | |
" <nd ref='{}' />\n".format(diffMapping['node'][-289][0])+\ | |
" <nd ref='{}' />\n".format(diffMapping['node'][-2008][0])+\ | |
" <nd ref='{}' />\n".format(newNodeIdVer[0])+\ | |
" <tag k='comment' v='foobar' />\n" +\ | |
" </way>\n"+\ | |
"</modify>\n"+\ | |
"</osmChange>\n" | |
response = requests.post(baseurl+"/0.6/changeset/"+str(cid)+"/upload",data=modifyWay,auth=userpass) | |
if verbose: print (response.text) | |
if response.status_code != 200: return (0,"Error inserting node") | |
diffMapping4 = ParseDiff(response.text) | |
CloseChangeset(userpass, cid, verbose) | |
#chkBbox = GetChangesetBbox(cid) #This doesn't seem to match any sensible result | |
#expectedBbox = PtsToBbox([newPos2, posLi[1], newPos]) | |
#maxErr = CompareBboxes(chkBbox, expectedBbox) | |
#if maxErr > 1e-6: | |
# print ("While inserting node into way") | |
# print ("Bbox don't match expected", chkBbox) | |
# print ("Expected: ", expectedBbox) | |
#Delete a node | |
ok, cid = CreateChangeset(userpass) | |
modifyWay = '<osmChange version="0.6" generator="JOSM">'+"\n"+\ | |
"<modify>\n"+\ | |
" <way id='{}' version='{}' changeset='{}'>\n".format(wayIdVer[0], diffMapping4['way'][wayIdVer[0]][1], cid)+\ | |
" <nd ref='{}' />\n".format(diffMapping['node'][-289][0])+\ | |
" <nd ref='{}' />\n".format(newNodeIdVer[0])+\ | |
" <tag k='comment' v='parrot' />\n" +\ | |
" </way>\n"+\ | |
"</modify>\n"+\ | |
"</osmChange>\n" | |
response = requests.post(baseurl+"/0.6/changeset/"+str(cid)+"/upload",data=modifyWay,auth=userpass) | |
if verbose: print (response.text) | |
if response.status_code != 200: return (0,"Error removing node") | |
CloseChangeset(userpass, cid, verbose) | |
chkBbox = GetChangesetBbox(cid) | |
expectedBbox = PtsToBbox([newPos2, posLi[1], newPos]) #All nodes used, plus the deleted node, in way define the bbox | |
maxErr = CompareBboxes(chkBbox, expectedBbox) | |
if maxErr > 1e-6: | |
print ("While removing node into way") | |
print ("Bbox don't match expected", chkBbox) | |
print ("Expected: ", expectedBbox) | |
return (1,"OK") | |
def TestInsertNodeIntoWay(userpass, verbose=0): | |
ok, cid = CreateChangeset(userpass) | |
posLi = [(51.25022331526812, -0.6042092878597837), (51.2419166618214, -0.5910182209303836), (51.250, -0.606)] | |
#Create a way between two nodes | |
create = "<?xml version='1.0' encoding='UTF-8'?>\n" +\ | |
"<osmChange version='0.6' generator='JOSM'>\n" +\ | |
"<create version='0.6' generator='JOSM'>\n" +\ | |
" <node id='-289' changeset='{}' lat='{}' lon='{}' />\n".format(cid, posLi[0][0], posLi[0][1]) +\ | |
" <node id='-2008' changeset='{}' lat='{}' lon='{}' />\n".format(cid, posLi[1][0], posLi[1][1]) +\ | |
" <node id='-559' changeset='{}' lat='{}' lon='{}' />\n".format(cid, posLi[2][0], posLi[2][1]) +\ | |
" <way id='-2010' changeset='"+str(cid)+"'>\n"+\ | |
" <nd ref='-289' />\n"+\ | |
" <nd ref='-2008' />\n"+\ | |
" </way>\n"+\ | |
"</create>\n" +\ | |
"</osmChange>\n" | |
response = requests.post(baseurl+"/0.6/changeset/"+str(cid)+"/upload",data=create,auth=userpass) | |
if verbose: print (response.text) | |
if response.status_code != 200: return (0,"Error creating objects") | |
diffMapping = ParseDiff(response.text) | |
CloseChangeset(userpass, cid, verbose) | |
ok, cid = CreateChangeset(userpass) | |
modifyWay = '<osmChange version="0.6" generator="JOSM">'+"\n"+\ | |
"<modify>\n"+\ | |
" <way id='{}' version='{}' changeset='{}'>\n".format(diffMapping['way'][-2010][0], diffMapping['way'][-2010][1], cid)+\ | |
" <nd ref='{}' />\n".format(diffMapping['node'][-289][0])+\ | |
" <nd ref='{}' />\n".format(diffMapping['node'][-2008][0])+\ | |
" <nd ref='{}' />\n".format(diffMapping['node'][-559][0])+\ | |
" <tag k='comment' v='parrot' />\n" +\ | |
" </way>\n"+\ | |
"</modify>\n"+\ | |
"</osmChange>\n" | |
response = requests.post(baseurl+"/0.6/changeset/"+str(cid)+"/upload",data=modifyWay,auth=userpass) | |
if verbose: print (response.text) | |
if response.status_code != 200: return (0,"Error modifying way") | |
CloseChangeset(userpass, cid, verbose) | |
chkBbox = GetChangesetBbox(cid) #This doesn't seem to match any sensible result | |
expectedBbox = PtsToBbox(posLi) | |
maxErr = CompareBboxes(chkBbox, expectedBbox) | |
if maxErr > 1e-6: | |
print ("While inserting node into way") | |
print ("Bbox don't match expected", chkBbox) | |
print ("Expected: ", expectedBbox) | |
return (1,"OK") | |
baseurl = "https://master.apis.dev.openstreetmap.org/api" | |
username = raw_input("Username:") | |
password = raw_input("Password:") | |
userpass = username+":"+password | |
print (TestCreateWayWithNodes(HTTPBasicAuth(username, password),0)) | |
print (TestInsertNodeIntoWay(HTTPBasicAuth(username, password),0)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment