Obliczanie nowej długości geograficznej, szerokości geograficznej ze starych + n metrów

86

Chcę utworzyć 2 nowe długości geograficzne i 2 nowe szerokości geograficzne na podstawie współrzędnych i odległości w metrach. Chcę utworzyć ładną ramkę ograniczającą wokół określonego punktu. Dotyczy części miasta i maksymalnie ± 1500 metrów. Dlatego nie sądzę, aby trzeba było brać pod uwagę krzywiznę Ziemi.

Więc mam 50.0452345(x) i 4.3242234(y) i chcę wiedzieć x + 500 metrów, x - 500 metrów, y - 500 metrów, y + 500 metrów

Znalazłem wiele algorytmów, ale prawie wszystkie wydają się radzić sobie z odległością między punktami.

Benjamin Udink ten Cate
źródło

Odpowiedzi:

125

Liczba kilometrów na stopień długości geograficznej wynosi w przybliżeniu

(2*pi/360) * r_earth * cos(theta)

gdzie thetajest szerokość geograficzna w stopniach i r_earthwynosi około 6378 km.

Liczba kilometrów na stopień szerokości geograficznej jest w przybliżeniu taka sama we wszystkich lokalizacjach, ok

(2*pi/360) * r_earth = 111 km / degree 

Możesz więc:

new_latitude  = latitude  + (dy / r_earth) * (180 / pi);
new_longitude = longitude + (dx / r_earth) * (180 / pi) / cos(latitude * pi/180);

Tak długo, jak dxi dysą małe w porównaniu z promieniem ziemi i nie zbliżasz się zbytnio do biegunów.

nibot
źródło
2
przekonwertować z stopnia na radiany należy pomnożyć z py i podzielić przez 180. Ale piszeszcos(latitude*180/pi)
josch
9
@josch: Dobry chwyt. Spróbuj skorygować odpowiedź następnym razem, zamiast po prostu proponować korektę. Wiele osób po prostu kopiuje i wkleja kod ze StackOverflow, myśląc, że jest poprawny i gotowy do użycia.
Alex Essilfie,
4
ok, jaki będzie kierunek? Chodzi mi o to, że jeśli chcę dodać 50 metrów, gdzie zostanie dodane? W prawo, w lewo, w górę czy w dół?
Tushar Monirul
3
Ziemia nie jest idealnie kulista, więc użycie jednej wartości dla „promienia” jest przybliżeniem. Wikipedia podaje, że „odległości punktów na powierzchni do centrum wahają się od 6 353 km do 6 384 km”. Jest tam również napisane: „Kilka różnych sposobów modelowania Ziemi jako kuli, każdy daje średni promień 6 371 km”, co wskazuje na twoją wartość. Naprawdę, jeśli ta poprawka jest znacząca w twojej aplikacji, i tak powinieneś użyć lepszego algorytmu.
nibot
5
Dla każdego, kto nie jest pewien, zmienna r_earth powinna być wyrażona w metrach i powinna wynosić około 6371000,0
Amit Assaraf
30

Przyjęta odpowiedź jest całkowicie poprawna i działa. Zrobiłem kilka poprawek i przekształciłem się w to:

double meters = 50;

// number of km per degree = ~111km (111.32 in google maps, but range varies
   between 110.567km at the equator and 111.699km at the poles)
// 1km in degree = 1 / 111.32km = 0.0089
// 1m in degree = 0.0089 / 1000 = 0.0000089
double coef = meters * 0.0000089;

double new_lat = my_lat + coef;

// pi / 180 = 0.018
double new_long = my_long + coef / Math.cos(my_lat * 0.018);

Mam nadzieję, że to też pomoże.

Numan Karaaslan
źródło
28
0.0000089? Staraj się unikać magicznych liczb, nikt tego nie zrozumie.
scai
2
Jest to skrócona wersja kodu średnicy ziemi i liczb pi. nie magia.
Numan Karaaslan
17
To wciąż magia, jeśli nikt nie wie, jak odtworzyć tę liczbę. Dlaczego nie umieścisz pełnego obliczenia w swoim kodzie?
scai
13
1 stopień na mapie google to 111,32 kilometr. 1 stopień = 111,32 km. 1 KM w stopniach = 1 / 111,32 = 0,008983. 1 M w stopniach = 0,000008983.
Muhammad Azeem
7
Powinieneś był zamieścić komentarz w swojej odpowiedzi, umieszczanie go w komentarzach nie jest pomocne.
chutsu,
18

W przypadku szerokości geograficznej wykonaj:

var earth = 6378.137,  //radius of the earth in kilometer
    pi = Math.PI,
    m = (1 / ((2 * pi / 360) * earth)) / 1000;  //1 meter in degree

