1 км об'їжджає довгі точки в багатьох місцях світу


11

У мене сотні ширин довгих точок, рознесених по всьому світу, і я повинен створювати коло-багатокутники навколо кожного з них, радіусом рівно 1000 метрів. Я розумію, що точки потрібно спочатку проектувати від градусів (лат. В довжину) до метричних одиниць, але як це можна зробити без ручного пошуку та визначення UTM-зон для кожної точки?

Ось mwe для першого пункту у Фінляндії.

library(sp)
library(rgdal)
library(rgeos)
the.points.latlong <- data.frame(
  Country=c("Finland", "Canada", "Tanzania", "Bolivia", "France"),
  lat=c(63.293001, 54.239631, -2.855123, -13.795272, 48.603949),
  long=c(27.472918, -90.476303, 34.679950, -65.691146, 4.533465))
the.points.sp <- SpatialPointsDataFrame(the.points.latlong[, c("long", "lat")], data.frame(ID=seq(1:nrow(the.points.latlong))), proj4string=CRS("+proj=longlat +ellps=WGS84 +datum=WGS84"))

the.points.projected <- spTransform(the.points.sp[1, ], CRS( "+init=epsg:32635" ))  # Only first point (Finland)
the.circles.projected <- gBuffer(the.points.projected, width=1000, byid=TRUE)
plot(the.circles.projected)
points(the.points.projected)

the.circles.sp <- spTransform(the.circles.projected, CRS("+proj=longlat +ellps=WGS84 +datum=WGS84"))

Але з другого пункту (Канада) він не працює (тому що неправильна UTM-зона).

the.points.projected <- spTransform(the.points.sp[2, ], CRS( "+init=epsg:32635" ))

Як це можна зробити, не отримуючи вручну та вказуючи точку зони UTM на точку вручну? У мене немає більше інформації за бал, ніж лат.

Оновлення:

Використовуючи та поєднуючи чудові відповіді як від AndreJ, так і від Mike T, ось код обох версій та сюжетів. Вони різні на 4-му десятковому рівні, але обидва дуже хороші відповіді!

gnomic.buffer <- function(p, r) {
  stopifnot(length(p) == 1)
  gnom <- sprintf("+proj=gnom +lat_0=%s +lon_0=%s +x_0=0 +y_0=0",
                  p@coords[[2]], p@coords[[1]])
  projected <- spTransform(p, CRS(gnom))
  buffered <- gBuffer(projected, width=r, byid=TRUE)
  spTransform(buffered, p@proj4string)
}

custom.buffer <- function(p, r) {
  stopifnot(length(p) == 1)
  cust <- sprintf("+proj=tmerc +lat_0=%s +lon_0=%s +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs", 
                  p@coords[[2]], p@coords[[1]])
  projected <- spTransform(p, CRS(cust))
  buffered <- gBuffer(projected, width=r, byid=TRUE)
  spTransform(buffered, p@proj4string)
}

test.1 <- gnomic.buffer(the.points.sp[2,], 1000)
test.2 <- custom.buffer(the.points.sp[2,], 1000)

library(ggplot2)
test.1.f <- fortify(test.1)
test.2.f <- fortify(test.2)
test.1.f$transf <- "gnomic"
test.2.f$transf <- "custom"
test.3.f <- rbind(test.1.f, test.2.f)

p <- ggplot(test.3.f, aes(x=long, y=lat, group=transf))
p <- p + geom_path()
p <- p + facet_wrap(~transf)
p

(Не впевнений, як повернути сюжет в оновлення).


1
Можливе рішення частини ручного пошуку: Що робити, якщо ви отримаєте сітку зони UTM Zone та перетинаєте її з точками, щоб ви додали відповідну зону як атрибут? Атрибут може бути або назвою зони, або кодом EPSG, але щось, що може подаватися у вигляді змінної для автоматичного вибору потрібної CRS для кожної точки.
Кріс Ш

1
У мене проблема з «рівно 1000 м» та фразою «коло-багатокутники». Ваш коло багатокутників потрібні нескінченні сегменти , щоб бути точно 1000м, і конвертація в UTM (або будь-який інший плоскою систему) збираються ввести ще більше помилок. Будьте обережні з використанням "точно".
Спайсмен

