Я хочу создать круг площадью 100 как объект научной фантастики. Я думал, что st_buffer() сделает это, но область чуть меньше 100.
pt.df <- data.frame(pt = 1, x = 20, y = 20)
pt.sf <- st_as_sf(pt.df, coords = c("x", "y"))
circle1 <- st_buffer(pt.sf, dist = sqrt(100 / pi))
st_area(circle1) # 99.95431 on my PC
Я могу использовать фактор выдумки, чтобы умножить радиус, и я получаю то, что хочу.
fudge <- sqrt( 100 / st_area(circle1) )
circle2 <- st_buffer(pt.sf, dist = fudge * sqrt(100 / pi))
st_area(circle2) # 100
Но кажется глупым использовать фактор выдумки.
Есть ли способ создать круг известной области в пакете sf без фактор выдумки в st_buffer ?
пи - иррациональное число. Аналитически точная площадь 100 невозможна. Вычисленный результат ограничен точностью пи, используемой в расчете.
Это проблема точности с плавающей запятой, вычисляющая радиус с усеченной формой числа пи. Это приведет к тому, что круг будет немного меньше желаемого результата. Вы можете видеть, что число пи может быть сохранено только с машинной точностью:
.Machine$double.eps
# 2.22044604925031e-16
pi
# 3.14159265358979
Если вы хотите исправить это, вы можете использовать линейную коррекцию в нужной области. Обратите внимание, что это все еще приблизительное значение, но оно должно значительно приблизить вас к желаемому результату.
radius <- function(area){
A <- area + (area * 0.000457099999999997)
return(sqrt(A / pi))
}
system.file("shape/nc.shp", package = "sf") %>%
st_read() %>%
st_centroid() %>%
st_transform(st_crs(5070)) %>%
st_buffer(radius(100)) %>%
st_area()
Основная проблема в том, что st_buffer
работает внутри с многоугольниками, а не с кругами. Увеличение аргумента nQuadSegs
(по умолчанию = 30) позволяет вам использовать лучшее приближение к кругу за счет памяти и времени вычислений (не знаю, важно ли это для вас):
library(sf)
pt.df <- data.frame(pt = 1, x = 20, y = 20)
pt.sf <- st_as_sf(pt.df, coords = c("x", "y"))
get_area <- function(nq) {
circle1 <- st_buffer(pt.sf, dist = sqrt(100 / pi), nQuadSegs=nq)
st_area(circle1)
}
sapply(c(30,100,300,1000), get_area)
## [1] 99.95431 99.99589 99.99954 99.99996
Если вам действительно нужна площадь ровно 100, то «выдумка», которую предлагает ваш вопрос (и ответ @AdamTrevisan), - это путь (поскольку увеличение количества сегментов до миллиона по-прежнему дает вам только область 99,999999999997200461621) . Чтобы быть действительно умным, вы могли бы использовать формулу для площади вписанного многоугольника, чтобы получить поправочный коэффициент ...
Имеет ли значение ошибка в 0,05%? Почему ?