diff --git a/.github/workflows/rhub.yaml b/.github/workflows/rhub.yaml index 930b41bb..74ec7b05 100644 --- a/.github/workflows/rhub.yaml +++ b/.github/workflows/rhub.yaml @@ -76,10 +76,6 @@ jobs: config: ${{ fromJson(needs.setup.outputs.platforms) }} steps: - - name: Query dependencies - run: | - install.packages('terra', repos='https://rspatial.r-universe.dev') - shell: Rscript {0} - uses: r-hub/actions/checkout@v1 - uses: r-hub/actions/setup-r@v1 with: diff --git a/README.md b/README.md index f5285248..eb53fe5c 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![R-CMD-check](https://github.com/JeremyGelb/spNetwork/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/JeremyGelb/spNetwork/actions/workflows/R-CMD-check.yaml) -[![](https://img.shields.io/badge/devel%20version-0.4.4-green.svg)](https://jeremygelb.github.io/spNetwork/) +[![](https://img.shields.io/badge/devel%20version-0.4.4.2-green.svg)](https://jeremygelb.github.io/spNetwork/) [![](https://www.r-pkg.org/badges/version/spNetwork?color=blue)](https://cran.r-project.org/package=spNetwork) [![](http://cranlogs.r-pkg.org/badges/grand-total/spNetwork?color=blue)](https://cran.r-project.org/package=spNetwork) [![](http://cranlogs.r-pkg.org/badges/last-month/spNetwork?color=green)](https://cran.r-project.org/package=spNetwork) diff --git a/docs/404.html b/docs/404.html index 04b0c1bf..6ee3313b 100644 --- a/docs/404.html +++ b/docs/404.html @@ -32,7 +32,7 @@ K-nearest neighbour adaptive bandwidth
@@ -52,7 +52,7 @@vignettes/KNetworkFunctions.Rmd
KNetworkFunctions.Rmd
vignettes/NKDE.Rmd
NKDE.Rmd
vignettes/NetworkBuilding.Rmd
NetworkBuilding.Rmd
vignettes/SpatialWeightMatrices.Rmd
SpatialWeightMatrices.Rmd
vignettes/TNKDE.Rmd
TNKDE.Rmd
vignettes/web_vignettes/AdaptiveBW.Rmd
AdaptiveBW.Rmd
vignettes/web_vignettes/Isochrones.Rmd
+ Isochrones.Rmd
An isochrone is a geometrical representation of the area that can be +reached for a starting on a network within a given distance (in time or +space units).
+There are already several libraries to build isochrones with R
+(opentripplanner
, osrm
, rmapzen
,
+etc.), but they are all based on OpenStreetMap data or on external API.
+We propose here a simple implementation that can be used on a
+geographical network read as SpatialLinesDataFrame.
We give here a simple example with the Montreal network dataset and +calculate several isochrones from the centre of the dataset.
+The first step is to load (or create) a geographical network and to +have some starting points.
+
+# first load data and packages
+library(sf)
+library(spNetwork)
+library(tmap)
+
+data(mtl_network)
+
+# calculating the length of each segment
+mtl_network$length <- as.numeric(st_length(mtl_network))
+
+# extracting the coordinates in one matrix
+coords <- st_coordinates(mtl_network)
+center <- colMeans(coords)
+df_center <- data.frame("OID" = 1,
+ "x" = center[1],
+ "y" = center[2])
+df_center <- st_as_sf(df_center, coords = c("x","y"), crs = st_crs(mtl_network))
+
+# then plotting the data
+tm_shape(mtl_network) +
+ tm_lines("black") +
+ tm_shape(df_center) +
+ tm_dots("red", size = 0.2)
The second step is to calculate the isochrones with the function
+calc_isochrones
. In this example, we use the length of a
+segment as the weight but other values could be used. We also consider
+that all the roads can be used in both directions (see parameter
+direction
)
+iso_results <- calc_isochrones(lines = mtl_network,
+ start_points = df_center,
+ dists = c(500,1000,2000),
+ weight = "length"
+ )
The results are reported as lines, which can be mapped.
+
+# creating a factor and changing order for better vizualisation
+iso_results$fac_dist <- as.factor(iso_results$distance)
+iso_results <- iso_results[order(-1*iso_results$distance),]
+
+tm_shape(mtl_network) +
+ tm_lines(col = "grey") +
+ tm_shape(iso_results) +
+ tm_lines(col = "fac_dist",title.col = "distance (m)",
+ palette = c("500"="#005f73", "1000"="#ca6702", "2000"="#9b2226"))+
+ tm_layout(legend.outside = TRUE) +
+ tm_shape(df_center) +
+ tm_dots(col = "black", size = 0.1)
The lines are the most exact form of an isochrone because they depict +exactly what parts of the network can be reached. However, isochrones +are represented as polygons most of the time. We propose here some +approaches to build some meaningful polygons for isochrones.
+The best starting point is probably to calculate for each set of
+points a concave hull. This is different from the traditional convex
+hull and is more adapted to the irregular geometry of an isochrone. To
+do so, we use the library concaveman
+library(concaveman)
+
+# identifying each isochrone
+iso_results$iso_oid <- paste(iso_results$point_id,
+ iso_results$distance,
+ sep = "_")
+
+# creating the polygons for each isochrone
+polygons <- lapply(unique(iso_results$iso_oid), function(oid){
+
+ # subseting the required lines
+ lines <- subset(iso_results, iso_results$iso_oid == oid)
+
+ # extracting the coordinates of the lines
+ coords <- st_coordinates(lines)
+ poly_coords <- concaveman(points = coords, concavity = 3)
+ poly <- st_polygon(list(poly_coords[,1:2]))
+ return(poly)
+})
+
+# creating a SpatialPolygonsDataFrame
+iso_sp <- st_sf(
+ iso_oid = unique(iso_results$iso_oid),
+ distance = unique(iso_results$distance),
+ geometry = polygons,
+ crs = st_crs(iso_results)
+)
We can now map the obtained polygons.
+
+# creating a factor and changing order for better vizualisation
+iso_sp$fac_dist <- as.factor(iso_sp$distance)
+iso_sp <- iso_sp[order(-1*iso_sp$distance),]
+
+tm_shape(iso_results) +
+ tm_lines(col = "black")+
+ tm_shape(iso_sp) +
+ tm_polygons(col = "fac_dist",title.col = "distance (m)",
+ palette = c("500"="#005f73", "1000"="#ca6702", "2000"="#9b2226"),
+ alpha = 0.6, border.col = "white") +
+ tm_shape(df_center) +
+ tm_dots(col = "black", size = 0.1)
This is more similar to classical isochrone maps. Another possible
+enhancement would be to simplify and smooth the limits of the polygons.
+To do so, we will use the functions st_simplify
from
+sf
and smooth
from smoothr
.
+library(smoothr)
+
+simple_polygons <- st_simplify(iso_sp, dTolerance = 50)
+smooth_iso <- smooth(simple_polygons, method = "chaikin",
+ refinements = 5)
+
+tm_shape(iso_results) +
+ tm_lines(col = "black")+
+ tm_shape(smooth_iso) +
+ tm_polygons(col = "fac_dist",
+ title.col = "distance (m)",
+ palette = c("500"="#005f73", "1000"="#ca6702", "2000"="#9b2226"),
+ border.col = "white",
+ alpha = 0.6) +
+ tm_shape(df_center) +
+ tm_dots(col = "black", size = 0.1) +
+ tm_layout(legend.outside = TRUE)
The shapes are cleaner for mapping but the results are not exact +anymore.
+vignettes/web_vignettes/NKDEdetailed.Rmd
NKDEdetailed.Rmd
d3_plot_situation(all_lines, event, samples_pts, simple_kernel, scales = c(1,1,3))
(The function used to display the 3d plot is available in the source +
+(The function used to display the 3d plot is available in the source code of the vignette)
As one can see, NKDE is only determined by the distance between the sampling points and the event. This is a problem, because at @@ -249,8 +249,8 @@
d3_plot_situation(all_lines, event, samples_pts, discontinuous_kernel, scales = c(1,1,3))
As one can see, the values of the NKDE are split at intersections to +
+As one can see, the values of the NKDE are split at intersections to avoid the multiplication of the mass observed in the simple version. However, this NKDE is discontinuous, which is counter-intuitive, and leads to sharp differences between density values in the network, and @@ -300,8 +300,8 @@
d3_plot_situation(all_lines, event, samples_pts, continuous_kernel, scales = c(1,1,3))
As one can see, the values of the NKDE are continuous, and the +
+As one can see, the values of the NKDE are continuous, and the density values close to the events have been adjusted. This method produces smoother results than the discontinuous method.
what to retain about the discontinuous method
@@ -338,8 +338,8 @@
d3_plot_situation(all_lines, events, samples_pts, continuous_kernel, scales = c(1,1,3))
The larger the bandwidth, the more common links the events share in +
+The larger the bandwidth, the more common links the events share in their range.
@@ -351,13 +351,13 @@ The continuous method verbose = FALSE)
d3_plot_situation(all_lines, events, samples_pts, continuous_kernel, scales = c(1,1,3))
vignettes/web_vignettes/SpaceTimeDBscan.Rmd
SpaceTimeDBscan.Rmd
vignettes/web_vignettes/SpeedVSprecision.Rmd
SpeedVSprecision.Rmd
The package’s website is available here
This is an important release!