Missing data/ 0 value for Chl-a on 180 degree meridian (Oceanmap) - raster

My first querstion here, fantastic community.
I have a slight issue projecting some chl-a data across the 180 meridian (Fiji), using Oceanmap package. I can do this in GIS but would like to be able to produce these results in R. Please see below for code and images. Basically when I project a larger frame of the area I want to display the data projects perfectly, however when I zoom in closer to Fiji which is really what I want, I get a white line (0 value I assume) across the 180 meridian. Is this a coordinate projection issue and the stitching now working at such resolution?
library(oceanmap)
library(ncdf4)
library(raster)
library(viridis)
chl.win <- ('~/Desktop/A20200812020172.L3m_SNSP_CHL_chlor_a_4km.nc')
chl.dat <- nc_open(chl.win)
chl.dat.raster <- nc2raster(chl.dat, "chlor_a", lonname="lon", latname="lat", date=T)
chl.flip <- flip(chl.dat.raster, "y")
chl.360 <- shift(raster::rotate(shift(chl.flip, 180)), 180)
chl.360.crop = raster::crop(chl.360, extent(c(176, 183, -19.8, -15.5)))
vpal <- viridis(100, alpha = 1, begin = 0, end = 1, option = "mako")
v(chl.360.crop, cbpos = "r", pal = "jet", zlim = c(0,1), cb.xlab = expression("Chlorophyll-a (mg m"^-3*")"),
bwd = 0, grid = F, replace.na = F, Save = T, plotname = "First_Quarter_2020", fileformat = "png", width = 12,
height = 6)
Image showing white line on 180 meridian

Related

Assigning projection to a block of code, home range polygons

