Plotting a raster behind a shapefile - r

How can I plot a "raster" object behind a shapefile object? Both plot fine on their own but the points don't plot over the raster:
require(rgdal)
require(maptools)
require(raster)
myproj = "+proj=utm +zone=12 +north +ellps=WGS84 +units=m"
shp = readShapeSpatial(fn.shp, proj4string = CRS(myproj))
ras = raster(fn.tif)
plot(ras)
plot(shp, bg="transparent", add=TRUE)

Overplotting raster plots with points, lines, and polygons should work just fine, as the following example shows.
My best guess would be that the Spatial* objects you are attempting to plot on top of the raster fall outside of the region being plotted. Have you checked that both the raster and Spatial* objects are in the same CRS, and (assuming they are) that the bounding boxes overlap? (i.e. try bbox(shp) and bbox(ras), and compare the results).
library(rgdal)
library(raster)
# Create a raster
ras <- raster(ncols=36, nrows=18)
ras[] <- runif(ncell(ras))
# Create a SpatialPoints object
shpPts <- spsample(Spatial(bbox=bbox(ras)), 20, type="random")
# Create a SpatialPolygons object
p1 <- rbind(c(-10,0), c(140,60), c(160,0), c(140,-55), c(-10,0))
shpPolys <- SpatialPolygons( list(Polygons(list(Polygon(p1)), 1)))
# Plot them, one layer after another
plot(ras)
plot(shpPts, pch=16, col="red", add=TRUE)
plot(shpPolys, col="yellow", add=TRUE)

Related

Shapefile and Raster with same CRS but NO output when clipping

Problem: Plot is empty, no results when clipping raster with shapefile.
I am using a shapefile with original EPSG4326 projection and a MODIS product with original sinusoidal projection. I converted both to the same projection (DesiredCRS) as you can see in the script, however when making a clip of the raster I don't get any results.
library(terra)
library(sf)
library(sp)
library(raster)
# Inputs
HDFfile <- "ModisProductsOriginal/MCD18A1.A2001001.h15v05.061.2020097222704.hdf"
Shapefile <- "Shapefile/Outline_5/Portugal_Outline_5_CAOP2019.shp"
DesiredCRS <- "+proj=longlat +datum=WGS84"
# Feature
Shp <- st_read(Shapefile)
Terceira <- Shp[Shp$DI == '43',1]
Terceira <- st_transform(Terceira, DesiredCRS)
plot(Terceira, axes=TRUE)
Terceira's plot:
Plot Output
# Modis data
SDSs <- sds(HDFfile)
SDS8 <- SDSs[8]
SDS8_template <- rast(ncol=1200, nrow=1200, xmin=-34, xmax=-24, ymin=36, ymax=41, crs=DesiredCRS)
SDS8_reprojected <- project(SDS8, SDS8_template) # Reproject changes pixels?
SDS8_raster <- raster(SDS8_reprojected)
plot(SDS8_raster)
SDS8_raster's plot: Plot Output
# Clip
Clip.step1 <- crop(SDS8_raster, extent(Terceira))
Clip <- mask(Clip.step1, Terceira)
plot(Clip)
Clip.step1's plot: Plot Output
Clip's plot: Plot Output
All images show axes with the same projection. I don't understand what I'm doing wrong... Am I correctly defining the CRS and the extent?
Updated:
Panoply view of original shapefile and original HDF product:
Panoply Output
Plot of the two datasets together by Hijmans: Plot Output
This is but tricky to debug because you mix different packages, and you do not show(object). Anyway, here is a terra approach, showing where it would be useful to see the objects metadata; and a plot that shows the raster and vector data together.
library(terra)
HDFfile <- "MCD18A1.A2001001.h15v05.061.2020097222704.hdf"
Shapefile <- "Portugal_Outline_5_CAOP2019.shp"
DesiredCRS <- "+proj=longlat +datum=WGS84"
Shp <- vect(Shapefile)
Terceira <- Shp[Shp$DI == '43',1]
SDSs <- sds(HDFfile)
SDS8 <- SDSs[8]
Start by projecting the vector data to the original raster data.
TercSin <- project(Terceira, crs(SDS8))
plot(SDS8, 1)
lines(TercSin)
As you saw, that does not work. The reason is that GDAL/PROJ reads from file or assumes the wrong ellipsoid
cat(substr(crs(SDS8),1,230), "\n")
#PROJCRS["unnamed",
# BASEGEOGCRS["Unknown datum based upon the Clarke 1866 ellipsoid",
# DATUM["Not specified (based on Clarke 1866 spheroid)",
# ELLIPSOID["Clarke 1866",6378206.4,294.978698213898,
Or like this
describe("HDF4_EOS:EOS_GRID:\"MCD18A1.A2001001.h15v05.061.2020097222704.hdf\":MODISRAD:GMT_1200_DSR")[1:8]
#[1] "Driver: HDF4Image/HDF4 Dataset"
#[2] "Files: MCD18A1.A2001001.h15v05.061.2020097222704.hdf"
#[3] "Size is 1200, 1200"
#[4] "Coordinate System is:"
#[5] "PROJCRS[\"unnamed\","
#[6] " BASEGEOGCRS[\"Unknown datum based upon the Clarke 1866 ellipsoid\","
#[7] " DATUM[\"Not specified (based on Clarke 1866 spheroid)\","
#[8] " ELLIPSOID[\"Clarke 1866\",6378206.4,294.978698213898,"
As you point out (and see here), MODIS (or at least some products) uses
modcrs <- "+proj=sinu +lon_0=0 +x_0=0 +y_0=0 +a=6371007.181 +b=6371007.181 +units=m"
So let's try that
TercSin <- project(Terceira, modcrs)
plot(SDS8, 1)
lines(TercSin)
That looks OK. So we need to do
crs(SDS8) <- modcrs
and continue
Terceira <- project(Terceira, DesiredCRS)
Terceira
SDS8_template <- rast(ncol=1200, nrow=1200, xmin=-34, xmax=-24, ymin=36, ymax=41, crs=DesiredCRS)
SDS8_reprojected <- project(SDS8, SDS8_template)
SDS8_reprojected
# Again plot the two datasets together
plot(SDS8_reprojected)
lines(Terceira)
Clip.step1 <- crop(SDS8_reprojected, Terceira)
Clip <- mask(Clip.step1, Terceira)
Clip
plot(Clip)
lines(Terceira)

