Skip to content

Instantly share code, notes, and snippets.

@LtGlahn
Last active June 7, 2017 08:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LtGlahn/ee15d47a3e0eb8fcb8cd6998aaa1cd9a to your computer and use it in GitHub Desktop.
Save LtGlahn/ee15d47a3e0eb8fcb8cd6998aaa1cd9a to your computer and use it in GitHub Desktop.
Check alignment of NVDB road network and metering system (vegreferanse)
# -*- 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