var new_latitude = latitude + (your_meters * m);

W przypadku długości geograficznej wykonaj:

var earth = 6378.137,  //radius of the earth in kilometer
    pi = Math.PI,
    cos = Math.cos,
    m = (1 / ((2 * pi / 360) * earth)) / 1000;  //1 meter in degree

var new_longitude = longitude + (your_meters * m) / cos(latitude * (pi / 180));

Zmienna your_metersmoże zawierać wartość dodatnią lub ujemną.

ssten
źródło
9

Sprawdziłeś: Jak znaleźć szerokość / długość, która jest x km na północ od podanej szerokości / długości ?

Te obliczenia są w najlepszym razie irytujące, zrobiłem ich wiele. Formuła haversine będzie Twoim przyjacielem.

Niektóre źródła: http://www.movable-type.co.uk/scripts/latlong.html

Ryan Ternier
źródło
jeśli pracujesz na dość małym obszarze, czy naprawdę źle jest zrobić po prostu szerokość-0,09 i długość-0,0148, aby uzyskać obszar w przybliżeniu na kilometr kwadratowy?
Benjamin Udink ten Cate
Powiedziałbym, że nie jest źle. Kilometr kwadratowy na tym poziomie nie będzie zniekształcony przez krzywiznę Ziemi - o ile szerokość / długość, z którą masz do czynienia, jest dziesiętna.
Ryan Ternier,
1
@BenjaminUdinktenCate To zadziała w Amsterdamie, ale będzie niedokładne w innych częściach świata. Wykonanie „longitude-0,0148” da ci tylko około 0,16 km na równiku.
nibot
4

Musiałem poświęcić około dwóch godzin na wypracowanie rozwiązania @nibota, po prostu potrzebowałem metody tworzenia ramki granicznej, biorąc pod uwagę jej środek i szerokość / wysokość (lub promień) w kilometrach:

Nie rozumiem rozwiązania matematycznie / geograficznie. Poprawiłem rozwiązanie (metodą prób i błędów), aby uzyskać cztery współrzędne:

Północ:

private static Position FromKmToNPosition(Position p, double km)
{
    double r_earth = 6378;
    var pi = Math.PI;
    var new_latitude = p.Lat + (km / r_earth) * (180 / pi);
    return new Position(new_latitude, p.Long);
}

Wschód:

private static Position FromKmToEPosition(Position p, double km)
{
    double r_earth = 6378;
    var pi = Math.PI;
    var new_longitude = p.Long + (km / r_earth) * (180 / pi) / Math.Cos(p.Lat * pi / 180);
    return new Position(p.Lat, new_longitude);
}

Południe:

private static Position FromKmToSPosition(Position p, double km)
{
    double r_earth = 6378;
    var pi = Math.PI;
    var new_latitude = p.Lat - (km / r_earth) * (180 / pi);
    return new Position(new_latitude, p.Long);
}

Zachód:

private static Position FromKmToWPosition(Position p, double km)
{
    double r_earth = 6378;
    var pi = Math.PI;
    var new_longitude = p.Long - (km / r_earth) * (180 / pi) / Math.Cos(p.Lat * pi / 180);
    return new Position(p.Lat, new_longitude);
}
mshwf
źródło
1

jeśli nie musisz być bardzo dokładny, to: każdy 10000 metrów to około 0,1 dla szerokości i długości geograficznej. na przykład chcę załadować lokalizacje 3000 metrów wokół punktu_A z mojej bazy danych:

double newMeter =  3000 * 0.1 / 10000;
double lat1 = point_A.latitude - newMeter;
double lat2 = point_A.latitude + newMeter;
double lon1 = point_A.longitude - newMeter;
double lon1 = point_A.longitude + newMeter;
Cursor c = mDb.rawQuery("select * from TABLE1  where lat >= " + lat1 + " and lat <= " + lat2 + " and lon >= " + lon1 + " and lon <= " + lon2 + " order by id", null);
farhad.kargaran
źródło
0
public double MeterToDegree(double meters, double latitude)
{
    return meters / (111.32 * 1000 * Math.Cos(latitude * (Math.PI / 180)));
}
M Komaei
źródło
-1
var meters = 50;
var coef = meters * 0.0000089;
var new_lat = map.getCenter().lat.apply() + coef;
var new_long = map.getCenter().lng.apply() + coef / Math.cos(new_lat * 0.018);
map.setCenter({lat:new_lat, lng:new_long});
Eyni Kave
źródło
2
Dodaj wyjaśnienie do swojej odpowiedzi.
Anna
jeśli chcesz przesunąć obiekt mapy o około 50 metrów w pobliżu środka bieżącej mapy, możesz użyć tego kodu z numerami +, - jako zamiennik +50
Eyni Kave,