Overlay shapefile over Raster in Multiple plots

I am trying overlay the shapefile of south asia on top of multiple raster plots using the code as below: 'a' is a multilayered raster file. Here is the link to the data (917KB size) Test_Data
ras <- list.files("/filepath/", pattern = "\\.tif$", full=TRUE)
s <- stack(ras)
south_asia <- readOGR('/filepath/south_asia.shp') #to import shapefile
cropped <- crop(x = s, y = extent(south_asia)) #crop raster
plot(cropped)
plot(south_asia, add=TRUE)
This code gives me one shapefile and multiple raster plots. How do i overlay the shapefile on top of the rasters?
Any help will be appreciated.
P.S: They are in same CRS
Thanks
First, please try to give a reproducible example instead of a link to download files externally!
If you manually construct the plot (e.g. using par with base plotting) you can get your desired behaviour:
library(raster)
## testdata
# shapefile
shp <- getData(country='IND', level=1)
# raster
r <- getData('alt', country='IND', mask=TRUE)
# create 4 layer rasterstack
rs <- stack(r,r,r,r)
## finally plot
# 2 rows, 2 cols
par(mfrow=c(2,2))
# loop layers
for (ii in 1:nlayers(rs)){
plot(subset(rs,ii), main=names(rs)[ii])
plot(shp, add=T)
}
Edit:
Use plot(subset(rs,ii), main=names(rs)[ii]) in the loop to plot the respective layer.
The result:
I would suggest using the argument addfun in the plot option for raster stack/brick
For example:
# Function to add shapefile "shp_file" on each raster plot
add_shp=function(){plot(shp_file, bg="transparent", add=TRUE)}
#Plot selected raster of a raster stack, rs
plot(rs[[c(1:5)]],col=tim.colors(5),addfun=add_shp)
This will add shapefile shp_file to each of the 5 plots from the rasterstack rs.

Plotting a raster with recentered Mollweide projection in R

I would like to generate a map of the world in Mollweide projection, but centered on longitude 150. I would like to plot a raster and a vector map of the world on top.
library(maptools)
library(raster)
library(rgdal)
# generate some dummy data
data(wrld_simpl)
ras <- raster(ext=extent(wrld_simpl), res=c(2,2))
values(ras) <- runif(ncell(ras))
ras <- mask(ras, wrld_simpl, inverse=TRUE)
# Here is the map unprojected, without recentering
plot(ras)
plot(wrld_simpl, add=TRUE, col='black')
# now I transform to Mollweide
mollproj <- '+proj=moll +lon_0=150 +ellps=WGS84'
# project raster
ext <- projectExtent(ras, mollproj)
rasMoll <- projectRaster(ras, to=ext)
# project vector map
wrldMoll <- spTransform(wrld_simpl, CRS(mollproj))
# plot
plot(rasMoll)
plot(wrldMoll, add=TRUE)
There are several problems here. The map is not at full extent, the vector map has horizontal lines, and there are floating pieces of the raster beyond the bounds of the world.
Any suggestions on how to get this to work?
Thanks!

Can I clip an area around a shapefile in R by specifying the coordinates?

I have a map of landcover data in R and want to clip a circle of specific area, say 20km, and extract the resultant circular shapefile.
# read in the shape file, assign the CRS and plot it
area <- readShapePoly("Corrine Land Use ITM Projection - Copy.shp", proj4string = CRS("+init=epsg:2157"))
plot(area, xlim = c(560000,600000), ylim = c(530000,580000), axes=TRUE)
# create a dataframe of the location where the buffer should be made and plot it
locations<-data.frame(latitude=584503.3,longitude = 560164.5)
points(locations, bg='tomato2', pch=21, cex=3)
Do I need to change my points into a coordinate system first before I do this?
The shape file is the Corine Landcover 2012 - National http://gis.epa.ie/GetData/Download
Thanks
Your polygons
area <- shapefile("Corrine Land Use ITM Projection - Copy.shp")
You can create a circle (or multiple circles) like this:
library(dismo)
p <- polygons(circles(cbind(0,0), sqrt(20000 / pi), lonlat=FALSE, dissolve=FALSE))
crs(p) <- crs(area)
Intersect
int <- crop(area, p)
Write
shapefile(int, 'landcover_circle.shp')
#Manassa: I believe you will need to ensure the shapefile and raster are in the same projection before you clip, then you can use the crop function in the raster library. Please note, the output will be a clipped raster, not a shapefile as stated in your original question.
# Reproject shapefile to same projection as the raster
#shp = shapefile
#r = raster
library(rdgal)
shp.reproject <- spTransform(shp, crs(r))
#crop raster with polygon
library(raster)
r.crop <- crop(r, shp.reproject)

Clipping raster using shapefile in R, but keeping the geometry of the shapefile

I am using {raster} to clip (or crop) a raster based on an irregular shapefile (the Amazon biome) but the output always has a rectangular extent. However, I need the output in the exact same geometry of the shapefile. Any tips? Cheers.
library(raster)
library(rgdal)
myshp <- readOGR("Amazon.shp", layer="Amazon")
e <- extent(myshp)
myraster <- raster("Temperature.tif")
myraster.crop <- crop(myraster, e, snap="out", filename="myoutput.tif")
One option is to use raster::mask()
library(maptools) ## For wrld_simpl
library(raster)
## Example SpatialPolygonsDataFrame
data(wrld_simpl)
SPDF <- subset(wrld_simpl, NAME=="Brazil")
## Example RasterLayer
r <- raster(nrow=1e3, ncol=1e3, crs=proj4string(SPDF))
r[] <- 1:length(r)
## crop and mask
r2 <- crop(r, extent(SPDF))
r3 <- mask(r2, SPDF)
## Check that it worked
plot(r3)
plot(SPDF, add=TRUE, lwd=2)
Package terra:: made it simpler, you can ::crop and mask in the same step.
# Load packages
library(maptools) # For geometry
library(terra) # Perform the crop and mask
###--- Preparing polygon and raster ---###
# Example SpatialPolygonsDataFrame
data(wrld_simpl)
polygon <- subset(wrld_simpl, NAME=="Luxembourg")
plot(polygon) # have a look
# Convert from SpatialPolygonsDataFrame to SpatVector (terra package format)
# And create a smaller polygon with buffer (negative to be "inside")
polygon_bf <- buffer(vect(polygon), width= -100000)
plot(polygon_bf, add= T) # have a look on both
# Create a SpatRaster from a file
f <- system.file("ex/elev.tif", package="terra")
r_lux <- rast(f)
plot(r_lux) # have a look on SpatRaster (terra package format)
# See the steps with plot
plot(polygon, add= T)
plot(polygon_bf, add= T)
Click to see intermediate steps (all files)
########################################################
### Crop and mask by any polygon ###
raster_cp <- crop(r_lux, polygon_bf, mask= T)
# Note: if mask= F, the crop will be by extent (box) ###
########################################################
### Check the results
plot(raster_cp)
plot(polygon_bf, lwd=1, add=T)
Click to see the final output
In addition, (with raster package) in case you want to perform with a simple geometry (i.g. box), the coordinates of the extent can be place directly:
e <- as(extent(c(xmin= -16, xmax= -7.25, ymin= 4, ymax= 12.75)), 'SpatialPolygons')
crs(e) <- "+proj=longlat +datum=WGS84 +no_defs"
r <- crop(my_raster, e)

Resources