Calcule simple pentru lucrul cu lat/lon și distanța în km? (Programare, Algoritm, Geometrie, Geolocalizare)

Phillip B Oldham a intrebat.

Există un calcul simplu pe care îl pot face pentru a converti km într-o valoare pe care să o pot adăuga la o valoare flotantă lat sau lon pentru a calcula o cutie de delimitare pentru căutări? Nu este nevoie să fie complet precis.

De exemplu: dacă mi s-ar da un lat/lon pentru Londra, Anglia (51.5001524, -0.1262362) și aș vrea să calculez care ar fi lat-ul la 25 km est/vest de acel punct și care ar fi lon-ul la 25 km nord/sud de acel punct, ce ar trebui să fac pentru a converti cei 25 km într-o zecimală pe care să o adaug la valorile de mai sus?

Caut o regulă generală, adică: 1km == +/- 0,XXX

Editați:

Căutarea mea inițială pentru „lat lon” nu a returnat acest rezultat:

Cum se calculează caseta de delimitare pentru o anumită locație lat/lng?

Răspunsul acceptat pare adecvat pentru cerințele mele.

Comentarii

  • Posibil duplicat al How to calculate the bounding box for a given lat/lng location? –  > Por Stephen Kennedy.
6 răspunsuri
Jim Lewis

Conversiile aproximative sunt:

  • Latitudine: 1 grad = 110,574 km
  • Longitudine: 1 grad = 111.320*cos(latitudine) km

Acest lucru nu corectează complet aplatizarea polară a Pământului – pentru asta probabil că ai vrea o formulă mai complicată, folosind elipsoidul de referință WGS84 (modelul folosit pentru GPS). Dar eroarea este probabil neglijabilă pentru scopurile dumneavoastră.

Sursă: http://en.wikipedia.org/wiki/Latitude

Atenție:: Fiți atenți la faptul că coordonatele latlong sunt exprimate în grade, în timp ce coordonatele cos în majoritatea (toate?) limbilor acceptă de obicei radiani, prin urmare, o funcție conversia grade în radiani este necesară.

Comentarii

  • Vă referiți la cos(longitudine) în cea de-a doua formulă? –  > Por Odys.
  • Cum ați ajuns la această formulă? Îmi scapă ceva, puteți să detaliați calculele privind longitudinea? Ty.  > Por Odys.
  • @Odys: Dacă compari două puncte care se află pe aceeași linie de longitudine (nord/sud), ele se află pe un cerc mare, iar factorul de conversie este doar circumferința polară a Pământului împărțită la 360 de grade. Dar este diferit pentru măsurătorile est-vest, pentru că (cu excepția ecuatorului) nu măsori de-a lungul unui „mare cerc”, deci „circumferința” la o anumită latitudine este mai mică. Iar factorul de corecție se dovedește a fi cosinusul latitudinii. –  > Por Jim Lewis.
  • 17

  • Explicația mea: cos(0°) = 1 => Prin urmare, nu se aplică niciun factor de corecție la ecuator. Acolo longitudinile sunt cele mai largi. cos(90°) = 0 => La poli longitudinile se întâlnesc într-un singur punct. Nu există nicio distanță care să fie calculată. –  > Por Krisztián Balla.
  • @Stijn: Trebuie să convertiți din grade în radiani înainte de a apela Math.cos(). –  > Por Jim Lewis.
skaffman

Dacă folosiți Java, Javascript sau PHP, atunci există o bibliotecă care va face aceste calcule exact, folosind o trigonometrie amuzant de complicată (dar totuși rapidă):

http://www.jstott.me.uk/jcoord/

Comentarii

  • Site-ul are acum biblioteca. –  > Por midfield99.
  • Linkul este stricat! –  > Por chatzich.
  • Pentru PHP, puteți folosi acest fork: github.com/dvdoug/PHPCoord –  > Por dearsina.
Serj Kultenko

Îi mulțumesc lui Jim Lewis pentru răspunsul său excelent și aș dori să ilustrez această soluție prin funcția mea în Swift:

func getRandomLocation(forLocation location: CLLocation, withOffsetKM offset: Double) -> CLLocation {
        let latDistance = (Double(arc4random()) / Double(UInt32.max)) * offset * 2.0 - offset
        let longDistanceMax = sqrt(offset * offset - latDistance * latDistance)
        let longDistance = (Double(arc4random()) / Double(UInt32.max)) * longDistanceMax * 2.0 - longDistanceMax

        let lat: CLLocationDegrees = location.coordinate.latitude + latDistance / 110.574
        let lng: CLLocationDegrees = location.coordinate.longitude + longDistance / (111.320 * cos(lat / .pi / 180))
        return CLLocation(latitude: lat, longitude: lng)
    }

În această funcție, pentru a converti distanța, folosesc următoarele formule:

latDistance / 110.574
longDistance / (111.320 * cos(lat / .pi / 180))

Comentarii

  • Cred că ar trebui să fie „lat * pi / 180” –  > Por magamig.
Nikhil Dinesh

http://www.jstott.me.uk/jcoord/ – utilizați această bibliotecă

            LatLng lld1 = new LatLng(40.718119, -73.995667);
            LatLng lld2 = new LatLng(51.499981, -0.125313);
            Double distance = lld1.distance(lld2);
            Log.d(TAG, "Distance in kilometers " + distance);

Mircea

Interesant că nu am văzut o mențiune despre coordonatele UTM.

https://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system.

Cel puțin dacă vrei să adaugi km la aceeași zonă, ar trebui să fie simplu (în Python : https://pypi.org/project/utm/ )

utm.from_latlon și utm.to_latlon.

Comentarii

  • Mulțumesc pentru linkul către utm. Șocant că pare să nu aibă deloc documentație. –  > Por Westworld.
George Karadov

De ce să nu folosiți interogări geospațiale corect formulate????

Aici este pagina de referință SQL Server privind funcția geospațială STContains:

https://docs.microsoft.com/en-us/sql/t-sql/spatial-geography/stcontains-geography-data-type?view=sql-server-ver15

sau, dacă nu doriți să utilizați conversia box și radian, puteți utiliza întotdeauna funcția de distanță pentru a găsi punctele de care aveți nevoie:

DECLARE @CurrentLocation geography; 
SET @CurrentLocation  = geography::Point(12.822222, 80.222222, 4326)

SELECT * , Round (GeoLocation.STDistance(@CurrentLocation ),0) AS Distance FROM [Landmark]
WHERE GeoLocation.STDistance(@CurrentLocation )<= 2000 -- 2 Km

Ar trebui să existe o funcționalitate similară pentru aproape orice bază de date existentă.

Dacă ați implementat corect indexarea geospațială, căutările dvs. ar fi mult mai rapide decât abordarea pe care o utilizați.

Comentarii

  • Vă rugăm să acordați un moment pentru a citi ajutorul de editare din centrul de asistență. Formatarea pe Stack Overflow este diferită față de alte site-uri. –  > Por Dharman.