Создать пространственную линию через точку под заданным углом - PullRequest
0 голосов
/ 23 января 2020

У меня есть пространственный многоугольник, например, форма Гренландии:

library("rnaturalearth")
Greenland <- ne_countries(scale = "medium", country="Greenland")
plot(Greenland)

, и я знаю, как рассчитать его геометрию c центр, то есть центроид:

library("rgeos")
Greenland_cent <- gCentroid(Greenland)
plot(Greenland_cent,add=T,col="red")

Теперь я хотел бы создать линии под разными углами, которые все проходят через центроид, чтобы разрезать Гренландию пополам (примерно, отредактируйте: как упоминалось @Henry, это может быть не совсем половина). Тем не менее, я еще не нашел ни одного метода, который бы позволял создавать линии, заданные углом ... ... есть идеи?

Или есть какие-то другие способы разрезания многоугольника на две части приблизительно или даже точно такой же размер?

Ответы [ 2 ]

2 голосов
/ 23 января 2020

Я реализовал линию, используя тригонометрию. Я предполагал, что вы всегда захотите, чтобы линия начиналась и заканчивалась в Гренландии или за ее пределами, поэтому я нахожу наименьший окружающий круг и заставляю линии начинаться или заканчиваться на этом. Разрезать фигуру пополам - это больше работы, но я предполагаю, что вы можете создать два полукруга, используя координаты, и использовать их, чтобы замаскировать исходную форму Гренландии, чтобы сделать два новых. Оттуда центроиды и области легко.

library(rnaturalearth)
library(sp)
library(rgeos)
library(raster)
projection <- '+proj=stere +lat_0=90 +lat_ts=90 +lon_0=-33 +k=0.994 +x_0=2000000 +y_0=2000000 +datum=WGS84 +units=m +no_defs '
Greenland.raw <- ne_countries(scale = "medium", country="Greenland")
# use a different projection to avoid some warnings
Greenland = spTransform(Greenland.raw, CRSobj = projection)
Greenland_cent <- gCentroid(Greenland)
# Make a simpler Greenland shape - expand and contract to smooth out the crinkly edges 
SimplerGreenland <- gBuffer(gBuffer(Greenland, width = 1), width=-1)
# Make a line from the shape
SimplerGreenlandLine <- as(SimplerGreenland, 'SpatialLines')
# sample all around the simpler line
PointsAroundGreenland <- spsample(x = SimplerGreenlandLine, n = 1000, type = 'regular')
# find the furthest point from the centroid
distances <- gDistance(PointsAroundGreenland, Greenland_cent, byid = T)
furthestpointfromcentroid <- distances[which.max(distances)]
# make the smallest circle that encloses Greenland to ensure that any line we draw will be in Greenland
enclosingcircle <- gBuffer(spgeom = Greenland_cent, width = furthestpointfromcentroid, quadsegs = 100)
# choose an angle and make a line that goes through the centroid and starts and ends on the enclosing circle
angleindegrees <- 5
angle <- angleindegrees * pi / 180
dx <- furthestpointfromcentroid * cos(angle)
dy <- furthestpointfromcentroid * sin(angle)
centroid <- as.numeric(coordinates(Greenland_cent))
x1 <- centroid[1] + dx
y1 <- centroid[2] + dy
x2 <- centroid[1] - dx
y2 <- centroid[2] - dy
l1 <- Line(cbind(c(x1,x2), c(y1,y2)))
l2 <- Lines(list(l1), ID = 'line')
lineatangle <- SpatialLines(list(l2))
crs(lineatangle) <- crs(Greenland)

# plot everything
plot(Greenland)
plot(Greenland_cent, add = T, col = 'red')
plot(lineatangle, add = T, col = 'green')

enter image description here

1 голос
/ 04 февраля 2020

Вот ответ на другой вопрос, а именно нахождение угла, который делит фигуру на 2 равные части. Он не использует вычисление линий, поэтому я решил сделать его вторым ответом, чтобы не потерять первый ответ.

library(rnaturalearth)
library(sp)
library(rgeos)
library(raster)
library(dplyr)
library(swfscMisc)
library(ggplot2)
projection <- '+proj=stere +lat_0=90 +lat_ts=90 +lon_0=-33 +k=0.994 +x_0=2000000 +y_0=2000000 +datum=WGS84 +units=m +no_defs '
Greenland.raw <- ne_countries(scale = "medium", country="Greenland")
# use a different projection to avoid some warnings
Greenland = spTransform(Greenland.raw, CRSobj = projection)
Greenland_cent <- gCentroid(Greenland)
# Make a simpler Greenland shape - expand and contract to smooth out the crinkly edges 
SimplerGreenland <- gBuffer(gBuffer(Greenland, width = 1), width=-1)
# Make a line from the shape
SimplerGreenlandLine <- as(SimplerGreenland, 'SpatialLines')
# sample all around the simpler line
PointsAroundGreenland <- spsample(x = SimplerGreenlandLine, n = 1000, type = 'regular')
# find the furthest point from the centroid
distances <- gDistance(PointsAroundGreenland, Greenland_cent, byid = T)
furthestpointfromcentroid <- distances[which.max(distances)]
findArc <- function(angleindegrees, country_centroid, radius) {
    startandend = c(90-angleindegrees, 90-angleindegrees+180)
    centroid <- as.numeric(coordinates(country_centroid))
    arc = circle.polygon(
        x = centroid[1], 
        y = centroid[2], 
        radius = radius, units = 'km', 
        poly.type = 'cartesian', sides = 100, by.length = F,
        brng.limits = startandend)
    arc = arc[!duplicated(arc),]
    segment = centroid %>% rbind(arc) %>% rbind(centroid)
    p = Polygon(segment)
    ps = Polygons(list(p), 1)
    sps = SpatialPolygons(list(ps))
    crs(sps) = crs(country_centroid)
    sps
}
findHalf <- function(angleindegrees, country_centroid, radius, country_shape) {
    areaCountry = gArea(country_shape)
    sps <- findArc(angleindegrees, country_centroid, radius)
    halfCountry <- crop(country_shape, sps)
    areaHalfCountry <- gArea(halfCountry)
    ratio <- areaHalfCountry / areaCountry
    ratio
}

angle <- seq(from = 1, to = 70, by = 1)
lratios <- lapply(angle, function(a) findHalf(a, Greenland_cent, furthestpointfromcentroid, Greenland))
ratios.df <- do.call(rbind.data.frame, lratios)
names(ratios.df) <- 'ratio'
results.df <- data.frame(angle = angle) %>% dplyr::bind_cols(ratios.df)

ggplot(results.df, aes(x=angle, y=ratio)) + geom_line() + ggtitle('Ratio of half country to whole country')

Полученный график выглядит следующим образом.

enter image description here

Угол в 10 градусов и угол около 69 градусов делит Гренландию на две равные области (в предположении 2-й страны).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...