Content uploaded by Tamas Tettamanti
Author content
All content in this area was uploaded by Tamas Tettamanti on Jan 29, 2023
Content may be subject to copyright.
OSM2VISSIM TOOL TO IMPORT OPEN STREET MAP (OSM)
INTO PTV VISSIM
An open-source OSM conversion tool for seamless automatized generation of microscopic
traffic simulation for PTV VISSIM
Authors: Levente T˝ok´es and Tam´as Tettamanti
Technical report for the open-source code of https://github.com/bmetrafficlab/OSM2VISSIM
Budapest University of Technology and Economics
Dept. of Control for Transportation and Vehicle Systems,
Fac. of Transportation Eng. and Vehicle Eng.
Budapest, 2023
Contents
1 Purpose of the program 3
2 Background 3
2.1 OpenStreetMap(OSM) ......................................... 3
2.2 PTV VISSIM and VISSIM COM programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3 Overview of the program 4
3.1 Startingtheprogram........................................... 4
3.2 Buildingthenetwork........................................... 4
3.3 Trafficsignalheads............................................ 5
3.4 Connectors ................................................ 6
3.5 Programending.............................................. 7
4 A working example 8
5 Limitations 11
5.1 Falsedirectionproblem ......................................... 11
5.2 Identicallanewidth ........................................... 11
5.3 Nogradientmodeling .......................................... 12
5.4 Issuesofthetrafficsignalheads..................................... 12
5.5 Issueoncreatingconnectors....................................... 12
5.6 Manual editing for traffic signal programs and vehicle inputs . . . . . . . . . . . . . . . . . . . . 12
6 Appendix: the full code of the OSM2VISSIM program 14
2
1 Purpose of the program
OpenStreetMap (OSM) is a free, editable map of the whole world being developed by volunteers and released
under an open-content license. Due to this open-source nature of OSM, it is more and more important for
software tools dealing with map data to have the capability of smooth importing. Software tools for modeling
or simulating road traffic represent a group of programs for which proper maps are of crucial importance,
i.e. traffic is simulated on a traffic network graph.
SUMO traffic simulator [2] has an efficient tool to import OSM, called OSMWebWizard providing an easy
solution to start with SUMO based on a selection of an OSM excerpt together with randomized traffic demand.
The main capability of OSMWebWizard are:
•demand generation,
•importing public transport,
•creating signal programs.
Similarly to SUMO traffic simulator’s OSMWebWizard we developed an open-source conversion tool for
PTV VISSIM microscopic simulation suite to help and support VISSIM users. According to the above, the
main aim of the developed OSM2VISSIM tool is to provide the capability of:
•importing OSM map with all properties into PTV VISSIM, i.e. automatically generate VISSIM project
file based on the OSM data with proper geometry and traffic light data;
•generating traffic simulation scenario with customized traffic demand.
2 Background
In this section, the applied map format and traffic simulation environment are briefly summarized used for the
developed converter tool.
2.1 OpenStreetMap (OSM)
OSM is a collaborative map format that can be edited by any registered user, the data was entered into the
system manually (by GPS survey), but currently, the map has several business and government sources. Existing
data is stored in a PostGIS database according to the Mercator projection, and several additions have been
made to the base map, which can be accessed by additional servers. The topological structure contains:
•node: spatial position with a coordinate;
•way: a series of vertices that represent either a polyline or a polygon;
•relation: groups of vertices or paths that have some properties;
•tag: descriptive data for nodes, ways, or relations.
2.2 PTV VISSIM and VISSIM COM programming
VISSIM is a microscopic traffic simulation tool based on the individual behavior of the vehicles. The simulator
applies the Wiedemann car-following model [4]. VISSIM is widely used for diverse problems by traffic engineers
in practice as well as by researchers for developments related to road traffic. VISSIM offers a user-friendly
graphical interface (GUI) through which one can design the geometry of any type of road networks and set up
simulations in a simple way. However, for several problems, the GUI is not satisfying. This is the case, for
example, when the user aims to access and manipulate VISSIM objects during the simulation dynamically. To
this end, an additional interface is offered by the manufacturer based on the COM (Component Object Model)
technology enabling interprocess communication between software [1]. The VISSIM COM interface defines a
hierarchical model in which the functions and parameters of the simulator originally provided by the GUI can be
handled by programming as COM objects. Through VISSIM COM the user is able to manipulate the attributes
of most of the internal objects dynamically [3].
3
3 Overview of the program
In this part, the main features of the developed program are introduced.
3.1 Starting the program
When starting the program, a GUI asks for the name of the OSM file. The user only has to provide the name of
the file without the .osm extension. The source file has to be in the same folder where the program is, otherwise
the program cannot find it.
After entering the filename and clicking on the Set button the window closes and creates a VISSIM input
file (.inpx) with the name of the OSM file containing only one line: < network >\n< /network >. Without
this step the program is not working because at starting VISSIM needs an input file to save the data in.
To access and manipulate VISSIM objects, or in this case add new ones, a COM interface is required so the
program and the simulation can communicate with each other to execute commands. In our development the
applied programming language is Python but any other languages can be used as long as they can handle COM
objects. As a first step the win32com.client must be imported. In this paper, the module has been imported
as ”com”. After this the connection to the COM server can be created with the following command:
V is s im = c om . g en c ac h e . E n su r e Di s p at c h ( "Vissim.Vissim")
In case of multiple VISSIM versions on the computer the version must be specified by adding the version
number as well (i.e. ”Vissim.Vissim.XXXX”). Once the cache has been generated, it is faster to call Dispatch
which also creates the connection to VISSIM:
V is s im = c om . D is p at c h ( "Vissim.Vissim")
The next step is naming the input file that has been created earlier in the program. For this the path to the
file has to be given either directly or with the help of the os.path.join() and os.getcwd() commands. The latter
one is more practical since all the files are being created in the current working directory and the user does not
have to change the path in the program.
After the input file is named it must be loaded into VISSIM with the Vissim.LoadNet() command which
takes 2 arguments. The first one is the input file, the second one is a boolean variable which in the case of ”True”
value allows users to read network elements additionally. The default value of the later variable is ”False” but
for the program to work it needs to be set to ”True”.
3.2 Building the network
For creating links in the network VISSIM requires the coordinates of the links’ points. To get these parameters
from the OSM file the features of the file must be first exported into JavaScript Object Notation (JSON) format.
A JSON file is a text-based, human-readable file that stores simple data structures and objects. A basic unit of
JSON is a key:value pair which is similar to the Python dictionaries. To access these data a driver is required
from the ogr module which is called OSM in this case. This driver can open and read OSM files and get the
required layer and features in it. The first layer the program needs is the ”lines” layer which contains the ”way”
elements of the OSM file including the roads and sidewalks. The features of the layer are saved in a list. The
commands for these steps are:
d ri ve r = og r . Ge t Dr i ve r By N am e ( ’O SM ’ )
d at a _s o ur c e = d r iv er . O pe n ( o sm _f i le )
l ay er = d a ta _ so u rc e . G et La y er ( ’ l i ne s ’ )
f ea t u re s =[ x for xin l a ye r ]
The following steps are happening in a cycle that goes through all the features in the selected layer. First,
the feature is exported into JSON:
d at a = f e at ur e . E xp o rt T oJ s on ( a s _o b je ct = T r ue )
In the next step some of the feature’s attributes are read. The most important ones are coordinates,highway
and other tags. The first one is needed for creating the links, the second one helps to assort the features that are
in the layer but are irrelevant to the simulation, the last one contains extra information that might be needed,
like the number of lanes.
4
To find the relevant features a list of key values is given for the highway key. If the value of highway is not in
the list the program skips the feature. The list contains the following elements: steps; footway; cycleway; mo-
torway; trunk; primary; secondary; tertiary; unclassified; residental; motorway link; trunk link; primary link;
secondary link; tertiary link; service; track; bus guideway; escape; raceway; road; busway; living street; residen-
tial.
For adding links to the network coordinates and the width and number of lanes are needed. The program
starts with determining the last one. In OSM there are 2 keys containing information about it, lanes and
turn:lanes, furthermore both of them can include information about the forward and backward directions
(e.g. turn:lanes:forward). The program checks if the current object contains the key with the smallest group
and if not, then checks the next key and so on. Checking the keys one by one is necessary because some OSM
objects do not contain all of them which can lead to errors. The order of these keys is the following:
turn:lanes:forward/backward −→ lanes:forward/backward −→ lanes
Furthermore, if the object does not hold any of these keys the program checks if it contains the key oneway.
If it does then the object is handled like a link with one lane but if it does not then a backward direction is
given with one lane.
In OSM no information is given about the width of the lanes. That is why all the footways are 1 meter while
the cycle ways 1.5 meters wide. Most of the car ways are 3.5 meters wide except when a backward direction is
generated as explained in the last paragraph.
The last step before creating a link is generating its coordinates. The way elements of the exported OSM
file are ordered lists of nodes, and each node has its own coordinates. This information can be extracted as
explained above. The problem is that OSM is based on the WGS-84 coordinate system, while VISSIM uses the
Web Mercator, so a transformation must be executed. For this the following equations are used:
Latitude =ln(tan π
4+Latitude in radian
2)) ×Earth radius
Longitude =Longitude in radian ×Earth radius
In Python:
de f C o n ve r t _t o _ me r c at o r ( la t , lo n ) :
RADIUS = 63781 3 7 . 0
l at _ me r = m at h . l og ( m a th . t an ( m a th . p i / 4 + m at h . r ad i an s ( l at ) / 2 )) * R A DI U S
l on _ me r = m at h . r ad i a ns ( l o n ) * R AD I U S
return [ lo n _m e r , la t _m e r ]
The last step creating the link itself, which can be done with the following command:
V is si m . N et . L in k s . Ad d Li n k (K ey , W k tL i ne s tr i ng , L an e Wi d t hs )
where Key is the key of the generated link, WktLinestring contains the coordinates of the points of the link
and LaneWidths is a list with the width of each lane. In this program the key is the ID of the way element in
OSM. The linestring is created with the shapely.geometry.Linestring(list of coordinates) command. The length
of the list given as LaneWidths is equal to the number of lanes, which was already defined as explained above,
just as the value of width. Currently the widths for one link are all equal. The final command:
V is s im . N e t . Li n ks . A d dL i n k ( wa y_ i d , st r ( sg . L in e S t ri n g ( m e r ca t o r ) ) , w id t h s )
where mercator is a list of the transformed coordinates.
The opposite direction (if exists) is created with a specific command, which needs the original link and
the number of lanes (see above) as inputs. For each link generated like this, the attribute Name is set to the
opposite key of the original link. The command with the variables:
Vi s si m . Ne t . L in ks . G e n er a te O p po s it e D ir e ct i on ( V is si m . N et . L in ks . I t em B yK e y ( wa y _i d ) , la n es _ ba c kw a rd )
For later use the links used by vehicles, bikes and pedestrians are sorted in 3 different lists. Also for later
use, the name of the links and that of their opposite direction, which has a common point, are placed into a
list.
3.3 Traffic signal heads
The placing of the signal head starts with accessing the XML-formatted OSM file. Through a cycle it looks for
node objects that have an attribute with the value traffic signals. If it finds one, it saves the object’s ID, and
another cycle looks for way objects that has a reference with the value of this ID. These are the links controlled
5
by the traffic light. In the case of a two-way street, the selected link is the one that’s ending is closer to the
traffic light.
The next thing to do is determine the ID of its signal controller. In general, a new signal controller is
created with an ID equal to the number of signal controllers, but there is an exception. For each traffic light
the program searches for other signal heads within 30 meters. In case it finds one, the ID of the new signal
controller is equal to the ID of the found signal controller. Then, the signal heads’ coordinates are saved in a
dictionary.
The final parameter the program needs to place the signal heads is their position. The first step is finding
the one point of the link that is closest to the traffic light. The program saves the index (X) of this point and
creates a new link with the first X points of the original link. The length of this new link gives the position of the
signal head on the original link. The only problem this way is that the closest point is often inside the junction
the traffic light is controlling, so 5 meters is subtracted from the position. It is not a calculated number, it is
only based on trying out different values. In the case of a link with multiple lanes, a signal head is placed on
each lane.
Now, that the position and the signal controller’s ID are determined, the signal heads can be placed. The
most important commands are the following:
Vi s si m . Ne t . Si gn a lC o nt r ol l er s . A dd S ig n al C on tr o ll e r ( SC _I D )
Vi s s im . N et . S ig n a lC o n tr o l le r s . I t em B yK e y ( S C_ I D ) . SG s . A dd S i gn a l Gr o u p ( le n ( V is s im . Ne t .
S ig n a lC o n tr o l le r s . I t em B yK e y ( S C_ I D ) . SG s ) +1 )
Vi s si m . Ne t . Si g na l He ad s . A dd S ig n al H ea d ( SH _I D , la ne , Li nk s [ - 1] . At t Va l ue ( ’ L en g t h2 D ’ ) -5 )
Links[-1] refers to the new link that helps to determine the signal head’s position. At the and of the cycle
this link is removed from the network:
Vi s s im . N et . Li n ks . Re m o ve L i nk ( L i nk s [ -1 ])
The main steps of placing the signal heads are:
1. Searching for traffic light objects in the OSM file.
2. Searching for the way objects that have the traffic light object’s ID as reference.
3. Searching for other traffic light objects within 30 meters.
4. Determining the signal controller’s ID.
5. Searching for the link’s point closest to the traffic light object’s coordinates.
6. Creating a link that ends at the closest point.
7. Placing the signal heads 5 meters before the new link’s end.
8. Deleting the new link.
3.4 Connectors
For creating connectors between links the program follows the rule that all directions are allowed except in case
of restrictions, which can be found as relation objects in the OSM file. There are two types of restrictions. The
first one forbids certain directions (e.g. no right turn, while the other one allows only one (e.g. only straight on).
These objects contain 3 keys, from,via and to with the value of other objects’ ID. The from and to keys refer
to the way objects that the restriction is for. For later use, these are saved in different lists based on the type
of restriction.
The next step is starting a cycle that goes through the links. The program first checks if the link (henceforth:
Link1) is part of any only type restriction and saves it in a boolean variable named has rest. Another cycle
starts going through the links (henceforth: Link2). If the value of has rest is True, the program checks if the
[Link1, Link2] list can be found in the list containing the only type restrictions. In case the list does not contain
it Link2 is skipped. Link2 is also skipped if [Link1, Link2] is not in the list that contains the link with common
points saved earlier while building the network.
If skipping is not necessary a third cycle is started which examines the points of Link2. The program checks
if any of the points is within 3 or 5 meters (depending on the length of Link1 and Link2) of the first or last
point of Link1. If the first point is, the program handles Link1 as the to object and Link2 as the from object
6
and vice versa if the last point is. However, Link2 is skipped if the [Link1,Link2] pair can be found in the list
containing the no turn type restrictions.
The method of placing the connector is the same in the two cases and similar to the method of placing the
signal heads (see 3.3). If the Link1 is the from object, a cycle searches for the point of Link2 that is closest to
the last point of Link1. After it is found a new link is created with the points of Link2 but ends at the closest
point. The length of this new link gives the position of the connector’s ending point. This position might be
altered depending on the length of Link1 and Link2 and the role of Link1 (from/to). The reason for this change
is partly aesthetics but a more important reason is that in case the first or last point of Link1 and the closest
point have the same coordinates the length of the created connector is 0. The new link created in the process
is deleted at the end of the cycle.
The last part before placing the connector is choosing the number of its lanes and the lanes where the
connector starts and ends. For the first problem, the rule is that the number of lanes is equal to the minimum
number of lanes between Link1 and Link2:
l an e s = min( w ay _ 1 . At t Va l ue ( ’ N u mL a ne s ’ ) , w a y_ 2 . A t t Va l u e ( ’ N um L a ne s ’ ))
The rule for starting and ending lanes is the same. If the connector has only 1 lane, it starts and ends in
the outer lanes while in the case of multiple lanes, it starts and ends in the inner lanes.
Finally, the command to create a connector:
V is si m . N et . L in k s . Ad d Co n n ec t or ( K ey , F ro mL a ne , Fr o mP os , To La n e , T oP o s , N u mb e rO f La ne s ,
W kt L in es t ri n g )
The steps of creating connectors are:
1. Searching for and saving restrictions.
2. Choosing Link1.
3. Searching for restrictions containing Link1.
4. Choosing Link2.
5. Checking if Link1 and Link2 have restrictions or common point.
6. Searching for close points.
7. Searching for the closest point.
8. Creating a new link ending at the closest point.
9. Determining the number of lanes and the starting and ending lanes.
10. Creating the connector.
11. Deleting the link created in step 8.
3.5 Program ending
The last step of creating the input file is saving it. By default, the name the file is saved by is always the name
of the original OSM file. The saving is executed with the following command:
V is s i m . S av e N e tA s ( o s . p at h . j o in ( o s . g e tc w d ( ) , s tr ( o s m_ f il e ) +" . i np x " ))
It is important to note that while the program is running (i.e. before saving) the network cannot be edited
because it may cause program and VISSIM crash.
7
4 A working example
To help understand the process of the program a minimal example is presented in this section. The OSM file
named example can be found in the Working example folder. The coordinates of the example OSM map are
47.51576°, 19.05958°(a junction in Budapest, Hungary) as shown in Fig. 1. Do not forget that the exported/-
Figure 1: Example junction in OSM (47.51576°, 19.05958°)
downloaded OSM file must be in the same folder as the program. After pasting the OSM file into the working
directory the program can be started. First, the GUI opens asking for the name of the OSM file. Do not put
the extension (.osm) on the end of the file’s name, only the name of the file must be given as shown in Fig. 2.
After entering the file name and clicking on the Set button the window closes and VISSIM opens.
Figure 2: GUI for the name of the OSM file
After starting the Start page of VISSIM should be closed (top right corner). At first the world map is shown
but by clicking on Show entire network VISSIM should zoom to the new road network (Fig. 3). The program
starts building the network automatically so it can be observed as the links are placed.
Before going on placing the signal head the network should look like in Fig. 4 without traffic lights and/or
connectors. During the process of generating signal heads new links can be seen that only appear for a moment
before getting deleted. These links are only used temporally for technical reason, to determine the position of
the signal heads (see Section 3.3).
8
Figure 3: Click on Show entire network in VISSIM
Figure 4: Example network before generating signal heads
Fig. 5 depicts the creation of Link-8 to find the position of the signal head placed on the sidewalk before the
crossing. The signal head is placed 5 meters before the end of Link-8. In the next step Link-8 is deleted and
the program searches for the next traffic light in an iterative loop. If all signal heads are generated the network
should look as shown by Fig. 6.
Figure 5: Example for placing a signal head
The last part is creating the connectors between links. If Toggle wireframe is on pink lines should mark the
connectors but, as seen in Fig. 7, they are missing. The program continues by creating the connectors for cycle
ways but in the example junction there are none so it goes right to car ways. Just like in case of the traffic
lights there are links appearing for a second determining the position of the connector’s starting and ending
position. By the end of the program the network should look like in Fig. 8.
If the file is saved it means the program has ended and the network might be edited.
9
Figure 6: Example network after generating the signal heads
Figure 7: Example network without connectors
Figure 8: Example network with connectors
Finally, it is important to note the capability of the program to handle roundabouts. This is not presented
by the above working example, but you can consider an example (Esztergom.osm) in the Examples folder.
10
5 Limitations
Hereby, the known limitation of the program are presented.
5.1 False direction problem
Although the program is capable of building the road network, placing signal heads and creating connectors,
there are limitations that are basically the consequences of the OSM’s imperfection.
During the network creation, the order of link (edge) points is the same as that of the coordinates in the OSM
file but this order does not always give a continuous direction for the given link. As an example consider a part
of the BME.osm file (see Examples folder under https://github.com/bmetrafficlab/OSM2VISSIM) depicted by
Fig. 9 after conversion.
Figure 9: Links with opposite direction before the manual inversion of the directions and connectors
The two links are successive edges in the network but their directions are opposite due to the OSM’s
imperfection. After manually generating the opposite directions and creating the corresponding connectors, the
continuity problem can be resolved. Nevertheless, after this operation the final network might look fallen apart
in VISSIM, and so need manual correction.
Although the issue, presented above, generally does not cause any complication regarding the program’s
operation and it is rather an aesthetic issue, it might still cause some errors in very specific circumstances.
In these special cases, it is suggested to manually remove the problematic edge from the OSM file before the
execution of the program.
5.2 Identical lane width
Another limitation regarding the link generation is the lane width setting. Since usually there is no information
about the lane width in the OSM files, the lane width parameter of the links is set to 3.5 meters identically. A
possible solution to this issue might be to automatically choose the lane width based on the road category that
can be extracted from the OSM file’s highway attribute (this solution is not yet coded in the program).
11
5.3 No gradient modeling
Although VISSIM is capable of height modeling, our program only works in 2D. Fortunately, OSM data contain
restrictions that forbid connections between way objects that are not on the same height, i.e., even if they cross
each other in 2D there will be no connection created between the 2 links.
5.4 Issues of the traffic signal heads
Although for placing the signal heads a working solution was presented (see Subsection 3.3), the generated
positions might be not perfect. During the tests in some of the example files a few signal heads have been
placed inside the junction area. Raising the distance from the link’s end may cause too long distance at other
junctions. Therefore, in these special cases, for now, the problem can only be fixed with additional manual
editing.
In some other cases, the signal heads for pedestrian crossings are duplicated. The reason for this is the OSM
data structure. When searching for signal head objects the program looks for any object that has an attribute
that’s value is traffic signals. There are two types of these objects, one of them being for junctions and the other
one for crossings. In most cases, only one of these belongs to a given link. However, in some other cases, two
objects with the same attribute value traffic signals are saved for a crossing. As an example Fig. 10 is shown
where crossing attribute has the value traffic signals too. Due to this redundancy, duplicated signal heads are
generated in VISSIM. This redundancy can be handled by additional manual editing in VISSIM.
Figure 10: Duplicated signal heads in VISSIM
5.5 Issue on creating connectors
Creating connectors is one of the most critical parts of the program due to the restrictions and specific circum-
stances that are not revealed until testing for the first time. Generally, the program creates all connectors but
it might happen that a connector will be missing in the produced network.
Another issue, when creating connectors, is the relatively high processing time. Due to the loop based
iteration in this part of the program the whole process can last for several minutes depending on the size of
the network. Although the program only checks the links with common points, since it examines every links’
points, the period of the program grows nearly exponentially.
5.6 Manual editing for traffic signal programs and vehicle inputs
Finally, it is noted that manual editing is needed before running the simulation. On the one hand, signal
programs must be created for each of the signal controllers. On the other hand, vehicle inputs must be placed
on the relevant links asn defined as they are not generated automatically.
The simulation can be run without these manual settings, but warnings will be produced by VISSIM.
12
References
[1] D Box. Essential COM. Addison-Wesley, London, 1988. ISBN 0-201-63446-5.
[2] Pablo Alvarez Lopez, Michael Behrisch, Laura Bieker-Walz, Jakob Erdmann, Yun-Pang Fl¨otter¨od, Robert
Hilbrich, Leonhard L¨ucken, Johannes Rummel, Peter Wagner, and Evamarie Wießner. Microscopic traffic
simulation using sumo. In The 21st IEEE International Conference on Intelligent Transportation Systems.
IEEE, 2018.
[3] T. Tettamanti and M.T. Horv´ath. A practical manual for Vissim-COM programming in Matlab and Python
– 5th edition for Vissim version 2020 and 2021, 5th edition, 2021.
[4] R Wiedemann. Simulation des straßenverkehrsflusses. Schriftenreihe des Instituts f¨ur Verkehrswesen der
Universit¨at Karlsruhe, 8, 1974.
13
6 Appendix: the full code of the OSM2VISSIM program
The code is available at github.com/bmetrafficlab/OSM2VISSIM.
# -* - co d in g : utf -8 -* -
"" "
Cr e a t e d o n Tue Ja n 2 0 1 4 : 2 7:03 2023
@a u th o r : to ke s
"" "
import w in 32 c om . c l ie n t as co m
import os
import math
from os g e o import ogr
import sh a pe l y . ge o me t ry a s sg
import xm l . e tr ee . E l em e n tT r ee a s ET
import tk i n t e r a s tk
f il e _ wi n d o w = tk . T k ( c l as s N a me = ’O S M f il e ’ )
f il e _ ca n v a s = tk . Ca n v as ( fi l e _w i nd o w , wi d th =2 5 0 , he i g ht = 20 0 )
f il e _c a nv a s . p ac k ()
f il e _ la b e l = t k . La b e l ( f il e _w i n do w , te x t = ’ E n ter t h e n a me of t he OS M f i le ’ , f on t =( ’ h e l ve t ic a ’, 1 2 )
)
f il e_ c an v as . c r ea t e_ w in d ow ( 12 5 , 50 , wi n do w = f il e_ l ab e l )
f il e _e n tr y = tk . E nt r y ( fi l e_ w in do w , wi d th = 20 , j u st i fy = " r ig h t ")
f il e_ c an v as . c r ea t e_ w in d ow ( 12 5 , 10 0 , wi nd o w = fi l e_ en t ry )
o sm _ l ab e l = t k . L ab e l ( f il e _ wi n do w , t ex t = ’ . os m ’ , fo nt = ( ’ h el v et i c a ’ , 9, ’italic ’) )
f il e_ c an v as . c r ea t e_ wi n do w ( 20 0 , 100 , w i nd ow = o sm _ la b el )
de f Set_osm_file ():
global osm _ f i l e
os m _f i le = f i le _e n tr y . ge t ()
f il e _w i nd o w . de st r oy ( )
f il e _ bu t t o n = tk . Bu t t on ( fi l e _w i nd o w , te x t = ’ Se t ’, c om m an d = S et _ os m _f il e , fo n t =( ’ h e lv e t ic a ’ , 9 , ’
bold’) , bg = ’ b r o wn ’, fg = ’ w h i te ’)
f il e_ c an v as . c r ea t e_ w in d ow ( 12 5 , 15 0 , wi nd ow = f i le _ bu t to n )
f il e_ w in d ow . m a in l oo p ( )
# C re at e b as e . in p x XM L fi le
# f = o pe n ( s tr ( o s m_ f i le ) + " . os m . i np x " , " w +" )
f= open( o s m_ fi l e +" . o sm . in p x " ,"w+")
f . wr it e ( " < ne t w or k >\ n </ n e t wo r k > " )
f . cl os e ( )
# Con n n e c t i n g C O M s e r v e r
Vi s s im = c om . D i sp a t ch ( "Vissim.Vissim")
# Ge t V is s im v e r si o n fo r XM L f il e
Fi l e na m e = o s . pa th . j o in ( o s . ge t cw d ( ) , os m _f i le + " . o sm . i n px " )# in C u r rent Wo r k i n g D i r e c t o ry
Vi s si m . L oa d Ne t ( Fi le n am e , T ru e )
# -- - - Ba s e da ta - -- - - -
# Th i s b ase da t a w e r e a dded i n o r d er to s o l v e f u l f ill an d s o l v e e m pty fil e i s s u e
Vi s s im . N et . V eh i c le C l as s e s . A dd V e hi c l eC l a ss (1 )
# V is s im . N e t . V eh i cl e T yp e s . A d d Ve h i cl e T yp e ( 1 )
# # Vi s si m . N et . Ti m e Di s t ri b u t io n s . A d dT i m eD i s t ri b u ti o n No r m a l (1 )
# # Vi s si m . N et . Dr i v in g B eh a v io r s . A d d Dr i v in g B eh a v io r (1 )
# # Vi s si m . N et . Li n k Be h a vi o r T yp e s . A d dL i n kB e h av i o rT y p e ( 1)
14
# V is s im . N e t . L in k B eh a v io r T yp e s . I t em B y Ke y ( 1 ) . V eh C l as s D ri v B eh a v . A d d Ve h C la s s D ri v i ng B e h av i o r ( V is s im
. Ne t . V e hi c l eC l a ss e s . I t em B yK e y ( 30 ) )
# V is s im . N e t . D is p la y T yp e s . A d d Di s p la y T yp e ( 1 )
# # Vi ss i m . Ne t . Le v el s . A dd L ev el ( 1)
# -- - - - -- - L in k s - - - - -- - - - - -- - - -
# In p u t p a r a m e t e r s t o add l i n k s
dr i v er = o gr . G et D r iv e r By N a me ( ’ O SM ’ )
d at a _s o ur c e = dr iv e r . Op e n ( os m _f i l e + ’. o sm ’ )
tr e e = E T . p a rs e ( o s m _f i l e + ’ . os m ’ )
ro o t = t r ee . g e tr o ot ( )
no_turn_restrictions=[]
only_restrictions=[]
SH _ ID = 1
la y e r = d a t a _s o u rc e . Ge t L a ye r ( ’ l i ne s ’ )
fe a t u re s = [ x fo r xi n l ay er ]
s ho rt _l i nk s =0
Li n ks = []
li n k_ ke y =1
carways=[]
fo o tw ay s =[ ]
c yc le wa ys = []
all_cycleway_coords={}
all_carway_coords={}
c ar wa ys _w i th _c ro s si ng = []
cycleways_with_crossing=[]
pr i nt (’ C r e at i ng li n ks ’)
fo r feature i n f ea t ur e s :
da t a = fe a tu r e . E xp o rt T o Js o n ( a s_ o bj e ct = Tr u e )
way_id=in t ( d at a [ ’ pr o p er t i es ’] [ ’osm_id ’] )
co o rd s = d at a [ ’ g eo m et r y ’ ] [ ’coordinates’]
me r ca to r =[ ]
o th e r_ t ag s = d at a [ ’ p ro p e rt i e s ’ ][ ’ o t he r _t a g s ’ ]
name=data[’ pr o p er t i es ’ ][ ’ n am e ’ ]
hi g h wa y = d at a [ ’ pr o p er t ie s ’ ] [ ’highway’]
hi g hw a ys =[ ’ s t e ps ’ ,’footway’,’ c y c le w a y ’ ,’ mo t o rw a y ’ ,’ t ru n k ’ ,’primary’,’ s ec o n da r y ’ ,’
te r ti ar y ’ ,’unclassified’,’ r e si d e nt a l ’ ,’motoway_link ’,’ t ru n k _l i n k ’ ,’primary_link’,’
secondary_link’,’ t e r ti a r y_ l in k ’ ,’service’,’ t r a ck ’,’ bus_guideway’,’escape’,’raceway ’,
’ ro a d ’ ,’ b us w a y ’ ,’living_street’,’ r es i d en t ia l ’ ]
if highway i n h ig h wa y s :
if o t h e r _ t a g s and (’ " la n es : f o rw ar d " ’ in o t h er_tags o r ’ " l a ne s : b a c kw a r d " ’ in other _ t a g s
or ’ " t ur n : la n es : f o rw ar d " ’ in o t h e r_tags o r ’ " t ur n : la n es : b a c kw a rd " ’ in o t he r_ t ag s ) :
if ’ " t ur n : la n es : f o rw a rd " ’ in o t he r _t a gs :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’, ’)if ’ " t ur n : l an es : fo r wa r d " ’ i n x][0]
lanes_forward=l e n ( fe at [ f e at . r f in d ( ’> ’) +2 : f e at . r fi n d ( ’ " ’) ] . s p li t ( ’ ; ’ ))
tr y :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’,’)if ’ " l a ne s " ’ in x][0]
lanes_backward=i n t ( fe a t [ fe at . r f in d ( ’ > ’) + 2: f e a t . r fi n d ( ’ " ’) ] ) - l a ne s _ f or w a r d
except:
tr y :
15
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’,’)if ’ " t ur n : la n es : b a c kw a rd " ’ in x
][0]
lanes_backward=l e n ( fe a t [ fe at . r f in d ( ’ > ’) + 2: f e a t . r fi n d ( ’"’) ] . s pl i t ( ’ ; ’) )
except:
lanes_backward=0
elif ’" t u rn : l a ne s : b ac k wa r d " ’ i n o t he r_ t ag s :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’, ’)if ’ " t ur n : l an es : ba c k wa r d " ’ i n x][0]
lanes_backward=l e n ( fe a t [ fe at . r f in d ( ’ > ’) + 2: f e a t . r fi n d ( ’ " ’) ] . s p li t ( ’ ; ’ ))
tr y :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’,’)if ’ " l a ne s " ’ in x][0]
lanes_forward=i n t ( fe at [ f e at . r f in d ( ’>’) +2 : f e at . rf i n d ( ’" ’ )])- lanes_backward
except:
tr y :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’,’)if ’ " t ur n : la n es : f o rw a r d "’ in x
][0]
l an e s_ f o rw a r d = le n ( f ea t [ f ea t . rf i nd ( ’ > ’ ) + 2 : f ea t . r f in d ( ’ " ’ ) ]. s p l it ( ’ ; ’ ) )
except:
l an es _f o rw ar d =0
elif ’" l a ne s : fo r wa r d "’ in ot h er _ ta g s :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’, ’)if ’ " l a ne s : f o r wa r d " ’ in x][0]
lanes_forward=l e n ( fe at [ f e at . r f in d ( ’> ’) +2 : f e at . r fi n d ( ’ " ’) ] . s p li t ( ’ ; ’ ))
tr y :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’,’)if ’ " l a ne s " ’ in x][0]
lanes_backward=i n t ( fe a t [ fe at . r f in d ( ’ > ’) + 2: f e a t . r fi n d ( ’ " ’) ] ) - l a ne s _ f or w a r d
except:
tr y :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’,’)if ’ " l a ne s : b a c kw a r d " ’ in x][0]
lanes_backward=l e n ( fe a t [ fe at . r f in d ( ’ > ’) + 2: f e a t . r fi n d ( ’"’) ] . s pl i t ( ’ ; ’) )
except:
lanes_backward=0
elif ’" l a ne s : ba c kw a rd " ’ in o th e r_ t ag s :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’, ’)if ’ " l a ne s : b a c kw a r d " ’ in x][0]
lanes_backward=l e n ( fe a t [ fe at . r f in d ( ’ > ’) + 2: f e a t . r fi n d ( ’ " ’) ] . s p li t ( ’ ; ’ ))
tr y :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’,’)if ’ " l a ne s " ’ in x][0]
lanes_forward=i n t ( fe at [ f e at . r f in d ( ’>’) +2 : f e at . rf i n d ( ’" ’ )])- lanes_backward
except:
tr y :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’,’)if ’ " la n es : f o rw ar d " ’ in x][0]
l an e s_ f o rw a r d = le n ( f ea t [ f ea t . rf i nd ( ’ > ’ ) + 2 : f ea t . r f in d ( ’ " ’ ) ]. s p l it ( ’ ; ’ ) )
except:
16
l an es _f o rw ar d =1
la n es = 0
else:
tr y :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’, ’)if ’ " l a ne s " ’ in x][0]
la n es = int( f ea t [ f ea t . rf i nd ( ’>’) + 2: f e at . r fi n d ( ’" ’ ) ])
except:
la n es = 1
l an es _f o rw ar d =0
lanes_backward=0
de f Convert_to_mercator(lat, lon):
RA D I U S = 6 3 7 8 1 3 7 .0
la t _ me r = m at h . lo g ( ma t h . ta n ( ma t h . pi / 4 + ma th . r a d ia n s ( la t ) / 2) ) * RA D IU S
lo n _m e r = ma th . r a di an s ( l on ) * R A DI U S
return [ lo n _m er , l at _ me r ]
fo r ki n ra n ge (l en ( c o or d s )) :
me r ca t or . a p pe n d ( Co n ve r t _t o _m e r ca t or ( c o or d s [k ] [1 ] , co o rd s [ k ][ 0] ) )
if highway ==’ c y cl e w ay ’:
wi dt h =1 .5
elif highway==’footway’ or highway ==’ s t ep s ’ :
wi d th = 1
elif oth e r _ t a g s a n d ’ " on ew a y " ’ i n o th e r_ t ag s :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’, ’)if ’ " o n ew a y " ’ in x][0]
on e wa y = f ea t [ f ea t . r fi nd ( ’>’) + 2: f e at . r fi n d ( ’" ’ ) ]. s pl i t ( ’;’) [ 0]
if ’ " j u nc t i o n " ’ i n o t he r _t ag s :
oneway=’ y es ’
if oneway ==’ y es ’ :
wi dt h =3 .5
else:
lanes_forward=1
lanes_backward=1
if l an es = =1 :
wi dt h =2 .7 5
else:
wi dt h =3 .5
la n es = 0
elif oth e r _ t a g s a nd n o t (’" o n e wa y " ’ in o t he r_ t ag s ) :
if ’ " j u nc t i o n " ’ i n o t he r _t ag s :
17
tr y :
fe a t = [ x for xin o t h er _ t a gs . sp l i t ( ’,’)if ’ " l a ne s " ’ in x][0]
la n es = int( f ea t [ f ea t . rf i nd ( ’>’) + 2: f e at . r fi n d ( ’" ’ ) ])
wi dt h =3 .5
lanes_forward=0
lanes_backward=0
except:
wi dt h =3 .5
else:
lanes_forward=1
lanes_backward=1
if l an es = =1 :
wi dt h =2 .7 5
else:
wi dt h =3 .5
la n es = 0
else:
wi dt h =3 .5
widths=[]
if w id th = =1 .5 :
ke y _ li s t = li st ( all_cycleway_coords. keys())
v al u e_ l is t = list(all_cycleway_coords.values())
fo r way_1_coords i n coords:
fo r way_2_coords i n v al u e_ l is t :
if way_1_coords i n way_2_coords:
cycleways_with_crossing.append([st r (way_id ), s t r ( ke y _l i st [ v al u e_ l is t .
in d ex ( w a y_ 2 _ co o rd s ) ]) ] )
cycleways_with_crossing.append([’-’+st r (way_id ), s tr ( k e y_ l is t [
v al u e_ l is t . i nd ex ( w ay _ 2_ c oo r ds ) ]) ] )
cycleways_with_crossing.append([st r (way_id ), ’-’+s tr ( k e y_ l is t [
v al u e_ l is t . i nd ex ( w ay _ 2_ c oo r ds ) ]) ] )
cycleways_with_crossing.append([’-’+st r (way_id ), ’-’+s tr ( k e y_ li s t [
v al u e_ l is t . i nd ex ( w ay _ 2_ c oo r ds ) ]) ] )
a ll _ cy c le w a y_ c oo r ds [ wa y _i d ] = co o rd s
elif wi dt h == 3. 5 or w id th = =2 .7 5:
ke y _ li s t = li st ( a l l_ c ar w ay _ co o rd s . ke y s () )
v al u e_ l is t = list( a l l_ c a r w ay _ c o or d s . v a l ue s () )
fo r way_1_coords i n coords:
fo r way_2_coords i n v al u e_ l is t :
if way_1_coords i n way_2_coords:
18
c ar w ay s _w i t h_ c ro s s in g . a pp e nd ( [ st r (way_id ), s tr ( k e y_ l is t [ v al u e_ l is t .
in d ex ( w a y_ 2 _ co o rd s ) ]) ] )
c ar w ay s _ wi t h_ c r os s in g . a pp e nd ([ ’-’+str(way_id), s tr ( k e y_ l is t [ v al ue _ li s t
. in d ex ( w a y _2 _ co o rd s ) ] ) ])
c ar w ay s _w i t h_ c ro s s in g . a pp e nd ( [ st r (way_id ), ’-’+s tr ( k e y_ l is t [ v al ue _ li s t
. in d ex ( w a y _2 _ co o rd s ) ] ) ])
c ar w ay s _ wi t h_ c r os s in g . a pp e nd ([ ’-’+str(way_id), ’-’+str( k e y_ l is t [
v al u e_ l is t . i nd ex ( w ay _ 2_ c oo r ds ) ]) ] )
a ll _c a rw ay _ co o rd s [ wa y_ id ] = co o rd s
if l an e s_ fo rw ar d == 0:
fo r ki n ra n ge ( l an e s ):
wi d th s . a pp e nd ( w id t h )
else:
fo r ki n ra n ge ( l an e s_ f or w ar d ) :
wi d th s . a pp e nd ( w id t h )
Li n ks . a p pe nd (
Vi s s im . N et . Li n ks . Ad d L in k ( w ay _i d , st r ( sg . L i n e St r i ng ( m er c a to r ) ) , w id t h s )
)
Li n k s [ - 1] . S e t A tt V a lu e ( ’ N a m e ’ , way_id)
if w id th = =3 .5 o r w id th = =2 .7 5:
ca r wa y s . ap p en d ( Li n ks [ -1 ])
elif wi dt h == 1. 5:
c yc l ew a ys . a p pe nd ( Li n ks [ -1 ])
else:
fo o tw a ys . ap p en d ( L in k s [ -1 ])
if l an e s_ fo rw ar d != 0:
Li n ks . a p pe nd (
Vi s si m . Ne t . L in ks . G e n er a te O p po s it e D ir e ct i on ( V is si m . N et . L in ks . I t em B yK e y ( wa y _i d ) ,
lanes_backward)
)
Li n k s [ - 1] . S e t A tt V a lu e ( ’ N a m e ’ , -way_id)
if w id th = =3 .5 o r w id th = =2 .7 5:
ca r wa y s . ap p en d ( Li n ks [ -1 ])
elif wi dt h == 2:
c yc l ew a ys . a p pe nd ( Li n ks [ -1 ])
else:
fo o t wa y s . ap p en d ( Li n ks [ -1 ])
li n k_ k ey = l i nk _ ke y +1
li n k_ k ey = l i nk _ ke y +1
pr i nt (’ C r e at i ng si g na l h e ad s ’ )
l am p_ co or ds = {}
19
fo r n o d es in root :
if n o de s . ta g == ’ n o d e ’ :
fo r node i n n od e s :
if n o de . at t r ib [ ’v ’ ] == ’ t r a ff i c_ s i gn a l s ’ :
la m p_ i d = no d es . a tt r ib [ ’ id ’ ]
fo r ways i n root:
if w a ys . t ag == ’ w ay ’ :
fo r way i n ways:
if ’ r ef ’ in w ay . a t t ri b an d w ay . a t tr i b [’ r ef ’ ]= = l am p _i d :
SC _ ne a r = Fa l se
way_id=ways.attrib [’ i d ’]
fo r coords i n lamp_coords:
if math.dist(Convert_to_mercator( f lo a t ( no de s . a tt ri b [ ’ la t ’
]) , f lo at ( n o de s . a tt r ib [ ’ lo n ’ ]) ) , l am p _ co o r d s [ c oo r d s ]) < 30 :
SC _ ID = list ( l am p _ co o rd s ) . in de x ( c oo r ds ) + 1
SC _ n ea r = T ru e
br e a k
if n ot ( SC_near):
SC _ ID = len( V i ss i m . Ne t . S i gn a l Co n t ro l l er s ) + 1
Vi s si m . Ne t . Si gn a lC o nt r ol l er s . A dd S ig n al C on tr o ll e r ( SC _I D )
Vi s s im . N et . S ig n a lC o n tr o l le r s . I t em B yK e y ( S C_ I D ) . SG s .
AddSignalGroup(l e n ( Vi s si m . N et . S ig n a lC o n tr o l le r s . I t em B yK e y ( S C_ I D ) . SG s ) +1 )
l in k _f o un d = F al s e
fo r link i n V is s im . N e t . Li n ks :
if l in k . A tt V al ue ( ’ N a me ’) = = w a y_ i d :
# if li n k . La ne s . G et A ll ( ) [ 0] . A tt V al u e ( ’ Wi dt h ’ ) == 3 .5 a nd
no d e . at tr i b [’ k ’] == ’ c r os s in g ’ :
# co n t i n u e
l in k po l y pt s _1 = l i nk . L i n kP o ly P ts . G et A ll ( )
l in k _f o un d = T ru e
br e a k
if n ot ( l i nk _ fo u nd ) :
co n t i n u e
fo r link i n V is s im . N e t . Li n ks :
if l in k . A tt V al ue ( ’ N a me ’) = = ’-’+way_id :
l in k po l y pt s _2 = l i nk . L i n kP o ly P ts . G et A ll ( )
20
on e wa y = F al s e
br e a k
else:
on e wa y = T ru e
l in k_ st a rt _1 = [ li nk p ol yp ts _ 1 [ -1] . At t Va lu e (’ X ’ ) , li n k po l y p ts _ 1
[ - 1] . A t tV a l ue ( ’Y ’ ) ]
tr y :
l in k_ st a rt _2 = [ li nk p ol yp ts _ 2 [ -1] . At t Va lu e (’ X ’ ) ,
l in k p o ly p t s_ 2 [ - 1] . A t tV a l ue ( ’Y ’ ) ]
except:
pass
if oneway :
l in k_ n am e = w ay _ id
else:
if math.dist(Convert_to_mercator( f lo a t ( no de s . a tt ri b [ ’ la t ’
]) , f lo at ( n o de s . a tt r ib [ ’ lo n ’ ]) ) , l in k _ st a r t _1 ) < ma t h . d is t ( C o n v er t _ t o_ m e r c at o r ( f l oa t ( n od es .
attrib[’ l at ’ ]) , f lo a t ( no de s . a tt r ib [ ’ l on ’ ])), link_start_2):
l in k_ n am e = w ay _ id
else:
l in k _ na m e = ’ - ’ +way_id
fo r link i n V is s im . N e t . Li n ks :
tr y :
if l in k . A tt V al ue ( ’ N a me ’) = = l i n k_ n a me :
p ol yp o in t s = li nk . L i nk Po l yP t s . Ge tA l l ()
fo r point_index i n ra n ge (len( p ol yp o in t s )) :
if p oi n t_ in de x != 0:
if math.dist(Convert_to_mercator( f loa t
( no d es . a t tr ib [ ’ l at ’ ]) , f lo at ( n o de s . a tt r ib [ ’ lo n ’ ]) ) , [p o l y po i n ts [ p o in t _ in d e x ] . A t tV a l ue ( ’X ’ )
, po l y po i n ts [ p oi n t _ in d e x ] . A t tV a l ue ( ’Y ’ ) ]) < m a th . d is t ( C o nv e r t_ t o_ m e rc a t or ( f l oa t ( n od es . a t tr i b
[’ la t ’] ) , fl oa t ( n od e s . at tr i b [ ’l o n ’] ) ) , [ po l y po i n t s [ p oi n t _i n de x - 1 ]. A tt V a l ue ( ’ X ’ ) ,
p ol y p oi n t s [ p o in t _i n d ex -1] . At t V al u e ( ’ Y ’ ) ]) :
c lo se s t_ p oi n t = po l yp o in t s [
p oi nt _ in d ex ]
else:
pass
p oi n ts _ fo r _ li n k = p ol y po i nt s [ 0: p ol y po i nt s . i nd e x (
c lo s es t _ po i n t ) +1 ]
c oo rd s_ fo r _l in k =[ ]
fo r p o i nt in r a ng e (le n ( p oi n ts _ fo r _l i nk ) ) :
c oo rd s _f o r_ l in k . a pp en d ([ p oi n ts _ fo r_ l in k [
po i n t ]. A tt V a lu e ( ’ X ’ ) , po i n ts _ f o r_ l i n k [ p o in t ] . A t tV a l ue ( ’Y ’ ) ] )
21
Li n ks . a p pe nd (
Vi s s im . N et . Li n ks . Ad d L in k ( 0 , st r (s g .
L in e S tr i n g ( c o o rd s _ f or _ l i nk ) ) , [ 3 . 5] )
)
fo r lane i n l in k . L an es :
Vi s s im . N et . S ig n al H e ad s . A d d Si g n al H e ad ( S H _I D
, lan e , Li n ks [ -1 ] . A t tV a l ue ( ’ Le n g th 2 D ’ ) -5 )
Vi s s im . N et . S ig n al H e ad s . I t e mB y Ke y ( S H _I D ) .
S et A t tV a l u e ( ’ SG ’ , Vi ss i m . Ne t. S ig n al C on t ro l le r s . It e mB y Ke y ( SC _ ID ) . SG s . It e mB yK e y ( len(Vissim .
Ne t . S i gn a l Co n t r ol l e rs . It e m By K e y ( SC _ ID ). S G s ) ))
SH _ ID = S H _I D +1
Vi s s im . N et . Li n ks . Re m o ve L i nk ( L i nk s [ -1 ])
if n ot ( lamp_id in la m p_ c oo r ds ) a nd n ot ( SC_near):
l am p _ co o r d s [ n od e s . a t tr i b [ ’ id ’ ]]=
Convert_to_mercator(f l oa t ( n od es . a t tr i b [’ l at ’ ]) , f lo a t ( no d es . a tt r ib [ ’ lo n ’] ) )
except:
pass
fo r relations i n root:
if r e la t i on s . t ag == ’ r e la t i on ’:
fo r r e l a t i on in r e la t io n s :
if ’ k ’ in r el a ti o n . at t ri b :
if r e la t io n . a tt ri b [ ’ k ’ ]= = ’ re s t ri c t io n ’ an d ( r e l a ti o n . a t tr i b [ ’ v ’ ]==’
n o_ ri gh t _t ur n ’ o r r e la ti o n . at t ri b [ ’v ’] = = ’no_left_turn’) :
fo r ways i n r el a ti o ns :
if ’ r o le ’ i n w ay s . a tt r ib :
if w a ys . at t r ib [ ’ ro l e ’ ] == ’ f ro m ’ :
f ro m _w a y _i d = i nt ( w a ys . a t tr i b [ ’r e f ’ ])
if w a ys . at t r ib [ ’ ro l e ’ ] == ’ to ’ :
t o_ w ay _ i d = int( w ay s . a tt r ib [ ’ r ef ’ ])
else:
co n t i n u e
n o_ t ur n _r e s tr i ct i on s . a p pe nd ([ f r om _ wa y_ i d , t o_ w ay _ id ])
n o_ t ur n_ r es t ri c ti o ns . a pp e nd ( [ - fr om _w a y_ id , t o_ w ay _i d ] )
n o_ t u rn _ r es t r i ct i o ns . a pp e nd ([ fr o m_ w ay _ i d , - t o_ w a y_ i d ] )
n o_ t ur n_ r es t ri c ti o ns . a pp e nd ( [ - fr om _w a y_ id , - to _ wa y _i d ])
if r e la t io n . a tt ri b [ ’ k ’ ]= = ’ re s t ri c t io n ’ an d ( r e l a ti o n . a t tr i b [ ’ v ’ ]==’
only_straight_on’ o r r el a ti o n . at t ri b [ ’v ’ ] == ’ o n l y_ r i gh t _t u r n ’ or r el a ti o n . at t ri b [ ’v ’ ] == ’
only_left_turn’) :
fo r ways i n r el a ti o ns :
if ’ r o le ’ i n w ay s . a tt r ib :
if w a ys . at t r ib [ ’ ro l e ’ ] == ’ f ro m ’ :
f ro m _w a y _i d = i nt ( w a ys . a t tr i b [ ’r e f ’ ])
22
if w a ys . at t r ib [ ’ ro l e ’ ] == ’ to ’ :
t o_ w ay _ i d = int( w ay s . a tt r ib [ ’ r ef ’ ])
else:
co n t i n u e
o nl y _r e st r ic t i on s . a pp en d ( [ fr o m_ w ay _i d , to _ wa y _i d ] )
o nl y _r es t ri c ti o ns . a p pe nd ( [ - fr om _w a y_ id , t o_ w ay _ id ] )
o nl y _ re s t ri c t io n s . a p pe n d ( [ fr o m _w a y_ i d , - t o_ w a y_ i d ] )
o nl y _r es t ri c ti o ns . a p pe nd ( [ - fr om _w a y_ id , - t o_ wa y _i d ])
de f C r ea t e_ c on n ec t or s ( w a y_ ty p e ):
if w a y_ t yp e == c ar wa y s :
w ay _2 _ li s t = ca r wa y s_ w it h _c r o ss i ng
pr i nt (’ C r e at i ng ca r wa y c o nn e c to r s ’ )
elif wa y _t y pe = = c yc l ew ay s :
w ay _2 _ li s t = cy c le w ay s _w i t h_ c ro s si n g
pr i nt (’ C r e at i ng cy c l ew a y c on n e ct o r s ’ )
s er ia l_ n um be r =0
p er ce nt ag es = []
fo r w a y _1 in w a y_ t yp e :
p er c en t a ge = s er i a l_ n u mb e r / len( w a y_ t yp e ) *1 0 0
if i nt ( p e rc e nt a ge ) % 1 0= = 0 an d no t (in t ( p er c en t ag e ) in p er c en t ag e s ):
p er c en t a ge s . a p pe n d ( int( p e rc e nt a ge ) )
pr i nt (" % . 2 f" %in t ( p er c en t ag e ) +"%")
s er ia l _n u mb e r = se r ia l _n u mb er +1
if o nl y _r es tr ic ti on s != [] :
fo r restriction i n only_restrictions:
if r e st ri ct i on [ 0] == int ( w ay _1 . At t Va l ue ( ’ Na m e ’ )):
ha s _ re s t = Tr u e
br e a k
else:
ha s _r e st = Fa l se
else:
ha s _r e st = Fa l se
l in k po l yp t s_ 1 = w ay _ 1 . Li n k Po l yP t s . Ge t Al l ( )
c oo rd _ x_ 1 = l in kp o ly p ts _ 1 [ -1 ]. A t tV a lu e ( ’X ’ )
c oo rd _ y_ 1 = l in kp o ly p ts _ 1 [ -1 ]. A t tV a lu e ( ’Y ’ )
w ay _ 1 _s t a r t = [ l in k p o ly p t s _1 [ 0] . A t t V al u e ( ’ X ’) , l i nk p o l yp t s _ 1 [ 0] . At t V al u e ( ’ Y ’ )]
23
fo r w a y _2 in w a y_ t yp e :
if w a y_ 2 . A t t V al u e ( ’ L en g t h2 D ’ ) < =5 or w ay _1 . A t tV a lu e ( ’ Le n gt h 2 D ’ ) <= 5:
di s t =3
else:
di s t =5
if [ w a y_ 1 . A tt V al u e (’ N a m e ’ ) , w a y _2 . At t V al u e ( ’ N a me ’) ] i n w a y _ 2 _ l ist or [ w a y_ 2 .
At t V a lu e ( ’ N a me ’) , w ay _ 1 . A t tV a l ue ( ’ Na m e ’ ) ] in w a y_ 2 _l i st :
pass
else:
co n t i n u e
if has_rest a nd n ot ( [ int( w ay _ 1 . At t Va l ue ( ’ N a me ’) ) , int( wa y _2 . A t tV a lu e ( ’ N am e ’ ) ) ] in
only_restrictions):
co n t i n u e
fo r linkpoly_2_index i n ra n ge (len( wa y _2 . L i nk P ol y P ts . G e tA ll () ) ) :
l in kp o ly _ 2 = wa y_ 2 . L in k Po ly P ts . G e tA ll ( ) [ li n kp o ly _ 2_ i nd e x ]
c oo rd _ x_ 2 = l in k po l y_ 2 . A tt Va l ue ( ’ X ’ )
c oo rd _ y_ 2 = l in k po l y_ 2 . A tt Va l ue ( ’ Y ’ )
if linkpoly_2_index !=l en ( w a y_ 2 . Li n kP o ly Pt s . G et Al l ( )) -1 and w ay _1 ! = wa y_ 2 an d
in t ( w a y_ 1 . A t t Va l u e ( ’ Na m e ’ ) ) != - int( w a y_ 2 . A t t Va l u e ( ’ N am e ’ ) ) a nd n ot ( [ in t ( w ay _ 1 . A t tV a l ue ( ’
Name’) ) , int( wa y _2 . A t tV a lu e ( ’ N am e ’ ) ) ] in no_turn_restrictions) a n d m at h . di s t ([ c o or d _x _ 1 ,
c oo r d _y _ 1 ] , [ co o r d_ x _2 , c o o rd _ y _2 ]) < di s t :
p ol yp o in t s = wa y_ 2 . L in k Po ly P ts . G e tA ll ( )
p oi nt s_ fo r _l in k =p ol y po in ts [ 0: l in kp ol y _2 _i nd ex + 1]
c oo rd s_ fo r _l in k =[ ]
fo r p o i nt in r a ng e (le n ( p oi n ts _ fo r _l in k ) ) :
c oo rd s _f o r_ l in k . a pp en d ([ p oi n ts _ fo r_ l in k [ p oi nt ] . A tt Va l ue ( ’ X ’) ,
p oi n t s _f o r _ li n k [ p o in t ] . A t t Va l u e ( ’ Y ’) ] )
if linkpoly_2_index !=0:
Li n ks . a p pe nd (
Vi s s im . N et . Li n ks . Ad d L in k ( 0 , st r (s g . L i n eS t r in g ( c oo r d s _f o r _ li n k ) ) ,
[3.5])
)
la n es = min( w ay _ 1 . At t Va l ue ( ’ N u mL a n es ’) , w ay _ 2 . A t tV a l u e ( ’ Nu m L an e s ’ ))
if l an es = =1 :
lane_connection_1=1
lane_connection_2=1
else:
l an e _c o nn e c ti o n_ 1 = w ay _ 1 . At t Va l ue ( ’ N u mL a n es ’ )- l a n es +1
l an e _c o nn e c ti o n_ 2 = w ay _ 2 . At t Va l ue ( ’ N u mL a n es ’ )- l a n es +1
if linkpoly_2_index !=0 and linkpoly_2_index!=len( w ay _ 2 . Li n kP o l yP t s . Ge t Al l
() ) -2 :
c on n e ct _ p o s = L in k s [ - 1 ]. At t V al u e ( ’ L e ng t h2 D ’ ) + 5
24
elif linkpoly_2_index!=0:
c on n e ct _ p o s = L in k s [ - 1 ]. At t V al u e ( ’ L e ng t h2 D ’ ) + 1
else:
if w a y_ 2 . A t t V al u e ( ’ L en g t h2 D ’ ) < 3:
c on ne ct _ po s =1
elif wa y _2 . A t tV al u e ( ’L e n gt h 2 D ’) < 5:
c on ne ct _ po s =2
else:
c on ne ct _ po s =5
Vi s si m . N et . L in k s . Ad d Co n ne c t or ( 0 , wa y _1 . L an e s . It e mB y Ke y ( l a ne _ c on n ec t io n _ 1 ) ,
wa y _ 1 . A tt V a l ue ( ’ Le n g th 2 D ’ ) , w a y _2 . La n e s . I te m B yK e y ( l a n e _ co n n e ct i o n _2 ) , co nn e c t_ p o s , l an e s ,
’ L IN E ST R I NG E M PT Y ’ )
if linkpoly_2_index !=0:
Vi s si m . N et . L in k s . Re m ov e Li n k ( Li n ks [ - 1 ])
br e a k
if linkpoly_2_index !=l en ( w a y_ 2 . Li n kP o ly Pt s . G et Al l ( )) -1 and linkpoly_2_index!=
le n ( w ay _2 . L i nk Po l yP t s . Ge tA l l () ) -2 a nd linkpoly_2_index!=1 and linkpoly_2_index !=0 an d
wa y _1 ! = wa y_ 2 and int( w ay _ 1 . At t Va l ue ( ’ N a me ’) ) ! = - i nt ( w a y _2 . At t V al u e ( ’ N a me ’) ) a nd n ot ( [ int(
wa y _ 2 . A tt V a l ue ( ’ Na m e ’ ) ) ,int ( w ay _ 1 . At t Va l ue ( ’ N a me ’) ) ] i n no_turn_restrictions) an d math .
di s t ( w a y_ 1 _ st a r t , [ c o o rd _ x_ 2 , c oo r d _ y_ 2 ]) < d i st :
p ol yp o in t s = wa y_ 2 . L in k Po ly P ts . G e tA ll ( )
p oi nt s_ fo r _l in k =p ol y po in ts [ 0: l in kp ol y _2 _i nd ex + 1]
c oo rd s_ fo r _l in k =[ ]
fo r p o i nt in r a ng e (le n ( p oi n ts _ fo r _l in k ) ) :
c oo rd s _f o r_ l in k . a pp en d ([ p oi n ts _ fo r_ l in k [ p oi nt ] . A tt Va l ue ( ’ X ’) ,
p oi n t s _f o r _ li n k [ p o in t ] . A t t Va l u e ( ’ Y ’) ] )
if linkpoly_2_index !=1:
Li n ks . a p pe nd (
Vi s s im . N et . Li n ks . Ad d L in k ( 0 , st r (s g . L i n eS t r in g ( c oo r d s _f o r _ li n k ) ) ,
[3.5])
)
la n es = min( w ay _ 1 . At t Va l ue ( ’ N u mL a n es ’) , w ay _ 2 . A t tV a l u e ( ’ Nu m L an e s ’ ))
if l an es = =1 :
lane_connection_1=1
lane_connection_2=1
else:
l an e _c o nn e c ti o n_ 1 = w ay _ 1 . At t Va l ue ( ’ N u mL a n es ’ )- l a n es +1
l an e _c o nn e c ti o n_ 2 = w ay _ 2 . At t Va l ue ( ’ N u mL a n es ’ )- l a n es +1
c on n e ct _ p o s = L in k s [ - 1 ]. At t V al u e ( ’ L e ng t h2 D ’ ) - 3
Vi s si m . N et . L in k s . Ad d Co n ne c t or ( 0 , wa y_ 2 . L an e s . It e mB y Ke y ( l an e _ co n ne c t io n _2 ) ,
co n ne c t_ p os , wa y _1 . L a ne s . I te m By K ey ( l a n e_ c on n ec t i on _ 1 ) , 3 , la ne s , ’ L IN E ST R I NG E M PT Y ’ )
25
if linkpoly_2_index !=0:
Vi s si m . N et . L in k s . Re m ov e Li n k ( Li n ks [ - 1 ])
br e a k
C re a te _ co n ne c to r s ( cy c le w ay s )
pr i nt (’100.0%’)
C re a te _ co n ne c to r s ( c ar wa y s )
pr i nt (’100.0%’)
Vi s s im . S av e N et A s ( o s . p at h . j o in ( o s . g e tc w d ( ) , os m _f i l e + " . in px " ) )
26