Skip to content

Instantly share code, notes, and snippets.

@LtGlahn
Last active May 1, 2024 10:49
Show Gist options
  • Save LtGlahn/98bb3e12ee9f4817b5d6ab175624634f to your computer and use it in GitHub Desktop.
Save LtGlahn/98bb3e12ee9f4817b5d6ab175624634f to your computer and use it in GitHub Desktop.
Finn nytt vegnett - brute force metode
"""
Finner veglenkesekvenser (veglenker) som er kommet til etter angitt dato
Laster ned ALT av segmentert vegnett (HELE historikken til segmentert vegnett) og sorterer ut
de veglenkesekvensene som A) har veglenker nyere enn angitt dato, B) ikke har historiske veglenker
På kvelden 30.4 så det slik ut når jeg ba om vegnett fra 29.4 eller nyere (dvs vegnett som oppstod i går eller i dag):
Fant 187 nye vegsementer fordelt på 65 nye veglenkesekvenser etter å ha gått gjennom 10737373 vegsegmenter / 1314106 veglenkesekvens ID.
Dette tok ca 1 time på et ikke spesielt sprekt hjemmenettverk, men på et tidspunkt der vi forventer liten belastning
på NVDB api LES.
De nye vegene fordelte seg på 379m Gang/sykkelveg i Stjørdal sentrum, 12km ny Fv565 på Radøy, inklusive et par kommunal
og privatveger - samt 988m uten trafikantgruppe fordelt på typeVeg=Fortau, Gangfelt og Gangveg. Dette burde la seg reprodusere
ved å føye til betingelsen `and veg['metadata']['startdato'] < '2024-05-01'` til if-setningen på linje 50
"""
import pandas as pd
from datetime import datetime
import geopandas as gpd
from shapely import wkt
import nvdbapiv3 # https://github.com/ltglahn/nvdbapi-V3/
if __name__ == '__main__':
t0 = datetime.now()
count = 0
angittDato = '2024-04-29'
v = nvdbapiv3.nvdbVegnett()
v.filter( {'historisk' : True }) # Må være med - vi skal jo filtrere ut veglenker
# som har historikk før angitt dato
#####################################################################################################
## Eksempel på filter som kan redusere datavolum
# v.filter( {'kartutsnitt' : '-40821,6764494,-40464,6764954'}) # Bitteliten flekk på Radøy med nybygget Fv565 den 29.4.2024
# v.filter( {'kommune' : 4631 }) # Alver kommune, der Radøy ligger
# v.filter( {'trafikantgruppe' : 'K' }) # Kun kjørbar bilveg
forkast = set() # Veglenkesekvenser som har eldre historikk
nye = {} # Veglenkesekvenser som kun har veglenker nyere enn angitt dato, dvs IKKE finnes i mengden forkast
# Hver oppføring her er en liste som holder alle vegsegmentene nyere enn angitt dato
for veg in v:
count += 1
if count % 100000 == 0:
print( f"Segment {count} (totalt i NVDB: ca 10 millioner)")
if veg['veglenkesekvensid'] in forkast:
pass
elif veg['metadata']['startdato'] >= angittDato:
if veg['veglenkesekvensid'] in nye:
nye[ veg['veglenkesekvensid']].append( veg )
else:
nye[ veg['veglenkesekvensid']] = [ veg ] # Oppretter en ny liste for denne veglenkesekvensen
# der vi lagrer alle segmentene som tilhører denne veglenkesekvensen
else:
# Hvis vi fant vegsegmenter eldre enn angitt dato så forkaster vi denne veglenkesekvensen
if veg['veglenkesekvensid'] in nye:
del( nye[ veg['veglenkesekvensid']] )
forkast.add( veg['veglenkesekvensid'])
print( f"Tidsbruk datanedlasting og analyse {datetime.now()-t0}")
# Oppsummerer de nye veglenkene
allenye = []
for myKey in nye.keys():
for segment in nye[myKey]:
allenye.append( nvdbapiv3.flatutvegnettsegment( segment ) )
###################################################################################################
###
### allenye = liste med forenklet (flat) dictionary-struktur, denne kan jo brukes på mange vis
### Jeg synes det er lettvint å jobbe i pandas dataframe, men det er jo min preferanse
mydf = pd.DataFrame( allenye )
print( f"Fant {len(mydf)} nye vegsementer fordelt på {len(nye)} nye veglenkesekvenser etter å ha gått gjennom {count} vegsegmenter")
print( f"Fordeling på vegkategori og trafikantgruppe")
print( mydf.groupby([ 'vegkategori', 'trafikantgruppe'], dropna=False ).agg( { 'vref' : 'count', 'lengde' : 'sum' } ))
###################################################################################################
####
#### Lagrer til GIS-vennlig format via geopandas https://geopandas.org/en/stable/
#### Flere formater og databaser er støttet, slik som geojson, postgis, parquet, esri shape, esri fil-geodatabase med flere
#### https://geopandas.org/en/stable/docs/reference/io.html og https://geopandas.org/en/v0.4.0/io.html
myGdf = gpd.GeoDataFrame( mydf, geometry=mydf['geometri'].apply( wkt.loads ), crs=5973 )
outfile = 'nyttvegnett_etter' + angittDato + '.gpkg'
# Kartlag med kjørbar bilveg
if len( myGdf[ myGdf['trafikantgruppe'] == 'K' ]) > 0:
myGdf[ myGdf['trafikantgruppe'] == 'K' ].to_file( outfile, layer='trafikantgruppe K', driver='GPKG')
# Kartlag med nettverk for gående der vi har lagt på metrering og trafikantgruppe
if len( myGdf[ myGdf['trafikantgruppe'] == 'G' ]) > 0:
myGdf[ myGdf['trafikantgruppe'] == 'G' ].to_file( outfile, layer='trafikantgruppe G', driver='GPKG')
# Nettverk uten metrering (typisk gangfelt, fortau m.m. - og etter hvert sti)
if len( myGdf[ myGdf['trafikantgruppe'].isnull() ]) > 0:
myGdf[ myGdf['trafikantgruppe'].isnull() ].to_file( outfile, layer='Ingen trafikantgruppe', driver='GPKG')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment