Ich versuche, zufällige Standorte in der Nähe meines Standorts zu erstellen. Ich möchte zufällige Längen- und Breitengrade in einem 200-Meter-Kreis um meinen Standort erstellen.
Dies ist die Formel, die ich (mithilfe von Leuten bei StackOverFlow) gefunden habe: (Zufallszahl zwischen -1 und 1) * Radius + (alter Längengrad) = neuer Längengrad innerhalb des Radius des alten Längengrads
(Zufallszahl zwischen -1 und 1) * Radius + (alter Breitengrad) = neuer Breitengrad innerhalb des Radius des alten Breitengrads
Die Sache ist, dass mit meiner Implementierung etwas Seltsames passiert, weil alle zufälligen Orte zu nahe an meinem Standortzentrum liegen. Es scheint, dass die Formel nicht den gesamten Radius abdeckt.
Irgendeine Idee, was mit meiner Formel falsch sein könnte?
Bearbeitet, um die aktuelle Java-Implementierung anzuzeigen:
public static Location getLocation(Location location, int radius) {
Random random = new Random();
// Convert radius from meters to degrees
double radiusInDegrees = radius / METERS_IN_DEGREES;
double x0 = location.getLongitude() * 1E6;
double y0 = location.getLatitude() * 1E6;
double u = random.nextInt(1001) / 1000;
double v = random.nextInt(1001) / 1000;
double w = radiusInDegrees * Math.sqrt(u);
double t = 2 * Math.PI * v;
double x = w * Math.cos(t);
double y = w * Math.sin(t);
// Adjust the x-coordinate for the shrinking of the east-west distances
double new_x = x / Math.cos(y0);
// Set the adjusted location
Location newLocation = new Location("Loc in radius");
newLocation.setLongitude(new_x + x0);
newLocation.setLatitude(y + y0);
return newLocation;
}
Ich bin mir nicht sicher, was ich falsch mache, weil die neuen Orte mitten auf dem Meer entstehen.
Irgendeine Idee?
quelle
random.nextInt(1001)/1000
wird in etwa 0,1% der Fälle ein Wert größer als 1 zurückgegeben. Warum benutzt du nichtrandom.nextDouble
oderrandom.nextFloat
? (ii) Multipliziertx0
undy0
durch1E6
ist ziemlich mysteriös; es scheint nicht so, als würde es zu korrekten Ergebnissen führen.Antworten:
Dies ist aus zwei Gründen schwierig: Erstens: Beschränken der Punkte auf einen Kreis anstelle eines Quadrats; zweitens die Berücksichtigung von Verzerrungen bei den Entfernungsberechnungen.
Viele GIS enthalten Funktionen, die beide Komplikationen automatisch und transparent behandeln. Die Tags hier legen jedoch nahe, dass eine GIS-unabhängige Beschreibung eines Algorithmus wünschenswert sein kann.
Um Punkte gleichmäßig, zufällig und unabhängig voneinander innerhalb eines Kreises mit dem Radius r um einen Ort (x0, y0) zu erzeugen, erzeugen Sie zunächst zwei unabhängige gleichmäßige Zufallswerte u und v im Intervall [0, 1). (Dies ist, was fast jeder Zufallszahlengenerator bietet.) Compute
Der gewünschte zufällige Punkt befindet sich an der Position (x + x0, y + y0).
Bei Verwendung von geografischen Koordinaten (Lat, Lon) werden x0 (Längengrad) und y0 (Breitengrad) in Grad angegeben , r wird jedoch höchstwahrscheinlich in Metern (oder Fuß oder Meilen) oder einem anderen linearen Maß angegeben. Berechnen Sie zunächst den Radius r in Grad, als ob Sie sich in der Nähe des Äquators befänden. Hier sind es etwa 111.300 Meter in einem Grad.
Zweitens stellen Sie nach dem Erzeugen von x und y wie in Schritt (1) die x-Koordinate für das Schrumpfen der Ost-West-Abstände ein:
Der gewünschte zufällige Punkt befindet sich an der Position (x '+ x0, y + y0). Dies ist eine ungefähre Vorgehensweise. Bei kleinen Radien (weniger als ein paar hundert Kilometer), die sich nicht über einen der Erdpole erstrecken, ist die Genauigkeit in der Regel so hoch, dass Sie selbst dann keinen Fehler feststellen können, wenn Sie zehntausende zufällige Punkte um jedes Zentrum (x0, y0) erzeugen. .
quelle
Implementiert für Javascript:
quelle
Die korrekte Implementierung ist:
Ich habe die Abhängigkeit von externen Bibliotheken entfernt, um den Zugriff zu erleichtern.
quelle
Akzeptierte Antworten und Derivate haben bei mir nicht funktioniert. Die Ergebnisse waren sehr ungenau.
Richtige Implementierung in Javascript:
Voller Kern hier
In der akzeptierten Antwort stellte ich fest, dass Punkte in einer Ellipse mit der 1,5-fachen Breite (in Panama) und der 8-fachen Höhe (in Nordschweden) verteilt sind. Wenn ich die x-Koord-Anpassung aus der @ whuber-Antwort entfernt habe, ist die Ellipse in die andere Richtung verzerrt, achtmal höher als ihre Breite.
Der Code in meiner Antwort basierte auf Algorithmen von hier
Unten sehen Sie zwei jsfiddles, die das Problem mit der Streckellipse zeigen
Richtiger Algorithmus
Verzerrter Algorithmus
quelle
whuberPointAtDistance()
: vorgenommenx1 = (w * Math.cos(t)) / Math.cos(y0 * (Math.PI / 180))
.In Python
Ausgabe
Die Entfernung zwischen Punkten beträgt 0.288044147914. Die Entfernung zwischen Punkten beträgt 0.409557451806. Die Entfernung zwischen Punkten beträgt 0.368260305716. Die Entfernung zwischen Punkten beträgt 0.340720560546. Die Entfernung zwischen Punkten beträgt 0.453773334731. Die Entfernung zwischen Punkten beträgt 0.497188825576. Die Entfernung zwischen Punkten beträgt 0.6031781888888 Die Entfernung zwischen Punkten beträgt 0.503691568896. Die Entfernung zwischen Punkten beträgt 0.175153349209. Die Entfernung zwischen Punkten beträgt 0.195149463735. Die Entfernung zwischen Punkten beträgt 0.424094009858. Die Entfernung zwischen Punkten beträgt 0.558049206307. Die Entfernung zwischen Punkten beträgt 0.498612171417. Die Entfernung zwischen Punkten beträgt 0.047344718215
quelle
Sie können die Ergebnisse Ihrer Berechnungen überprüfen hier . Scrollen Sie zum Abschnitt "Zielpunkt bei gegebener Entfernung und Peilung vom Startpunkt". Es gibt sogar eine einfache JavaScript-Formel am unteren Rand, um dies zu implementieren. Sie müssen weiterhin eine zufällige Peilung $ \ theta $ im Bogenmaß (gemessen im Uhrzeigersinn von Norden) generieren, obwohl dies ziemlich einfach sein sollte. Diese Formeln gehen von einer kugelförmigen Erde aus (obwohl sie ellipsoidisch ist), was gut genug ist, da sie Fehler von bis zu 0,3% erzeugt.
quelle
Implementierung für Swift
Lat und Lng vom Geoencoder holen und an diese Funktion übergeben
In meinem obigen Beispiel erhalte ich die geografischen Längen- und Breitengrade, indem ich den Namen des Landes geografisch codiere, da der Name des Landes jedes Mal die gleichen Breiten- und Längengrade angibt, die auch in der Mitte des Landes vorkommen, sodass ich Zufälligkeit brauchte.
quelle
private void drawPolyline (double lat, double lng) {
quelle