Last active
June 7, 2017 08:45
-
-
Save LtGlahn/ee15d47a3e0eb8fcb8cd6998aaa1cd9a to your computer and use it in GitHub Desktop.
Check alignment of NVDB road network and metering system (vegreferanse)
This file contains 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
# -*- coding: utf-8 -*- | |
""" | |
Check alignment of NVDB road network and metering system (vegreferanse) | |
in a particular point at the road network, specified as road | |
link ID and (non-dimmensional) linear reference position. | |
Usage: | |
(roadDir, meterDir) = nvdbdirection( 971429, 0.2) # Input: NVDB Road linkID | |
# and position | |
The return value is a tuple with two values: | |
- The road network alignment at that point | |
- Metreringsretning (aligment of metering system), which is either | |
identical to _*or oposite of*_ the road network alignment | |
If you are working with NVDB data (objects) that are located at POINTS in the | |
road network, you can specify the unique ID of that particular NVDB object to | |
the function nvdbdirection4nvdbobj, and we'll find the road net position of | |
that object, which are then given as input values to nvdbdirection. | |
Usage: | |
(roadDir, meterDir) = nvdbdirection4nvdbobj(80825257) # Input:NVDB objectId | |
Technical details: | |
We use the REST api visveginfo | |
http://visveginfo-static.opentns.org/help.htm | |
First, we get all data for the road link position using the | |
GetRoadReferenceForNVDBReference - functionality. | |
http://visveginfo-static.opentns.org/RoadInfoService/GetRoadReferenceForNVDBReference?reflinkoid=248917&rellen=0.5 | |
The result is an XML that looks like this: | |
<RoadReference | |
xmlns="http://schemas.datacontract.org/2004/07/RoadInfoServiceContracts" | |
xmlns:i="http://www.w3.org/2001/XMLSchema-instance" | |
i:type="RoadPointReference"> | |
<County>15</County> | |
<Municipality>0</Municipality> | |
<ReflinkOID>248917</ReflinkOID> | |
<RoadCategory>E</RoadCategory> | |
<RoadNumber>39</RoadNumber> | |
<RoadNumberSegment>29</RoadNumberSegment> | |
<RoadStatus>V</RoadStatus> | |
<TextualRoadReference>1500EV0003902907614</TextualRoadReference> | |
<Measure>0.5</Measure> | |
<RoadNetPosition> | |
<SRID>25833</SRID> | |
<X>151894.22510113672</X> | |
<Y>7009975.503034506</Y> | |
</RoadNetPosition> | |
<RoadNumberSegmentDistance>7614</RoadNumberSegmentDistance> | |
<RoadnetHeading>66.855190998537481</RoadnetHeading> | |
</RoadReference> | |
OK, so now we have the road net heading and the Vegreferanse - information. | |
We perturb the meter value (7614) by +- 1 meter (7613, 7615) and send | |
two new requests to the GetRoadReferenceForReference - endpoint: | |
http://visveginfo-static.opentns.org/RoadInfoService/GetRoadReferenceForReference?roadReference=1500EV0003902907613&topologyLevel=Overview | |
and | |
http://visveginfo-static.opentns.org/RoadInfoService/GetRoadReferenceForReference?roadReference=1500EV0003902907615&topologyLevel=Overview | |
If you're close to the end points, one of these may fail because the meter | |
values are beyond the valid range (i.e < 0 or > max.value) - but you're | |
pretty sure to get valid data from at least one of them. | |
(yes, it's a hack, and not pretty!) | |
Comparing the changes in <Measure> (non-dimensional linear reference | |
position along that link) it's straigthforward to check the direction | |
of the metering system (identical or oposite of the road link direction) | |
""" | |
import xmltodict | |
import requests | |
def anropvisveginfo( path, params ): | |
baseurl = 'http://visveginfo-static.opentns.org/RoadInfoService/' | |
url = baseurl + path | |
r = requests.get( url, params=params) | |
return xmltodict.parse( r.text ) | |
def visveginfo_vegreferanseoppslag( vegreftxt ): | |
"""Returnerer lenkeposisjon ut fra vegreferanse-oppslag. Returnerer Null | |
hvis oppslaget er ugyldig. | |
""" | |
path = 'GetRoadReferenceForReference' | |
params = { 'roadReference' : vegreftxt, 'topologyLevel' : 'Overview' } | |
b = anropvisveginfo( path, params ) | |
if 'RoadReference' in b['ArrayOfRoadReference'].keys(): | |
return float( b['ArrayOfRoadReference']['RoadReference']['Measure'] ) | |
else: | |
return None | |
def sjekkmetreringretning( vvidata ): | |
"""Take the data from the service visveginfo, make 1m pertibations to the | |
meter value and see if the road net position is increasing or decreasing. | |
Will return METRERINGSRETNING, which is the direction of the metering system. | |
Which may be identical or oposite of the road network itself (with the | |
non-dimentional linear reference system) | |
""" | |
# Initialiserer en del variabler til None | |
pos0 = retning = motsatt = None | |
hp = vvidata['RoadReference']['TextualRoadReference'][0:14] | |
minmeter = int( vvidata['RoadReference']['RoadNumberSegmentDistance']) | |
minpos = float( vvidata['RoadReference']['Measure'] ) | |
if minmeter >= 1: | |
pos0 = visveginfo_vegreferanseoppslag( hp + str( minmeter-1 ).zfill(5)) | |
pos2 = visveginfo_vegreferanseoppslag( hp + str( minmeter+1).zfill(5)) | |
if pos0 and pos0 > minpos: | |
motsatt = True | |
if pos2 and pos2 < minpos: | |
motsatt = True | |
if pos0 and pos2 and pos0 > pos2 and not motsatt: | |
print( '\t'.join( [ 'FEIL METRERINGSLOGIKK', hp, 'm'+str(minmeter) ] )) | |
if pos0 or pos2: | |
retning = float( vvidata['RoadReference']['RoadnetHeading']) | |
if motsatt: | |
retning = (retning + 180.0) % 360 | |
return retning | |
def nvdbdirection( veglenke, posisjon ): | |
"""Use the visveginfo-service to find the road net heading and | |
vegreferanse-data (road number, parcel number, meter) for a particular | |
location in the network | |
""" | |
path = 'GetRoadReferenceForNVDBReference' | |
params = { 'reflinkoid' : veglenke, 'rellen' : posisjon } | |
vvidata = anropvisveginfo( path, params ) | |
vegnettretn = float( vvidata['RoadReference']['RoadnetHeading'] ) | |
metreringsretn = sjekkmetreringretning( vvidata ) | |
return (vegnettretn, metreringsretn) | |
def nvdbdirection4nvdbobj( nvdbId ): | |
"""Will find the road network positon for a particular NVDB object, | |
specified by its ID | |
""" | |
headers = { 'accept' : 'application/vnd.vegvesen.nvdb-v2+json', | |
'X-Client' : 'nvdbapi.py', | |
'X-Kontaktperson' : 'your@email.adress.com'} | |
url = 'https://www.vegvesen.no/nvdb/api/v2/' + 'vegobjekt' | |
params = { 'id' : nvdbId } | |
r = requests.get( url, params=params, headers = headers) | |
nvdbdata = r.json() | |
# Only the first "stedfesting" per object. For POINTS there should | |
# logically be only one... | |
sted = nvdbdata['lokasjon']['stedfestinger'][0] | |
if 'posisjon' in sted.keys(): | |
(vegnettretn, metreringsretn) = nvdbdirection( sted['veglenkeid'], sted['posisjon'] ) | |
elif 'fra_posisjon' in sted.keys(): | |
print( 'NVDB object', str(nvdbId), 'is not a POINT, but a LINE. Returning data for first position' ) | |
(vegnettretn, metreringsretn) = nvdbdirection( sted['veglenkeid'], sted['fra_posisjon'] ) | |
else: | |
print( 'NVDB object', str(nvdbId), 'is not attatched to NVDB road network???' ) | |
print( 'Probably obsolete bridge or something else attached to historical (obsolete) road network?') | |
vegnettretn = None | |
metreringsretn = None | |
return( vegnettretn, metreringsretn) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment