Berechnen Sie Breite / Länge X Meilen vom Punkt?


46

Ich möchte einen Breiten- und Längengradpunkt finden, der eine Peilung, eine Entfernung und einen Startbreiten- und -längengrad aufweist.

Dies scheint das Gegenteil dieser Frage zu sein ( Abstand zwischen Lat / Long-Punkten ).

Ich habe mich bereits mit der Haversine-Formel befasst und denke, dass die Annäherung an die Welt wahrscheinlich nahe genug ist.

Ich gehe davon aus, dass ich die Haversin-Formel für meinen unbekannten Lat / Long lösen muss. Stimmt das? Gibt es gute Websites, die über solche Dinge sprechen? Es scheint, als wäre es üblich, aber mein Googeln hat nur Fragen aufgeworfen, die denen oben ähneln.

Was ich wirklich suche, ist nur eine Formel dafür. Ich würde ihm gerne eine Startzeit, eine Peilung und eine Entfernung (Meilen oder Kilometer) geben und ich würde gerne ein Paar aus der Startzeit herausholen, das darstellt, wo man gelandet wäre, wenn sie mitgereist wären diese Route.


Suchen Sie nach einem Tool, das dies leistet (wie Esri's pe.dll), oder nach einer Formel?
Kirk Kuykendall

Entschuldigung, ich war nicht genau ... Ich suche nach einer Formel. Ich werde meine Frage genauer aktualisieren.
Jason Whitehorn

Eine Reihe ausgearbeiteter mathematischer Beispiele finden Sie hier <a href=" moving-type.co.uk/scripts/latlong.html"> Berechnen Sie Entfernung, Peilung und mehr zwischen Breiten- / Längenpunkten </a>, einschließlich der Lösung für "Ziel" gegebene Entfernung und Peilung vom Startpunkt ".
Stephen Quan


hier ist die Seite, die auf lat / long Berechnungen [Lat / lange Berechnungen] ( movable-type.co.uk/scripts/latlong.html ) auch diese Seite Lat / lange Berechnungen gibt es einen Code + Rechner
Abo gaseem

Antworten:


21

Ich wäre gespannt, wie sich die Ergebnisse dieser Formel mit denen von Esri's pe.dll vergleichen lassen .

( Zitat ).

Ein Punkt {lat, lon} ist ein Abstand d auf dem tc radial von Punkt 1, wenn:

 lat=asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc))
 IF (cos(lat)=0)
    lon=lon1      // endpoint a pole
 ELSE
    lon=mod(lon1-asin(sin(tc)*sin(d)/cos(lat))+pi,2*pi)-pi
 ENDIF

Dieser Algorithmus ist auf Entfernungen beschränkt, bei denen dlon <pi / 2 ist, dh solche, die sich in der Länge um weniger als ein Viertel des Erdumfangs erstrecken. Ein vollständig allgemeiner, aber komplizierterer Algorithmus ist erforderlich, wenn größere Entfernungen zulässig sind:

 lat =asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc))
 dlon=atan2(sin(tc)*sin(d)*cos(lat1),cos(d)-sin(lat1)*sin(lat))
 lon=mod( lon1-dlon +pi,2*pi )-pi

Hier ist eine HTML-Seite zum Testen .


Danke für die schnelle Antwort. Lassen Sie mich einige dieser Informationen verdauen, und ich melde mich bei Ihnen. An der Oberfläche sieht dies jedoch genau richtig aus.
Jason Whitehorn

1
Ich habe den direkten Fall mit pe.dll (tatsächlich libpe.so unter Solaris) versucht, nachdem ich die Entfernung und den Vorwärtsazimut von der HTML-Seite für 32N, 117W bis 40N, 82W abgerufen hatte. Unter Verwendung von 32 N, 117 W, d = 3255,056515890041, azi = 64,24498012065699 erhielt ich 40 N, 82 W (tatsächlich 82,00000000064).
Mkennedy

3
Genial! Vielen Dank für den Link zum Aviation Formulary-Artikel von Ed Williams, den ich vorher noch nicht gesehen hatte, der sich bisher als großartig erwiesen hat. Nur eine Anmerkung für alle, die dies in Zukunft betrachten: Die Ein- und Ausgänge dieser Formel sind ALLE im Bogenmaß, sogar die Entfernung.
Jason Whitehorn

1
Was ist die Entfernungseinheit in dieser Formel?
Karthik Murugan

1
@KarthikMurugan Eds Intro besagt, dass die Entfernungseinheiten im Bogenmaß entlang eines großen Kreises angegeben sind.
Kirk Kuykendall

18

Wenn Sie in einer Ebene sind, dann der Punkt, ist r Meter entfernt auf einem Lager von einem Grad östlich von Norden verschoben wird durch r * cos (a) in der Nordrichtung und r * sin (a) in der Ost - Richtung. (Diese Aussagen definieren mehr oder weniger den Sinus und den Cosinus.)

Obwohl Sie sich nicht in einer Ebene befinden - Sie arbeiten an der Oberfläche eines gekrümmten Ellipsoids, das die Erdoberfläche modelliert -, bedeckt jede Entfernung von weniger als ein paar hundert Kilometern einen so kleinen Teil der Oberfläche, dass dies für die meisten praktischen Zwecke möglich ist als flach angesehen werden. Die einzige verbleibende Komplikation besteht darin, dass ein Längengrad nicht die gleiche Entfernung wie ein Breitengrad zurücklegt. In einem sphärischen Erdmodell ist ein Längengrad nur cos (Breite) so lang wie ein Breitengrad. (In einem Ellipsoid-Modell ist dies immer noch eine hervorragende Annäherung, die ungefähr 2,5 signifikante Zahlen ergibt.)

Schließlich ist ein Breitengrad ungefähr 10 ^ 7/90 = 111,111 Meter. Wir haben jetzt alle Informationen, die benötigt werden, um Meter in Grad umzuwandeln:

Die Verschiebung nach Norden beträgt r * cos (a) / 111111 Grad;

Die Verschiebung nach Osten beträgt r * sin (a) / cos (Breite) / 111111 Grad.

Zum Beispiel können wir bei einer Breite von -0,31399 Grad und einer Peilung von a = 30 Grad östlich von Norden berechnen

cos(a) = cos(30 degrees) = cos(pi/6 radians) = Sqrt(3)/2 = 0.866025.
sin(a) = sin(30 degrees) = sin(pi/6 radians) = 1/2 = 0.5.
cos(latitude) = cos(-0.31399 degrees) = cos(-0.00548016 radian) = 0.999984984.
r = 100 meters.
east displacement = 100 * 0.5 / 0.999984984 / 111111 = 0.000450007 degree.
north displacement = 100 * 0.866025 / 111111 = 0.000779423 degree.

Ab (-78.4437, -0.31399) ist der neue Standort (-78.4437 + 0.00045, -0.31399 + 0.0007794) = (-78.4432, -0.313211).

Eine genauere Antwort im modernen ITRF00-Referenzsystem ist (-78,4433, -0,313207): Dies ist 0,43 Meter von der ungefähren Antwort entfernt, was angibt, dass die Annäherung in diesem Fall um 0,43% fehlerhaft ist. Um eine höhere Genauigkeit zu erzielen, müssen Sie entweder ellipsoide Abstandsformeln (die weitaus komplizierter sind) oder eine konforme High-Fidelity-Projektion ohne Divergenz verwenden (damit die Peilung korrekt ist).


2
+1 für das richtige Verständnis des mathematischen Kontexts (dh seiner lokalen Ebene)
Frank Conry

4

Wenn Sie eine JavaScript-Lösung benötigen, sollten Sie diese functionsund diese Tipps beachten :