Newbie here - I am creating homerange polygons from pnt data using different proportion of pnts (100, 95, 70, 50). I can generate this but I cant assign a projection to the shapefile polygon within the same block of code. Previous to this I have split a file based on tag and month, and these are the inputs for here.
Help, I know there is a simple fix but Im too fresh to work it out...
#User defined input to be modified
per100 = 100 # percent MCP to create (e.g. 95, 100 etc)
per95 = 95
per70 = 70
per50 = 50
#load required packages
require(sf)
require(sp)
require(maptools)
require(adehabitatHR)
require(rgdal)
mcpresults = matrix(nrow = 0, ncol = 5)
colnames(mcpresults) <- c("ID", "HR_TYPE", "MCP_LEVEL", "POINTS", "AREA_KM2")
for (i in 1:length(newlist)){
xy.mcp = SpatialPoints(newlist[[i]]#coords)
mcp.out = mcp(xy.mcp, per100, unout = "km2")
plot(xy.mcp, main=names(newlist[i]))
plot(mcp.out, add=TRUE)
name = names(newlist[i])
area = mcp.out$area
row = nrow(newlist[[i]])
mcpresults = rbind(mcpresults , c(name, "MCP", per100, row, area))
coord_map(projection = sf::st_crs(4326))
writePolyShape(mcp.out, paste0(name, "_", per100, "MCP"), factor2char = TRUE)
cat(showWKT(proj4string(newlist[[i]])), file = paste0(name, "_", per100, "_MCP.prj"))
}
Im expecting there to be WGS84 projection on the generated polygon shapefiles, so I can view them in ArcGIS

How to add polygon to 3D Map in r rayshader?

I am new to geo spatial data and just manage to plot in small bits & pieces by looking at few articles on web.
I am trying to plot polygon boundaries on the 3D plot which I have built using rayshader package but facing issues with displaying polygon boundaries on top.
Shape file used is 2011_Dist.shp which can be downloaded from Shapefile Github link
Code I have tried:
library(tidyverse)
library(sf)
library(elevatr)
library(raster)
library(rayshader)
library(osmdata)
# read districts shape file
ind_distirct_shp <- sf::st_read("local path/2011_Dist.shp")
ind_distirct_shp
# filter State
delhi_district_shp <- ind_distirct_shp %>%
sf::st_as_sf() %>%
filter(ST_NM %in% c("NCT of Delhi"))
# this shows the polygon boundaries that I need on top of map
plot(delhi_district_shp)
# download elevation data for State Delhi
delhi_raster <- elevatr::get_elev_raster(delhi_district_shp, z = 10, clip = "location")
# convert to matrix
delhi_mat <- raster_to_matrix(delhi_raster)
# 3D plot using Rayshader
delhi_mat %>%
height_shade(texture = grDevices::colorRampPalette(c("#9a133d","orange","red","purple"
))(256)) %>%
plot_3d(heightmap = delhi_mat,
windowsize = c(800,800), # c(800*wr,800*hr)
solid = FALSE,
zscale = 1,
phi = 90,
zoom = .6,
theta = 0,
shadowcolor = "grey50",
linewidth = 6,
background = "white",
solidlinecolor = "#013b39")
Issue: Now when I try to Modify this to add polygon lines it doesn't work.
polygon_layer = generate_polygon_overlay(delhi_district_shp, extent = extent(delhi_raster),
heightmap = delhi_mat) # , palette="grey30"
polygon_layer
delhi_mat %>%
height_shade(texture = grDevices::colorRampPalette(c("#9a133d","orange","red","purple"
))(256)) %>%
add_overlay(polygon_layer) %>%
plot_3d(heightmap = delhi_mat,
windowsize = c(800,800), # c(800*wr,800*hr)
solid = FALSE,
zscale = 1,
phi = 90,
zoom = .6,
theta = 0,
shadowcolor = "grey50",
linewidth = 6,
background = "white",
solidlinecolor = "#013b39")
It should have been polygon lines on top of the Orange 3D map but it didn't work as I expected.
I also tried with Rayshder's tyler website example https://www.tylermw.com/adding-open-street-map-data-to-rayshader-maps-in-r/
library(osmdata)
osm_bbox = c(extent(delhi_raster)[3],extent(delhi_raster)[1],extent(delhi_raster)[4],extent(delhi_raster)[2])
osm_bbox
raster_polygon_boundary <- osmdata::opq(osm_bbox) %>%
add_osm_feature("highway") %>% # "admin_level"
osmdata_sf()
raster_polygon_boundary
Output:
Object of class 'osmdata' with:
$bbox : 76.8425681832661,28.4030759258059,77.347719586084,28.8793200072187
$overpass_call : The call submitted to the overpass API
$meta : metadata including timestamp and version numbers
$osm_points : 'sf' Simple Features Collection with 0 points
$osm_lines : NULL
$osm_polygons : 'sf' Simple Features Collection with 0 polygons
$osm_multilines : NULL
$osm_multipolygons : NULL
I am getting 0 polygons & lines above so I wont't be able to add any polygon on top of 3D plot.
How can I fix this. Appreciate any help.
Adding alphalayer to add_overlay(polygon_layer,alphalayer = .6) helped even though it worked but still transparency is not working perfectly. It is causing some whiteness in the plot. If anyone else has better answer or way to improve it then please feel free to share.
delhi_mat %>%
height_shade(texture = grDevices::colorRampPalette(c("#9a133d","orange","red","purple"
))(256)) %>%
add_overlay(polygon_layer,alphalayer = .6) %>%
add_overlay(generate_label_overlay(delhi_district_shp, extent = extent(delhi_raster),
text_size = 5, point_size = 1,
halo_color = "white",halo_expand = 5,
seed=1,
heightmap = delhi_mat, data_label_column = "DISTRICT")) %>%
plot_3d(heightmap = delhi_mat,
windowsize = c(800,800), # c(800*wr,800*hr)
solid = FALSE,
zscale = .7,
phi = 90,
zoom = .6,
theta = 0,
shadowcolor = "grey50",
linewidth = 6,
background = "white",
solidlinecolor = "#013b39")

Animated 3D scatterplot and save it as gif in R

I want to plot a animated 3D scatterplot and save it as gif. I followed the code provided by the R Graph Gallery example: https://www.r-graph-gallery.com/3-r-animated-cube.html.
library(rgl)
library(magick)
options(rgl.printRglwidget = TRUE)
# Let's use the iris dataset
# iris
# This is ugly
colors <- c("royalblue1", "darkcyan", "oldlace")
iris$color <- colors[ as.numeric( as.factor(iris$Species) ) ]
# Static chart
plot3d( iris[,1], iris[,2], iris[,3], col = iris$color, type = "s", radius = .2 )
# We can indicate the axis and the rotation velocity
play3d( spin3d( axis = c(0, 0, 1), rpm = 20,dev = cur3d()),startTime = 0, duration = 10 )
# Save like gif
movie3d(
movie="3dAnimatedScatterplot",
spin3d( axis = c(0, 0, 1), rpm = 20,dev = cur3d()),
startTime = 0,
duration = 10,
dir = ".",
type = "gif",
clean = T,
fps=10,
convert=T
)
plot3d was successed output a 3d scatter plot.
Static 3d scatter plot
But the final output: 3dAnimatedScatterplot.gif,just a black image
3dAnimatedScatterplot.gif
when I set clean=F, all frame images are black. So, I guess the play3d() was not working.
Can anyone provide any help to me ? Thanks a lot !
Most likely snapshot3d isn't working for you. Try it with the option webshot = FALSE instead of the default webshot = TRUE. That uses a different mechanism for saving the image.

Error encountered while plotting right half of facial surface mesh in R by subsetting full face vertices and indices data

I have vertices and indices data for human face here. I have a post one year ago on plotting 3D facial surface mesh based on these data. Now, I want to plot only the right half and mid-facial vertices while ignoring the left side vertices. Based on my earlier plot, I tried the following code:
library(tidyverse)
library(readxl)
library(rgl)
vb <- read_excel("...\\vb.xlsx", sheet = "Sheet1", col_names = F)
it <- read_excel("...\\it.xlsx", sheet = "Sheet1", col_names = F)
# Extract vertices for the right side
lm_right_ind <- which(vb[,1] < 0)
vb_mat_right <- t(vb[lm_right_ind, ])
vb_mat_right <- rbind(vb_mat_right, 1)
rownames(vb_mat_right) <- c("xpts", "ypts", "zpts", "")
vertices1_right <- c(vb_mat_right)
# Extract `it` whose rows do not contain vertices on the left side
# Left-side vertices have vb[,1] greater than 0
lm_left_ind <- which(vb[,1] > 0)
leftContain <- NULL
for (i in 1: dim(it)[1]) {
if (T %in% (it[i,] %in% lm_left_ind)) {
leftContain[i] <- i
} else {leftContain[i] <- NA}
}
leftContain <- leftContain[!is.na(leftContain)]
# Remove indices that involve left-side vertices
it_rightMid <- it[-leftContain,]
it_mat_right <- t(as.matrix(it_rightMid))
rownames(it_mat_right) <- NULL
indices_right <- c(it_mat_right)
# Plot
try1_right <- tmesh3d(vertices = vertices1_right, indices = indices_right, homogeneous = TRUE,
material = NULL, normals = NULL, texcoords = NULL)
# Use addNormals to smooth the plot. See my Stackoverflow question:
# https://stackoverflow.com/questions/53918849/smooth-3d-trangular-mesh-in-r
try12_right <- addNormals(try1_right)
shade3d(try12_right, col="#add9ec", specular = "#202020", alpha = 0.8)
I got an error whing trying to obtain try12_right:
Error in v[, it[3, i]] : subscript out of bounds.
I did exactly as what I did in my earlier plot but why something went wrong here? Thank you.
Here's an example of using a clipping plane to leave off the left hand side of a mesh object:
library(rgl)
open3d()
root <- currentSubscene3d()
newSubscene3d("inherit", "inherit", "inherit", parent = root) # Clipping limited to this subscene
shade3d(addNormals(subdivision3d(icosahedron3d(), 2)), col = "pink")
clipplanes3d(a = 1, b = 0, c = 0, d = 0)
useSubscene3d(root)
decorate3d()
The fiddling with subscenes limits the clipping to just the shaded sphere, not everything else in the picture.
This produces this output:
If there's nothing else there, it's simpler:
library(rgl)
open3d()
shade3d(addNormals(subdivision3d(icosahedron3d(), 2)), col = "pink")
clipplanes3d(a = 1, b = 0, c = 0, d = 0)
which produces

RGoogleMaps axes

I can't find any documentation of the following problem I'm having with the axis labels in RGoogleMaps:
library(RgoogleMaps)
datas <- structure(list(LAT = c(37.875, 37.925, 37.775, 37.875, 37.875),
LON = c(-122.225, -122.225, -122.075, -122.075, -122.025)),
.Names = c("LAT", "LON"), class = "data.frame",
row.names = c(1L, 2L, 3L, 4L, 5L))
# Get bounding box.
boxt <- qbbox(lat = datas$LAT, lon = datas$LON)
MyMap <- GetMap.bbox(boxt$lonR, boxt$latR, destfile = "Arvin12Map.png",
maptype = "mobile")
PlotOnStaticMap(MyMap, lat = datas$LAT, lon = datas$LON,
axes = TRUE, mar = rep(4, 4))
When I run this on my computer the horizontal axis ranges from 300W to 60E, but the ticks in between aren't linearly spaced (300W, 200W, 100W, 0, 100E, 160W, 60W).
Also, the vertical axis moves linearly from 300S to 300N. It seems that no matter what data I supply for datas, the axes are always labeled this way.
My question is:
1. Does this problem occur on other machines using this code?
2. Does anyone have an explanation for it?
and
3. Can anybody suggest a way to get the correct axes labels (assuming these are "incorrect", but maybe i'm somehow misinterpreting the plot!)?
Thank you for your time.
Yes
As #Andrie suggested, this appears to be a bug. When axes = TRUE, the degAxis() function called by PlotOnStaticMap() extracts the x and y plot coordinates of the pretty tickmarks found by axTicks(). degAxis() expects these coords to be in the coordinate system of the map, but rGoogleMaps returns them as pixel coordinates, calculated from a central origin. With a plot size of 640 x 640, the pretty tickmarks are assigned to -300, -200, -100, 0,100, 200, 300 in both E-W and N-S directions. You end up with 300W, 200W, 100W, 0, 100E, 160W, 60W, because the degreeLabelsEW() function called by degAxis() assumes that, given longitudes must fall within [-180, 180], any longitudes higher than 180 are in fact in the western hemisphere (e.g. 200E is 20 degrees eastward into the western hemisphere, i.e. 160W). Not sure why it doesn't perform similarly with nonsensical N, S and W coordinates.
A quick workaround, continuing with your MyMap object:
PlotOnStaticMap(MyMap, lat = datas$LAT, lon = datas$LON,
axes = FALSE, mar = rep(4.5, 4))
# x-axis
xrange <- MyMap$BBOX$ur[2] - MyMap$BBOX$ll[2]
xticklength <- xrange / (length(axTicks(1)) - 1)
xticklabs <- seq(MyMap$BBOX$ll[2], MyMap$BBOX$ur[2], xticklength)
xticklabs <- parse(text = paste(sprintf('%.2f', abs(xticklabs)),
ifelse(xticklabs < 0, '*degree*W', '*degree*E'), sep=''))
axis(1, at=axTicks(1), xticklabs, cex.axis=0.8)
# y-axis
yrange <- MyMap$BBOX$ur[1] - MyMap$BBOX$ll[1]
yticklength <- yrange / (length(axTicks(2)) - 1)
yticklabs <- seq(MyMap$BBOX$ll[1], MyMap$BBOX$ur[1], yticklength)
yticklabs <- parse(text = paste(sprintf('%.2f', abs(yticklabs)),
ifelse(yticklabs < 0, '*degree*S', '*degree*N'), sep=''))
axis(2, at=axTicks(2), yticklabs, cex.axis=0.8, las=1)

Resources