Vòng tròn 1km quanh các điểm dài ở nhiều nơi trên thế giới


11

Tôi có hàng trăm điểm lat-lat trải rộng trên khắp thế giới và phải tạo ra các đa giác hình tròn xung quanh mỗi điểm, với bán kính chính xác 1000 mét. Tôi hiểu các điểm trước tiên phải được chiếu từ độ (lat long) đến thứ gì đó có đơn vị mét, nhưng làm thế nào để thực hiện điều này mà không cần tìm kiếm và xác định vùng UTM theo cách thủ công cho từng điểm?

Đây là một mwe cho điểm đầu tiên ở Phần Lan.

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"))

Nhưng với điểm thứ hai (Canada) thì nó không hoạt động (vì sai vùng UTM).

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

Làm thế nào điều này có thể được thực hiện mà không nhận và chỉ định thủ công điểm UTM cho mỗi điểm? Tôi không có thêm thông tin cho mỗi điểm hơn lat long.

Cập nhật:

Sử dụng và kết hợp các câu trả lời tuyệt vời từ cả AndreJ và Mike T, đây là mã cho cả hai phiên bản và cốt truyện. Chúng khác nhau về số thập phân thứ 4 hoặc hơn, nhưng cả hai câu trả lời rất tốt!

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

(Không chắc chắn làm thế nào để có được cốt truyện vào bản cập nhật).


1
Một giải pháp khả thi cho phần tìm kiếm thủ công: Điều gì sẽ xảy ra nếu bạn nhận được lưới UTM và giao điểm đó với các điểm của bạn, để bạn thêm vùng thích hợp làm thuộc tính? Thuộc tính có thể là tên vùng hoặc mã EPSG, nhưng một cái gì đó có thể được cung cấp dưới dạng một biến để tự động chọn CRS đúng cho mỗi điểm.
Chris W

1
Tôi gặp vấn đề với "chính xác 1000m" và cụm từ "đa giác hình tròn". Đa giác vòng tròn của bạn cần các phân đoạn vô hạn chính xác là 1000m và chuyển đổi sang UTM (hoặc bất kỳ hệ thống phẳng nào khác) sẽ gây ra nhiều lỗi hơn nữa. Hãy cẩn thận với việc sử dụng "chính xác".
Spainedman

Vâng, tôi không nên thể hiện nó khác nhau. Tôi có nghĩa là 1100m hoặc 900m sẽ quá tắt, và khoảng 20 phân đoạn trên vòng tròn là ok.
Chris

Câu trả lời:


9

Tương tự như @AndreJ, nhưng sử dụng phép chiếu gnomic động , ý tôi là phép chiếu đẳng thức phương vị động cho độ chính xác cao hơn nữa. Một phép chiếu AEQ tập trung vào mỗi điểm sẽ chiếu các khoảng cách bằng nhau theo mọi hướng, chẳng hạn như một vòng tròn được đệm. (Một phép chiếu Mercator sẽ có một số biến dạng ở hướng bắc và hướng đông, vì nó quấn quanh một bên của hình trụ.)

Vì vậy, đối với điểm đầu tiên của bạn xung quanh Phần Lan, chuỗi PROJ.4 sẽ trông như thế này:

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

Vì vậy, bạn có thể tạo một hàm R để thực hiện phép chiếu động này:

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)
}

Sau đó làm một cái gì đó như thế này cho Canada (mục 2):

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

1
Từ trang wikipedia: "Không có biến dạng xảy ra tại điểm tiếp tuyến, nhưng độ méo tăng nhanh khỏi nó". Bạn đã thực hiện một tính toán bù mẫu? Có lẽ en.wikipedia.org/wiki/Azimuthal_equidistant_projection phù hợp hơn.
AndreJ

2
Bất kỳ phép chiếu nào có tỷ lệ chính xác tại điểm gốc của vòng tròn và tuân thủ sẽ có hiệu quả, đơn giản vì 1000m quá nhỏ. Tuy nhiên, đối với bán kính lớn hơn nhiều, phép chiếu Gnomonic sẽ rất tệ. Bạn có thể có nghĩa là để quy định một phép chiếu Equidistant .
whuber

2
Phản hồi tuyệt vời, một phép chiếu AEQ rõ ràng là hoạt động tốt hơn nhiều cho kỹ thuật này, vì vậy tôi đã chuyển ra gnomic. AEQP cũng sẽ giữ khoảng cách lớn hơn nhiều, như trong phạm vi hơn 10.000 km.
Mike T

1
Tôi có thể hiểu nhầm mã, nhưng bạn chỉ cần xây dựng đa giác bộ đệm một lần, trong bất kỳ phép chiếu AEQD nào (Trung tâm luôn bằng 0, tọa độ tối thiểu luôn là -1k, tối đa luôn là + 1k. AEQD tập trung vào từng điểm mà bạn cần để nhận các giá trị lat / lon ...
mkennedy

2
@mkennedy bạn có một điểm tốt. projectedthực sự luôn luôn ở (0, 0) và bufferedcó các điểm ± 1000 m theo hướng x - và y . Nếu việc tối ưu hóa điều này là rất quan trọng, thì bạn chỉ cần chuyển đổi một phiên bản bộ đệm đơn giản của bộ đệm từ AEQD động sang WGS84.
Mike T

4

Thay vì tìm kiếm vùng UTM phù hợp, bạn có thể tạo phép chiếu Mercator ngang tùy chỉnh cho mọi điểm với

+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

Vẽ đường tròn trong hình chiếu đó. Các tọa độ đỉnh của vòng tròn được chiếu sẽ luôn giống nhau, vì vậy bạn chỉ phải tạo chúng một lần. Đối với phần sau, chỉ cần gán CRS tùy chỉnh mới cho chúng.

Tái định hình vòng tròn thành EPSG: 4326 để sử dụng tiếp.

Trong phạm vi 1000m, vòng tròn sẽ gần như chính xác. Nếu không (hoặc cho các vòng tròn lớn hơn), sử dụng aeqdthay vì tmerc.


0

Điều gì sẽ xảy ra nếu bạn thực hiện phương pháp tạo 1000 mét trong EPSG: 4326 xung quanh mỗi điểm của bạn. Sau đó chuyển đổi EPSG: 4326 sang hệ tọa độ khác của bạn? Ưu điểm của việc chiếu điểm, là bạn không phải lo lắng về độ cong của trái đất với EPSG: 4326.


1
Làm thế nào chính xác bạn sẽ tạo ra 1000 m bộ đệm từ EPSG: 4326, có đơn vị độ dài tính bằng độ?
Mike T

Một cách tôi muốn tiếp cận là tạo bộ đệm 1000 mét trong EPSG: 32635. Chuyển đổi nó thành EPSG: 4326 và bây giờ bạn sẽ có số bạn cần.
Greg

1
Đó là cách tiếp cận tương tự được mô tả trong câu hỏi, cùng với những hạn chế của kỹ thuật này.
Mike T
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.