var gis = {
  /**
  * All coordinates expected EPSG:4326
  * @param {Array} start Expected [lon, lat]
  * @param {Array} end Expected [lon, lat]
  * @return {number} Distance - meter.
  */
  calculateDistance: function(start, end) {
    var lat1 = parseFloat(start[1]),
        lon1 = parseFloat(start[0]),
        lat2 = parseFloat(end[1]),
        lon2 = parseFloat(end[0]);

    return gis.sphericalCosinus(lat1, lon1, lat2, lon2);
  },

  /**
  * All coordinates expected EPSG:4326
  * @param {number} lat1 Start Latitude
  * @param {number} lon1 Start Longitude
  * @param {number} lat2 End Latitude
  * @param {number} lon2 End Longitude
  * @return {number} Distance - meters.
  */
  sphericalCosinus: function(lat1, lon1, lat2, lon2) {
    var radius = 6371e3; // meters
    var dLon = gis.toRad(lon2 - lon1),
        lat1 = gis.toRad(lat1),
        lat2 = gis.toRad(lat2),
        distance = Math.acos(Math.sin(lat1) * Math.sin(lat2) +
            Math.cos(lat1) * Math.cos(lat2) * Math.cos(dLon)) * radius;

    return distance;
  },

  /**
  * @param {Array} coord Expected [lon, lat] EPSG:4326
  * @param {number} bearing Bearing in degrees
  * @param {number} distance Distance in meters
  * @return {Array} Lon-lat coordinate.
  */
  createCoord: function(coord, bearing, distance) {
    /** http://www.movable-type.co.uk/scripts/latlong.html
    * φ is latitude, λ is longitude, 
    * θ is the bearing (clockwise from north), 
    * δ is the angular distance d/R; 
    * d being the distance travelled, R the earth’s radius*
    **/
    var 
      radius = 6371e3, // meters
      δ = Number(distance) / radius, // angular distance in radians
      θ = gis.toRad(Number(bearing));
      φ1 = gis.toRad(coord[1]),
      λ1 = gis.toRad(coord[0]);

    var φ2 = Math.asin(Math.sin(φ1)*Math.cos(δ) + 
      Math.cos(φ1)*Math.sin(δ)*Math.cos(θ));

    var λ2 = λ1 + Math.atan2(Math.sin(θ) * Math.sin(δ)*Math.cos(φ1),
      Math.cos(δ)-Math.sin(φ1)*Math.sin(φ2));
    // normalise to -180..+180°
    λ2 = (λ2 + 3 * Math.PI) % (2 * Math.PI) - Math.PI; 

    return [gis.toDeg(λ2), gis.toDeg(φ2)];
  },
  /**
   * All coordinates expected EPSG:4326
   * @param {Array} start Expected [lon, lat]
   * @param {Array} end Expected [lon, lat]
   * @return {number} Bearing in degrees.
   */
  getBearing: function(start, end){
    var
      startLat = gis.toRad(start[1]),
      startLong = gis.toRad(start[0]),
      endLat = gis.toRad(end[1]),
      endLong = gis.toRad(end[0]),
      dLong = endLong - startLong;

    var dPhi = Math.log(Math.tan(endLat/2.0 + Math.PI/4.0) / 
      Math.tan(startLat/2.0 + Math.PI/4.0));

    if (Math.abs(dLong) > Math.PI) {
      dLong = (dLong > 0.0) ? -(2.0 * Math.PI - dLong) : (2.0 * Math.PI + dLong);
    }

    return (gis.toDeg(Math.atan2(dLong, dPhi)) + 360.0) % 360.0;
  },
  toDeg: function(n) { return n * 180 / Math.PI; },
  toRad: function(n) { return n * Math.PI / 180; }
};

Wenn Sie also eine neue Koordinate berechnen möchten, kann dies folgendermaßen aussehen:

var start = [15, 38.70250];
var end = [21.54967, 38.70250];
var total_distance = gis.calculateDistance(start, end); // meters
var percent = 10;
// this can be also meters
var distance = (percent / 100) * total_distance;
var bearing = gis.getBearing(start, end);
var new_coord = gis.createCoord(icon_coord, bearing, distance);

2

Ich habe dies in ObjectiveC funktioniert. Der Schlüssel hierbei ist zu wissen, dass Sie Lat / Lng-Punkte im Bogenmaß benötigen und diese nach Anwendung der Gleichung wieder in Lat / Lng konvertieren müssen. Beachten Sie auch, dass Abstand und tc im Bogenmaß angegeben sind.

Hier ist die ursprüngliche Gleichung:

 lat=asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc))
 IF (cos(lat)=0)
    lon=lon1      // endpoint a pole
 ELSE
    lon=mod(lon1-asin(sin(tc)*sin(d)/cos(lat))+pi,2*pi)-pi
 ENDIF

Hier wird es in ObjC implementiert, wobei der Bogenmaßstab ein Bogenmaßstab ist, der gegen den Uhrzeigersinn von N aus gemessen wird (z. B. PI / 2 ist W, PI ist S, 2 PI / 3 ist E) und die Entfernung in Kilometern.

+ (CLLocationCoordinate2D)displaceLatLng:(CLLocationCoordinate2D)coordinate2D withRadian:(double)radian
                            withDistance:(CGFloat)distance {
  double lat1Radians = coordinate2D.latitude * (M_PI / 180);
  double lon1Radians = coordinate2D.longitude * (M_PI / 180);
  double distanceRadians = distance / 6371;
  double lat = asin(sin(lat1Radians)*cos(distanceRadians)+cos(lat1Radians)*sin(distanceRadians)
      *cos(radian));
  double lon;
  if (cos(lat) == 0) {
    lon = lon1Radians;
  } else {
    lon = fmodf((float) (lon1Radians - asin(sin(radian) * sin(distanceRadians) / cos(lat)) + M_PI),
        (float) (2 * M_PI)) - M_PI;
  }
  double newLat = lat * (180 / M_PI);
  double newLon = lon * (180 / M_PI);
  return CLLocationCoordinate2DMake(newLat, newLon);
}

Ich bin auf der Suche nach einer Lösung, bei der ich 4 Lat erhalten möchte, und zwar von dem Punkt an, an dem ich stehe, bis zu 50 Meilen nördlich, 50 Meilen westlich, 50 Meilen östlich usw. ... In der obigen Antwort können Sie erläutern, wie ich dies erreichen kann diese ?
Rahul Vyas

1

Wenn Sie an einer besseren Genauigkeit interessiert sind, gibt es Vincenty . (Link ist auf die "direkte" Form, die genau das ist, was Sie suchen).

Es gibt eine ganze Reihe von Implementierungen, wenn Sie Code suchen.

Außerdem eine Frage: Sie gehen nicht davon aus, dass der Reisende während der gesamten Reise die gleiche Orientierung hat, oder? Wenn ja, dann beantworten diese Methoden nicht die richtige Frage. (Es ist besser, auf mercator zu projizieren, eine gerade Linie zu zeichnen und das Ergebnis dann zu entfernen.)


Sehr gute Frage, trotz der Formulierung in meiner Frage, die darauf hindeutet, dass ich ein Reiseziel für einen Reisenden berechnet habe, bin ich es nicht. Guter Punkt. Dies diente hauptsächlich dazu, dass ich einen Grenzbereich berechnen konnte (bei einer kleinen Bestellung, sagen wir 50 Meilen) ... Ich hoffe, das macht Sinn.
Jason Whitehorn

gis.stackexchange.com/questions/3264/… hatte die gleiche Frage ( Erstellen von Grenzbereichen aus einer bestimmten Entfernung)
Dan S.

0

Hier ist eine Python-Lösung:

    def displace(self, theta, distance):
    """
    Displace a LatLng theta degrees counterclockwise and some
    meters in that direction.
    Notes:
        http://www.movable-type.co.uk/scripts/latlong.html
        0 DEGREES IS THE VERTICAL Y AXIS! IMPORTANT!
    Args:
        theta:    A number in degrees.
        distance: A number in meters.
    Returns:
        A new LatLng.
    """
    theta = np.float32(theta)

    delta = np.divide(np.float32(distance), np.float32(E_RADIUS))

    def to_radians(theta):
        return np.divide(np.dot(theta, np.pi), np.float32(180.0))

    def to_degrees(theta):
        return np.divide(np.dot(theta, np.float32(180.0)), np.pi)

    theta = to_radians(theta)
    lat1 = to_radians(self.lat)
    lng1 = to_radians(self.lng)

    lat2 = np.arcsin( np.sin(lat1) * np.cos(delta) +
                      np.cos(lat1) * np.sin(delta) * np.cos(theta) )

    lng2 = lng1 + np.arctan2( np.sin(theta) * np.sin(delta) * np.cos(lat1),
                              np.cos(delta) - np.sin(lat1) * np.sin(lat2))

    lng2 = (lng2 + 3 * np.pi) % (2 * np.pi) - np.pi

    return LatLng(to_degrees(lat2), to_degrees(lng2))

-2

Ich benutze den unten beschriebenen Ansatz, um die nächste Koordinate unter Berücksichtigung der Peilung und des Abstands von der vorherigen Koordinate zu bestimmen. Ich habe ein Problem mit der Genauigkeit eines anderen Ansatzes, den ich aus dem Internet gelesen habe.

Ich benutze dies, um die Landfläche zu bestimmen, die ein Polygon ist, und zeichne dieses Polygon in Google Earth. Ein Landtitel weist Peilungen und Entfernungen auf, die wie folgt geschrieben sind: "Nord oder Süd x Grad y Minuten Ost oder West, z Meter bis Punkt n;".

