21.01.2014, Vladimír Klaus, navštíveno 12434x

ASP.NET/C#

K napsání tohoto článku mě vedla potřeba zjistit, jak daleko jsou od sebe dvě fotky. Přesněji řečeno, jak hodně špatně se určila poloha u jedné fotky, zatímco u druhé byla zcela korektní, přičemž obě byly pořízené jen pár metrů od sebe.

Zjišťujeme vzdálenost mezi dvěma GPS souřadnicemi, tentokrát v ASP.NET

Na webu se dá najít spousta (šílených) vzorečků, návodů a matematických vysvětlení, jak to celé funguje. Nebojte, takovými detaily se tu zabývat nebudu.

Pro výpočet budeme potřebovat goniometrické funkce. Drobnou komplikací je to, že v Math knihovně očekávají tyto funkce úhel v radiánech. Nejprve si tedy napíšeme jednoduchou převodní funkci.

//pomocná funkce na převod stupňů na radiány
double DegToRad(double uhel) {
    return uhel * Math.PI / 180.0;
} 

Pak už přijde na řadu vlastní výpočet, který vypadá docela sofistikovaně.

//funkce, na výpočet přibližné vzdálenosti dvou míst zadaných
//pomocí dvou zeměpisných šířek a délek
double VzdalenostNaZemi1(double sirka1, double delka1,
                         double sirka2, double delka2) {
    //přibližný "průměrný" poloměr Země (není to koule, takže
    //to je na různých místech různé)
    var R = 6371;
    //zjistím rozdíl šířek a délek
    var rozdilSirek = DegToRad(sirka2-sirka1);
    var rozdilDelek = DegToRad(delka2-delka1);
    sirka1 = DegToRad(sirka1);
    sirka2 = DegToRad(sirka2);
    var a = Math.Sin(rozdilSirek/2) * Math.Sin(rozdilSirek/2) +
            Math.Sin(rozdilDelek/2) * Math.Sin(rozdilDelek/2) *
            Math.Cos(sirka1) * Math.Cos(sirka2); 
    var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1-a)); 
    var d = R * c;

    //vrátím vzdálenost v kilometrech
    return d;
} 

Je tu ale ještě jedna jednodušší funkce, jak určit vzdálenost na povrchu koule.

//jednodušší, přesto přesná (srovnatelná) metoda
double VzdalenostNaZemi2(double sirka1, double delka1,
                         double sirka2, double delka2)  {
    sirka1 = DegToRad(sirka1);
    delka1 = DegToRad(delka1);
    sirka2 = DegToRad(sirka2);
    delka2 = DegToRad(delka2);

    return 6371 * Math.Acos(
        Math.Sin(sirka1) * Math.Sin(sirka2)
        + Math.Cos(sirka1) * Math.Cos(sirka2)
        * Math.Cos(delka2 - delka1));
} 

Jako příklad můžeme vzít tyto souřadnice.

GPS 1 = 50.128328, 14.493012
GPS 2 = 50.126062, 14.443097

Výsledek obou funkcí je v podstatě identický.

vzdálenost 1 = 3,56712317650752
vzdálenost 2 = 3,56712317775145

Zjišťujeme vzdálenost mezi dvěma GPS souřadnicemi, tentokrát v ASP.NET

Obě funkce VzdalenostNaZemi() nám tedy vracejí 3,567 km, zatímco měření na mapy.cz ukáže 3,577 km. Rozdíl je tedy pouhých 10 m, což je myslím vynikající. Nemám ponětí o tom, jak Seznam určuje vzdálenosti a tak nelze říci, co je přesnější. Pro mě bylo a je důležité, že funkce splnila účel a její naprogramování nebylo náročné.

Pokud budete zadávat polohu ze západní/jižní polokoule, nezapomeňte, že hodnoty musí být záporné. Například New York je na severní polokouli (+40 st. severní šířky), ale zároveň je také na západní polokouli (-74 st. západní délky). Zde jsou údaje pro Sochu Svobody a Central Park.

GPS 1 = 40.68962, -74.045647
GPS 2 = 40.782361, -73.965996

Vzdálenost opět vychází stejně, při měření na Google mapách je výsledek 12,3175 km, tedy opět rozdíl jen asi 14 m.

vzdálenost 1 = 12,3037262216122
vzdálenost 2 = 12,3037262213739

Pro nadšené matematiky uvádím ještě odkaz na další povídání a pěkné vzorečky.

http://en.wikipedia.org/wiki/Great-circle_distance