13.4 Nodes

Nodes are points. Broadly are two main types of transport nodes:

  • Origins and destinations such as houses and workplaces
  • Intersections between pathways (junctions) and points for entering or exiting a transport network such as bus stops and train stations

The network then consists of edges and nodes.

A common barrier preventing people from switching away from cars for commuting to work is that the distance from home to work is too far to walk or cycle. Public transport can reduce this barrier by providing a fast and high-volume option for common routes into cities. From an active travel perspective, public transport ‘legs’ of longer journeys divide trips into three:

  • The origin leg, typically from residential areas to public transport stations
  • The public transport leg, which typically goes from the station nearest a trip’s origin to the station nearest its destination
  • The destination leg, from the station of alighting to the destination

Public transport nodes can be used to construct three-part desire lines for trips that can be taken by bus and rail.

Let’s look at rail:

desire_rail = dplyr::slice_max(desire_lines, n = 10, order_by = train)

three stages: - matrix creation (of origins, destinations and the ‘via’ points representing rail stations), - identification of nearest neighbors - conversion to multilinestrings.

Using the stplanr line_via() function

(desire_rail <- line_via(desire_rail, bristol_stations))
## Simple feature collection with 10 features and 8 fields
## Active geometry column: geometry
## Geometry type: LINESTRING
## Dimension:     XY
## Bounding box:  xmin: -2.785131 ymin: 51.40862 xmax: -2.536041 ymax: 51.53713
## Geodetic CRS:  WGS 84
##            o         d all bicycle foot car_driver train    Active
## 1  E02003104 E02006887 143       6    1         57    58  4.895105
## 2  E02003106 E02006887 221       8    3        113    54  4.977376
## 3  E02003072 E02006887 163       3    2         75    49  3.067485
## 4  E02003073 E02006887 144       7    0         65    46  4.861111
## 5  E02003098 E02006887 192       4    2        102    45  3.125000
## 6  E02006887 E02003106 147      13    6         59    42 12.925170
## 7  E02003106 E02003043 365      24    5        176    41  7.945205
## 8  E02003107 E02006887 181      20    9         70    38 16.022099
## 9  E02003101 E02006887 210      10    2        131    36  5.714286
## 10 E02003075 E02006887 139      10    1         74    34  7.913669
##                          geometry                       leg_orig
## 1  LINESTRING (-2.551731 51.52... LINESTRING (-2.551731 51.52...
## 2  LINESTRING (-2.536041 51.50... LINESTRING (-2.536041 51.50...
## 3  LINESTRING (-2.785131 51.42... LINESTRING (-2.785131 51.42...
## 4  LINESTRING (-2.754764 51.42... LINESTRING (-2.754764 51.42...
## 5  LINESTRING (-2.546061 51.53... LINESTRING (-2.546061 51.53...
## 6  LINESTRING (-2.578791 51.45... LINESTRING (-2.578791 51.45...
## 7  LINESTRING (-2.536041 51.50... LINESTRING (-2.536041 51.50...
## 8  LINESTRING (-2.573264 51.51... LINESTRING (-2.573264 51.51...
## 9  LINESTRING (-2.55124 51.532... LINESTRING (-2.55124 51.532...
## 10 LINESTRING (-2.71725 51.408... LINESTRING (-2.71725 51.408...
##                           leg_via                       leg_dest
## 1  LINESTRING (-2.562345 51.52... LINESTRING (-2.579529 51.44...
## 2  LINESTRING (-2.542979 51.51... LINESTRING (-2.579529 51.44...
## 3  LINESTRING (-2.74969 51.419... LINESTRING (-2.579529 51.44...
## 4  LINESTRING (-2.74969 51.419... LINESTRING (-2.579529 51.44...
## 5  LINESTRING (-2.562345 51.52... LINESTRING (-2.579529 51.44...
## 6  LINESTRING (-2.579529 51.44... LINESTRING (-2.542979 51.51...
## 7  LINESTRING (-2.542979 51.51... LINESTRING (-2.605539 51.44...
## 8  LINESTRING (-2.563826 51.50... LINESTRING (-2.579529 51.44...
## 9  LINESTRING (-2.562345 51.52... LINESTRING (-2.579529 51.44...
## 10 LINESTRING (-2.74969 51.419... LINESTRING (-2.579529 51.44...

Note each of the legs

zone_cents <- st_centroid(zones_od)
## Warning: st_centroid assumes attributes are constant over geometries
## Warning in st_centroid.sfc(st_geometry(x), of_largest_polygon =
## of_largest_polygon): st_centroid does not give correct centroids for
## longitude/latitude data
zone_cents_rail <- zone_cents[desire_rail, ]
## although coordinates are longitude/latitude, st_intersects assumes that they
## are planar
bb <-  tmaptools::bb(desire_rail, ext = 1.1)

desire_rail_plot = rbind(
  st_sf(data.frame(Geometry = "Desire line (original)"), geometry = desire_rail$geometry),
  st_sf(data.frame(Geometry = "Leg 1 (origin to station)"), geometry = desire_rail$leg_orig),
  st_sf(data.frame(Geometry = "Leg 2 (station to station)"), geometry = desire_rail$leg_via),
  st_sf(data.frame(Geometry = "Leg 3 (station to destination)"), geometry = desire_rail$leg_dest)
) 

desire_rail_plot = desire_rail_plot |> 
  mutate(lty = case_when(Geometry == "Desire line (original)" ~ 2, TRUE ~ 1)) |> 
  mutate(size = case_when(Geometry == "Desire line (original)" ~ 1, TRUE ~ 2))

bristol_rail_points = rbind(
  st_sf(data.frame(
    Node = "Origin and destination locations",
    col = "black"
    ), geometry = zone_cents_rail$geometry),
  st_sf(data.frame(
    Node = "Public transport node",
    col = "red"
    ), geometry = bristol_stations$geometry)
)

tm_shape(desire_rail_plot, bbox = bb) +
  tm_lines(col = "Geometry", palette = "Set2", lwd = "size", scale = 3, legend.lwd.show = FALSE) +
  tm_shape(bristol_rail_points) +
  tm_dots(col = "col", size = 0.05) +
  tm_scale_bar()