Ausgehend von den angegebenen Koordinaten des Bezugspunkts berechne ich zunächst die Entfernung pro Breitengrad und Längengrad mit der Haversinus-Formel, da diese je nach Standort unterschiedlich ist. Dann bestimme ich die nächste Koordinate aus der Sinus- und Cosinusformel der Trigonometrie.

Unten ist das Javascript:

var mapCenter = new google.maps.LatLng(referencePointLatitude, referencePointLongitude); //the ref point lat and lon must be given, usually a land mark (BLLM)
var latDiv = latDiv(mapCenter); //distance per one degree latitude in this location
var lngDiv = lngDiv(mapCenter); //distance per one degree longitude in this location
var LatLng2 = NextCoord(PrevCoord,NorthOrSouth,x,y,EastOrWest,z); //next coordinate given the bearing and distance from previous coordinate
var Lat2 = LatLng2.lat(); //next coord latitude in degrees
var Lng2 = LatLng2.lng(); //next coord longitude in degrees
var polygon=[p1,p2,...,pn-1,pn,p1]; //p1,p2,etc. are the coordinates of points of the polygon, i.e. the land Title. Be sure to close the polygon to the point of beginning p1
var area = Area(polygon); //area of the polygon in sq.m.
function NextCoord(PrevCoord,NorthOrSouth,x,y,EastOrWest,z) {
  var angle = ( x + ( y / 60 ) ) * Math.PI / 180;
  var a = 1;
  var b = 1;
  if (NorthOrSouth == 'South') { a = -1; }
  if (EastOrWest == 'West') { b = -1; }
  var nextLat = PrevCoord.lat() +  ( a * z * Math.cos(angle) / latDiv );
  var nextLng = PrevCoord.lng() +  ( b * z * Math.sin(angle) / lngDiv );
  var nextCoord = new google.maps.LatLng(nextLat, nextLng);
  return nextCoord;
}
function latDiv(mapCenter) {
  var p1 = new google.maps.LatLng(mapCenter.lat()-0.5, mapCenter.lng());
  var p2 = new google.maps.LatLng(mapCenter.lat()+0.5, mapCenter.lng());
  return dist(p1,p2);
}
function lngDiv(mapCenter) {
  var p3 = new google.maps.LatLng(mapCenter.lat(), mapCenter.lng()-0.5);
  var p4 = new google.maps.LatLng(mapCenter.lat(), mapCenter.lng()+0.5);
  return dist(p3,p4);
}
function dist(pt1, pt2) {
    var dLat  = ( pt2.lat() - pt1.lat() ) * Math.PI / 180;
    var dLng = ( pt2.lng() - pt1.lng() ) * Math.PI / 180;
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +                 
            Math.cos(rad(pt1.lat())) * Math.cos(rad(pt2.lat())) *
            Math.sin(dLng/2) * Math.sin(dLng/2);
    var R = 6372800; //earth's radius
    var distance = R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    return distance;
}
function Area(polygon) {
  var xPts=[];
  for (i=1; i&lt;polygon.length; i++) {
    xPts[i-1] = ( polygon[i].lat() - polygon[0].lat() ) * latDiv;
  }
  var yPts=[];
  for (i=1; i&lt;polygon.length; i++) {
    yPts[i-1] = ( polygon[i].lng() - polygon[0].lng() ) * lngDiv;
  }
  var area = 0;
  j = polygon.length-2;
  for (i=0; i&lt;polygon.length-1; i++) {
    area = area +  ( xPts[j] + xPts[i] ) * ( yPts[j] - yPts[i] );
    j = i;
  }
  area = Math.abs(area/2);
  return area;
}

1
Die kartesische Formel für die Polygonfläche, die Sie hier anwenden möchten, gilt nicht für Abstände und Winkel, die auf einer gekrümmten Oberfläche (z. B. einem Sphäroid) berechnet wurden. Diese Formel macht einen zusätzlichen Fehler, indem Breiten- und Längengrade verwendet werden, als ob sie kartesische Koordinaten wären. Die einzigen Umstände, unter denen seine Verwendung in Betracht gezogen werden könnte, wären genau diejenigen (für sehr kleine Polygone), bei denen die Haversin-Formel ohnehin nicht erforderlich ist. Insgesamt scheint es, dass dieser Code viel zu hart für keinen Gewinn arbeitet.
Whuber
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.