Skip to content

Instantly share code, notes, and snippets.

@ramnathv
Last active November 6, 2022 21:58
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save ramnathv/9998388 to your computer and use it in GitHub Desktop.
Save ramnathv/9998388 to your computer and use it in GitHub Desktop.
Leaflet Routing Machine with rCharts

Leaflet Routing Machine Plugin

I saw the following issue posted to the rMaps github repo today.

I am new to using rMaps and leaflet. I would like to plot the route between two locations. The leaflet routing machine plugin allows us to do this (https://github.com/perliedman/leaflet-routing-machine). I am not quite sure how to use the functions addAssets() and setTemplate() to be able to use this plugin.

This was a good exercise for me to test whether these newly introduced mechanisms addAssets and setTemplate would allow one to easily extend the base leaflet binding in rMaps.

Let us start by creating the base map.

map = Leaflet$new()
map$setView(c(40.73846, -73.99413), 16)
map$tileLayer(provider = 'Stamen.TonerLite')
map

At this point, you should be able to view this map in your chosen viewer.

simplemap

We now want to add a route between the following waypoints. I have chosen the data structure to be an unnamed list of vectors, since it converts easily to the JSON structure expected by by routing plugin.

mywaypoints = list(c(40.74119, -73.9925), c(40.73573, -73.99302))

In order to use the routing plugin, we first need to add the required js/css assets. I introduced the addAssets method in the dev version of rCharts precisely to serve this need (NOTE: It is currently a little buggy in terms of order in which the assets are specified, but I will take care of that this week).

map$addAssets(
  css = "http://www.liedman.net/leaflet-routing-machine/dist/leaflet-routing-machine.css",
  jshead = "http://www.liedman.net/leaflet-routing-machine/dist/leaflet-routing-machine.min.js"
)

All that is left to do now is to add the javascript snippet that would add these waypoints to the map. If you visit the github page of the routing plugin, you will notice that all I have done is replaced the hardcoded waypoints with a placeholder, which I will fill using data from R.

routingTemplate =  "
  <script>
   var mywaypoints = %s
   L.Routing.control({
     waypoints: [
       L.latLng.apply(null, mywaypoints[0]),
       L.latLng.apply(null, mywaypoints[1])
    ]
   }).addTo(map);
  </script>
"

So how do we inject this snippet into our HTML. This was the idea behind the afterScript template. (NOTE: The name indicates that this snippet will be added after the script used to generate the base map. I am open to suggestions for a name that would be more indicative of this argument). I use sprintf to populate the placeholder in the template, and convert waypoints to JSON before invoking it.

map$setTemplate(afterScript = sprintf(routingTemplate, RJSONIO::toJSON(mywaypoints))

At this point, typing map in your R console should give you the following map. Click on the map to be taken to a full page interactive version, where you can see the routing directions as well.

map_with_routing.

You can download the full code here.

# INSTALL DEPENDENCIES IF YOU HAVEN'T ALREADY DONE SO
# library(devtools)
# install_github("ramnathv/rCharts@dev")
# install_github("ramnathv/rMaps")
library(rMaps)
map = Leaflet$new()
map$setView(c(40.73846, -73.99413), 16)
map$tileLayer(provider = 'Stamen.TonerLite')
mywaypoints = list(c(40.74119, -73.9925), c(40.73573, -73.99302))
map$addAssets(
css = "http://www.liedman.net/leaflet-routing-machine/dist/leaflet-routing-machine.css",
jshead = "http://www.liedman.net/leaflet-routing-machine/dist/leaflet-routing-machine.min.js"
)
routingTemplate = "
<script>
var mywaypoints = %s
L.Routing.control({
waypoints: [
L.latLng.apply(null, mywaypoints[0]),
L.latLng.apply(null, mywaypoints[1])
]
}).addTo(map);
</script>"
map$setTemplate(
afterScript = sprintf(routingTemplate, RJSONIO::toJSON(mywaypoints))
)
map$set(width = 1450, height = 800)
map
<!doctype HTML>
<meta charset = 'utf-8'>
<html>
<head>
<link rel='stylesheet' href='http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.css'>
<link rel='stylesheet' href='http://www.liedman.net/leaflet-routing-machine/dist/leaflet-routing-machine.css'>
<script src='http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.js' type='text/javascript'></script>
<script src='https://rawgithub.com/leaflet-extras/leaflet-providers/gh-pages/leaflet-providers.js' type='text/javascript'></script>
<script src='http://harrywood.co.uk/maps/examples/leaflet/leaflet-plugins/layer/vector/KML.js' type='text/javascript'></script>
<script src='http://www.liedman.net/leaflet-routing-machine/dist/leaflet-routing-machine.min.js' type='text/javascript'></script>
<style>
.rChart {
display: block;
margin-left: auto;
margin-right: auto;
width: 1450px;
height: 800px;
}
</style>
</head>
<body >
<div id = 'chart6d58205347ac' class = 'rChart leaflet'></div>
<script>
var spec = {
"dom": "chart6d58205347ac",
"width": 1450,
"height": 800,
"urlTemplate": "http://{s}.tile.osm.org/{z}/{x}/{y}.png",
"layerOpts": {
"attribution": "Map data<a href=\"http://openstreetmap.org\">OpenStreetMap</a>\n contributors, Imagery<a href=\"http://mapbox.com\">MapBox</a>"
},
"center": [ 40.73846, -73.99413 ],
"zoom": 16,
"provider": "Stamen.TonerLite",
"id": "chart6d58205347ac"
}
var map = L.map(spec.dom, spec.mapOpts)
map.setView(spec.center, spec.zoom);
if (spec.provider){
L.tileLayer.provider(spec.provider).addTo(map)
} else {
L.tileLayer(spec.urlTemplate, spec.layerOpts).addTo(map)
}
if (spec.circle2){
for (var c in spec.circle2){
var circle = L.circle(c.center, c.radius, c.opts)
.addTo(map);
}
}
</script>
<script>
var mywaypoints = [
[ 40.741, -73.993 ],
[ 40.736, -73.993 ]
]
L.Routing.control({
waypoints: [
L.latLng.apply(null, mywaypoints[0]),
L.latLng.apply(null, mywaypoints[1])
]
}).addTo(map);
</script>
</body>
<script>
function getURLParameter(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null
}
console.log(getURLParameter("viewer_pane"))
if (getURLParameter("viewer_pane") === "1"){
document.write("<style>.rChart { width: 100% }</style>");
}
</script>
</html>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@jravichetan
Copy link

Hi Ramnath - When I try to wrap the code.R onto a Shiny app, I am able to get the map but not the plotting and route. Can I use showOutput("map_container", "leaflet") in ui.R after wrapping (code.R) lines of code into output$map_container <- renderMap({ }) in server.R ?

@jravichetan
Copy link

Sorry for posting here, I found history in "ramnathv/rMaps#45"
Will wait for updates. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment