Um das geodätische Puffern zu verstehen , unterscheidet das Esri Geoprocessing Development Team zwischen euklidischem und geodätischem Puffern. Sie schließen mit "Euklidische Pufferung, die an projizierten Feature-Classes durchgeführt wird, kann zu irreführenden und technisch inkorrekten Puffern führen. Geodätische Pufferung führt jedoch immer zu geografisch genauen Ergebnissen, da geodätische Puffer nicht durch die durch projizierte Koordinatensysteme verursachten Verzerrungen beeinflusst werden."
Ich muss mit einem globalen Punktdatensatz arbeiten und die Koordinaten sind nicht projiziert ( +proj=longlat +ellps=WGS84 +datum=WGS84
). Gibt es eine Funktion zum Erstellen eines geodätischen Puffers in R, wenn die Breite in metrischen Einheiten angegeben wird? Mir ist gBuffer
aus dem rgeos
Paket bekannt. Diese Funktion erstellt einen Puffer in Einheiten des verwendeten räumlichen Objekts ( Beispiel ). Daher muss ich die Koordinaten projizieren, um einen Puffer mit den gewünschten X km erstellen zu können. Projizieren und dann ein gBuffer
Mittel anwenden , um tatsächlich einen euklidischen Puffer zu erstellen, im Gegensatz zu einem geodätischen, den ich brauche. Unten finden Sie einen Code, der meine Bedenken veranschaulicht:
require(rgeos)
require(sp)
require(plotKML)
# Generate a random grid-points for a (almost) global bounding box
b.box <- as(raster::extent(120, -120, -60, 60), "SpatialPolygons")
proj4string(b.box) <- "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
set.seed(2017)
pts <- sp::spsample(b.box, n=100, type="regular")
plot(pts@coords)
# Project to Mollweide to be able to apply buffer with `gBuffer`
# (one could use other projection)
pts.moll <- sp::spTransform(pts, CRSobj = "+proj=moll")
# create 1000 km buffers around the points
buf1000km.moll <- rgeos::gBuffer(spgeom = pts.moll, byid = TRUE, width = 10^6)
plot(buf1000km.moll)
# convert back to WGS84 unprojected
buf1000km.WGS84 <- sp::spTransform(buf1000km.moll, CRSobj = proj4string(pts))
plot(buf1000km.WGS84) # distorsions are present
# save as KML to better visualize distorted Euclidian buffers on Google Earth
plotKML::kml(buf1000km.WGS84, file.name = "buf1000km.WGS84.kml")
Das Bild unten zeigt die verzerrten euklidischen Puffer (Radius 1000 km), die mit dem Code von oben erzeugt wurden.
Robert J. Hijmans in Abschnitt Einführung in das Paket "Geosphäre"4 Point at distance and bearing
gibt ein Beispiel für die Herstellung von "kreisförmigen Polygonen mit festem Radius, jedoch in Längen- / Breitengradkoordinaten", die meines Erachtens als "geodätischer Puffer" bezeichnet werden können. Ich bin dieser Idee gefolgt und habe Code geschrieben, der hoffentlich das Richtige tut, aber ich frage mich, ob es in einem Paket bereits eine geodätische Puffer-R-Funktion gibt, die den metrischen Radius als Eingabe zulässt:
require(geosphere)
make_GeodesicBuffer <- function(pts, width) {
### A) Construct buffers as points at given distance and bearing
# a vector of bearings (fallows a circle)
dg <- seq(from = 0, to = 360, by = 5)
# Construct equidistant points defining circle shapes (the "buffer points")
buff.XY <- geosphere::destPoint(p = pts,
b = rep(dg, each = length(pts)),
d = width)
### B) Make SpatialPolygons
# group (split) "buffer points" by id
buff.XY <- as.data.frame(buff.XY)
id <- rep(1:length(pts), times = length(dg))
lst <- split(buff.XY, id)
# Make SpatialPolygons out of the list of coordinates
poly <- lapply(lst, sp::Polygon, hole = FALSE)
polys <- lapply(list(poly), sp::Polygons, ID = NA)
spolys <- sp::SpatialPolygons(Srl = polys,
proj4string = CRS(as.character("+proj=longlat +ellps=WGS84 +datum=WGS84")))
# Disaggregate (split in unique polygons)
spolys <- sp::disaggregate(spolys)
return(spolys)
}
buf1000km.geodesic <- make_GeodesicBuffer(pts, width=10^6)
# save as KML to visualize geodesic buffers on Google Earth
plotKML::kml(buf1000km.geodesic, file.name = "buf1000km.geodesic.kml")
Das Bild unten zeigt die geodätischen Puffer (Radius 1000 km).
Edit 2019-02-12 : Der Einfachheit halber habe ich eine Version der Funktion in das Geobuffer- Paket eingeschlossen. Fühlen Sie sich frei, mit Pull-Anfragen beizutragen.
R
kann das - es ist ein großartiger Vorschlag. Da dies für ein sphärisches Erdmodell eine so einfache Projektion ist, ist es einfach genug, den Code direkt zu schreiben.Antworten:
Für die meisten Zwecke ist es genau genug, um ein sphärisches Modell der Erde zu verwenden - und die Codierung wird einfacher und die Berechnungen viel schneller.
Nach den Vorschlägen von M. Kennedy in einem Kommentar puffert diese Lösung den Nordpol (was einfach ist: Die Puffergrenze liegt auf einem festen Breitengrad) und dreht diesen Puffer dann an eine beliebige gewünschte Stelle.
Die Drehung erfolgt durch Konvertieren des ursprünglichen Puffers in geozentrische kartesische (XYZ) Koordinaten, Drehen derjenigen mit einer (schnellen) Matrixmultiplikation entlang des Nullmeridians zum Zielbreiten, Konvertieren seiner Koordinaten zurück in geografische (lat-lon) und anschließendes Drehen den Puffer um die Erdachse einfach durch Hinzufügen der Ziellänge zu jeder zweiten Koordinate.
Warum in zwei Schritten, wenn (normalerweise) eine einzelne Matrixmultiplikation funktionieren würde? Weil kein spezieller Code erforderlich ist, um die Brüche am +/- 180-Grad-Meridian zu identifizieren. Stattdessen kann dieser Ansatz Längengrade erzeugen, die über den ursprünglichen Bereich hinausgehen (ob -180 bis 180 Grad oder 0 bis 360 Grad oder was auch immer). Auf diese Weise funktionieren Standardverfahren zum Zeichnen von Polygonen (und andere Analyseverfahren) ohne Änderung einwandfrei. Wenn Sie Längengrade in einem bestimmten Bereich haben müssen, reduzieren Sie diese ganz am Ende einfach um 360 Grad: Das geht schnell und einfach.
Beim Puffern von Punkten haben normalerweise alle Puffer den gleichen Radius. Diese modulare Lösung ermöglicht in diesem Fall eine Beschleunigung: Sie können den Nordpol puffern und ihn dann ein für alle Mal in XYZ-Koordinaten umwandeln. Das Puffern jedes Punktes erfordert dabei eine (sehr schnelle) Matrixmultiplikation, eine Umrechnung in Lat-Lon-Koordinaten und eine Verschiebung der Längen (ebenfalls sehr schnell). Erwarten Sie etwa 10.000 hochauflösende Puffer (360 Eckpunkte) pro Sekunde.
Dieser
R
Code zeigt die Details. Da es sich um eine Illustration handelt, werden keine Zusatzpakete verwendet. nichts ist verborgen oder begraben. Es enthält einen Test, bei dem eine Reihe von zufälligen Punkten generiert, gepuffert und unter Verwendung der rohen Lat-Lon-Koordinaten (geografisch) angezeigt wird. Hier ist die Ausgabe:quelle