Extract coordinates of raster cells that overlap with multilinestring - coordinates

I'm working with R and I have a raster (population) with population density data on each cell and a multilinestring (border_365_366) that represents an international border. I'd like to extract the coordinates of the raster cells that overlap with the international border.
Does anyone know how to extract this? I think one of the major issues here is that I'm working with a multilestring instead of a data.frame with coordinates.
> class(border_365_366)
[1] "sf" "data.frame"
> class(population)
[1] "RasterLayer"
attr(,"package")
[1] "raster"
> border_365_366
Simple feature collection with 1 feature and 0 fields
geometry type: MULTILINESTRING
dimension: XY
bbox: xmin: 27.32998 ymin: 57.52933 xmax: 28.21014 ymax: 59.46253
geographic CRS: WGS 84
geometry
1 MULTILINESTRING ((27.66656 ...
> population
class : RasterLayer
dimensions : 21600, 34926, 754401600 (nrow, ncol, ncell)
resolution : 0.01030751, 0.01046373 (x, y)
extent : -180, 180, -120.053, 105.9636 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs
names : pop_new
values : 0, 107475 (min, max)

I was able to solve this issue by converting the line to linestring
border_365_366<- st_cast(border_365_366,'LINESTRING')

Related

How to correctly find UV on sphere

I have a sphere and a texture for it.
Texture consist of 16 tiles of zoom = 2 from OSM. Tile size is 256x256.
At top and bottom I added space to cover area in ranges [90, 85.0511] and [-85.0511, -90], proportionally. So texture size was 1024x1083.
I also tried texture without these two spaces, its size was 1024x1024 (map tiles only).
The problem is that after UV mapping on Y-axis objects are smaller on equator and bigger on poles.
There are two types of formulas
u = (lon + 180) / 360; // lon = [-180, 180]
v = (lat + 90) / 180; // lat = [-85.0511, 85.0511]
----
u = Math.atan2(z, x) / (2 * Math.PI) + 0.5; // x, y, z are vertex coordinates
v = Math.asin(y) / Math.PI + 0.5;
I tried all 8 variations: two textures, two u-formulas and two v-formulas.
The result is like on image above, or worse.
What am I doing wrong? Is it about texture, or UV-formulas, or something else?
P.S.: for poles (vertices in lat range = [-90, -85.0511], [85.0511, 90]) in fragment shader I don't use color from texture, but just solid color
OSM uses the Web Mercator projection. See also on OSM wiki.
The conversion from world (x,y,z) to texture (u,v) coordinates would be:
lon = atan2(y, x)
lat = atan2(z, sqrt(x*x+y*y))
u = (lon + pi)/(2*pi)
v = (log(tan(lat/2 + pi/4)) + pi)/(2*pi)
(I assume that z points north like in WGS-84 and all coordinates are right-handed.)
This projection doesn't cover the entire sphere: as the latitude approaches the poles, the v coordinate blows up to infinity. Therefore extending the map to the north or south direction is not going to be helpful.
Instead keep the original square 1024x1024 texture and render a texture mapped sphere capped at the ±85.051129° latitute (that's where v = 0,1) using the above coordinate mapping.
Alternatively (and this is more in-line with Web Mercator spirit), render each tile regular in the UV coordinates, and calculate the XYZ coordinates by reversing the above transformation.

Cluster analysis of a Rasterlayer

Is there a way that i can analyse a cluster of a rasterlayer directly? If modify my Raster into a Matrix it does not work.I used kmeans so far, after i turned my raster into a matrix. But still dont work. I also used this code: r <- getValues(r) to turn my raster into a matrix but still does not work.Another problem is that all my values are NA if i turn my Raster into a matrix. So i dont know how to handle this problem.
my Raster looks like this:
class : RasterLayer
dimensions : 23320, 37199, 867480680 (nrow, ncol, ncell)
resolution : 0.02, 0.02 (x, y)
extent : 341668.9, 342412.9, 5879602, 5880069 (xmin, xmax, ymin, ymax)
crs : +proj=utm +zone=33 +ellps=WGS84 +units=m +no_defs
source : r_tmp_2022-07-13_141214_9150_15152.grd
names : layer
values : 2.220446e-16, 1 (min, max)

as.polygons(SpatRaster, values=FALSE) seems to dissolve cells when it should not

Maybe there is something I do not understand. According to the help page, as.polygons() applied to a SpatRaster with the option values = FALSE should not dissolve cells. But:
library(terra)
# terra 1.5.21
r <- rast(ncols=2, nrows=2, vals=1)
as.polygons(r) # correctly gives a dissolved 1x1 polygon:
# class : SpatVector
# geometry : polygons
# dimensions : 1, 1 (geometries, attributes)
# extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
# coord. ref. : lon/lat WGS 84
# names : lyr.1
# type : <int>
# values : 1
as.polygons(r, values=FALSE) # improperly (?) gives a dissolved 1x1 polygon:
# class : SpatVector
# geometry : polygons
# dimensions : 1, 0 (geometries, attributes)
# extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
# coord. ref. : lon/lat WGS 84
whereas it should give an undissolved polygon, such as the one obtained with dissolve=FALSE (but without the values):
as.polygons(r,dissolve=FALSE)
# class : SpatVector
# geometry : polygons
# dimensions : 4, 1 (geometries, attributes)
# extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
# coord. ref. : lon/lat WGS 84
As you noted, the documentation is incorrect. If you do not want the cells to be dissolved, you need to use dissolve=FALSE.
If you do not want to dissolve, and do not want the values, you can do
library(terra)
r <- rast(ncols=2, nrows=2, vals=1)
p <- as.polygons(r, dissolve=FALSE, values=FALSE)
# or
p <- as.polygons(rast(r))
p
# class : SpatVector
# geometry : polygons
# dimensions : 4, 0 (geometries, attributes)
# extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
# coord. ref. : lon/lat WGS 84
The latter works the way it does, despite the default dissolve=TRUE because there is nothing to dissolve with since rast(r) has no values. If you want the extent you can do
as.polygons(r, extent=TRUE)
# class : SpatVector
# geometry : polygons
# dimensions : 1, 0 (geometries, attributes)
# extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
# coord. ref. : lon/lat WGS 84
That is a (much more) efficient approach that is otherwise equivalent to dissolving (aggregating) all cells.

Draw circle using latitude and longitude

I want to plot a latitude and longitude using matlab. Using that latitude and longitude as center of the circle, I want to plot a circle of radius 5 Nm.
r = 5/60;
nseg = 100;
x = 25.01;
y = 55.01;
theta = 0 : (2 * pi / nseg) : (2 * pi);
pline_x = r * cos(theta) + x;
pline_y = r * sin(theta) + y;
hold all
geoshow(pline_x, pline_y)
geoshow(x, y)
The circle does not look of what I expected.
Drawing a circle on earth is more complex that it looks like.
Drawing a line or a poly line is simple, because the vertices are defined.
Not so on circle.
a circle is defined by all points having the same distance from center (in meters! not in degrees!!!)
Unfortuantley lat and lon coordinates have not the same scale.
(The distance between two degrees of latidtude is always approx. 111.3 km, while for longitude this is only true at the equator. At the poles the distance between two longitudes approach zero. In Europe the factor is about 0.6. (cos(48deg))
There are two solution, the first is more universal, usefull for nearly all problems.
convert spherical coordinate (of circle center) to cartesian plane with unit = 1m, using a transformation (e.g equidistant transformation, also called equirectangular transf., this transformation works with the cos(centerLat) compensation factor)
calculate points (e.g circle points) in x,y plane using school mathematics.
transform all (x,y) points back to spherical (lat, lon) coordinates, using the inverse transformation of point 1.
Other solution
1. write a function which draws an ellipse in defined rectangle (all cartesian x,y)
2. define bounding of the circle to draw:
2a: calculate north-south diameter of circle/ in degrees: this a bit tricky: the distance is define in meters, you need a transformation to get the latitudeSpan: one degrees of lat is approx 111.3 km (eart circumence / 360.0): With this meters_per_degree value calc the N-S disatcne in degrees.
2b: calculate E-W span in degrees: now more tricky: calculate like 2a, but now divide by cos(centerLatitude) to compensate that E-W distances need more degrees when moving north to have the same meters.
Now draw ellipseInRectangle using N-S and E_W span for heigh and width.
But a circle on a sphere looks on the projected monitor display (or paper) only like a circle in the center of the projection. This shows:
Tissot's Error Ellipse

In MongoDB's query, what unit is "center" "radius" in?

> center = [50, 50]
> radius = 10
> db.places.find({"loc" : {"$within" : {"$center" : [center, radius]}}})
Is it 10 km, miles, feet, or meters?
Lat/long?
I must be the same units than your data. If you store location in meters, your query will operate in meters. You have to choose what units you want to use.
I you need to use lat/long, the units for the position of your objects will be in decimal degrees and the units for the distances will be in radians. You need to use the spherical model to handle the fact that earth is round.
They're in degrees - so 1 ~= 69 miles.