PHP lan SQL: Ngetung utawa Nganggo Jarak Lingkaran Gedhe Antarane Nomer Latitude lan Bujur Kanthi Formula Haversine

Formula Haversine - Ngetung Jarak Lingkaran Gedhe nganggo PHP utawa MySQL

Sasi iki aku wis program ing PHP lan MySQL babagan GIS. Ngeling-eling ing jaring, aku pancen angel golek sawetara Petungan geografis kanggo nggoleki jarak antarane rong lokasi mula aku pengin nuduhake ing kene.

Peta Penerbangan Eropa Kanthi Jarak Lingkaran Gedhe

Cara sederhana kanggo ngetung jarak antarane rong poin yaiku nggunakake formula Pythagoras kanggo ngetung hypotenuse segitiga (A² + B² = C²). Iki dikenal minangka Jarak Euclidean.

Iku wiwitan sing apik nanging ora cocog karo Geografi amarga jarak antarane garis garis lintang lan garis bujur dudu jarak sing padha pisah. Nalika sampeyan nyedhaki khatulistiwa, garis garis lintang saya adoh. Yen sampeyan nggunakake sawetara persamaan triangulasi sederhana, bisa ngukur jarak kanthi akurat ing sak lokasi lan pancen salah ing papan liyane, amarga lengkungan Bumi.

Jarak Lingkaran Gedhe

Rute sing lelungan adoh ing saindenging Bumi dikenal minangka Jarak Lingkaran Gedhe. Yaiku ... jarak paling cedhak antara rong titik ing bola beda karo poin ing peta datar. Gabungke karo kasunyatan manawa garis garis lintang lan garis bujur ora padha ... lan sampeyan bakal duwe pitungan sing angel.

Mangkene panjelasan video sing hebat babagan cara kerjane Great Circles.

Formula Haversine

Jarak nggunakake lengkungan Bumi tergabung ing Formula haversine, sing nggunakake trigonometri kanggo ngidini kelengkungan bumi. Nalika sampeyan nemokake jarak antarane 2 panggonan ing bumi (nalika mabur kluruk), garis lurus pancen busur.

Iki ditrapake kanggo penerbangan udhara - apa sampeyan nate ndeleng peta penerbangan sing sejatine lan ngerteni manawa ana gandhengane? Iku amarga luwih cendhek mabur ing lengkungan antarane rong poin tinimbang langsung menyang lokasi.

PHP: Ngetung Jarak Antarane 2 Poin Lintang lan Bujur

Oalah, iki formula PHP kanggo ngitung jarak antarane rong titik (bebarengan karo konversi Mile vs. Kilometer) dibunderake dadi rong desimal.

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: Nggawe Kabeh Data Ing Jangkoan Kanthi Ngitung Jarak Ing Mil Nggunakake Latitude lan Bujur

Sampeyan uga bisa nggunakake SQL kanggo nindakake pitungan kanggo nemokake kabeh cathetan ing jarak tartamtu. Ing conto iki, aku bakal takon MyTable ing MySQL kanggo nemokake kabeh cathetan sing kurang saka utawa padha karo jarak $ variabel (ing Mil) menyang lokasi ing $ lintang lan $ bujur:

Pitakon kanggo njupuk kabeh cathetan ing tartamtu kadohan kanthi ngitung jarak mil ing antarane rong titik lintang lan garis bujur yaiku:

$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."

Sampeyan kudu ngatur iki:

  • $ bujur - iki minangka variabel PHP ing endi aku nuduhake garis bujur saka titik kasebut.
  • $ garis lintang - iki minangka variabel PHP ing endi aku nuduhake garis bujur saka titik kasebut.
  • $ kadohan - iki jarak sing sampeyan pengin nemokake kabeh cathetan kurang utawa padha.
  • Tabel - iki tabel… sampeyan bakal pengin ngganti sing nganggo jeneng tabel.
  • garis lintang - iki lapangan garis lintang sampeyan.
  • bujur - iki lapangan bawahan sampeyan.

