Dünyanın birçok yerinde lat-long noktalarının etrafında 1km daireler


11

Dünyaya yayılmış yüzlerce enlemesine uzun noktam var ve her birinin çevresinde tam olarak 1000 metre yarıçapı olan daire çokgenler oluşturmalıyım. Noktaların önce derece (enlem) uzunluğundan metre birimleriyle bir şeylere yansıtılması gerektiğini anlıyorum, ancak bu, her nokta için UTM bölgelerini manuel olarak arama ve tanımlamadan nasıl yapılabilir?

İşte Finlandiya'da ilk nokta için bir 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"))

Ancak ikinci nokta ile (Kanada) işe yaramıyor (çünkü yanlış UTM bölgesi).

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

Bu, nokta başına UTM bölge noktasını manuel olarak alıp belirtmeden nasıl yapılabilir? Her nokta için lat long'dan daha fazla bilgi yok.

Güncelleme:

Hem AndreJ hem de Mike T'den gelen harika cevapları kullanarak ve birleştirerek, hem sürümler hem de grafikler için kod burada. Ondalık ondalık sayıları farklı, ama ikisi de çok iyi cevaplar!

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

(Çizimin nasıl güncelleneceğinden emin değilim).


1
Manuel arama kısmına olası bir çözüm: Bir UTM Zone ızgarası alıp puanlarınızla kesişirseniz, uygun bölgeyi nitelik olarak eklemeniz için ne olur? Özellik bölge adı veya EPSG kodu olabilir, ancak her nokta için doğru CRS'yi otomatik olarak seçmek üzere değişken olarak beslenebilecek bir şey olabilir.
Chris W

1
"Tam 1000m" ve "circle-polygons" ifadesi ile ilgili bir sorunum var. Daire çokgenlerinizin tam olarak 1000m olması için sonsuz segmentlere ihtiyacı vardır ve UTM'ye (veya başka bir düzlemsel sisteme) dönüştürmek daha da fazla hata getirecektir. "Tam" kullanımı konusunda dikkatli olun.
Spacedman

Evet, farklı ifade etmemeliydim. 1100m veya 900m'nin çok kapalı olacağını ve çemberdeki yaklaşık 20 segmentin iyi olduğunu söyledim.
Chris

Yanıtlar:


9

@AndreJ'ye benzer, ancak dinamik bir gnomik projeksiyon kullanın , daha fazla doğruluk için dinamik bir azimuthal eşit uzaklıkta projeksiyon demek . Her nokta üzerinde ortalanmış bir AEQ projeksiyonu, tamponlu daire gibi tüm yönlerde eşit mesafeler yansıtacaktır. (Bir Mercator projeksiyonu, silindirin kenarına sarıldığından, kuzey ve doğu yönlerinde bazı bozulmalar olacaktır.)

Finlandiya etrafında ilk noktası için Yani, PROJ.4 dize olacak gibi görünen bu:

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

Böylece bu dinamik projeksiyonu yapmak için bir R işlevi yapabilirsiniz:

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

Sonra Kanada için böyle bir şey yapın (madde 2):

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

1
Vikipedi sayfasından: "Teğet noktada hiçbir bozulma meydana gelmez, ancak bozulma hızla uzaklaşır". Örnek bir ofset hesaplaması yaptınız mı? Belki en.wikipedia.org/wiki/Azimuthal_equidistant_projection daha uygundur.
AndreJ

2
Dairenin kökeninde doğru ölçeğe sahip olan ve uyumlu olan herhangi bir projeksiyon, 1000m çok küçük olduğu için iyi olacaktır. Ancak daha büyük yarıçaplar için bir Gnomonic projeksiyon korkunç olacaktır. Muhtemelen Eşitlikçi bir projeksiyon şart koştunuz .
whuber

2
Harika geri bildirim, bir AEQ projeksiyonu bu teknik için çok daha iyi performans gösteriyor, bu yüzden gnomic'i değiştirdim. AEQP, 10.000'den fazla km menzili gibi çok daha uzun mesafeler de kaldıracak.
Mike T

1
Kodu yanlış anlıyor olabilirim, ancak herhangi bir AEQD projeksiyonunda yalnızca bir kez tampon poligonu oluşturmanız gerekir (Merkez her zaman sıfırdır, min koordinat her zaman -1k, max her zaman + 1k'dir. Sonra bir AEQD, lat / lon değerlerini almanız için ihtiyacınız olan her bir noktayı merkez aldı ...
mkennedy

2
@mkennedy iyi bir noktanız var. projectedgerçekten her zaman (0, 0) 'dır ve x - ve y yönlerinde buffered± 1000 m'lik noktalara sahiptir . Bunu optimize etmek önemliyse, tamponun basit bir Kartezyen versiyonunu dinamik AEQD'den WGS84'e dönüştürün.
Mike T

4

Doğru UTM bölgesini aramak yerine, her nokta için özel bir enine mercator projeksiyonu oluşturabilirsiniz.

+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

Bu projeksiyondaki daireyi çizin. Yansıtılan daire tepe koordinatları her zaman aynı olacaktır, bu yüzden bunları yalnızca bir kez oluşturmanız gerekir. Aşağıdakiler için, yeni özel CRS'yi bunlara atamanız yeterlidir.

Daha fazla kullanım için daireyi EPSG: 4326 olarak yeniden projekte edin.

1000m menzil içinde, daire neredeyse kesin olacaktır. Değilse (veya daha büyük daireler için) aeqdyerine kullanın tmerc.


0

Ya noktalarınızın her birinde EPSG: 4326'da 1000 metre oluşturma yaklaşımını kullanırsanız ne olur? O zaman EPSG: 4326'yı diğer koordinat sisteminize dönüştürün? Konuyu yansıtmanın avantajı, EPSG: 4326 ile dünyanın eğriliği hakkında endişelenmenize gerek olmamasıdır.


1
Derece uzunluk birimleri olan EPSG: 4326'dan tam olarak 1000 m tamponlar nasıl oluşturursunuz?
Mike T

Buna yaklaşmamın bir yolu EPSG'de 32 metrelik bir tampon oluşturmaktır: 32635. Bunu EPSG: 4326'ya dönüştürün ve şimdi ihtiyacınız olan numaraya sahip olacaksınız.
Greg

1
Bu tekniğin sınırlamaları ile birlikte soruda açıklananla aynı yaklaşım budur.
Mike T
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.