Browsed by
Archiv pro štítek: GPS

Výpočet vzdálenosti z GPS souřadnic

Výpočet vzdálenosti z GPS souřadnic

Při práci se souřadnicemi často narazíte na úkol určit vzdálenost dvou míst. Dlouhou dobu jsme pro tento případ používali jednoduchý vzoreček okořeněný magickou konstantou:

dist = sqrt( (lat1 - lat2) ^ 2  + (lng1 - lng2) ^ 2 ) * 0.012

kde lat1, lat2, lng1, lng2 jsou souřadnice bodů jejichž vzdálenost máme určit a 0.012 je magická konstanta, která v našich zeměpisných šířkách upravuje výsledek tak, aby udával vzdálenost v kilometrech.

Bohužel předchozí věta není úplně pravdivá: výsledek se tu více, tu méně skutečné vzdálenosti pouze blíží. To podle toho, kterým směrem jsou od sebe body položeny a v jaké se pohybujeme zeměpisné šířce. Když pak přišla potřeba výpočet zpřesnit, museli jsme používaný vztah změnit.

Problém se vztahem je asi každému zřejmý. Bohužel nežijeme na placce, ale na kouli (zhruba) a tak nevystačíme s rovinnou geometrií a Pythagorovo větou, ale musíme počítat s geometrií sférickou. Nepotřebujeme dostat přímou vzdálenost mezi body (pokud nejste krtek a nepočítáte tunel). Zajímá nás vzdálenost mezi body po obvodu kružnice, jejíž poloměr je dán poloměrem Země.

Pro tento případ lze odvodit tzv. haversine vzorec, který lze s nevelkou chybou zjednodušit na následující vztah:

dist = acos (sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lng1 - lng2) ) * 6371

kde lat1, lat2, lng1, lng2 jsou souřadnice bodů a 6371 poloměr země v km, výsledkem je vzdálenost v kilometrech. Pozor: předpokládáme zde výpočet ve stupních. Pro výpočet v radiánech je třeba konstantu poloměru Země náležitě upravit (na 6371 / 360 * 2 * Pi = 111.19).

Protože souřadnice udáváme nejčastěji ve stupních, je nutné i tyto nejprve převést na radiány. Výsledný kód funkce pro výpočet vzdálenosti v PHP je pak následující:


function distance($lat1, $lng1, $lat2, $lng2) {
  $theta = $lng1 - $lng2;
  $dist = acos(
      sin(deg2rad($lat1)) * sin(deg2rad($lat2)) 
      + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta))
    );
  $kms = $dist * 111.19;
  return $kms;
}

Popis dalších metod výpočtů týkajících se vzdáleností a souřadnic v angličtině je k nahlédnutí zde http://www.movable-type.co.uk/scripts/latlong.html.

Získání GPS polohy v prohlížeči

Získání GPS polohy v prohlížeči

UPDATE:
Prohlížeč Chrome od verze 50 považuje informace o poloze uživatele za soukromá data a přes Geolocation API je zpřístupňuje pouze na stránkách zabezpečených HTTPS protokolem.

========================

Mobilní telefon máme v kapse skoro všichni a snadno jsme si zvykli, že jsou zobrazované informace přizpůsobené naší poloze. Je to komfortní, dokáže to ušetřit spoustu času a přitom je velmi jednoduché se prohlížeče na aktuální polohu zeptat.

Využívá se k tomu Geolocation API, které má dnes již širokou podporu, viz. caniuse.com. Komunikace s API je velmi jednoduchá a stačí ošetřit několik možných stavů.

Definice metody geolocation.getCurrentPosition je do velké míry samovysvětlující:

 navigator.geolocation.getCurrentPosition(success, error, options) 
  • v success poskytujeme callback pro úspěšně získanou polohu,
  • v error poskytneme callback pro případ odmítnutí poskytnutí polohy a
  • v options můžeme upřesnit dodatečné volby metody

více informací můžete získat třeba na stránce MDN

Firefox

Zde nám do toho zákeřně vstupuje Firefox se svojí volbou „Nyní ne„, která oproti všem očekáváním nevyvolá error callback. Nevyvolá totiž žádnou událost. Z pohledu kódu se poté zdá, že se uživatel stále nerozhodl jestli sdílení polohy povolí, nebo odmítne.

Jako nejrozumnější reakce na tento stav se mi jeví vyvolat po nějaké době vhodnou akci pomocí setTimeout() a tento timeout rušit pokud uživatel zareaguje dříve než se tento timeout provede.

Ukázka kódu

V ukázce si připravíme dvě jednoduché metody. V první nastavíme timeout pokud nedostaneme do 5 vteřin žádnou reakci a vytvoříme callbacky pro jednotlivé stavy. Na konci vyvoláme druhou metodu pro získání vlastní polohy:


var showPosition = function () {
    var timeout = setTimeout(function() {
        console.log("Timeout vyprsel...");
    }, 5000);
    
    var success = function (position) {
        clearTimeout(timeout);
        console.log("Ziskani polohy povoleno", position);
    };
    
    var failure = function(error) {
        clearTimeout(timeout);
        console.log("Poloha nedostupna...", error);
    };

    getPosition(success, failure);
};

Ve druhé metodě již komunikujeme s API a pomocí poskytnutých callbacků si vrátíme patřičné odpovědi. V případě úspěšného získání polohy to bude objekt se souřadnicemi, jinak chybový objekt:


var getPosition = function (success, failure) {
    var available = function (location) {
        var lat, lng, acc;
        lat = location.coords.latitude;
        lng = location.coords.longitude;
        acc = location.coords.accuracy;

        success({lat: lat, lng: lng, acc: acc});
    };
    
    var unavailable = function(error) {
        failure(error);
    };
    
    var options = {enableHighAccuracy: true, timeout: 5000, maximumAge: 0};

    navigator.geolocation.getCurrentPosition(available, unavailable, options);
};

To je vše. Nyní byste v konzoli měli vidět vaše souřadnice :-)

Pokud toto vyzkoušíte třeba v klasickém desktopovém prohlížeči na notebooku, tak nemusí být souřadnice přesné. V závislosti na vašem připojení, nebo poskytovateli připojení mohou být i velmi nepřesné a nemusí souhlasit ani kraj. Nicméně tento způsob získávání informací o poloze uživatele je asi nejpřesnější z dostupných a v mobilních zařízeních se zapnutou GPS funguje velmi spolehlivě.