PHP en SQL: bereken of vraag groot sirkelafstand tussen breedte- en lengtepunte met die Haversine-formule

Haversine Formula - Bereken groot sirkelafstand met PHP of MySQL

Hierdie maand het ek nogal in PHP en MySQL geprogrammeer met betrekking tot GIS. Ek het eintlik 'n bietjie gesukkel om die internet te soek Geografiese berekeninge om die afstand tussen twee plekke te vind, so ek wou dit hier deel.

Vliegkaart Europa met groot sirkelafstand

Die eenvoudige manier om 'n afstand tussen twee punte te bereken, is deur die Pythagorese formule te gebruik om die skuinssy van 'n driehoek te bereken (A² + B² = C²). Dit staan ​​bekend as die Euklidiese afstand.

Dit is 'n interessante begin, maar dit geld nie vir geografie nie, aangesien die afstand tussen breedte- en lengtelyne is nie 'n gelyke afstand nie uitmekaar. Wanneer u nader aan die ewenaar kom, word breedtelyne verder uitmekaar. As u 'n soort eenvoudige driehoeksvergelyking gebruik, kan dit die afstand op die een plek akkuraat meet en verskriklik verkeerd op die ander plek as gevolg van die kromming van die Aarde.

Groot sirkelafstand

Die roetes wat lang afstande rondom die aarde afgelê word, staan ​​bekend as die Groot sirkelafstand. Dit is ... die kortste afstand tussen twee punte op 'n sfeer verskil van die punte op 'n plat kaart. Kombineer dit met die feit dat die breedte- en lengtelyne nie ewe ver is nie ... en u het 'n moeilike berekening.

Hier is 'n fantastiese video-uiteensetting van hoe Great Circles werk.

Die Haversine-formule

Die afstand met behulp van die kromming van die Aarde is opgeneem in die Haversine formule, wat trigonometrie gebruik om die kromming van die aarde moontlik te maak. As u die afstand tussen twee plekke op aarde vind (soos die kraai vlieg), is 'n reguit lyn 'n boog.

Dit is van toepassing op lugvlug - het u al ooit na die werklike kaart van vlugte gekyk en opgemerk dat dit geboë is? Dit is omdat dit korter is om tussen twee punte in 'n boog te vlieg as direk na die plek.

PHP: Bereken afstand tussen 2 punte van breedte en lengte

Hoe dit ook al sy, hier is die PHP-formule vir die berekening van die afstand tussen twee punte (saam met Mile versus Kilometer-omskakeling) afgerond tot twee desimale plekke.

function getDistanceBetweenPointsNew($latitude1, $longitude1, $latitude2, $longitude2, $unit = 'miles') {
  $theta = $longitude1 - $longitude2; 
  $distance = (sin(deg2rad($latitude1)) * sin(deg2rad($latitude2))) + (cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * cos(deg2rad($theta))); 
  $distance = acos($distance); 
  $distance = rad2deg($distance); 
  $distance = $distance * 60 * 1.1515; 
  switch($unit) { 
    case 'miles': 
      break; 
    case 'kilometers' : 
      $distance = $distance * 1.609344; 
  } 
  return (round($distance,2)); 
}

SQL: Alle rekords binne 'n reeks haal deur afstand in myle te bereken met behulp van breedte- en lengtegraad

Dit is ook moontlik om SQL te gebruik om 'n berekening te doen om alle rekords binne 'n spesifieke afstand te vind. In hierdie voorbeeld gaan ek MyTable in MySQL navraag doen om al die rekords te vind wat kleiner as of gelyk is aan die veranderlike $ afstand (in Miles) na my plek op $ breedtegraad en $ lengte:

Die navraag om al die rekords in 'n spesifieke op te spoor afstand deur die afstand in myl te bereken tussen twee breedte- en lengtepunte is:

$query = "SELECT *, (((acos(sin((".$latitude."*pi()/180)) * sin((`latitude`*pi()/180)) + cos((".$latitude."*pi()/180)) * cos((`latitude`*pi()/180)) * cos(((".$longitude."- `longitude`)*pi()/180)))) * 180/pi()) * 60 * 1.1515) as distance FROM `table` WHERE distance <= ".$distance."

U moet dit aanpas:

  • $ lengte - dit is 'n PHP-veranderlike waar ek die lengte van die punt deurgee.
  • $ breedtegraad - dit is 'n PHP-veranderlike waar ek die lengte van die punt deurgee.
  • $ afstand - dit is die afstand waarop u al die rekords minder of gelyk wil vind.
  • tafel - dit is die tabel ... u wil dit vervang deur u tafelnaam.
  • breedtegraad - dit is die veld van u breedtegraad.
  • lengtegraad - dit is die veld van u lengtegraad.

SQL: haal alle rekords binne 'n reeks deur afstand in kilometers te bereken met behulp van breedte- en lengtegraad

En hier is die SQL-vraag wat kilometers in MySQL gebruik:

$query = "SELECT *, (((acos(sin((".$latitude."*pi()/180)) * sin((`latitude`*pi()/180)) + cos((".$latitude."*pi()/180)) * cos((`latitude`*pi()/180)) * cos(((".$longitude."- `longitude`) * pi()/180)))) * 180/pi()) * 60 * 1.1515 * 1.609344) as distance FROM `table` WHERE distance <= ".$distance."

U moet dit aanpas:

  • $ lengte - dit is 'n PHP-veranderlike waar ek die lengte van die punt deurgee.
  • $ breedtegraad - dit is 'n PHP-veranderlike waar ek die lengte van die punt deurgee.
  • $ afstand - dit is die afstand waarop u al die rekords minder of gelyk wil vind.
  • tafel - dit is die tabel ... u wil dit vervang deur u tafelnaam.
  • breedtegraad - dit is die veld van u breedtegraad.
  • lengtegraad - dit is die veld van u lengtegraad.

Ek het hierdie kode gebruik in 'n kaarteplatform vir ondernemings wat ons gebruik het vir 'n kleinhandelwinkel met meer as 1,000 XNUMX plekke in Noord-Amerika, en dit het pragtig gewerk.