То, что я пытаюсь сделать, это то, что у меня есть записи в базе данных, у которых есть lat / long. Я хочу рассчитать расстояние между пользователями lat / long и записями lat / long (в DB). После этого я хочу повторить те, которые пройдут дистанцию менее 500 метров. Пока я могу сделать это с помощью foreach
.
<?php mysql_connect("localhost", "beepbee_kunwarh", "kunwar") or die('MySQL Error.'); mysql_select_db("beepbee_demotest") or die('MySQL Error.'); $Lat = $_REQUEST['Lat']; $long = $_REQUEST['long']; $query = mysql_query("SELECT a.*, 3956 * 2 * ASIN(SQRT( POWER(SIN(($Lat - Lat) * pi()/180 / 2), 2) + COS($Lat * pi()/180) * COS(Lat * pi()/180) *POWER(SIN(($long - long) * pi()/180 / 2), 2) )) as distance FROM userResponse GROUP BY beepid HAVING distance <= 500 ORDER by distance ASC;"); $data = array(); while ($row = mysql_fetch_array($query)) { $data[] = $row; } echo json_encode($data); ?>
Я сделал это несколько недель назад.
Эта ссылка – ваш лучший выбор:
http://code.google.com/apis/maps/articles/phpsqlsearch.html
Даже если вы не используете их API, их PHP и SQL-запрос очень помогли.
я бы не рекомендовал вычислять расстояния в вашем sql-заявлении, хотя я признаю, что решение, представленное «денилом», изобретательно.
есть 3 недостатка: обслуживание кода, перегрузка сервера sql и (прежде всего) земля не симметрична (это похоже на старый помятый бейсбол, который был запущен грузовиком). это означает, что вы захотите изменить код в будущем (есть некоторые ОЧЕНЬ сложные алгоритмы там – http://en.wikipedia.org/wiki/Geographical_distance ).
Я рекомендую использовать отдельную функцию, которая вычисляет расстояние с помощью простого общего алгоритма (аналогичного, если не идентичного денилу). Я представляю этот код, который является чистым php (не нужно использовать googlemaps api):
<?php function distanceGeoPoints ($lat1, $lng1, $lat2, $lng2) { $earthRadius = 3958.75; $dLat = deg2rad($lat2-$lat1); $dLng = deg2rad($lng2-$lng1); $a = sin($dLat/2) * sin($dLat/2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLng/2) * sin($dLng/2); $c = 2 * atan2(sqrt($a), sqrt(1-$a)); $dist = $earthRadius * $c; // from miles $meterConversion = 1609; $geopointDistance = $dist * $meterConversion; return $geopointDistance; } // YOUR CODE HERE echo distanceGeoPoints(22,50,22.1,50.1); ?>
существует множество бесплатных программ (попробуйте gps trackmaker), которые позволят вам проверить допустимую погрешность для вашей части земного шара (если вам нужна точность). для вышеупомянутой пары lat / long ошибка находится в пределах +/- 0,1% (согласно местным топографам).
ВНИМАНИЕ: эта формула дает вам расстояние CARTOGRAPHIC (расстояние на уровне моря), а не ТОПОГРАФИЧЕСКОЕ расстояние (не учитывает топографию).
Попробуйте этот запрос. Я нашел это, когда гуглинг, но забыл, кто его создал
SELECT a.*, 3956 * 2 * ASIN(SQRT( POWER(SIN(($lat - lat) * pi()/180 / 2), 2) + COS($lat * pi()/180) * COS(lat * pi()/180) * POWER(SIN(($long - longi) * pi()/180 / 2), 2) )) as distance FROM table GROUP BY id HAVING distance <= 500 ORDER by distance ASC
$ lat и $ long – текущая позиция пользователя. lat и longi – широта и продольность записей
http://www.geodatasource.com/developers/php
<?php /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ /*:: :*/ /*:: This routine calculates the distance between two points (given the :*/ /*:: latitude/longitude of those points). It is being used to calculate :*/ /*:: the distance between two locations using GeoDataSource(TM) Products :*/ /*:: :*/ /*:: Definitions: :*/ /*:: South latitudes are negative, east longitudes are positive :*/ /*:: :*/ /*:: Passed to function: :*/ /*:: lat1, lon1 = Latitude and Longitude of point 1 (in decimal degrees) :*/ /*:: lat2, lon2 = Latitude and Longitude of point 2 (in decimal degrees) :*/ /*:: unit = the unit you desire for results :*/ /*:: where: 'M' is statute miles :*/ /*:: 'K' is kilometers (default) :*/ /*:: 'N' is nautical miles :*/ /*:: Worldwide cities and other features databases with latitude longitude :*/ /*:: are available at http://www.geodatasource.com :*/ /*:: :*/ /*:: For enquiries, please contact sales@geodatasource.com :*/ /*:: :*/ /*:: Official Web site: http://www.geodatasource.com :*/ /*:: :*/ /*:: GeoDataSource.com (C) All Rights Reserved 2014 :*/ /*:: :*/ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ function distance($lat1, $lon1, $lat2, $lon2, $unit) { $theta = $lon1 - $lon2; $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); $dist = acos($dist); $dist = rad2deg($dist); $miles = $dist * 60 * 1.1515; $unit = strtoupper($unit); if ($unit == "K") { return ($miles * 1.609344); } else if ($unit == "N") { return ($miles * 0.8684); } else { return $miles; } } echo distance(32.9697, -96.80322, 29.46786, -98.53506, "M") . " Miles<br>"; echo distance(32.9697, -96.80322, 29.46786, -98.53506, "K") . " Kilometers<br>"; echo distance(32.9697, -96.80322, 29.46786, -98.53506, "N") . " Nautical Miles<br>"; ?>
Протестировано, как 3 функции и 3 запроса, и только один показал хорошее расстояние:
В метрах:
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) * 1000 ) as `distance` FROM `table` ORDER BY `distance` ASC
В километрах:
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` ORDER BY `distance` ASC
Этот запрос был идеальным для меня:
$latitude = "23.139422"; //your current lat $longitude = "-82.382617"; //your current long SELECT ( 3959 * acos( cos( radians( '.$latitude.' ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians( '.$longitude.' ) ) + sin( radians( '.$latitude.' ) ) * sin( radians( latitude ) ) ) ) AS distance from TABLE HAVING distance <= 100 ORDER BY distance ASC
Простой и простой способ
<?php $lat1 = Yourstart_latitude; $lon1 = Yourstart_longitude; $lat2 = Yourend_latitude; $lon2 = Yourend_longitude; $theta = $lon1 - $lon2; $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); $dist = acos($dist); $dist = rad2deg($dist); $miles= $dist * 60 * 1.1515; $unit = 'K'; $km = $miles*1.609344; echo number_format($km,1); ?>
Используйте distance-matrix google api для вычисления расстояния между широтой и долготой.
$ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_URL, 'https://maps.googleapis.com/maps/api/distancematrix/json?origins='.$prev_add.'&destinations='.$curr_add.'&key=keyyouhavetogenerate' ); $content = curl_exec($ch); $array = json_decode($content); $obj = json_decode($content, TRUE); $distance = $obj['rows'][0]['elements'][0]['distance']['text'];
для использования этого api вам понадобится ключ, чтобы узнать больше о том, как сгенерировать ключ, посетите https://developers.google.com/maps/documentation/distance-matrix/intro