Skip to content

Commit 633778c

Browse files
committed
- Initial Support for CRS.
1 parent 3536d45 commit 633778c

File tree

9 files changed

+149
-27
lines changed

9 files changed

+149
-27
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export(colorFactor)
5252
export(colorNumeric)
5353
export(colorQuantile)
5454
export(createLeafletMap)
55+
export(crs)
5556
export(dispatch)
5657
export(fitBounds)
5758
export(hideGroup)

R/leaflet.R

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@
2626
#' @export
2727
leaflet = function(data = NULL, width = NULL, height = NULL,
2828
padding = 0, mapOptions = list()) {
29+
30+
# Validate the CRS if specified
31+
if(!is.null(mapOptions[['crs']]) &&
32+
!inherits(mapOptions[['crs']], 'leaflet_crs')) {
33+
stop("CRS in mapOptions should be a return value of crs() function")
34+
}
35+
2936
htmlwidgets::createWidget(
3037
'leaflet',
3138
structure(
@@ -76,3 +83,71 @@ mapOptions <- function(map, zoomToLimits = c("always", "first", "never")) {
7683

7784
map
7885
}
86+
87+
# CRS classes supported
88+
crsClasses <- list( 'L.CRS.EPSG3857', 'L.CRS.EPSG4326', 'L.CRS.EPSG3395',
89+
'L.CRS.Simple', 'L.Proj.CRS', 'L.Proj.CRS.TMS' )
90+
91+
#' creates a custom CRS
92+
#' Refer to \url{https://kartena.github.io/Proj4Leaflet/api/} for details.
93+
#' @param crsClass One of L.CRS.EPSG3857, L.CRS.EPSG4326, L.CRS.EPSG3395,
94+
#' L.CRS.Simple, L.Proj.CRS, L.Proj.CRS.TMS
95+
#' @param code CRS identifier
96+
#' @param proj4def Proj4 string
97+
#' @param projectedBounds Only when crsClass = 'L.Proj.CRS.TMS'
98+
#' @param origin Origin in projected coordinates, if set overrides transformation option.
99+
#' @param transformation to use when transforming projected coordinates into pixel coordinates
100+
#' @param scales Scale factors (pixels per projection unit, for example pixels/meter)
101+
#' for zoom levels; specify either scales or resolutions, not both
102+
#' @param resolutions factors (projection units per pixel, for example meters/pixel)
103+
#' for zoom levels; specify either scales or resolutions, not both
104+
#' @param bounds Bounds of the CRS, in projected coordinates; if defined,
105+
#' Proj4Leaflet will use this in the getSize method, otherwise
106+
#' defaulting to Leaflet's default CRS size
107+
#' @param tileSize Tile size, in pixels, to use in this CRS (Default 256)
108+
#' Only needed when crsClass = 'L.Proj.CRS.TMS'
109+
#' @export
110+
crs <- function(
111+
crsClass = 'L.CRS.EPSG3857',
112+
code = NULL,
113+
proj4def = NULL,
114+
projectedBounds = NULL,
115+
origin = NULL,
116+
transformation = NULL,
117+
scales = NULL,
118+
resolutions = NULL,
119+
bounds = NULL,
120+
tileSize = NULL
121+
) {
122+
if(!crsClass %in% crsClasses) {
123+
stop(sprintf("crsClass argument must be one of %s",
124+
paste0(crsClasses, collapse = ', ')))
125+
126+
}
127+
if(crsClass %in% c('L.Proj.CRS', 'L.Proj.CRS.TMS') &&
128+
!is.null(scales) && !is.null(resolutions)) {
129+
stop(sprintf("Either input scales or resolutions"))
130+
}
131+
if(crsClass %in% c('L.Proj.CRS', 'L.Proj.CRS.TMS') &&
132+
is.null(scales) && is.null(resolutions)) {
133+
stop(sprintf("Input either scales or resolutions, not both"))
134+
}
135+
structure(
136+
list(
137+
crsClass = crsClass,
138+
code = code,
139+
proj4def = proj4def,
140+
projectedBounds = projectedBounds,
141+
options = filterNULL(list(
142+
origin = origin,
143+
transformation = transformation,
144+
scales = scales,
145+
resolutions = resolutions,
146+
bounds = bounds,
147+
tileSize = tileSize
148+
))
149+
),
150+
class = 'leaflet_crs'
151+
)
152+
}
153+

R/plugin-graticule.R

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ leafletGraticuleDependencies <- function() {
1414
#'
1515
#' @param map a map widget object
1616
#' @param interval The spacing in map units between horizontal and vertical lines.
17+
#' @param sphere boolean. Default FALSE
1718
#' @param style path options for the generated lines. See \url{http://leafletjs.com/reference.html#path-options}
1819
#' @param layerId the layer id
1920
#' @param group the name of the group this layer belongs to.
@@ -28,6 +29,7 @@ leafletGraticuleDependencies <- function() {
2829
addGraticule <- function(
2930
map,
3031
interval = 20,
32+
sphere = FALSE,
3133
style = list(color= '#333', weight= 1),
3234
layerId = NULL,
3335
group=NULL
@@ -38,6 +40,7 @@ addGraticule <- function(
3840
getMapData(map),
3941
'addGraticule',
4042
interval,
43+
sphere,
4144
style,
4245
layerId,
4346
group

inst/examples/proj4Leaflet.R

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ library(leaflet)
55

66

77
#' Default SPherical Mercator Projection specified explicitly
8-
leaflet(mapOptions=list(crs=list('_class'='L.CRS.EPSG3857'),
9-
center=c(0,0),
10-
zoom=3)) %>% addTiles()
8+
leaflet(mapOptions=list(crs=crs(crsClass='L.CRS.EPSG3857'),
9+
center=c(0,0), zoom=3)) %>% addTiles()
1110

1211
#' <br/><br/>Gothenberg, Sweeden in default projection
1312
leaflet(mapOptions = list(center=c(57.704, 11.965), zoom = 16)) %>%
@@ -17,14 +16,13 @@ leaflet(mapOptions = list(center=c(57.704, 11.965), zoom = 16)) %>%
1716
#' <br/><br/>Gothenberg, Sweeden in local projection
1817
leaflet(mapOptions = list(center=c(57.704, 11.965), zoom = 13,
1918
worldCopyJump = FALSE,
20-
crs=list('_class'="L.Proj.CRS", code='EPSG:3006',
19+
crs=crs(crsClass="L.Proj.CRS", code='EPSG:3006',
2120
proj4def='+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs',
22-
options=list(
23-
resolutions = c(
24-
8192, 4096, 2048, 1024, 512, 256, 128,
25-
64, 32, 16, 8, 4, 2, 1, 0.5
26-
),
27-
origin =c(0, 0))))) %>%
21+
resolutions = c(
22+
8192, 4096, 2048, 1024, 512, 256, 128,
23+
64, 32, 16, 8, 4, 2, 1, 0.5
24+
),
25+
origin =c(0, 0)))) %>%
2826
addTiles(urlTemplate = 'http://api.geosition.com/tile/osm-bright-3006/{z}/{x}/{y}.png',
2927
attribution = 'Map data &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap contributors</a>, Imagery &copy; 2013 <a href="http://www.kartena.se/">Kartena</a>',
3028
options = tileOptions(minZoom=0,maxZoom=14,continuousWorld = TRUE))
@@ -42,20 +40,19 @@ sp::proj4string(spdf) # Look MA no need to reproject
4240

4341
leaflet(mapOptions =
4442
list(maxZoom = 5,
45-
worldCopyJump = FALSE,
46-
crs=list('_class'="L.Proj.CRS", code='ESRI:53009',
43+
crs=crs(crsClass="L.Proj.CRS", code='ESRI:53009',
4744
proj4def= '+proj=moll +lon_0=0 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs',
48-
options=list(
49-
resolutions = c(65536, 32768, 16384, 8192, 4096, 2048)
50-
)))) %>%
45+
resolutions = c(65536, 32768, 16384, 8192, 4096, 2048)
46+
))) %>%
5147
addGraticule(style= list(color= '#999', weight= 0.5, opacity= 1)) %>%
48+
addGraticule(sphere = TRUE, style= list(color= '#777', weight= 1, opacity= 0.25)) %>%
5249
addPolygons(data=spdf, weight = 1, color = "#ff0000")
5350

5451
#' <br/><br/>L.CRS.Simple example.
5552
#' For now the image is specified via onRender and native JS call
5653
#' because we haven't coded the L.ImageLayer part yet.
57-
bounds <- c(0,0,1000,1000)
58-
leaflet(mapOptions = list(crs=list('_class'='L.CRS.Simple'))) %>%
54+
bounds <- c(-26.5,-25, 1021.5,1023)
55+
leaflet(mapOptions = list(crs=crs(crsClass='L.CRS.Simple'), minZoom= -5)) %>%
5956
fitBounds(bounds[1], bounds[2], bounds[3], bounds[4]) %>%
6057
setMaxBounds(bounds[1], bounds[2], bounds[3], bounds[4]) %>%
6158
htmlwidgets::onRender("
@@ -81,14 +78,14 @@ pal <- colorNumeric(
8178
)
8279

8380
bounds <- c(-125, 24 ,-75, 45)
81+
8482
leaflet(mapOptions =
8583
list(worldCopyJump = FALSE,
86-
crs=list('_class'="L.Proj.CRS", code='EPSG:2163',
84+
crs=crs(crsClass="L.Proj.CRS", code='EPSG:2163',
8785
proj4def='+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs',
88-
options=list(
89-
resolutions = c(65536, 32768, 16384, 8192, 4096, 2048,
90-
1024, 512, 256, 128)
91-
)))) %>%
86+
resolutions = c(65536, 32768, 16384, 8192, 4096, 2048,
87+
1024, 512, 256, 128)
88+
))) %>%
9289
fitBounds(bounds[1], bounds[2], bounds[3], bounds[4]) %>%
9390
setMaxBounds(bounds[1], bounds[2], bounds[3], bounds[4]) %>%
9491
addPolygons(data=spdf, weight = 1, color = "#000000",

inst/htmlwidgets/leaflet.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ _htmlwidgets2.default.widget({
450450
var crs = _leaflet2.default.CRS.EPSG3857; // Default Spherical Mercator
451451
var crsOptions = data.options.crs;
452452

453-
switch (crsOptions._class) {
453+
switch (crsOptions.crsClass) {
454454
case "L.CRS.EPSG3857":
455455
crs = _leaflet2.default.CRS.EPSG3857;
456456
break;

inst/htmlwidgets/plugins/Leaflet.Graticule/Graticule-binding.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
LeafletWidget.methods.addGraticule = function(interval, style, layerId, group) {
1+
LeafletWidget.methods.addGraticule = function(interval, sphere, style, layerId, group) {
22
(function() {
33
this.layerManager.addLayer(
44
L.graticule({
55
interval: interval,
6+
sphere: sphere,
67
style: style
78
}),
89
'shape', layerId, group);

javascript/src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ HTMLWidgets.widget({
9696
let crs = L.CRS.EPSG3857; // Default Spherical Mercator
9797
let crsOptions = data.options.crs;
9898

99-
switch(crsOptions._class) {
99+
switch(crsOptions.crsClass) {
100100
case "L.CRS.EPSG3857":
101101
crs = L.CRS.EPSG3857;
102102
break;

man/addGraticule.Rd

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/crs.Rd

Lines changed: 43 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)