SQL: Nggawe Kabeh Data Ing Jangkauan Kanthi Ngitung Jarak Ing Kilomèter Nggunakake Latitude lan Bujur

Lan iki pitakon SQL nggunakake kilometer ing MySQL:

$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."

Sampeyan kudu ngatur iki:

  • $ bujur - iki minangka variabel PHP ing endi aku nuduhake garis bujur saka titik kasebut.
  • $ garis lintang - iki minangka variabel PHP ing endi aku nuduhake garis bujur saka titik kasebut.
  • $ kadohan - iki jarak sing sampeyan pengin nemokake kabeh cathetan kurang utawa padha.
  • Tabel - iki tabel… sampeyan bakal pengin ngganti sing nganggo jeneng tabel.
  • garis lintang - iki lapangan garis lintang sampeyan.
  • bujur - iki lapangan bawahan sampeyan.

Kode iki digunakake ing platform pemetaan perusahaan sing digunakake kanggo toko ritel kanthi luwih saka 1,000 lokasi ing Amerika Utara lan bisa digunakake kanthi apik.

76 Komentar

  1. 1

    Matur nuwun kanthi sanget kanggo nuduhake. Iki tugas gampang nyalin lan nempel lan bisa sukses. Sampeyan wis ngirit wektu akeh.
    FYI kanggo sapa sing porting menyang C:
    pindho deg2rad (tikel kaping pindho) {bali deg * (3.14159265358979323846 / 180.0); }

  2. 2

    Kiriman sing apik banget - apik banget - aku mung kudu ngganti jeneng meja sing dawa lat-dawa. Kerjane cukup cepet kanggo .. Aku duwe sawetara lat-long sing cukup (<400) nanging aku mikir iki bakal skala kanthi apik. Situs sing apik uga - aku wis nambah ing akun del.icio.us lan bakal mriksa maneh kanthi rutin.

  3. 4
  4. 5

    Aku sedina muput nggoleki pitungan jarak lan nemokake algoritma harversine, matur nuwun amarga wis menehi conto babagan cara nyedhiyakake ing pratelan sql. Matur suwun lan salam, Daniel

  5. 8

    Aku mikir SQL sampeyan butuh pernyataan sing ana.
    tinimbang WHERE jarak <= $ kadohan sampeyan kudu
    gunakake ADUH jarak <= $ jarak

    yen ora, matur nuwun amarga wis ngirit wektu lan tenaga kanthi akeh.

  6. 10
  7. 11
  8. 12

    Matur nuwun kanthi sanget kanggo nuduhake kode iki. Ngirit wektu saya akeh. Kajaba iku, matur nuwun kanggo para pamiarsa amarga wis nuduhake manawa ana pratelan sing PUTUT perlu kanggo MySQL 5.x. Ngrewangi banget

  9. 14
  10. 15

    Halo,

    Pitakon liyane. Apa ana formula kanggo senar NMEA kaya ing ngisor iki?

    1342.7500, N, 10052.2287, E

    $GPRMC,032731.000,A,1342.7500,N,10052.2287,E,0.40,106.01,101106,,*0B

    Thanks,
    Harry

  11. 16

    Aku uga ngerti yen WHERE ora bisa digunakake kanggo aku. Owahi dadi duwe lan kabeh bisa sampurna. Wiwitane aku ora maca komentar lan nulis ulang nganggo pilihan sing disarangake. Loro-lorone bakal bisa digunakake kanthi apik.

  12. 17
  13. 18

    Mbantu tenan, matur nuwun kanthi sanget! Aku nemoni sawetara masalah karo "NGALAMI" sing anyar, tinimbang "ASI", nanging sawise maca komentar ing kene (sawise udakara setengah jam mecah untu amarga frustasi = P), aku bisa mlaku kanthi apik. Matur nuwun ^ _ ^

  14. 19
  15. 20

    Elinga yen pernyataan sing dipilih kaya ngono bakal dadi komputasi, mula alon-alon. Yen sampeyan duwe akeh pitakon kasebut, bisa uga cepet banget.

    Pendekatan sing kurang kuat yaiku mbukak sing pertama (minyak mentah) nggunakake area SQUARE sing ditemtokake kanthi jarak sing diitung yaiku "pilih * saka tablename ing garis lintang antara lat1 lan lat2 lan bujur antarane lon1 lan lon2". lat1 = targetlatitude - latdiff, lat2 = targetlatitude + latdiff, padha karo lon. latdiff ~ = jarak / 111 (kanggo km), utawa jarak / 69 mil wiwit 1 derajat lintang ~ ~ km (variasi sithik amarga bumi rada bunder, nanging cukup kanggo tujuan iki). londiff = jarak / (abs (cos (deg111rad (garis lintang)) * 2)) - utawa 111 mil (sampeyan sejatine bisa njupuk alun-alun sing luwih gedhe supaya bisa menehi variasi). Banjur njupuk asil kasebut lan pakan menyang radial select. Aja lali ngetrapake koordinat sing ora ana watese - yaiku kisaran bujur sing bisa ditampa yaiku -69 nganti +180 lan kisaran lintang sing bisa ditampa yaiku -180 nganti +90 - yen latdiff utawa londiff sampeyan mbukak njaba kisaran . Elinga, ing kasus biasane, iki ora bisa ditrapake amarga mung mangaruhi petungan liwat segara liwat samodra pasifik saka tiang menyang kutub, sanajan intersect bagean saka chukotka lan bagean alaska.

    Apa sing kita lakoni yaiku nyuda jumlah poin sing cocog kanggo sampeyan ngitung. Yen sampeyan duwe sejuta poin global ing basis data sing disebar rata-rata lan sampeyan pengin telusuran sajrone 100 km, mula telusuran (cepet) sing pertama yaiku 10000 km persegi lan bisa ngasilake 20 asil (adhedhasar distribusi jembaré udakara 500M sq km), tegese sampeyan ngetung jarak kompleks 20 kali kanggo pitakon iki tinimbang kaping pirang-pirang yuta.

    • 21
      • 22

        Saran sing apik banget! Aku nyatane nyambut gawe karo pangembang sing nulis fungsi sing narik alun-alun ing njero kothak, banjur fungsi rekursif sing nggawe 'kothak' ngubengi keliling kanggo nyakup lan nyingkirake poin sing isih ana. Asil kasebut minangka asil sing cepet banget - dheweke bisa ngevaluasi jutaan poin ing mikrosetik.

        Pendekatanku ing ndhuwur mesthi 'ora sopan' nanging bisa. Matur suwun maneh!

        • 23

          Doug,

          Aku nyoba nggunakake mysql lan php kanggo ngevaluasi manawa titik dawa lat ana ing polygon. Apa sampeyan ngerti manawa kanca pangembang nerbitake conto babagan cara ngrampungake tugas iki. Utawa sampeyan ngerti conto sing apik. Matur suwun dhisik.

  16. 24

    Hai kabeh, iki pratelan tes SQL:

    SELECT DISTINCT area_id, (
    (
    (
    acos( sin( ( 13.65 * pi( ) /180 ) ) * sin( (
    `lat_dec` * pi( ) /180 ) ) + cos( ( 13.65 * pi( ) /180 ) ) * cos( (
    `lat_dec` * pi( ) /180 )
    ) * cos( (
    ( 51.02 - `lon_dec` ) * pi( ) /180 )
    )
    )
    ) *180 / pi( )
    ) *60 * 1.1515 * 1.609344
    ) AS distance
    FROM `post_codes` WHERE distance <= 50

    lan Mysql ngandhani yen jarak kasebut, ora ana ing kolom, aku bisa nggunakake pesen kanthi, aku bisa nindakake tanpa ing endi, lan bisa digunakake, nanging ora nganggo…

  17. 26

    Iki apik banget, nanging kaya manuk sing mabur. Luwih becik nyoba lan nggabungake google maps API kanthi cara iki (bisa uga nggunakake dalan lsp) Kanggo menehi ide nggunakake macem-macem jinis transportasi. Aku isih durung nggawe fungsi anil simulasi ing PHP sing bakal bisa menehi solusi sing efisien kanggo masalah salesman lelungan. Nanging aku mikir manawa aku bisa nggunakake maneh sawetara kode supaya bisa ditindakake.

  18. 27
  19. 28

    Artikel apik! Aku nemokake akeh artikel sing njlentrehake babagan cara ngitung jarak antarane rong poin nanging aku pancen nggoleki potongan SQL.

  20. 29
  21. 30
  22. 31
  23. 32
  24. 36

    Riset 2 dina kanggo pungkasane nemokake kaca iki sing ngatasi masalahku. Kayane luwih becik aku njaluk WolframAlpha lan matematika. Pangowahan saka WHERE menyang HAVING duwe skrip supaya bisa digunakake. Matur Nuwun

  25. 37
    • 38

      Matur suwun Georgi. Aku terus njaluk 'jarak' kolom ora ditemokake. Sawise aku ngganti WHERE TO WAVE, kerjane kaya pesona!

  26. 39

    Muga-muga iki kaca pisanan sing ditemokake babagan iki. Sawise nyoba akeh macem-macem perintah, iki siji-sijine sing bisa digunakake kanthi bener, lan mung kudu ana pangowahan minimal supaya bisa cocog karo database dhewe.
    Thanks a lot!

  27. 40

    Muga-muga iki kaca pisanan sing ditemokake babagan iki. Sawise nyoba akeh macem-macem perintah, iki siji-sijine sing bisa digunakake kanthi bener, lan mung kudu ana pangowahan minimal supaya bisa cocog karo database dhewe.
    Thanks a lot!

  28. 41
  29. 42
  30. 43
  31. 45
  32. 46
  33. 47

    Aku ngerti formula iki bisa digunakake, nanging aku ora bisa ndeleng radius bumi sing bakal dipikirake. Apa ana sing bisa nerangake aku?

  34. 49
  35. 50
  36. 52
  37. 53
  38. 55
  39. 56
  40. 58

    matur nuwun kanggo ngirim artikel sing migunani iki,  
    nanging sakperangan alesan aku pengin takon
    kepiye supaya jarak antarane koord ing MySQL db lan coords dipasang menyang php dening pangguna?
    kanggo nerangake kanthi luwih cetha:
    1.user kudu masang [id] kanggo milih data sing ditemtokake saka db lan kord pangguna dhewe
    2. file php entuk data target (coords) nggunakake [id] banjur ngitung jarak antarane pangguna lan titik target

    utawa mung bisa entuk jarak saka kode ing ngisor iki?

    $ qry = “SELECT *, (((acos (sin ((“. $ lintang. ”* pi () / 180)) * sin ((` Latitude` * pi () / 180)) + cos ((“. $ lintang. ”* pi () / 180)) * cos ((` Latitude` * pi () / 180)) * cos (((". $ bujur." - `Bujur`) * pi () / 180) ))) * 180 / pi ()) * 60 * 1.1515 * 1.609344) kadohan saka `MyTable` WHERE jarak> =". $ Jarak. " >>>> apa aku bisa "njupuk" kadohan saka kene?
    matur nuwun maneh,
    Timmy S

    • 59

      ora preduli, aku wis ngerteni carane "fungsi" bisa digunakake ing php
      $ dis = getDistanceBet AntaraPointsNew ($ userLati, $ userLongi, $ lati, $ longi, $ unit = 'Km')
      matur nuwun sanget !! 

  41. 60

    ok, kabeh sing wis tak coba ora bisa. Maksudku, apa sing dakkarepake, nanging jarak adoh.

    Apa ana sing bisa ngerti apa sing salah karo kode iki?

    yen (ngetokake ($ _ POST ['diajukake'])) {$ z = $ _POST ['zipcode']; $ r = $ _POST ['radius']; kumandhang "Asil kanggo". $ z; $ sql = mysql_query (“SELECT DISTINCT m.zipcode, m.MktName, m.LocAddSt, m.LocAddCity, m.LocAddState, m.x1, m.y1, m. verifikasi, z1.lat, z2.lon, z1. kutha, z1.state MULAI mrk m, zip z1, zip z2 INI m.zipcode = z1.zipcode LAN z2.zipcode = $ z LAN (3963 * acos (truncate (sin (z2.lat / 57.2958) * sin (m. y1 / 57.2958) + cos (z2.lat / 57.2958) * cos (m.y1 / 57.2958) * cos (m.x1 / 57.2958 - z2.lon / 57.2958), 8))) <= $ r ") utawa mati (mysql_error ()); nalika ($ row = mysql_fetch_array ($ sql)) {$ store1 = $ row ['MktName']. ""; $ store = $ row ['LocAddSt']. ””; $ store. = $ row ['LocAddCity']. ",". $ row ['LocAddState']. " ". $ Row ['zipcode']; $ latitude1 = $ row ['lat']; $ longitude1 = $ saurutan ['lon']; $ latitude2 = $ row ['y1']; $ longitude2 = $ saurutan ['x1']; $ city = $ row ['city']; $ state = $ row ['state']; $ dis = getnew ($ latitude1, $ longitude1, $ latitude2, $ longitude2, $ unit = 'Mi'); // $ dis = jarak ($ ​​lat1, $ lon1, $ lat2, $ lon2); $ verified = $ row ['diverifikasi']; yen ($ diverifikasi == '1') {kumandhang “”; kumandhang "". $ toko. ""; kumandhang $ dis. "Mil (s) adoh"; kumandhang ""; } liya {kumandhang "". $ toko. ""; kumandhang $ dis. "Mil (s) adoh"; kumandhang ""; }}}

    kode fungsi.phpku
    fungsi getnew ($ latitude1, $ longitude1, $ latitude2, $ longitude2, $ unit = 'Mi') {$ theta = $ longitude1 - $ longitude2; $ kad = ); $ kadohan = aco ($ kadohan); $ kadohan = rad2deg ($ kadohan); $ kadohan = $ jarak * 1 * 2; ngalih ($ unit) {cilik 'Mi': break; cilik 'Km': $ kadohan = $ kadohan * 2; } bali (babak ($ ​​kadohan, 2)); }

    Matur nuwun sakdurunge

  42. 61
  43. 62

    Hei Douglas, artikel apik. Aku ngerti panjelasan sampeyan babagan konsep geografis lan kode kasebut pancen menarik. Siji-sijine saranku yaiku spasi lan indent kode kanggo ditampilake (kayata, Stackoverflow). Aku ngerti manawa sampeyan pengin ngirit ruangan, nanging jarak kode / lekukan konvensional bakal luwih gampang kanggo aku, minangka programmer, kanggo maca lan mbuwang. Nanging, iku prekara cilik. Terusake gaweyan sing apik.

  44. 64
  45. 65
  46. 66
  47. 67
  48. 68
  49. 69
  50. 70

    misale jek luwih cepet (MySQL 5.9) nggunakake rumus kaping pindho ing pilih lan ing endi:
    $ formula = “(((acos (sin ((“. $ lintang. ”* pi () / 180)) * sin ((` Latitude` * pi () / 180)) + cos ((“. $ lintang. ”* Pi () / 180)) * cos ((` Latitude` * pi () / 180)) * cos (((". $ Bujur." - `Bujur`) * pi () / 180)))) * 180 / pi ()) * 60 * 1.1515 * 1.609344) ”;
    $ sql = 'PILIH *,'. $ formula. ' kadohan saka tabel WHERE '.. $ formula.' <= '. $ jarak;

  51. 71
  52. 72

    Matur nuwun kanthi sanget kanggo nyukur artikel iki. Migunani banget.
    PHP pisanan digawe minangka platform skrip sederhana sing diarani "Kaca Ngarep Pribadi". Saiki PHP (singkatan saka Hypertext Preprocessor) minangka alternatif teknologi Microsoft Active Server Kaca (ASP).

    PHP minangka basa sisih server open source sing digunakake kanggo nggawe kaca web sing dinamis. Bisa ditempelake ing HTML. PHP biasane digunakake bebarengan karo basis data MySQL ing server web Linux / UNIX. Sampeyan bisa uga nganggo basa skrip sing paling populer.

  53. 73

    Aku nemokake solusi ing ndhuwur sing ora bisa digunakake kanthi bener.
    Aku kudu ganti dadi:

    $ qqq = "SELECT *, (((acos (sin ((". $ lintang. "* pi () / 180)) * sin ((` latt` * pi () / 180)) + cos ((". $ lintang. “* pi () / 180)) * cos ((` latt` * pi () / 180)) * cos (((". $ bujur." - `longt`) * pi () / 180) ))) * 180 / pi ()) * 60 * 1.1515) kadohan saka `register`“;

  54. 75

    matur nuwun Pak Wroking sampurna .. nanging aku duwe siji pitakonan yen pengin output tanpa titik desimal banjur apa sing bisa dak lakoni ..?

    Thanks in advance.

  55. 76

    Halo, tulung aku butuh banget pitulung sampeyan babagan iki.

    Aku njaluk panjaluk njaluk menyang server webku http://localhost:8000/users/findusers/53.47792/-2.23389/20/
    53.47792 = garis lintang $
    -2.23389 = bujur $
    lan 20 = jarak sing dakkarepake

    Nanging nggunakake rumus sampeyan, bakal njupuk kabeh larik ing db

    $ asil = DB :: pilih (DB :: mentah (“SELECT *, (((acos (sin ((“. $ lintang. ”* pi () / 180)) * sin ((lat * pi () / 180 )) + cos ((". $ lintang." * pi () / 180)) * cos ((lat * pi () / 180)) * cos (((". $ bujur." - lng) * pi ( ) / 180)))) * 180 / pi ()) * 60 * 1.1515 * 1.609344) kadohan saka marker Duwe jarak> = ". $ Jarak));

    [{“Id”: 1, ”jeneng”: ”Frankie Johnnie & Luigo Uga”, ”alamat”: ”939 W El Camino Real, Mountain View, CA”, ”lat”: 37.386337280273, ”lng”: - 122.08582305908, ”Jarak”: 16079.294719663}, {“id”: 2, ”jeneng”: ”Amici's East Coast Pizzeria”, ”alamat”: ”790 Castro St, Mountain View, CA”, ”lat”: 37.387138366699, ”lng”: -122.08323669434, ”jarak”: 16079.175940152}, {“id”: 3, ”jeneng”: ”Kapp's Pizza Bar & Grill”, ”alamat”: ”191 Castro St, Mountain View, CA”, ”lat”: 37.393886566162, ”Lng”: - 122.07891845703, ”jarak”: 16078.381373826}, {“id”: 4, ”jeneng”: ”Pizza Meja Babak: Mountain View”, ”alamat”: ”570 N Shoreline Blvd, Mountain View, CA”, ”Lat”: 37.402652740479, ”lng”: - 122.07935333252, ”jarak”: 16077.420540582}, {“id”: 5, ”jeneng”: ”Pizza & Pasta Tony & Alba”, ”alamat”: ”619 Escuela Ave, Mountain Deleng, CA ”,” lat ”: 37.394012451172,” lng ”: - 122.09552764893,” jarak ”: 16078.563225154}, {“ id ”: 6,” jeneng ”:” Pizza Kayu-Kayu Oregano ”,” alamat ”:” 4546 El Camino Real, Los Altos, CA ”,” lat ”: 37.401725769043,” lng ”: - 122.11464691162,” jarak ”: 16077.937560795}, {“ id ”: 7,” name ”:” The bar and grills ”,” address ”:” 24 Whiteley Street, Manchester ”,” lat ”: 53.485118865967,” lng ”: - 2.1828699111938,” jarak ”: 8038.7620112314}]

    Aku pengin njupuk mung baris kanthi 20 mil nanging nggawa kabeh larik. Tulung aku salah apa

Apa sampeyan mikir?

Situs iki nggunakake Akismet kanggo ngurangi spam. Sinau babagan proses data sampeyan.