-
Notifications
You must be signed in to change notification settings - Fork 0
Module 5a, Working with networks over a road network
learning objective: How to use the GeoDMS to calculate with networks
In this module, we will use the OpenStreetMap network and population data and Dutch intercity train stations, to calculate the number of people that can be reached within a set amount of time by car from each intercity train station. However, first, we must prepare the network since the downloaded OSM is just a set of lines with a typology. We must make sure that the network is connected and, therefore, we connect the origin and destination point sets to the network. For this purpose, we use a script that is quite extensive but necessary. In this section, you will build the script needed, and be guided through the more complex aspects of the script. In that way, you will be able to understand the different steps and begin to understand the GeoDMS logic behind it.
Before we begin, if you haven't downloaded the configuration yet, you can find it here. And open the networks_car configuration.
For this example, we will calculate the number of people that can be reached within a set amount of time by car from each intercity train station. For that, we need several components: a point data set containing intercity train stations, a point set with population data, and an arc data set of a car network.
Go to the configuration file. Here, you'll see an empty SourceData container. Here, you will create three units: Inhabitants, Train_stations, and Car_network. If you are not sure how to configure this, look at [Module 2, Working with different data sources]
-
Inhabitants, pointset in shapefile format, located at %ProjDir%/Data/Inwoners_2019_500m.shp. You should configure three attributes in this unit:
- geometry, with a rdc ValuesUnit.
- Inwoners_2, with a int32 Value Type (the number of characters in a name field of a shapefile is limited and cut off., In this case, the last three characters, '019', were cut off).
- Inhabitants_2019, with an int32 Value Type (this is not extremely necessary, but translates it to English like the rest of the configuration. And adds the full year for clarification reasons).
-
Train_stations, pointset in fss format, located at %ProjDir%/Data/IC_Stations_2019.fss
- geometry, with a rdc ValuesUnit.
- label, with a String Value Type
-
Car_network, arc set in fss format, located at %ProjDir%/Data/car_network_20200117_NL.fss
- line, which is an arc set, with a rdc ValuesUnit.
- wegtype, (Dutch for road type), with the ValuesUnit classifications/OSM/roadtype .
- maxspeed, with the int32 ValuesUnit.
Next, head to the analysis container. Here, create three units named org, dest, and network. We create those to make the input for the analysis easier to change and more robust to changes. They are simply redirections to the origin and destination domains that you have configured in the SourceData. The Value Type should be equal to the one configured in the SourceData, in this case uint32. The expression is simply a redirection, so the path of the domain, i.e. SourceData/Train_stations.
In this way, you can access sub-items from SourceData/Train_stations by simply referring to, for example, org/geometry. This is not necessary, but makes the code shorter and, more importantly, it makes the code more versatile and easier to change. When, for example, you change the origin point set to something else. Only the unit org has to change instead of all the references to items in org.
Furthermore, we will create a parameter, MaxTravelTime, that will be used later to refer to the number of seconds we want the maximum travel time to be. Since we are going to express it in seconds, the ValuesUnit should also indicate seconds. Look in the container with units to see which ones are already configured. In this case, we want the maximum travel time to be 30 minutes, so 1800 seconds. Just typing 1800 as the expression will give an error. As you might have read before, that would result in the default Value Type uint32. To make it seconds, you could type value(1800, s), or shorter version 1800[s]. Both methods convert the uint32 number 1800 to a number with the ValuesUnit s.
parameter<s> MaxTravelTime := 1800[s]; // 1800 seconds is 30 minutes
Now, it is time to create the network. For this, we will make use of a template that is already present in your downloaded project folder. It is called MakeNetwork and is located in the folder Templates. This template is quite complex to go over at this stage. However, if you are interested to see how it works, look here: Annex I: How to make a network.
What we are going to do is simply use that template. This is called template instantiation. A template is a set of calculation rules with at least one case parameter. In this case, the calculation rules create a usable network. This specific template needs seven arguments:
- The origin domain
- The destination domain
- The network domain
- The path to the origin point geometry
- The path to the destination point geometry
- The path to the network arc geometry
- A string value that indicates which transportation mode we are going to use. In this example, we will use the car.
A template is always instantiated using a container, and then the template name is followed by all its arguments. In this case, this will look like this:
container NetworkSpec := templates/MakeNetwork(
org
, dest
, network
, org/geometry
, dest/geometry
, network/geometry
, 'car'
);
The template MakeNetwork passes along the configured set of case parameters. This particular template needs 7 case parameters. What case parameters are needed is configured at the beginning of the template itself and looks like this:
template MakeNetwork
{
// begin case parameters
unit<uint32> orgDomain;
unit<uint32> destDomain;
unit<uint32> roadDomain;
attribute<rdc> orgLocations (orgDomain);
attribute<rdc> destLocations (destDomain);
attribute<rdc> roads (arc, roadDomain);
parameter<string> network_type;
// end case parameters
...
}
So, this template interprets the first seven arguments as these units/attributes/parameters. Within this template, you can refer to these case parameters as you would refer to any other item.
If you want to deep dive into how the network is created, go to the following page I: How to make a network. Otherwise, we skip that part for now and continue with the created network.
So, at this point, the network is created. We have roads, origin points, destination points, and roads connecting both pointsets to the road network. Furthermore, we have created a link set of each road segment and its corresponding impedance (or travel speed). With this done, we can actually begin the analysis. The first analysis we will do is calculate the number of people that can be reached from each train station within 30 minutes. For this case, we will use an impedance algorithm (we will not go into that at this point) and is specified with a couple of options. In this case, a string with several settings separated by a semi-colon additional settings for an option are specified using a colon. This string is followed by seven arguments separated by a comma:
impedance_matrix_od64('bidirectional(link_flag);startPoint(Node_rel):max_imp;endPoint(Node_rel);cut(OrgZone_max_imp);od:OrgZone_rel,DstZone_rel'
- The first argument is bidirectional(link_flag); this tells the algorithm that all roads are bidirectional except those specified using the link flag. The term between brackets shows that we need to give it some value. So, we give an argument which tells it which segments are not bidirectional. Those are the links that are motorways or motorway links.
- The second argument, startPoint(Node_rel):max_imp, tells the algorithm the index number of the origin points, the nr_orgNode. The additional term max_imp says that we want the maximum impedance from each origin point to each destination point.
- Third, endPoint(Node_rel), these are the index numbers of the destination points, the nr_destNode.
- Fourth, cut(OrgZone_max_imp), in this analysis, we want the algorithm to stop at a certain value. We want to know how many destinations can be reached within a set amount of time. So, we cut the search short at the maximum time (impedance) from the origin location.
- And lastly, od:OrgZone_rel,DstZone_rel, this argument tells the algorithm what information we want to see as output. In this case, we want to have for each origin point the reached destinations. So we ask for the OrgZone_rel and the DstZone_rel.
After the string with options, the arguments are listed. The first three are always required, no matter which settings you use: impedance, F1 and F2. That is the impedance (travel time in seconds) over a link (a connection between two points), and the F1 and F2 are the beginning and endpoints of said link. Then, the four arguments that are needed for the specified options we gave (the ones between brackets) are link_flag, nr_orgNode, nr_destNode, and MaxTravelTime.
unit<uint64> Impedance_cut :=
impedance_matrix_od64('bidirectional(link_flag);startPoint(Node_rel);endPoint(Node_rel);cut(OrgZone_max_imp);od:OrgZone_rel,DstZone_rel'
, NetworkSpec/impedance
, NetworkSpec/F1
, NetworkSpec/F2
//////
, NetworkSpec/LinkSet/roadtype!= OSM/roadtype/motorway
&& NetworkSpec/LinkSet/roadtype!= OSM/roadtype/motorway_link
, NetworkSpec/OrgToDest/nr_orgNode
, NetworkSpec/OrgToDest/nr_destNode
, MaxTravelTime
);
This operator creates now two attributes: OrgZone_rel and DstZone_rel as already explained above. These two items provide a lot of information that is not that convenient. So first, we make a relation from the DstZone_rel to the real destination points in order to visualise them properly:
attribute<int32> Inhabitants := dest/Inhabitants_2019[DstZone_rel];
And then we sum the number of inhabitants reached from each origin point, by summing over the OrgZone_rel:
attribute<int32> Inhabitants_org (org) := sum(Inhabitants, OrgZone_rel);
In the GeoDMS GUI, double-click on this last item (Inhabitants_org). It will probably be done calculating after about 10 to 30 seconds, and show for each train station the number of people that can be reached by car in 30 30-minute drive. If you are knowledgeable about Dutch topography/infrastructure, you can assess whether the outcome seems plausible.
There are many other applications for the impedance algorithm available within GeoDMS. For a full overview, look at Network functions. In this section, you will explore several variants.
For the next analysis, we will calculate a full origin-destination matrix. So, the travel time from each origin to each destination. For this, we use the same inputs as before. Remember that if we want to have the travel time from each origin to each destination, the output is quickly going to explode in size. In this case, we have 57 train stations and 54,211 population points. So that results in 57 * 54,211 = 3,090,027 origin-destination-pairs.
The impedance options that we will use for this application are slightly different than in the previous assignment. We omit the cut option since we want to know the travel time to each destination regardless of how long it will take. And we add the output option impedance to od. Configure the rest yourself and see if you get what we need! The calculation should take, depending on your computing power, between 20 and 60 seconds.
By now, it should have created three attributes: impedance, OrgZone_rel, and DstZone_rel. As mentioned earlier, we now have over 3 million rows of information. This is not very convenient, and if you have experience with OD matrices, you are probably more interested in data in a wide format instead of the now-displayed long format. So, let's convert it to something more usable that can also be exported to other applications. To see how that can be achieved, look at convert long to wide format.
With the GeoDMS, many OD matrices have been calculated; a nice example is the PC4 travel time matrix for Nederland van Boven(VPRO).
We can also invert the first impedance variant we made, instead of how many inhabitants we can reach within a set amount of time. We can calculate how long will it take to reach a certain amount of people. We used the option cut to cut off the allowed travel time. Now we will use the option limit to limit the number of inhabitants that we can reach. Limit the number of inhabitants to, for example, 10,000.
Try it yourself! Look through the impedance documentation in dijkstra options#filters to find out which options you should be using.
Instead of looking at the travel time to multiple destinations, we could also be interested in finding the nearest destination and getting feedback on how long that would take to travel there.
Instead of using the impedance_matrix we will now use the impedance_table variant:
impedance_table('bidirectional(link_flag);startPoint(Node_rel)
What other network analyses would be interesting to you? Let me know via email!
Go to previous module: Module 4, Basic analyses with grid data
Go to next module: Module 5b, Working with networks in a public transport setting
GeoDMS Academy
- 0: Install GeoDMS GUI and setup a configuration
- 1: Learning the basic concepts of GeoDMS
- 2: Loading and storing data sources
- 3: Basic analyses with vector data (WORK IN PROGRESS)
- 4: Basic analyses with grid data (WORK IN PROGRESS)
- 5a: Working with networks over a road network
- 5b: Working with networks in a public transport setting
- 6: Allocating land-use