bachelor thesis submission
commit
5b4edae20a
|
@ -0,0 +1,96 @@
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
# Files generated by invoking Julia with --code-coverage
|
||||||
|
*.jl.cov
|
||||||
|
*.jl.*.cov
|
||||||
|
|
||||||
|
# Files generated by invoking Julia with --track-allocation
|
||||||
|
*.jl.mem
|
||||||
|
|
||||||
|
# System-specific files and directories generated by the BinaryProvider and BinDeps packages
|
||||||
|
# They contain absolute paths specific to the host computer, and so should not be committed
|
||||||
|
deps/deps.jl
|
||||||
|
deps/build.log
|
||||||
|
deps/downloads/
|
||||||
|
deps/usr/
|
||||||
|
deps/src/
|
||||||
|
|
||||||
|
# Build artifacts for creating documentation generated by the Documenter package
|
||||||
|
docs/build/
|
||||||
|
docs/site/
|
||||||
|
|
||||||
|
# File generated by Pkg, the package manager, based on a corresponding Project.toml
|
||||||
|
# It records a fixed state of all packages used by the project. As such, it should not be
|
||||||
|
# committed for packages, but should be committed for applications that require a static
|
||||||
|
# environment.
|
||||||
|
Manifest.toml
|
||||||
|
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
# the following file-extensions are created by the prototype. Therefore they will be ignored
|
||||||
|
*.osm
|
||||||
|
*.pdf
|
||||||
|
*.yaml
|
|
@ -0,0 +1,15 @@
|
||||||
|
ISC License (ISC)
|
||||||
|
|
||||||
|
Copyright 2022 Falk Centner
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||||
|
with or without fee is hereby granted, provided that the above copyright notice
|
||||||
|
and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||||
|
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||||
|
THIS SOFTWARE.
|
|
@ -0,0 +1,40 @@
|
||||||
|
|
||||||
|
WARNING: This is a prototype which is still under development.
|
||||||
|
|
||||||
|
TODO: See source
|
||||||
|
|
||||||
|
# Required packages
|
||||||
|
|
||||||
|
- LightOSM.jl
|
||||||
|
- LightXML.jl
|
||||||
|
- Graphs.jl
|
||||||
|
- Cairo.jl
|
||||||
|
- MetaGraphs.jl
|
||||||
|
- HTTP.jl
|
||||||
|
- Plots.jl
|
||||||
|
- GraphPlot.jl
|
||||||
|
- GraphRecipes.jl
|
||||||
|
- Fontconfiq.jl
|
||||||
|
- Compose.jl
|
||||||
|
- YAML.jl
|
||||||
|
|
||||||
|
# Usage and Contributing
|
||||||
|
|
||||||
|
If there is an urgent usecase, here is a very short instruction:
|
||||||
|
Start the OSMTrainPath or DataGraph-class.
|
||||||
|
1.) Use the "addRelation(id)"/"addWay(id)"-function to download data from overpass.
|
||||||
|
2.) After you completed all downloads call the "createGraph()"-function.
|
||||||
|
3.) To see the data call "plotGraph()" and search for the "Buffer.pdf"-file in which the plot will be saved.
|
||||||
|
4.) Use "filterOnedirectional(startpoint-id, destinationpoint-id)"-function to get one specific directed graph.
|
||||||
|
5.) Plot again to see the filtered path.
|
||||||
|
6.) If there are maxspeeds "UNKNOWN" you must correct them with the "changeWaySpeed(way-id, newspeed)"-function.
|
||||||
|
7.) If there are more possible ways than one for your whished export, you must remove one way so there is no other possible way.
|
||||||
|
Therefore use the "removeWay(way-id)"-function.
|
||||||
|
8.) After you completed all maxspeeds and only one possibly way, you can export data to a YAML-file.
|
||||||
|
Therefore use the exportPathToYAML(description, filename, startpoint-id, destinationpoint-id).
|
||||||
|
Note that you have to name the filename like *name*.yaml.
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
ISC-License
|
||||||
|
Copyright 2022 Falk Centner
|
|
@ -0,0 +1,239 @@
|
||||||
|
using Graphs, MetaGraphs, GraphPlot, Plots, GraphRecipes, Fontconfig, Cairo, Compose
|
||||||
|
|
||||||
|
include("./input.jl")
|
||||||
|
include("./output.jl")
|
||||||
|
|
||||||
|
nodeDict = Dict()
|
||||||
|
g = Graphs.SimpleDiGraph(1)
|
||||||
|
mdg = MetaDiGraph(g)
|
||||||
|
nodeXPositions = Float64[]
|
||||||
|
nodeYPositions = Float64[]
|
||||||
|
vecXCoordinates, vecYCoordinates = spring_layout(mdg) # This set the layout for the Graph-Packge, witch is used for plotting
|
||||||
|
nodeColorArray = []
|
||||||
|
nodeLabelArray = []
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The createGraph-function set a all data from the input-class in a MetaDiGraph.
|
||||||
|
# Therefore are some nested functions implemented.
|
||||||
|
#
|
||||||
|
# addDataToDiGraph creates the vertices and the edges in the MetaDiGraph. The data from the NamedTuples will be stored in these graph-objects.
|
||||||
|
#
|
||||||
|
# getNodeColorIndex returns an index-number which will be used later to color the nodes.
|
||||||
|
#
|
||||||
|
# getCartesianX and getCartesianY are used to transfer the lat&lon-coordinates in cartesian coordinates which are used for a plot of the graph (function->plotGraph()).
|
||||||
|
#
|
||||||
|
function createGraph()
|
||||||
|
g = Graphs.SimpleDiGraph(length(getFilteredNodeArray()))
|
||||||
|
global mdg=MetaDiGraph(g)
|
||||||
|
|
||||||
|
function addDatasToDiGraph(filteredNodeArray::Vector{Any},filteredWayArray::Vector{Any})
|
||||||
|
lonCorrection=0
|
||||||
|
for node in filteredNodeArray
|
||||||
|
lonCorrection=lonCorrection+node.lon
|
||||||
|
end
|
||||||
|
lonCorrection=lonCorrection/length(filteredNodeArray)
|
||||||
|
for node in filteredNodeArray
|
||||||
|
push!(nodeDict,node.nodeID=>(length(nodeDict)+1))
|
||||||
|
set_prop!(mdg,get(nodeDict,node.nodeID,"default value"),:id, node.nodeID)
|
||||||
|
push!(nodeColorArray,getNodeColorIndex(node.issignal,node.isswitch))
|
||||||
|
append!(nodeXPositions,getCartesianX(node.lon-lonCorrection,node.lat))
|
||||||
|
append!(nodeYPositions,getCartesianY(node.lon-lonCorrection,node.lat))
|
||||||
|
push!(nodeLabelArray,node.nodeID)
|
||||||
|
end
|
||||||
|
|
||||||
|
for way in filteredWayArray
|
||||||
|
bufferNode = first(way.containedNodeIDs)
|
||||||
|
for node in way.containedNodeIDs
|
||||||
|
if(node == first(way.containedNodeIDs))
|
||||||
|
else
|
||||||
|
Graphs.add_edge!(mdg,get(nodeDict,bufferNode.nodeID,"default value"),get(nodeDict,node.nodeID,"default value"))
|
||||||
|
set_prop!(mdg,Graphs.Edge(get(nodeDict,bufferNode.nodeID,"default value"),get(nodeDict,node.nodeID,"default value")), :maxspeed,way.vmax.forward)
|
||||||
|
set_prop!(mdg,Graphs.Edge(get(nodeDict,bufferNode.nodeID,"default value"),get(nodeDict,node.nodeID,"default value")), :wayID, way.wayID)
|
||||||
|
set_prop!(mdg,Graphs.Edge(get(nodeDict,bufferNode.nodeID,"default value"),get(nodeDict,node.nodeID,"default value")), :length, getEdgelength(node.lat,node.lon,bufferNode.lat,bufferNode.lon))
|
||||||
|
set_prop!(mdg,Graphs.Edge(get(nodeDict,bufferNode.nodeID,"default value"),get(nodeDict,node.nodeID,"default value")), :incline, way.incline.forward)
|
||||||
|
|
||||||
|
Graphs.add_edge!(mdg,get(nodeDict,node.nodeID,"default value"),get(nodeDict,bufferNode.nodeID,"default value"))
|
||||||
|
set_prop!(mdg,Graphs.Edge(get(nodeDict,node.nodeID,"default value"),get(nodeDict,bufferNode.nodeID,"default value")), :maxspeed,way.vmax.backward)
|
||||||
|
set_prop!(mdg,Graphs.Edge(get(nodeDict,node.nodeID,"default value"),get(nodeDict,bufferNode.nodeID,"default value")), :wayID, way.wayID)
|
||||||
|
set_prop!(mdg,Graphs.Edge(get(nodeDict,node.nodeID,"default value"),get(nodeDict,bufferNode.nodeID,"default value")), :length, getEdgelength(node.lat,node.lon,bufferNode.lat,bufferNode.lon))
|
||||||
|
set_prop!(mdg,Graphs.Edge(get(nodeDict,node.nodeID,"default value"),get(nodeDict,bufferNode.nodeID,"default value")), :incline, way.incline.backward)
|
||||||
|
bufferNode = node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function getNodeColorIndex(issignal::Bool,isswitch::Bool)
|
||||||
|
if(issignal==false&&isswitch==false)
|
||||||
|
return 1
|
||||||
|
elseif(issignal==true&&isswitch==false)
|
||||||
|
return 2
|
||||||
|
elseif(issignal==false&&isswitch==true)
|
||||||
|
return 3
|
||||||
|
else error("signal and switch in one node")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function getCartesianY(lon::Float64,lat::Float64)
|
||||||
|
return cos(deg2rad(lon))*cos(deg2rad(lat))*6371000
|
||||||
|
end
|
||||||
|
|
||||||
|
function getCartesianX(lon::Float64,lat::Float64)
|
||||||
|
return cos(deg2rad(lat))*sin(deg2rad(lon))*6371000
|
||||||
|
end
|
||||||
|
addDatasToDiGraph(getFilteredNodeArray(),getFilteredWayArray())
|
||||||
|
println("Graph created")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The plotGraph-function is used by the user to plot the Graph in it's current data status.
|
||||||
|
# Therefore the allready filled Arrays with the Node-Coordinates will be converted to vectors (necessary for GraphPlot-Package).
|
||||||
|
# Afterwards the function starts to find the horizontal an vertical size for the plot to distort it to an satellite-like view.
|
||||||
|
# Then the function fills the wayLabelArray and the wayColorArray to set them in the graph. The data for the Nodes are allready setted in the nodeColorArray and the nodeLabelArray.
|
||||||
|
# Finaly the function starts the gplot-function from the GraphPlot-Package.
|
||||||
|
# You can change all plot-settings in the gplot-function as it's descripted in the GraphPlot-Package: https://github.com/JuliaGraphs/GraphPlot.jl
|
||||||
|
#
|
||||||
|
function plotGraph()
|
||||||
|
println("start building vectors")
|
||||||
|
vecXCoordinates = vec(nodeXPositions)
|
||||||
|
vecYCoordinates = vec(nodeYPositions)
|
||||||
|
horizontal = (maximum(vecXCoordinates)-minimum(vecXCoordinates))
|
||||||
|
vertical = (maximum(vecYCoordinates)-minimum(vecYCoordinates))
|
||||||
|
wayLabelArray = []
|
||||||
|
wayColorArray = []
|
||||||
|
graphEdges = collect(Graphs.edges(mdg))
|
||||||
|
# println(Graphs.ne(mdg)) # print's the actuell numbers of edges in the Graph
|
||||||
|
for graphEdge in graphEdges
|
||||||
|
push!(wayLabelArray,string(get_prop(mdg,graphEdge,:length))*" m, Way-ID="*string(get_prop(mdg,graphEdge,:wayID))*", maxspeed="*string(get_prop(mdg,graphEdge,:maxspeed))*", incline="*string(round(get_prop(mdg,graphEdge,:incline),digits=4)))
|
||||||
|
push!(wayColorArray, getEdgeColorIndex(get_prop(mdg,graphEdge,:maxspeed)))
|
||||||
|
end
|
||||||
|
nodeColor = [colorant"blue",colorant"red",colorant"orange"]
|
||||||
|
nodefillc = nodeColor[nodeColorArray]
|
||||||
|
edgestrokec = wayColorArray
|
||||||
|
println("start plotting")
|
||||||
|
draw(PDF("DataGraph-Plot.pdf",horizontal, vertical), gplot(mdg, vecXCoordinates, vecYCoordinates,nodelabel=nodeLabelArray, edgelabel=wayLabelArray, edgestrokec = edgestrokec, EDGELINEWIDTH = 1.0 / sqrt(Graphs.nv(g)),nodefillc = nodefillc ,arrowlengthfrac=0.0006 / sqrt(Graphs.nv(g)),NODESIZE = 0.0002 / sqrt(Graphs.nv(g))))
|
||||||
|
# draw(PDF("DataGraph-Plot.pdf"), gplot(mdg, vecXCoordinates, vecYCoordinates,nodelabel=nodeLabelArray, edgelabel=wayLabelArray, edgestrokec = edgestrokec, EDGELINEWIDTH = 1.0 / sqrt(Graphs.nv(g)),nodefillc = nodefillc ,arrowlengthfrac=0.0006 / sqrt(Graphs.nv(g)),NODESIZE = 0.0002 / sqrt(Graphs.nv(g))))
|
||||||
|
# draw(PDF("PlotSaveTestBS-UELZEN.pdf",horizontal, vertical), gplot(mdg, vecXN, vecYN, edgelabel=waylabel, edgestrokec = edgestrokec, EDGELINEWIDTH = 2.5 / sqrt(Graphs.nv(g)),nodefillc = nodefillc ,arrowlengthfrac=0.01 / sqrt(Graphs.nv(g)),NODESIZE = 0.005 / sqrt(Graphs.nv(g))))
|
||||||
|
println("Plot finished. Saved to DataGraph-Plot.pdf")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The getYAMLExportArray-function is normaly used by the exportPathToYAML-function.
|
||||||
|
# It first finds a route and saves the points of the route in "pointsOfRoute".
|
||||||
|
# After that, the exportDataArray will be filled with the parameters for TrainRun.
|
||||||
|
# For the return this exportDataArray will be converted to a vector.
|
||||||
|
#
|
||||||
|
function getYAMLExportArray(startpoint::Int,destinationpoint::Int)
|
||||||
|
exportDataArray=[]
|
||||||
|
sumlength=0
|
||||||
|
pointsOfRoute = Graphs.enumerate_paths(Graphs.dijkstra_shortest_paths(mdg,get(nodeDict,string(startpoint),"default value")),get(nodeDict,string(destinationpoint),"default value"))
|
||||||
|
bufferNode = first(pointsOfRoute)
|
||||||
|
for node in pointsOfRoute
|
||||||
|
if(node==first(pointsOfRoute))
|
||||||
|
else
|
||||||
|
push!(exportDataArray,[round(get_prop(mdg,Graphs.Edge(bufferNode,node), :length)+sumlength,digits=2),parse(Int,get_prop(mdg,Graphs.Edge(bufferNode,node), :maxspeed)),round(get_prop(mdg,Graphs.Edge(bufferNode,node),:incline),digits=4)])
|
||||||
|
sumlength=sumlength+get_prop(mdg,Graphs.Edge(bufferNode,node), :length)
|
||||||
|
bufferNode=node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
dataVector=vec(exportDataArray)
|
||||||
|
println("export-vector created")
|
||||||
|
return dataVector
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The exportPathToYAML-function calls an other function from the "output.jl"-class. Therefore it needs a description (saved in the yaml-file), a filename and the startpoint and the destinationpoint of the route.
|
||||||
|
# It doesn't matter if you've allready filtered the Path onedirectional or not.
|
||||||
|
# Note that it's possible to export only a part of the path of the plot.
|
||||||
|
#
|
||||||
|
function exportPathToYAML(description::String, filename::String, startpoint::Int,destinationpoint::Int)
|
||||||
|
createYAML(description, filename, getYAMLExportArray(startpoint,destinationpoint))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The getEdgelength-function returns the length between two coordinate-positions.
|
||||||
|
# The length is calculated by a formula for spherical geometry, cause the standard coordinates (latitude & longitude) are for a globe and not a typical x-y-chart (cartesian).
|
||||||
|
# It returns a value in meter rounded to two positions after decimal point (cm).
|
||||||
|
#
|
||||||
|
function getEdgelength(lat1,lon1,lat2,lon2)
|
||||||
|
c=acos(sin(lat1*pi/180)*sin(lat2*pi/180)+cos(lat1*pi/180)*cos(lat2*pi/180)*cos(lon1*pi/180-lon2*pi/180))
|
||||||
|
length = round(c*6371000,digits=2)
|
||||||
|
if(length==0.00)
|
||||||
|
return 0.01 #This is necessary because TrainRun is unable to work with an edgelength below 0.01m
|
||||||
|
else return length
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The getEdgeColorIndex-function returns a color for a given String. It's normaly used by the plotGraph()-function.
|
||||||
|
#
|
||||||
|
function getEdgeColorIndex(maxspeed::String)
|
||||||
|
if(maxspeed=="UNKNOWN")
|
||||||
|
return colorant"orange"
|
||||||
|
elseif(maxspeed!="UNKNOWN")
|
||||||
|
return colorant"green"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# filterOnedirectional needs a startpoint and an endpoint to remove all unused edges.
|
||||||
|
# CAUTION!: This function is seraching for the shortest path in the graph.
|
||||||
|
# If there are multiple possiblitys to connect startpoint and endpoint, this function may not find the astimated path.
|
||||||
|
# Prepare the Graph with the "removeWayFromGraph()"-function so there is only one possible path in the graph.
|
||||||
|
#
|
||||||
|
function filterOnedirectional(startpoint::Int,destinationpoint::Int)
|
||||||
|
pointsOfRoute = Graphs.enumerate_paths(Graphs.dijkstra_shortest_paths(mdg,get(nodeDict,string(destinationpoint),"default value")),get(nodeDict,string(startpoint),"default value"))
|
||||||
|
remainingEdges = []
|
||||||
|
bufferNode = first(pointsOfRoute)
|
||||||
|
for node in pointsOfRoute
|
||||||
|
if(node==first(pointsOfRoute))
|
||||||
|
else
|
||||||
|
push!(remainingEdges,Graphs.Edge(node,bufferNode))
|
||||||
|
bufferNode=node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for edge in collect(MetaGraphs.edges(mdg))
|
||||||
|
if(in(edge,remainingEdges))
|
||||||
|
else MetaGraphs.rem_edge!(mdg,edge)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
println("path filtered between "*string(startpoint)*" and "*string(destinationpoint))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The changeWaySpeed-function changes the speed of a way. It doesn't matter what the previous value was.
|
||||||
|
# NOTE!: If you haven't allready filtered the path onedirectional, you change the speed for both directions.
|
||||||
|
# It ist highly recommended to filter onedirectional bevore using this function.
|
||||||
|
# To filter onedirectional you can use the filterOnedirectional-function.
|
||||||
|
#
|
||||||
|
function changeWaySpeed(wayID::Int,newSpeed::Int)
|
||||||
|
for edge in MetaGraphs.edges(mdg)
|
||||||
|
if(get_prop(mdg,edge, :wayID)==string(wayID))
|
||||||
|
set_prop!(mdg,edge, :maxspeed, string(newSpeed))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
println("set new Wayspeed "*string(newSpeed)*" for Way "*string(wayID))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The removeWayFromGraph-function removes a given way from the graph, if the given way (found by it's OSM-ID) is in the graph.
|
||||||
|
#
|
||||||
|
function removeWayFromGraph(wayID::Int)
|
||||||
|
for edge in collect(MetaGraphs.edges(mdg))
|
||||||
|
if(get_prop(mdg,edge, :wayID)==string(wayID))
|
||||||
|
clear_props!(mdg,edge)
|
||||||
|
Graphs.rem_edge!(mdg,edge)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
println("Way "*string(wayID)*" was removed from the Graph")
|
||||||
|
end
|
|
@ -0,0 +1,12 @@
|
||||||
|
# This is the main-module
|
||||||
|
# All relevant functions are callable from here
|
||||||
|
# This prototype can create path-files for the TrainRun-Tool (https://doi.org/10.5281/zenodo.6448563)
|
||||||
|
# Cause of some problems the typical structure with modules isn't yet setted
|
||||||
|
|
||||||
|
|
||||||
|
include("./input.jl")
|
||||||
|
include("./DataGraph.jl")
|
||||||
|
include("./output.jl")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
|
||||||
|
using LightOSM, HTTP, LightXML
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function was created in the LightOSM-Package and is under the Copyright of this Package -> https://github.com/DeloitteDigitalAPAC/LightOSM.jl
|
||||||
|
# For the usage in this prototype the original LightOSM-function was addapted.
|
||||||
|
# The function checks if the overpass-server are available.
|
||||||
|
# Adaption of the original function: a print-information was removed.
|
||||||
|
#
|
||||||
|
function overpass_request(data::String)::String
|
||||||
|
LightOSM.check_overpass_server_availability()
|
||||||
|
return String(HTTP.post("http://overpass-api.de/api/interpreter",body=data).body)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function was created in the LightOSM-Package and is under the Copyright of this Package -> https://github.com/DeloitteDigitalAPAC/LightOSM.jl
|
||||||
|
# For the usage in this prototype the original LightOSM-function was addapted.
|
||||||
|
# It calls the overpass_request-function with the given string and a filepath for the datafile, which is also created with this function.
|
||||||
|
# The filetype is allways setted to "osm".
|
||||||
|
# Adaption of the original function: some given parameters were removed, additionally there usage in the function.
|
||||||
|
#
|
||||||
|
function download_osm_network(save_to_file_location,datas)::Union{XMLDocument,Dict{String,Any}}
|
||||||
|
data = overpass_request(datas)
|
||||||
|
#@info "Downloaded osm network data from $(["$k: $v" for (k, v) in download_kwargs]) in $download_format format"
|
||||||
|
|
||||||
|
if !(save_to_file_location isa Nothing)
|
||||||
|
save_to_file_location = LightOSM.validate_save_location(save_to_file_location, "osm")
|
||||||
|
write(save_to_file_location, data)
|
||||||
|
@info "Saved osm network data to disk: $save_to_file_location"
|
||||||
|
end
|
||||||
|
|
||||||
|
deserializer = LightOSM.string_deserializer(:osm)
|
||||||
|
return deserializer(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This funtion is used to call the download_osm_network-function with a specific download-query-String, which is created by this function with the given OSM-ID.
|
||||||
|
#
|
||||||
|
function getOSMRelationXML(relationID::Int)
|
||||||
|
return download_osm_network("./Buffer.osm","[out:xml][timeout:25];relation("*string(relationID)*");(._;>>;);out;")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This funtion is used to call the download_osm_network-function with a specific download-query-String, which is created by this function with the given OSM-ID.
|
||||||
|
#
|
||||||
|
function getOSMWayXML(wayID::Int)
|
||||||
|
return download_osm_network("./Buffer.osm","[out:xml][timeout:25];way("*string(wayID)*");(._;>>;);out;")
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,438 @@
|
||||||
|
|
||||||
|
using LightXML
|
||||||
|
include("./download.jl")
|
||||||
|
# `
|
||||||
|
# TODO: change variable names like Array(which are most time Any's).
|
||||||
|
# `
|
||||||
|
|
||||||
|
wayArray = []
|
||||||
|
nodeArray = []
|
||||||
|
filteredWayArray = []
|
||||||
|
filteredNodeArray = []
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function returns the filteredWayArray (which is an Any).
|
||||||
|
#
|
||||||
|
function getFilteredWayArray()
|
||||||
|
return filteredWayArray
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function returns the filteredNodeArray (which is an Any).
|
||||||
|
#
|
||||||
|
function getFilteredNodeArray()
|
||||||
|
return filteredNodeArray
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function does a filtering of the given xroot and removes all members with a specific role (for example platform-data).
|
||||||
|
# To get the information which data are relevant, the function needs the relationID where the members are listet.
|
||||||
|
#
|
||||||
|
function filterAllWaysByDataFromRelation(relationID::Union{String, Int},xroot)
|
||||||
|
ID=""
|
||||||
|
if(typeof(relationID)==Int)
|
||||||
|
ID=string(relationID)
|
||||||
|
else
|
||||||
|
ID=relationID
|
||||||
|
end
|
||||||
|
xmlRelations=get_elements_by_tagname(xroot, "relation")
|
||||||
|
for relation in xmlRelations
|
||||||
|
if(attribute(relation,"id")==ID)
|
||||||
|
childnodesOfRelation = collect(child_nodes(relation))
|
||||||
|
for elements in childnodesOfRelation
|
||||||
|
if is_elementnode(elements)
|
||||||
|
if name(elements) == "member"
|
||||||
|
g = XMLElement(elements)
|
||||||
|
if(attribute(g,"role")=="")
|
||||||
|
addToFilteredWayArray(getWayByID(attribute(g,"ref")))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function checks the data-type of the given wayID and afterwards calls the addToFilteredWayArray-function with the ID.
|
||||||
|
#
|
||||||
|
function filterWayToFilteredWayArray(wayID::Union{String, Int})
|
||||||
|
ID=""
|
||||||
|
if(typeof(wayID)==Int)
|
||||||
|
ID=string(wayID)
|
||||||
|
else
|
||||||
|
ID=wayID
|
||||||
|
end
|
||||||
|
addToFilteredWayArray(getWayByID(ID))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function adds all nodes of all ways to the filteredNodeArray by calling the addToFilteredNodeArray-funtion.
|
||||||
|
#
|
||||||
|
function filterAllNodesByDataFromFilteredWayArray(filteredWayArray::Any)
|
||||||
|
for way in filteredWayArray
|
||||||
|
nodes = way.containedNodeIDs
|
||||||
|
for node in nodes
|
||||||
|
addToFilteredNodeArray(node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function checks if a way is already saved in the filteredWayArray and returns the result with a Bool.
|
||||||
|
#
|
||||||
|
function checkIfAllreadyInFilteredWayArray(newway::NamedTuple)
|
||||||
|
for way in filteredWayArray
|
||||||
|
if(way==newway)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function checks if a node is already saved in the filteredNodeArray and returns the result with a Bool.
|
||||||
|
#
|
||||||
|
function checkIfAllreadyInFilteredNodeArray(newnode::NamedTuple)
|
||||||
|
for node in filteredNodeArray
|
||||||
|
if(node==newnode)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function adds a node to the filteredNodeArray if it's not already saved there.
|
||||||
|
#
|
||||||
|
function addToFilteredNodeArray(node::NamedTuple)
|
||||||
|
if(!checkIfAllreadyInFilteredNodeArray(node))
|
||||||
|
push!(filteredNodeArray,node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function adds a way to the filteredWayArray if it's not already saved there.
|
||||||
|
#
|
||||||
|
function addToFilteredWayArray(way::NamedTuple)
|
||||||
|
if(!checkIfAllreadyInFilteredWayArray(way))
|
||||||
|
push!(filteredWayArray,way)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function returns a node-NamedTuple. Therefore the node-ID is required.
|
||||||
|
#
|
||||||
|
function getNodeByID(nodeID::Union{Int,String})
|
||||||
|
if(typeof(nodeID)==Int)
|
||||||
|
for node in nodeArray
|
||||||
|
if(node.nodeID==string(nodeID))
|
||||||
|
return node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for node in nodeArray
|
||||||
|
if(node.nodeID==nodeID)
|
||||||
|
return node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@debug "missed Node called. NodeID that is missed is: $nodeID"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function returns a way-NamedTuple from the wayArray by the wayID.
|
||||||
|
#
|
||||||
|
function getWayByID(wayID::Union{Int,String})
|
||||||
|
if(typeof(wayID)==Int)
|
||||||
|
for way in wayArray
|
||||||
|
if(way.wayID==string(wayID))
|
||||||
|
return way
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for way in wayArray
|
||||||
|
if(way.wayID==wayID)
|
||||||
|
return way
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@debug "missed Way called. WayID that is missed is: $wayID"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function returns a way in the filteredWayArray by the wayID.
|
||||||
|
#
|
||||||
|
function getWayFromFilteredWayArrayByID(wayID::Union{Int,String})
|
||||||
|
if(typeof(wayID)==Int)
|
||||||
|
for way in filteredWayArray
|
||||||
|
if(way.wayID==string(wayID))
|
||||||
|
return way
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for way in filteredWayArray
|
||||||
|
if(way.wayID==wayID)
|
||||||
|
return way
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@debug "missed Way called. WayID that is missed is: $wayID"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The createNodes-function transfers the data from a given XMLElement to a NamedTuple and pushs this NamedTuple to the filteredNodeArray.
|
||||||
|
# In the transfer of the data the node-ID, the lat and lon coordinates and additional Bools for signal and switch information are stored in the NamedTuple.
|
||||||
|
#
|
||||||
|
function createNodes(xroot::XMLElement)
|
||||||
|
xmlNodes = get_elements_by_tagname(xroot, "node")
|
||||||
|
for node in xmlNodes
|
||||||
|
issignal = false
|
||||||
|
isswitch = false
|
||||||
|
if(has_children(node))
|
||||||
|
element = child_nodes(node)
|
||||||
|
for c in element
|
||||||
|
if(is_elementnode(c))
|
||||||
|
e= XMLElement(c)
|
||||||
|
if(attribute(e,"k")=="railway" && attribute(e,"v")=="signal")
|
||||||
|
issignal=true
|
||||||
|
end
|
||||||
|
if(attribute(e,"k")=="railway:switch"||(attribute(e,"k")=="railway"&&attribute(e,"v")=="switch"))
|
||||||
|
isswitch=true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
nd = (nodeID = attribute(node,"id"), lat=parse(Float64,attribute(node,"lat")), lon=parse(Float64,attribute(node,"lon")), issignal=issignal, isswitch=isswitch)
|
||||||
|
push!(nodeArray,nd)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The createWay-function transfers the data from a given XMLElement to a NamedTuple and pushs this NamedTuple to the filteredWayArray
|
||||||
|
# In the transfer of the data the way-ID, the containened Nodes (NamedTuples of the nodes), the maxspeed (NamedTuples because of direction-dependent maxspeeds) and the inclines (NamedTuples because of direction-dependent inclines) are stored in the NamedTuple.
|
||||||
|
#
|
||||||
|
function createWays(xroot::XMLElement)
|
||||||
|
xmlWays = get_elements_by_tagname(xroot, "way")
|
||||||
|
for way in xmlWays
|
||||||
|
w = (wayID = attribute(way,"id"), containedNodeIDs = getWayNodeIDs(way),vmax=getWayMaxspeed(way),incline=getWayIncline(way))
|
||||||
|
push!(wayArray,w)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function returns a NamedTuple with the direction-dependent inclines of a given way-XMLElement.
|
||||||
|
# The values in the OSM are percent while in german train-tracks the unit perthousand is common.
|
||||||
|
# To avoid an unit-change-mistake, the units are converted in this function.
|
||||||
|
#
|
||||||
|
function getWayIncline(xWay::XMLElement)
|
||||||
|
elements = child_nodes(xWay.node)
|
||||||
|
incline = 0.0
|
||||||
|
for e in elements
|
||||||
|
if(is_elementnode(e))
|
||||||
|
x = XMLElement(e)
|
||||||
|
if(attribute(x,"k")=="incline")
|
||||||
|
value = attribute(x,"v")
|
||||||
|
if(value=="down"||value=="up")
|
||||||
|
else incline = parse(Float64,replace(attribute(x,"v"),"%"=>""))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return (forward=incline*10,backward=incline*(-10)) # *10 necessary for change from % to per thousand -> (typically used for german-rail-incline)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The getWayMaxspeed-function returns a NamedTuple with the OSM-maxspeed-data in which the maxspeed is listet with the direction for which the value is valid.
|
||||||
|
# If the OSM-data specify a direction with :forward and :backward, this will be safed in the NamedTuple.
|
||||||
|
# If there is no specification of the direction, both will be saved with the maxspeed-value.
|
||||||
|
# If there is no maxspeed in one or both directions, the value(s) will be saved with "UNKNOWN".
|
||||||
|
#
|
||||||
|
function getWayMaxspeed(xWay::XMLElement)
|
||||||
|
element = child_nodes(xWay.node)
|
||||||
|
maxspeedforward = "UNKNOWN"
|
||||||
|
maxspeedbackward = "UNKNOWN"
|
||||||
|
for c in element
|
||||||
|
if(is_elementnode(c))
|
||||||
|
e = XMLElement(c)
|
||||||
|
if(attribute(e,"k")=="maxspeed")
|
||||||
|
return maxspeed = (forward = attribute(e,"v"), backward = attribute(e,"v"))
|
||||||
|
elseif (attribute(e,"k")=="maxspeed:forward")
|
||||||
|
maxspeedforward = attribute(e,"v")
|
||||||
|
elseif (attribute(e,"k")=="maxspeed:backward")
|
||||||
|
maxspeedbackward = attribute(e,"v")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if(maxspeedforward=="UNKNOWN"&&maxspeedbackward=="UNKNOWN")
|
||||||
|
return maxspeed=(forward = "UNKNOWN", backward = "UNKNOWN")
|
||||||
|
else return maxspeed = (forward = maxspeedforward, backward = maxspeedbackward)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function returns an Any which contains the NamedTuples of the Nodes from the given way-XMLElement.
|
||||||
|
# To get the Nodes for the Any, the getNodeByID-funtion is used.
|
||||||
|
#
|
||||||
|
function getWayNodeIDs(xWay::XMLElement)
|
||||||
|
nodeIDs = []
|
||||||
|
element = child_nodes(xWay.node)
|
||||||
|
for c in element
|
||||||
|
if(is_elementnode(c))
|
||||||
|
e = XMLElement(c)
|
||||||
|
if(name(e)=="nd")
|
||||||
|
#push!(nodeIDs,(attribute(e,"ref")))
|
||||||
|
#or entweder nur die Nummer oder den ganzen Knoten
|
||||||
|
push!(nodeIDs,getNodeByID(attribute(e,"ref")))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# println(attribute(xWay, "id")," = ", length(nodeIDs))
|
||||||
|
return nodeIDs
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function is used to add an OSM-Relation to the prototype memory.
|
||||||
|
# In contrast to the "addRelation"-funtion, this function reads the data from a given XML/OSM-file.
|
||||||
|
# Therefore the filepath and the OSM-Relation-ID is required.
|
||||||
|
# With these data the function calls the createWays/createNodes-functions and filters the NamedTuples with the filter***-functions.
|
||||||
|
#
|
||||||
|
function addRelationFromFile(id::Int,filepath::String)
|
||||||
|
xdoc = parse_file(filepath)
|
||||||
|
xroot = root(xdoc)
|
||||||
|
createNodes(xroot)
|
||||||
|
createWays(xroot)
|
||||||
|
println(length(nodeArray)," Nodes in nodeArray")
|
||||||
|
println(length(wayArray)," Ways in wayArray")
|
||||||
|
filterAllWaysByDataFromRelation(id,xroot)
|
||||||
|
filterAllNodesByDataFromFilteredWayArray(filteredWayArray)
|
||||||
|
println(length(filteredWayArray)," Ways in filteredWayArray")
|
||||||
|
println(length(filteredNodeArray)," Nodes in filteredNodeArray")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function is used to add an OSM-Way to the prototype memory.
|
||||||
|
# In contrast to the "addWay"-funtion this function reads the data from a given XML/OSM-file.
|
||||||
|
# Therefore the filepath and the OSM-Way-ID is required.
|
||||||
|
# With these data the function calls the createWays/createNodes-functions and filters the NamedTuples with the filter***-functions.
|
||||||
|
#
|
||||||
|
function addWayFromFile(id::Int,filepath::String)
|
||||||
|
xdoc = parse_file(filepath)
|
||||||
|
xroot = root(xdoc)
|
||||||
|
createNodes(xroot)
|
||||||
|
createWays(xroot)
|
||||||
|
println(length(nodeArray)," Nodes in nodeArray")
|
||||||
|
println(length(wayArray)," Ways in wayArray")
|
||||||
|
filterWayToFilteredWayArray(id)
|
||||||
|
filterAllNodesByDataFromFilteredWayArray(filteredWayArray)
|
||||||
|
println(length(filteredWayArray)," Ways in filteredWayArray")
|
||||||
|
println(length(filteredNodeArray)," Nodes in filteredNodeArray")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function is used to add an OSM-Relation to the prototype memory.
|
||||||
|
# It calls the Overpass-API via the download-class. Therefore the OSM-Relation-ID is required.
|
||||||
|
# After the download the function reads the Buffer.osm-file with the data and imports them.
|
||||||
|
# With these data the function calls the createWays/createNodes-functions and filters the NamedTuples with the filter***-functions.
|
||||||
|
#
|
||||||
|
function addRelation(id::Int)
|
||||||
|
getOSMRelationXML(id)
|
||||||
|
xdoc = parse_file("./Buffer.osm")
|
||||||
|
xroot = root(xdoc)
|
||||||
|
createNodes(xroot)
|
||||||
|
createWays(xroot)
|
||||||
|
println(length(nodeArray)," Nodes in nodeArray")
|
||||||
|
println(length(wayArray)," Ways in wayArray")
|
||||||
|
filterAllWaysByDataFromRelation(id,xroot)
|
||||||
|
filterAllNodesByDataFromFilteredWayArray(filteredWayArray)
|
||||||
|
println(length(filteredWayArray)," Ways in filteredWayArray")
|
||||||
|
println(length(filteredNodeArray)," Nodes in filteredNodeArray")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function is used to add an OSM-Way to the prototype memory.
|
||||||
|
# It calls the Overpass-API via the download-class. Therefore the OSM-Way-ID is required.
|
||||||
|
# After the download the function reads the Buffer.osm-file with the data and imports them.
|
||||||
|
# With these data the function calls the createWays/createNodes-functions and filters the NamedTuples with the filter***-functions.
|
||||||
|
#
|
||||||
|
function addWay(id::Int)
|
||||||
|
getOSMWayXML(id)
|
||||||
|
xdoc = parse_file("./Buffer.osm")
|
||||||
|
xroot = root(xdoc)
|
||||||
|
createNodes(xroot)
|
||||||
|
createWays(xroot)
|
||||||
|
println(length(nodeArray)," Nodes in nodeArray")
|
||||||
|
println(length(wayArray)," Ways in wayArray")
|
||||||
|
filterWayToFilteredWayArray(id)
|
||||||
|
filterAllNodesByDataFromFilteredWayArray(filteredWayArray)
|
||||||
|
println(length(filteredWayArray)," Ways in filteredWayArray")
|
||||||
|
println(length(filteredNodeArray)," Nodes in filteredNodeArray")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function is used to clear all collected data in any Arrays.
|
||||||
|
#
|
||||||
|
function clearAllArrays()
|
||||||
|
empty!(wayArray)
|
||||||
|
empty!(nodeArray)
|
||||||
|
empty!(filteredWayArray)
|
||||||
|
empty!(filteredNodeArray)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function prints the ways without maxspeed-information.
|
||||||
|
#
|
||||||
|
function checkWaySpeed()
|
||||||
|
waysWithoutSpeed=[]
|
||||||
|
for way in filteredWayArray
|
||||||
|
if(way.vmax.forward==""||way.vmax.backward=="")
|
||||||
|
push!(waysWithoutSpeed,way)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
println("The following ways have none or one-directional only maxpeed")
|
||||||
|
for way in waysWithoutSpeed
|
||||||
|
println(way.wayID," maxspeed forward = ", way.vmax.forward, ", maxspeed backward = ",way.vmax.backward)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function can set the speed of a way. Therefore maxspeed-information for both direction and the OSM-ID of the Way is required.
|
||||||
|
#
|
||||||
|
function setWaySpeed(wayID::Union{Int,String}, maxspeedforward::Int, maxspeedbackward::Int)
|
||||||
|
w = getWayFromFilteredWayArrayByID(wayID)
|
||||||
|
newW = (wayID = w.wayID, containedNodeIDs = w.containedNodeIDs,vmax=(forward = string(maxspeedforward), backward = string(maxspeedbackward)))
|
||||||
|
replace!(filteredWayArray,w=>newW)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This function can remove a way from the data. Therefore the OSM-ID of the Way is required.
|
||||||
|
#
|
||||||
|
function removeWay(id::Int)
|
||||||
|
println(indexin(getWayByID(id),filteredWayArray))
|
||||||
|
println("removed the way")
|
||||||
|
end
|
|
@ -0,0 +1,18 @@
|
||||||
|
using YAML
|
||||||
|
#
|
||||||
|
# The createYAML-function produce the YAML-output-file of this prototype.
|
||||||
|
# The file is named with the given filename which has to be in a "*name*.yaml" style (so with the .yaml).
|
||||||
|
# A given description is needed and will be setted in the file.
|
||||||
|
#
|
||||||
|
# In this version there is no information of the data-source in the file.
|
||||||
|
# TODO: add data-source information (OpenStreetMap).
|
||||||
|
#
|
||||||
|
function createYAML(description::String, filename::String, datas::Any)
|
||||||
|
dataVector=datas
|
||||||
|
d=Dict()
|
||||||
|
d2=Dict(:name => description, :sectionStarts => nothing, :sectionStarts_kmh => dataVector)
|
||||||
|
push!(d,:path => d2)
|
||||||
|
YAML.write_file(filename, d)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue