We can have road networks of the countries in GIS shape file.For exmple from here. Normally traffic flows are proportionate to populations of the cities.
I wonder how we can have the same in Mathematica?Is it possible at all?
Mathematica Stack Exchange is a question and answer site for users of Wolfram Mathematica. It only takes a minute to sign up.
Sign up to join this communityWe can have road networks of the countries in GIS shape file.For exmple from here. Normally traffic flows are proportionate to populations of the cities.
I wonder how we can have the same in Mathematica?Is it possible at all?
I chose to use the Australian data for patriotic reasons.
Going to the web site you suggested, it is straightforward to get the data for the Australian roads network. On unpacking the resulting ZIP file, there are four files: AUS_roads.dbf, AUS_roads.prj, AUS_roads.shp and AUS_roads.shx. Mathematica supports .shp import, so it is a simple matter of doing the following:
SetDirectory["~/Downloads/AUS_rds"];
initialdata = Import["AUS_roads.shp"]
(That little dot in the bottom right corner must be an anomaly. I can't find a matching inhabited island on Google Maps.)
The underlying data does not seem to include traffic flow data so I will have to make up the next bit. You would need to translate the underlying Graphics
output into something you can use as a graphics visualisation. This rather complex piece of code does that:
rules = #1 -> #2 & @@@ (Join @@ (Partition[#, 2, 1] & /@
(initialdata[[1, 2, 1, 2]] /. Line -> Sequence)));
What I'm doing here is picking out the pieces of the graphic that represent the red lines’ coordinates; I looked at the InputForm
of initialdata
to get the right Part
specification. I used the replacement rule to convert this into lists of points instead of lines, and then use Partition
to convert this in to pairs of points that are connected. I can then translate that into rules suitable for use in Graph
or GraphPlot
with the pure function #1 -> #2
that is applied at the row level (@@@
).
There are about a quarter of a million pairs of coordinates, so here is a small sample:
In[28]:= Take[rules, 10]
Out[28]= {{142.162, -10.1571} -> {142.149, -10.1496}, {142.149, \
-10.1496} -> {142.138, -10.1469}, {142.138, -10.1469} -> {142.125, \
-10.1378}, {142.125, -10.1378} -> {142.117, -10.1383}, {142.117, \
-10.1383} -> {142.111, -10.1291}, {142.111, -10.1291} -> {142.103, \
-10.1257}, {142.103, -10.1257} -> {142.101, -10.1212}, {142.101, \
-10.1212} -> {142.102, -10.114}, {142.102, -10.114} -> {142.099, \
-10.1094}, {142.33, -10.1855} -> {142.324, -10.1873}}
It should be possible to respecify this as a Graph
using something like the following:
Graph[Thread[Range[Length[rules]] -> Range[2, Length[rules] + 1]],
VertexCoordinates -> (Join[rules[[All, 1]], {rules[[-1, 2]]]})]
Here is an example where I only showed the first 101 points. Note the use of the undirected edge symbol. You could alternatively just turn off arrow heads.
Graph[Thread[Range[100] \[UndirectedEdge] Range[2, 101]],
VertexCoordinates -> (Join[rules[[1 ;; 100, 1]], {rules[[100, 2]]}])]
To get some ideas on how to get varying edge thicknesses, have a look at the answers to this question.