Error using getNOAA.bathy, are there restrictions on coordinates values? - r

I am trying to execute getNOAA.bathy from package marmap.
I can successfully execute the following (from here):
library(marmap)
getNOAA.bathy(lon1=-20,lon2=-90,lat1=50,lat2=20, resolution=10) -> a
plot(a, image=TRUE, deep=-6000, shallow=0, step=1000)
However, when I execute the following:
getNOAA.bathy(lon1=-80,lon2=-79.833333,lat1=32.7,lat2=32.833333, resolution=10) -> a
plot(a, image=TRUE, deep=-6000, shallow=0, step=1000)
I get the error:
Error in getNOAA.bathy(lon1 = -80, lon2 = -79.833333, lat1 = 32.7, lat2 = 32.833333, : The NOAA server cannot be reached
Questions:
Are there special restrictions to LAT/LON values? Am I
miscalculating something here?
Are there "better" packages that can support my LAT/LON values?

As stated in the help file for getNOAA.bathy(), the resolution argument is expressed in minutes. So resolution=10 means that the cells of your grid will have a dimension of 10 minutes in longitude by 10 minutes in latitude. The bigger the number, the worse the resolution. So considering your region, you need to use the highest resolution possible for the ETOPO1 dataset (i.e. the database that's fetched by getNOAA.bathy()):
getNOAA.bathy(lon1=-80, lon2= 79.833333, lat1=32.7, lat2=32.833333, res=1)
That's definitely not hi-res (you get a grid of 80 values: 10 latitude values by 8 longitude values), but that's the maximum you can get with getNOAA.bathy().
If you need a higher resolution, you should try other sources such as the GEBCO database and the readGEBCO() function of marmap. You should also have a look at sections 2 and 3 of the marmap-ImportExport vignette where other sources are listed.
vignette("marmap-ImportExport")

Related

st_join() inconsistent behaviour - should I trust the result? old version sf?

I am trying to match some points with long/lat coordinates with the associated regions using a map from GADM and st_join(). So the code is very simple:
x <- st_read(my_map)
y <- st_as_sf(my_points, coords = c('long', 'lat')
st_crs(y) = 4326
y <- st_join(y,x)
where both x and y are sf objects (x with polygons, y with points).
The issue is between my home and office computer, one works and the other one throws an error.
My home computer which runs the code without any issues is running on R4.0.4 and sf_0.9-7 (which I realise is older) on a Windows10x64
My office compute runs on R4.0.5 with sf_1.0-2 on a Windows10x64.
Here's the error code:
Error in s2_geography_from_wkb(x, oriented = oriented, check = check) :
Evaluation error: Found 4 features with invalid spherical geometry.
[201] Loop 2 is not valid: Edge 2 crosses edge 4
[935] Loop 16 edge 390 crosses loop 64 edge 6
[2667] Loop 20 edge 835 crosses loop 37 edge 24843
[3401] Loop 1 is not valid: Edge 818 crosses edge 820
Do you know if I can trust the output of the join by using the older version of the package? I briefly looked at the issues in Github but couldn't find something to alarm me, it might just be that they changed one default to FALSE. But I'm wondering if that is something that I should be wary of.

RasterFromXYZ and bi-linear interpolation (R, R-studio)

I have a set of data strucutured x,y,z running coordinates lon -179.5 to 180 and lat -90 to 90, points are at 5 degree increments and z is temperature. I need to convert this data to a raster and interpolate down to a higher resolution. Additionally, I need to fill in the resultant gap between -179.5 and 180 degrees (error on standard RasterFromXYZ function as this is uneven). I previously converted to Cartesian coordinates and used TPS interpolation; however, this has too large a smoothing effect over the data. The original publication (no script available) also used bi-linear interpolation, so I would like to remain consistent. What is the best method to do this?

calculating distance using latitude & longitude

I am calculating the distance covered by bike riders. I have the latitude and longitude info for their starting point and end point. I looked up earlier solutions but using distHaversine with Geosphere package did not work for me. Adding that code here as well.
DF <- data.frame(Start.Lat = c(40.74178, 40.72132, 40.79948, 40.75020, 40.71413, 40.74312, 40.72904, 40.74780, 40.69779, 40.72955), Start.Lon = c(-74.00150, -74.01006, -73.95561, -73.99093, -73.95234, -73.98215, -73.99405, -73.97344, -73.97374, -73.98057), End.Lat =c(40.74174, 40.70380, 40.79377, 40.76133, 40.71335, 40.76096, 40.71894, 40.73705, 40.75110, 40.73493), End.Lon = c(-73.99416, -74.00839, -73.97189, -73.97982, -73.94910, -73.96724, -73.99266 , -73.99009, -73.94074, -73.99201))
Code where I tried to use geosphere:
install.packages("geosphere")
library(geosphere)
distm(cbind(DF$Start.Lon, DF$Start.Lat), cbind(DF$End.Lon, DF$End.Lat), fun = distHaversine)
Error message: (only get this error when I use my full dataset consisting of 30,000 data points)
Error: cannot allocate vector of size 6.7 Gb

R code that evaluates line-of-sight (LOS) between two (lat, lon) points

I'm having trouble figuring out how to calculate line-of-sight (LOS) between two (lat, lon) points, within R code. Any advice on how to approach this problem would be appreciated. I would like to use the R package - raster - for reading in the terrain elevation data. It seems the spgrass package could be leveraged (based on http://grass.osgeo.org/grass70/manuals/r.viewshed.html) but I wanted to avoid loading up a GIS. Thanks.
If you just want to know if point A can see point B then sample a large number of elevations from the line joining A to B to form a terrain profile and then see if the straight line from A to B intersects the polygon formed by that profile. If it doesn't, then A can see B. Coding that is fairly trivial. Conversely you could sample a number of points along the straight line from A to B and see if any of them have an elevation below the terrain elevation.
If you have a large number of points to compute, or if your raster is very detailed, or if you want to compute the entire area visible from a point, then that might take a while to run.
Also, unless your data is over a large part of the earth, convert to a regular metric grid (eg a UTM zone) and assume a flat earth.
I don't know of any existing package having this functionality, but using GRASS really isn't that much of a hassle.
Here's some code that uses raster and plyr:
cansee <- function(r, xy1, xy2, h1=0, h2=0){
### can xy1 see xy2 on DEM r?
### r is a DEM in same x,y, z units
### xy1 and xy2 are 2-length vectors of x,y coords
### h1 and h2 are extra height offsets
### (eg top of mast, observer on a ladder etc)
xyz = rasterprofile(r, xy1, xy2)
np = nrow(xyz)-1
h1 = xyz$z[1] + h1
h2 = xyz$z[np] + h2
hpath = h1 + (0:np)*(h2-h1)/np
return(!any(hpath < xyz$z))
}
viewTo <- function(r, xy, xy2, h1=0, h2=0, progress="none"){
## xy2 is a matrix of x,y coords (not a data frame)
require(plyr)
aaply(xy2, 1, function(d){cansee(r,xy,d,h1,h2)}, .progress=progress)
}
rasterprofile <- function(r, xy1, xy2){
### sample a raster along a straight line between two points
### try to match the sampling size to the raster resolution
dx = sqrt( (xy1[1]-xy2[1])^2 + (xy1[2]-xy2[2])^2 )
nsteps = 1 + round(dx/ min(res(r)))
xc = xy1[1] + (0:nsteps) * (xy2[1]-xy1[1])/nsteps
yc = xy1[2] + (0:nsteps) * (xy2[2]-xy1[2])/nsteps
data.frame(x=xc, y=yc, z=r[cellFromXY(r,cbind(xc,yc))])
}
Hopefully fairly self-explanatory but maybe needs some real documentation. I produced this with it:
which is a map of the points where a 50m high person can see a 2m high tower at the red dot. Yes, I got those numbers wrong when I ran it. It took about 20 mins to run on my 4 year old PC. I suspect GRASS could do this almost instantaneously and more correctly too.

What unit does Spatialite's Distance() function return?

Spatialite has a the ability to calculate the distance between 2 geometries with it's Distance() function. There are other functions that work on LINESTRINGs. However I can't find out what units it returns it in. Is it metres? If I have 2 points, how do I calculate the distance between them in a spatialite query?
(For the record I'm using SRID 4326, i.e. WSG 86, i.e. the old traditional degrees of latitude and longitude).
the unit returned by ST_Distance(), ST_Length() and ST_Area()
exactly is the one defined by the corresponding SRID.
consequently, if you are using latitude and longitude (SRID=4326,
WGS 84), any length will be measured in DEGREES, and any area in
SQUARE DEGREES.
if you are interested in giving a more conventional
unit (METERS, SQUARE METERS), you simply have to project
your geometries into some appropriate 'planar' CRS (e.g. UTM)
using ST_Transform()
In version 2.4.4 and higher there is a function PtDistWithin() which returns meters for a distance query. See doc. section "SQL functions for distance relationships":
http://www.gaia-gis.it/spatialite-2.4.0-4/spatialite-sql-2.4-4.html#p13

Resources