An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-sig-geo/attachments/20140424/06457080/attachment.pl>
projection of ggmap:get_map() output
11 messages · Barry Rowlingson, Jon Olav Skoien, Edzer Pebesma +2 more
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-sig-geo/attachments/20140424/20ca1946/attachment.pl>
On 04/24/2014 03:52 PM, Barry Rowlingson wrote:
So do you mean (and I've not tried your code yet, sorry) that the corners may well be at the given lat-long points but half way along any edge might not be at the halfway-point in lat-long?
Indeed: library(ggmap) ggmap(get_map(matrix(c(-10,20,40,80),2,2))) and look at the tics along the y-axis: they're not linear, neither are they drawn by google (at least, they're not on the ggmapTemp.png file written). http://journal.r-project.org/archive/2013-1/kahle-wickham.pdf mention on p. 146 that "... the coordinate system is ?xed to the Mercator projection."
if you convert the bbox coords to epsg:3857 then maybe you have a correctly projected raster in those coordinates?
The google API wants long/lat in WGS84, and what gets returned has a different bbox anyway, but I believe that a long/lat aligned "box" in WGS84 remains a box in Mercator.
I've avoided ggmap et al because I've been unconvinced about their
geographic rigour vs their prettiness....
On Thu, Apr 24, 2014 at 12:43 PM, Agustin Lobo <alobolistas at gmail.com
<mailto:alobolistas at gmail.com>> wrote:
But the fact that the output of get_map() includes the bounding box in
geographic
coordinates (epsg:4326) does not imply that the matrix is on the same
projection.
This should be specified.
I can provide you a utm raster along with bounding box coordinates in
geographic coordinates (epsg:4326).
Actually, according to the code I just showed, it is not clear at all
that the matrix provided
in the ggmap "raster" object is in epsg:4326.
Agus
On Thu, Apr 24, 2014 at 10:21 AM, Edzer Pebesma
<edzer.pebesma at uni-muenster.de
<mailto:edzer.pebesma at uni-muenster.de>> wrote:
> EPSG:4326, or WGS84, is only one way to refer to places on the
earth by
> longitudes and latitudes; it seems that google maps come in a Mercator
> projection, EPSG:3857, read e.g. this:
>
> http://docs.openlayers.org/library/spherical_mercator.html
>
> or
>
>
>
> Iliffe and Lott: Datums and Map Projections: For Remote Sensing,
GIS and
> Surveying
>
> provide an excellent explanation on what goes on here, including what
> google maps does.
>
> On 04/24/2014 09:56 AM, Agustin Lobo wrote:
>> (follow up of previous message, I pressed enter as if I were in the R
>> session and sent the message...)
>>
>> On Wed, Apr 23, 2014 at 4:37 PM, Barry Rowlingson
>> <b.rowlingson at lancaster.ac.uk
<mailto:b.rowlingson at lancaster.ac.uk>> wrote:
>>> - I imagine the web services expect EPSG:4326.
>>
>> What they expect, yes. But what about what we retrieve? The bbox
>> coordinates might be in geographic coordinates (epsg:4326) but
>> the actual projection of the matrix could be any other. Actually, I
>> think that no geographic object without CRS information should be
>> admitted in R.
>>
>> In order to investigate this further, I've done the following:
>>
>> mibb <- matrix(c(-69.88634, -48.78450, -34.05533,
-18.63424),byrow=TRUE,nrow=2)
>> delme <- get_map(location = mibb, maptype = "hybrid", source=
>> "google", crop = FALSE, zoom = 5)
>>
>> mgmap <- as.matrix(gmap)
>> vgmap <- as.vector(mgmap)
>> vgmaprgb <- col2rgb(vgmap)
>> gmapr <- matrix(vgmaprgb[1,],ncol=ncol(
>> mgmap),nrow=nrow(mgmap))
>> gmapg <- matrix(vgmaprgb[2,],ncol=ncol(mgmap),nrow=nrow(mgmap))
>> gmapb <- matrix(vgmaprgb[3,],ncol=ncol(mgmap),nrow=nrow(mgmap))
>> rgmaprgb <- brick(raster(gmapr),raster(gmapg),raster(gmapb))
>> projection(rgmaprgb) <- CRS("+init=epsg:4326")
>> extent(rgmaprgb) <- unlist(attr(gmap,which="bb"))[c(2,4,1,3)]
>> rgmaprgb
>> plotRGB(rgmaprgb)
>>
>> This looks good, but when I save as GTiff
>>
writeRaster(rgmaprgb,file="rgmaprgb",format="GTiff",overwrite=TRUE,datatype="INT1U")
>>
>> and check with QGIS, there is a very significant shift versus the GM
>> layer that is downladed by plugin OpenLayers.
>>
>> Thus I worry that my overlay using rasterVis:levelplot and ggmap:
>> layer could actually be wrong as well.
>>
>> I'm going to test on a more local area and let you know.
>>
>> Agus
>>
>> _______________________________________________
>> R-sig-Geo mailing list
>> R-sig-Geo at r-project.org <mailto:R-sig-Geo at r-project.org>
>> https://stat.ethz.ch/mailman/listinfo/r-sig-geo
>>
>
> --
> Edzer Pebesma
> Institute for Geoinformatics (ifgi), University of M?nster
> Heisenbergstra?e 2, 48149 M?nster, Germany. Phone: +49 251
> 83 33081 http://ifgi.uni-muenster.de GPG key ID 0xAC227795
>
>
> _______________________________________________
> R-sig-Geo mailing list
> R-sig-Geo at r-project.org <mailto:R-sig-Geo at r-project.org>
> https://stat.ethz.ch/mailman/listinfo/r-sig-geo
>
_______________________________________________
R-sig-Geo mailing list
R-sig-Geo at r-project.org <mailto:R-sig-Geo at r-project.org>
https://stat.ethz.ch/mailman/listinfo/r-sig-geo
Edzer Pebesma Institute for Geoinformatics (ifgi), University of M?nster Heisenbergstra?e 2, 48149 M?nster, Germany. Phone: +49 251 83 33081 http://ifgi.uni-muenster.de GPG key ID 0xAC227795 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 490 bytes Desc: OpenPGP digital signature URL: <https://stat.ethz.ch/pipermail/r-sig-geo/attachments/20140424/abae40c4/attachment.bin>
On 04/24/2014 03:52 PM, Barry Rowlingson wrote:
So do you mean (and I've not tried your code yet, sorry) that the corners may well be at the given lat-long points but half way along any edge might not be at the halfway-point in lat-long?
Indeed: library(ggmap) ggmap(get_map(matrix(c(-10,20,40,80),2,2))) and look at the tics along the y-axis: they're not linear, neither are they drawn by google (at least, they're not on the ggmapTemp.png file written). http://journal.r-project.org/archive/2013-1/kahle-wickham.pdf mention on p. 146 that "... the coordinate system is ?xed to the Mercator projection."
Just as additional confirmation: inspecting the code, ggmap uses the mercator projection for displaying the "raster": https://github.com/dkahle/ggmap/blob/master/R/ggmap.R#L562
if you convert the bbox coords to epsg:3857 then maybe you have a correctly projected raster in those coordinates?
The google API wants long/lat in WGS84, and what gets returned has a different bbox anyway, but I believe that a long/lat aligned "box" in WGS84 remains a box in Mercator.
I have been playing with code to show the differences. If my code is
correct, the differences are very small, at least for the bounding box
I have chosen:
library(geosphere) ## provides a mercator function
## Bounding box: lower-left and upper-right
ll <- c(-10, 30)
ur <- c(10, 50)
## Bounding box in mercator projection
llxy <- mercator(ll)
urxy <- mercator(ur)
## Matrix of coordinates in mercator projection
xy <- expand.grid(x=seq(llxy[1], urxy[1], length=100),
y=seq(llxy[2], urxy[2], length=100))
## Matrix of lon-lat values using bounding box
lonlat <- expand.grid(x=seq(ll[1], ur[1], length=100),
y=seq(ll[2], ur[2], length=100))
## Mercator coordinates using matrix of lon-lat
xyproj <- mercator(lonlat)
## Differences between xy and xyproj
dif <- 1 - xyproj/xy
names(dif) <- paste0('dif', names(dif))
summary(dif)
library(lattice)
difXY <- cbind(xy, dif)
levelplot(difx + dify ~ x*y, data=difXY)
I've avoided ggmap et al because I've been unconvinced about their geographic rigour vs their prettiness....
IMHO ggmap and friends are useful only when you need an easy way to add an attractive context or "decorative" material to a graphic. Best, Oscar.
According to the results https://dl.dropboxusercontent.com/u/3180464/ggmap_GM_compare.odp of the code below, the matrix downloaded by get_map() is on epsg:3857, the so-called Google Pseudo Mercator, while the bounding box is given in epsg:4326 coordinates. The odp file shows the raster as created by the code below out of a get_map() command, and the same area displayed by plugin OpenLayers. Note there is still a bit of shift/distortion between the 2 when you compare alternatively, but this is much less than what I had assuming get_map() was downloading in epsg:4326 mibb <- matrix(c(-69.88634, -48.78450, -34.05533, -18.63424),byrow=TRUE,nrow=2) gmap <- get_map(location = mibb, maptype = "hybrid", source= "google", crop = FALSE, zoom = 5) # Make a raster brick object from gmap mgmap <- as.matrix(gmap) vgmap <- as.vector(mgmap) vgmaprgb <- col2rgb(vgmap) gmapr <- matrix(vgmaprgb[1,],ncol=ncol(mgmap),nrow=nrow(mgmap)) gmapg <- matrix(vgmaprgb[2,],ncol=ncol(mgmap),nrow=nrow(mgmap)) gmapb <- matrix(vgmaprgb[3,],ncol=ncol(mgmap),nrow=nrow(mgmap)) rgmaprgb <- brick(raster(gmapr),raster(gmapg),raster(gmapb)) #version in "Google PseudoMercator" epsg:3857 rgmaprgbGM <- rgmaprgb projection(rgmaprgbGM) <- CRS("+init=epsg:3857") #We have to find out the extent in the units of the new projection unlist(attr(gmap,which="bb"))[c(2,4,1,3)] rprobextSpDF <- as(extent(unlist(attr(gmap,which="bb"))[c(2,4,1,3)]), "SpatialPolygons") projection(rprobextSpDF) <- CRS("+init=epsg:4326") rprobextGM <- spTransform(rprobextSpDF,CRS("+init=epsg:3857")) rprobextGM at bbox extent(rgmaprgbGM) <- c(rprobextGM at bbox[1,],rprobextGM at bbox[2,]) rgmaprgbGM plotRGB(rgmaprgbGM) writeRaster(rgmaprgbGM,file="rgmaprgbGM",format="GTiff",overwrite=TRUE,datatype="INT1U") I therefore think that overlaying layers using levelplot() + layer() might have to be done with the user's layers in epsg:4326, but I'll confirm soon. It could be as well that ggmap reprojects from 4326 to 3857. The query for get_map() must be done in epsg:4326, though, that's for sure. ggmap should specify the projection of the object retrieved by get_map(). The mentions you find to "mercator" are not unambiguous, as "mercator" is not one projection but a projection family. Geo-graphics must be pretty **and** exact. Agus
On Fri, Apr 25, 2014 at 12:13 PM, Oscar Perpi?an <oscar.perpinan at upm.es> wrote:
On 04/24/2014 03:52 PM, Barry Rowlingson wrote:
So do you mean (and I've not tried your code yet, sorry) that the corners may well be at the given lat-long points but half way along any edge might not be at the halfway-point in lat-long?
Indeed: library(ggmap) ggmap(get_map(matrix(c(-10,20,40,80),2,2))) and look at the tics along the y-axis: they're not linear, neither are they drawn by google (at least, they're not on the ggmapTemp.png file written). http://journal.r-project.org/archive/2013-1/kahle-wickham.pdf mention on p. 146 that "... the coordinate system is ?xed to the Mercator projection."
Just as additional confirmation: inspecting the code, ggmap uses the mercator projection for displaying the "raster": https://github.com/dkahle/ggmap/blob/master/R/ggmap.R#L562
if you convert the bbox coords to epsg:3857 then maybe you have a correctly projected raster in those coordinates?
The google API wants long/lat in WGS84, and what gets returned has a different bbox anyway, but I believe that a long/lat aligned "box" in WGS84 remains a box in Mercator.
I have been playing with code to show the differences. If my code is
correct, the differences are very small, at least for the bounding box
I have chosen:
library(geosphere) ## provides a mercator function
## Bounding box: lower-left and upper-right
ll <- c(-10, 30)
ur <- c(10, 50)
## Bounding box in mercator projection
llxy <- mercator(ll)
urxy <- mercator(ur)
## Matrix of coordinates in mercator projection
xy <- expand.grid(x=seq(llxy[1], urxy[1], length=100),
y=seq(llxy[2], urxy[2], length=100))
## Matrix of lon-lat values using bounding box
lonlat <- expand.grid(x=seq(ll[1], ur[1], length=100),
y=seq(ll[2], ur[2], length=100))
## Mercator coordinates using matrix of lon-lat
xyproj <- mercator(lonlat)
## Differences between xy and xyproj
dif <- 1 - xyproj/xy
names(dif) <- paste0('dif', names(dif))
summary(dif)
library(lattice)
difXY <- cbind(xy, dif)
levelplot(difx + dify ~ x*y, data=difXY)
I've avoided ggmap et al because I've been unconvinced about their geographic rigour vs their prettiness....
IMHO ggmap and friends are useful only when you need an easy way to add an attractive context or "decorative" material to a graphic. Best, Oscar.
_______________________________________________ R-sig-Geo mailing list R-sig-Geo at r-project.org https://stat.ethz.ch/mailman/listinfo/r-sig-geo
I've tested the effect of the projections on overlaying graphs using levelplot() + layer() In short, the user's object must be in epsg:4326, probably because layer() carries out a reprojection. The bad news is that it carries out a wrong reprojection, perhaps because the incorrect (or insufficient) definition of the projection as just "mercator" in layer() Example: (shape file in https://dl.dropboxusercontent.com/u/3180464/NWEur.zip) gmap2 <- get_map(location = c(5,51), maptype = "hybrid", source= "google", crop = FALSE, zoom = 6) ggmap(gmap2) #convert gmap2 to rgb raster brick mgmap2 <- as.matrix(gmap2) vgmap2 <- as.vector(mgmap2) vgmap2rgb <- col2rgb(vgmap2) gmap2r <- matrix(vgmap2rgb[1,],ncol=ncol(mgmap2),nrow=nrow(mgmap2)) gmap2g <- matrix(vgmap2rgb[2,],ncol=ncol(mgmap2),nrow=nrow(mgmap2)) gmap2b <- matrix(vgmap2rgb[3,],ncol=ncol(mgmap2),nrow=nrow(mgmap2)) rgmap2 <- brick(raster(gmap2r),raster(gmap2g),raster(gmap2b)) extent(rgmap2) <- unlist(attr(gmap2,which="bb"))[c(2,4,1,3)] projection(rgmap2) <- CRS("+init=epsg:3857") plotRGB(rgmap2) plot(rgmap2[[3]],col=grey.colors(32,start=0,end=1,gamma=1)) #shapefiles to be overlaid: coastlines easy to follow in the resulting graphic NWEur <- readOGR(dsn="countries_shp",layer="NWEur",stringsAsFactors=FALSE) projection(NWEur) NWEurGM <- spTransform(NWEur,CRS("+init=epsg:3857")) #levelplots levelplot(rgmap2[[3]],margin=FALSE,par.settings=GrTheme) + layer(sp.polygons(NWEur)) levelplot(rgmap2[[3]],margin=FALSE,par.settings=GrTheme) + layer(sp.polygons(NWEurGM)) overlay with the layer in epsg3857 is totaly out of place, but the one with the layer in epsg4326 is clearly shifted. Thus, we cannot use levelplot() + layer() with get_map() output at the moment. Agus
On Fri, Apr 25, 2014 at 3:55 PM, Agustin Lobo <alobolistas at gmail.com> wrote:
According to the results https://dl.dropboxusercontent.com/u/3180464/ggmap_GM_compare.odp of the code below, the matrix downloaded by get_map() is on epsg:3857, the so-called Google Pseudo Mercator, while the bounding box is given in epsg:4326 coordinates. The odp file shows the raster as created by the code below out of a get_map() command, and the same area displayed by plugin OpenLayers. Note there is still a bit of shift/distortion between the 2 when you compare alternatively, but this is much less than what I had assuming get_map() was downloading in epsg:4326 mibb <- matrix(c(-69.88634, -48.78450, -34.05533, -18.63424),byrow=TRUE,nrow=2) gmap <- get_map(location = mibb, maptype = "hybrid", source= "google", crop = FALSE, zoom = 5) # Make a raster brick object from gmap mgmap <- as.matrix(gmap) vgmap <- as.vector(mgmap) vgmaprgb <- col2rgb(vgmap) gmapr <- matrix(vgmaprgb[1,],ncol=ncol(mgmap),nrow=nrow(mgmap)) gmapg <- matrix(vgmaprgb[2,],ncol=ncol(mgmap),nrow=nrow(mgmap)) gmapb <- matrix(vgmaprgb[3,],ncol=ncol(mgmap),nrow=nrow(mgmap)) rgmaprgb <- brick(raster(gmapr),raster(gmapg),raster(gmapb)) #version in "Google PseudoMercator" epsg:3857 rgmaprgbGM <- rgmaprgb projection(rgmaprgbGM) <- CRS("+init=epsg:3857") #We have to find out the extent in the units of the new projection unlist(attr(gmap,which="bb"))[c(2,4,1,3)] rprobextSpDF <- as(extent(unlist(attr(gmap,which="bb"))[c(2,4,1,3)]), "SpatialPolygons") projection(rprobextSpDF) <- CRS("+init=epsg:4326") rprobextGM <- spTransform(rprobextSpDF,CRS("+init=epsg:3857")) rprobextGM at bbox extent(rgmaprgbGM) <- c(rprobextGM at bbox[1,],rprobextGM at bbox[2,]) rgmaprgbGM plotRGB(rgmaprgbGM) writeRaster(rgmaprgbGM,file="rgmaprgbGM",format="GTiff",overwrite=TRUE,datatype="INT1U") I therefore think that overlaying layers using levelplot() + layer() might have to be done with the user's layers in epsg:4326, but I'll confirm soon. It could be as well that ggmap reprojects from 4326 to 3857. The query for get_map() must be done in epsg:4326, though, that's for sure. ggmap should specify the projection of the object retrieved by get_map(). The mentions you find to "mercator" are not unambiguous, as "mercator" is not one projection but a projection family. Geo-graphics must be pretty **and** exact. Agus On Fri, Apr 25, 2014 at 12:13 PM, Oscar Perpi?an <oscar.perpinan at upm.es> wrote:
On 04/24/2014 03:52 PM, Barry Rowlingson wrote:
So do you mean (and I've not tried your code yet, sorry) that the corners may well be at the given lat-long points but half way along any edge might not be at the halfway-point in lat-long?
Indeed: library(ggmap) ggmap(get_map(matrix(c(-10,20,40,80),2,2))) and look at the tics along the y-axis: they're not linear, neither are they drawn by google (at least, they're not on the ggmapTemp.png file written). http://journal.r-project.org/archive/2013-1/kahle-wickham.pdf mention on p. 146 that "... the coordinate system is ?xed to the Mercator projection."
Just as additional confirmation: inspecting the code, ggmap uses the mercator projection for displaying the "raster": https://github.com/dkahle/ggmap/blob/master/R/ggmap.R#L562
if you convert the bbox coords to epsg:3857 then maybe you have a correctly projected raster in those coordinates?
The google API wants long/lat in WGS84, and what gets returned has a different bbox anyway, but I believe that a long/lat aligned "box" in WGS84 remains a box in Mercator.
I have been playing with code to show the differences. If my code is
correct, the differences are very small, at least for the bounding box
I have chosen:
library(geosphere) ## provides a mercator function
## Bounding box: lower-left and upper-right
ll <- c(-10, 30)
ur <- c(10, 50)
## Bounding box in mercator projection
llxy <- mercator(ll)
urxy <- mercator(ur)
## Matrix of coordinates in mercator projection
xy <- expand.grid(x=seq(llxy[1], urxy[1], length=100),
y=seq(llxy[2], urxy[2], length=100))
## Matrix of lon-lat values using bounding box
lonlat <- expand.grid(x=seq(ll[1], ur[1], length=100),
y=seq(ll[2], ur[2], length=100))
## Mercator coordinates using matrix of lon-lat
xyproj <- mercator(lonlat)
## Differences between xy and xyproj
dif <- 1 - xyproj/xy
names(dif) <- paste0('dif', names(dif))
summary(dif)
library(lattice)
difXY <- cbind(xy, dif)
levelplot(difx + dify ~ x*y, data=difXY)
I've avoided ggmap et al because I've been unconvinced about their geographic rigour vs their prettiness....
IMHO ggmap and friends are useful only when you need an easy way to add an attractive context or "decorative" material to a graphic. Best, Oscar.
_______________________________________________ R-sig-Geo mailing list R-sig-Geo at r-project.org https://stat.ethz.ch/mailman/listinfo/r-sig-geo
2 days later
Hello,
I couldn't run your code because I am not able to read the file.
Anyway, some comments about your last email:
- "layer" is a function of the latticeExtra package. This function
modifies the panel function of a "trellis" graphic produced with a
function of the lattice package. This function, together with
"+.trellis" (of the same package) allows for overlaying layers. It is
important to note that it does not carry out any projection. It only
displays the graphical result of another function (for example,
sp.polygons or whatever).
- You create the canvas with "levelplot" displaying the ggmap raster,
and then overlay the data with layer. This is the same approach that
ggmap uses. Instead, I prefer to rely on the main data to be displayed
to configure the graphical window instead of using an auxiliary image
as the starting point.
- I'm not a fan of the ggmap approach. I agree with you that the
resulting object should include the projection information and even
adhere to the sp classes. However, I think that their results are
useful if managed with care.
In order to show that this is not an issue strictly related to
rasterVis::levelplot, I have written some code with spplot. I think
that the concordance between the ggmap raster and the shapefile is
aceptable.
Best,
Oscar.
##########################################################
library(sp)
library(ggmap)
## latticeExtra must be loaded after ggmap because both ggplot2 and
## latticeExtra define a 'layer' function. We need the definition from
## latticeExtra.
library(latticeExtra)
## Shape example
library(maptools)
owd <- getwd()
setwd(system.file("shapes", package = "maptools"))
sc90 <- readShapeSpatial("co45_d90")
proj4string(sc90) <- CRS("+proj=longlat +datum=NAD27")
setwd(owd)
## Get the stamen map
bbPoly <- bbox(sc90)
gmap <- get_map(c(bbPoly), maptype='toner', source='stamen', crop=FALSE)
bbMap <- attr(gmap, 'bb')
latCenter <- with(bbMap, ll.lat + ur.lat)/2
lonCenter <- with(bbMap, ll.lon + ur.lon)/2
height <- with(bbMap, ur.lat - ll.lat)
width <- with(bbMap, ur.lon - ll.lon)
## Use latticeExtra::+.trellis and latticeExtra::layer
spplot(sc90['AREA'], fill='transparent', col='indianred1') +
layer(grid.raster(gmap,
x=lonCenter, y=latCenter,
width=width, height=height,
default.units='native'),
under=TRUE)
Nice, thank you! Markus Loecher, author of RgoogleMaps, explained that ggmap uses https://github.com/dkahle/ggmap/blob/master/R/LonLat2XY.R to go from long/lat to XY (pixels in google map tiles), which was taken from the RgoogleMaps one: https://github.com/markusloecher/RgoogleMaps/blob/master/R/LatLon2XY.R which points to code by someone called Neil Young in a google groups: https://groups.google.com/forum/?hl=en#!topic/Google-Maps-API/0hA6wp6VaW8 I would expect that your cylindrical, equidistant projection (linear in long/lat) must collide more with the Mercator used by google when the plotted area becomes larger.
On 04/28/2014 11:58 AM, Oscar Perpi?an wrote:
Hello,
I couldn't run your code because I am not able to read the file.
Anyway, some comments about your last email:
- "layer" is a function of the latticeExtra package. This function
modifies the panel function of a "trellis" graphic produced with a
function of the lattice package. This function, together with
"+.trellis" (of the same package) allows for overlaying layers. It is
important to note that it does not carry out any projection. It only
displays the graphical result of another function (for example,
sp.polygons or whatever).
- You create the canvas with "levelplot" displaying the ggmap raster,
and then overlay the data with layer. This is the same approach that
ggmap uses. Instead, I prefer to rely on the main data to be displayed
to configure the graphical window instead of using an auxiliary image
as the starting point.
- I'm not a fan of the ggmap approach. I agree with you that the
resulting object should include the projection information and even
adhere to the sp classes. However, I think that their results are
useful if managed with care.
In order to show that this is not an issue strictly related to
rasterVis::levelplot, I have written some code with spplot. I think
that the concordance between the ggmap raster and the shapefile is
aceptable.
Best,
Oscar.
##########################################################
library(sp)
library(ggmap)
## latticeExtra must be loaded after ggmap because both ggplot2 and
## latticeExtra define a 'layer' function. We need the definition from
## latticeExtra.
library(latticeExtra)
## Shape example
library(maptools)
owd <- getwd()
setwd(system.file("shapes", package = "maptools"))
sc90 <- readShapeSpatial("co45_d90")
proj4string(sc90) <- CRS("+proj=longlat +datum=NAD27")
setwd(owd)
## Get the stamen map
bbPoly <- bbox(sc90)
gmap <- get_map(c(bbPoly), maptype='toner', source='stamen', crop=FALSE)
bbMap <- attr(gmap, 'bb')
latCenter <- with(bbMap, ll.lat + ur.lat)/2
lonCenter <- with(bbMap, ll.lon + ur.lon)/2
height <- with(bbMap, ur.lat - ll.lat)
width <- with(bbMap, ur.lon - ll.lon)
## Use latticeExtra::+.trellis and latticeExtra::layer
spplot(sc90['AREA'], fill='transparent', col='indianred1') +
layer(grid.raster(gmap,
x=lonCenter, y=latCenter,
width=width, height=height,
default.units='native'),
under=TRUE)
_______________________________________________ R-sig-Geo mailing list R-sig-Geo at r-project.org https://stat.ethz.ch/mailman/listinfo/r-sig-geo
Edzer Pebesma Institute for Geoinformatics (ifgi), University of M?nster Heisenbergstra?e 2, 48149 M?nster, Germany. Phone: +49 251 83 33081 http://ifgi.uni-muenster.de GPG key ID 0xAC227795 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 490 bytes Desc: OpenPGP digital signature URL: <https://stat.ethz.ch/pipermail/r-sig-geo/attachments/20140428/f137aa64/attachment.bin>
Oscar,
On Mon, Apr 28, 2014 at 11:58 AM, Oscar Perpi?an <oscar.perpinan at upm.es> wrote:
Hello, I couldn't run your code because I am not able to read the file.
Note dsn is the directory where you have the 4 files and layer is the name of the layer, which is the name of the files without extension.
Anyway, some comments about your last email: - "layer" is a function of the latticeExtra package. This function modifies the panel function of a "trellis" graphic produced with a function of the lattice package. This function, together with "+.trellis" (of the same package) allows for overlaying layers. It is important to note that it does not carry out any projection. It only displays the graphical result of another function (for example, sp.polygons or whatever).
There has to be a reprojection on the fly because the the two layers of the plot are on different coordinate systems. I think it is clear now that ggplot uses the Google "PseudoMercator" for the matrix while expects all user input on epsg4326
- You create the canvas with "levelplot" displaying the ggmap raster, and then overlay the data with layer. This is the same approach that ggmap uses. Instead, I prefer to rely on the main data to be displayed to configure the graphical window instead of using an auxiliary image as the starting point. - I'm not a fan of the ggmap approach. I agree with you that the resulting object should include the projection information and even adhere to the sp classes. However, I think that their results are useful if managed with care.
Users cannot handle with care undocumented idiosyncratic features.
In order to show that this is not an issue strictly related to rasterVis::levelplot,
I agree this is not an specific problem of reasterVis:levleplot.
I have written some code with spplot. I think that the concordance between the ggmap raster and the shapefile is aceptable.
I think "acceptable" depends on the scale only. At coarser scale you just do not see the error because it is relative to the extent and the result converges to the correct reprojection. I do not think we should settle for this kind of errors. In the code you provide, how do you know NAD27 is the appropriate datum? There is no prj file (one of the big shortcomings of shapefiles is that the presence of crs information in the form of a prj file is not compulsory). Note that you define a datum != WGS84 and you do not define the towgs argument. Agus
Best,
Oscar.
##########################################################
library(sp)
library(ggmap)
## latticeExtra must be loaded after ggmap because both ggplot2 and
## latticeExtra define a 'layer' function. We need the definition from
## latticeExtra.
library(latticeExtra)
## Shape example
library(maptools)
owd <- getwd()
setwd(system.file("shapes", package = "maptools"))
sc90 <- readShapeSpatial("co45_d90")
proj4string(sc90) <- CRS("+proj=longlat +datum=NAD27")
setwd(owd)
## Get the stamen map
bbPoly <- bbox(sc90)
gmap <- get_map(c(bbPoly), maptype='toner', source='stamen', crop=FALSE)
bbMap <- attr(gmap, 'bb')
latCenter <- with(bbMap, ll.lat + ur.lat)/2
lonCenter <- with(bbMap, ll.lon + ur.lon)/2
height <- with(bbMap, ur.lat - ll.lat)
width <- with(bbMap, ur.lon - ll.lon)
## Use latticeExtra::+.trellis and latticeExtra::layer
spplot(sc90['AREA'], fill='transparent', col='indianred1') +
layer(grid.raster(gmap,
x=lonCenter, y=latCenter,
width=width, height=height,
default.units='native'),
under=TRUE)
_______________________________________________ R-sig-Geo mailing list R-sig-Geo at r-project.org https://stat.ethz.ch/mailman/listinfo/r-sig-geo
This is great information, thanks. It is clear that without an infrastructure such as the proj4 used by spTransform() the overlays will never be without error. Agus On Mon, Apr 28, 2014 at 4:57 PM, Edzer Pebesma
<edzer.pebesma at uni-muenster.de> wrote:
Nice, thank you! Markus Loecher, author of RgoogleMaps, explained that ggmap uses https://github.com/dkahle/ggmap/blob/master/R/LonLat2XY.R to go from long/lat to XY (pixels in google map tiles), which was taken from the RgoogleMaps one: https://github.com/markusloecher/RgoogleMaps/blob/master/R/LatLon2XY.R which points to code by someone called Neil Young in a google groups: https://groups.google.com/forum/?hl=en#!topic/Google-Maps-API/0hA6wp6VaW8 I would expect that your cylindrical, equidistant projection (linear in long/lat) must collide more with the Mercator used by google when the plotted area becomes larger. On 04/28/2014 11:58 AM, Oscar Perpi?an wrote:
Hello,
I couldn't run your code because I am not able to read the file.
Anyway, some comments about your last email:
- "layer" is a function of the latticeExtra package. This function
modifies the panel function of a "trellis" graphic produced with a
function of the lattice package. This function, together with
"+.trellis" (of the same package) allows for overlaying layers. It is
important to note that it does not carry out any projection. It only
displays the graphical result of another function (for example,
sp.polygons or whatever).
- You create the canvas with "levelplot" displaying the ggmap raster,
and then overlay the data with layer. This is the same approach that
ggmap uses. Instead, I prefer to rely on the main data to be displayed
to configure the graphical window instead of using an auxiliary image
as the starting point.
- I'm not a fan of the ggmap approach. I agree with you that the
resulting object should include the projection information and even
adhere to the sp classes. However, I think that their results are
useful if managed with care.
In order to show that this is not an issue strictly related to
rasterVis::levelplot, I have written some code with spplot. I think
that the concordance between the ggmap raster and the shapefile is
aceptable.
Best,
Oscar.
##########################################################
library(sp)
library(ggmap)
## latticeExtra must be loaded after ggmap because both ggplot2 and
## latticeExtra define a 'layer' function. We need the definition from
## latticeExtra.
library(latticeExtra)
## Shape example
library(maptools)
owd <- getwd()
setwd(system.file("shapes", package = "maptools"))
sc90 <- readShapeSpatial("co45_d90")
proj4string(sc90) <- CRS("+proj=longlat +datum=NAD27")
setwd(owd)
## Get the stamen map
bbPoly <- bbox(sc90)
gmap <- get_map(c(bbPoly), maptype='toner', source='stamen', crop=FALSE)
bbMap <- attr(gmap, 'bb')
latCenter <- with(bbMap, ll.lat + ur.lat)/2
lonCenter <- with(bbMap, ll.lon + ur.lon)/2
height <- with(bbMap, ur.lat - ll.lat)
width <- with(bbMap, ur.lon - ll.lon)
## Use latticeExtra::+.trellis and latticeExtra::layer
spplot(sc90['AREA'], fill='transparent', col='indianred1') +
layer(grid.raster(gmap,
x=lonCenter, y=latCenter,
width=width, height=height,
default.units='native'),
under=TRUE)
_______________________________________________ R-sig-Geo mailing list R-sig-Geo at r-project.org https://stat.ethz.ch/mailman/listinfo/r-sig-geo
-- Edzer Pebesma Institute for Geoinformatics (ifgi), University of M?nster Heisenbergstra?e 2, 48149 M?nster, Germany. Phone: +49 251 83 33081 http://ifgi.uni-muenster.de GPG key ID 0xAC227795
_______________________________________________ R-sig-Geo mailing list R-sig-Geo at r-project.org https://stat.ethz.ch/mailman/listinfo/r-sig-geo
I couldn't run your code because I am not able to read the file.
Note dsn is the directory where you have the 4 files and layer is the name of the layer, which is the name of the files without extension.
My fault, sorry.
There has to be a reprojection on the fly because the the two layers of the plot are on different coordinate systems. I think it is clear now that ggplot uses the Google "PseudoMercator" for the matrix while expects all user input on epsg4326
I am not sure what do you mean with "reprojection on the fly" but "layer" does not make any reprojection. In fact, it is only a wrapper around "eval(substitute(expression(...)))" to modify easily the panel function of a trellis graphic. However, in my code I am using "grid.raster" with its arguments width, height, x and y, to resize the ggmap raster and to position it in the graphic window created with spplot.
I think "acceptable" depends on the scale only. At coarser scale you just do not see the error because it is relative to the extent and the result converges to the correct reprojection.
I think it depends on the extent. I have tested the code again with the administrative boundaries of Spain and some of its regions (http://biogeo.ucdavis.edu/data/gadm2/shp/ESP_adm.zip). It fails for the country extent (as Edzer suggested and you have found with your file) but it works correctly for a smaller extent (code copied below).
In the code you provide, how do you know NAD27 is the appropriate datum? There is no prj file (one of the big shortcomings of shapefiles is that the presence of crs information in the form of a prj file is not compulsory). Note that you define a datum != WGS84 and you do not define the towgs argument.
It is an example extracted from the p.121 of the 2008 edition of "Applied Spatial Data Analysis with R". That chapter is now available here: http://cran.r-project.org/web/packages/maptools/vignettes/combine_maptools.pdf Best, Oscar. ####################################################### library(ggmap) library(latticeExtra) library(sp) library(maptools) ## http://biogeo.ucdavis.edu/data/gadm2/shp/ESP_adm.zip setwd('/tmp') spain <- readShapePoly('ESP_adm/ESP_adm1') proj4string(spain) <- CRS("+proj=longlat +datum=WGS84") andalucia <- spain[spain$ID_1 == 1,] catalonia <- spain[spain$ID_1 == 6,] ## myPoly <- spain myPoly <- andalucia ## myPoly <- catalonia bbPoly <- bbox(myPoly) gmap <- get_map(c(bbPoly), maptype='watercolor', source='stamen', crop=FALSE) bbMap <- attr(gmap, 'bb') latCenter <- with(bbMap, ll.lat + ur.lat)/2 lonCenter <- with(bbMap, ll.lon + ur.lon)/2 height <- with(bbMap, ur.lat - ll.lat) width <- with(bbMap, ur.lon - ll.lon) spplot(myPoly["ID_1"], fill='transparent') + layer(grid.raster(gmap, x=lonCenter, y=latCenter, width=width, height=height, default.units='native'), under=TRUE)