Так, я не повинен був це виражати інакше. Я мав на увазі, що 1100 м або 900 м будуть занадто відключені, і приблизно 20 сегментів на колі добре.
Кріс

Відповіді:


9

Подібно до @AndreJ, але використовую динамічну гномічну проекцію , я маю на увазі динамічну азимутальну рівновіддалену проекцію для ще більшої точності. Проекція AEQ, орієнтована на кожну точку, буде проектувати рівні відстані у всіх напрямках, наприклад, буферне коло. (Проекція Меркатора матиме деякі спотворення в північному та східному напрямках, оскільки вона обертається навколо сторони циліндра.)

Тож для вашого першого пункту навколо Фінляндії рядок PROJ.4 буде виглядати приблизно так :

+proj=aeqd +lat_0=63.293001 +lon_0=27.472918 +x_0=0 +y_0=0

Таким чином, ви можете зробити функцію R, щоб зробити цю динамічну проекцію:

aeqd.buffer <- function(p, r)
{
    stopifnot(length(p) == 1)
    aeqd <- sprintf("+proj=aeqd +lat_0=%s +lon_0=%s +x_0=0 +y_0=0",
                    p@coords[[2]], p@coords[[1]])
    projected <- spTransform(p, CRS(aeqd))
    buffered <- gBuffer(projected, width=r, byid=TRUE)
    spTransform(buffered, p@proj4string)
}

Потім зробіть щось подібне для Канади (пункт 2):

aeqd.buffer(the.points.sp[2,], 1000)

1
Зі сторінки вікіпедії: "Жодне спотворення не відбувається в дотичній точці, але викривлення зростає швидко від нього". Чи зробили вибірковий розрахунок зміщення? Можливо, en.wikipedia.org/wiki/Azimuthal_equidistant_projection краще підходить.
AndreJ

2
Будь-яка проекція, яка має правильний масштаб у початку кола і є конформною, буде добре, просто тому, що 1000 м настільки малі. Однак для набагато більших радіусів проекція Gnomonic буде жахливою. Ви, мабуть, мали намір задати проекцію на рівномірну відстань .
whuber

2
Чудовий відгук, проекція AEQ, очевидно, набагато краща для цієї методики, тому я вийшов з гномічного. AEQP також витримає набагато більшу відстань, як, наприклад, на відстані 10 000+ км.
Майк T

1
Я можу нерозуміти код, але вам потрібно створити буферний багатокутник лише один раз, в будь-якій проекції AEQD (Центр завжди дорівнює нулю, хв. Координата завжди -1 к, макс завжди + 1 к. AEQD зосереджена на кожному з пунктів, необхідних для отримання значень lat / lon ...
mkennedy

2
@mkennedy у вас є хороший момент. projectedдійсно завжди знаходиться в (0, 0) і bufferedмає точки ± 1000 м у x - і y -напрямках. Якщо для оптимізації цього було важливо, просто перетворіть просту декартову версію буфера з динамічного AEQD в WGS84.
Майк Т

4

Замість пошуку потрібної зони UTM можна створити власну поперечну проекцію Меркатора для кожної точки

+proj=tmerc +lat_0=.... +lon_0=... +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs

Накресліть коло в цій проекції. Проектовані координати вершин кола завжди будуть однаковими, тому їх потрібно створити лише один раз. Для цього просто призначіть їм нові спеціальні CRS.

Відхиліть коло до EPSG: 4326 для подальшого використання.

У межах 1000 м коло буде майже точним. Якщо ні (або для великих кіл), використовуйте aeqdзамість tmerc.


0

Що робити, якщо ви скористаєтеся підходом до створення 1000 метрів в EPSG: 4326 навколо кожної точки. Потім конвертуйте EPSG: 4326 у вашу іншу систему координат? Перевага проектування точки полягає в тому, що вам не доведеться турбуватися про викривлення землі за допомогою EPSG: 4326.


1
Як саме ви створили б 1000 м буферів з EPSG: 4326, який має одиниці довжини в градусах?
Майк T

Один із способів я підійшов би до цього - створити буфер 1000 метрів в EPSG: 32635. Перетворіть це в EPSG: 4326, і тепер у вас буде номер, який вам потрібен.
Грег

1
Це той самий підхід, описаний у питанні, поряд з обмеженнями цієї методики.
Майк Т
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.