本文概述
- 1.了解我们的标记数据库
- 2.了解我们需要做什么
- 3.准备最近的位置查询
- 4.测试查询
这个想法本身很酷, 对吧?显然, 我们没有包括Google Maps中的地点, 这意味着这些标记显然是我们的, 它们存储在我们自己的数据库中。在本文中, 我们将向你解释如何从MySQL的坐标集合中知道最近的位置。
1.了解我们的标记数据库 首先, 你显然需要在数据库中存储位置, 在我们的情况下, 我们将拥有非常简单的数据库结构, 因此每个人都可以轻松理解它。可以使用以下查询创建数据库:
CREATE TABLE `markers` (`id` bigint(20) NOT NULL, `lat` decimal(10, 8) NOT NULL, `lng` decimal(11, 8) NOT NULL, `name` varchar(255) CHARACTER SET utf8 NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;
它仅存储由名称标识的标记, 并包含纬度和经度的坐标。它包含以下数据:
如果我们使用JavaScript在Google地图中放置上述位置的标记:
var markers = [{"id": "1", "lat": "4.66455174", "lng": "-74.07867091", "name": "Bogot\u00e1"}, {"id": "2", "lat": "6.24478548", "lng": "-75.57050110", "name": "Medell\u00edn"}, {"id": "3", "lat": "7.06125013", "lng": "-73.84928550", "name": "Barrancabermeja"}, {"id": "4", "lat": "7.88475514", "lng": "-72.49432589", "name": "C\u00facuta"}, {"id": "5", "lat": "3.48835279", "lng": "-76.51532198", "name": "Cali"}, {"id": "6", "lat": "4.13510880", "lng": "-73.63690401", "name": "Villavicencio"}, {"id": "7", "lat": "6.55526689", "lng": "-73.13373892", "name": "San Gil"}];
function setMarkers(map) {var image = {url: 'https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png', size: new google.maps.Size(20, 32), origin: new google.maps.Point(0, 0), anchor: new google.maps.Point(0, 32)};
for (var i = 0;
i <
markers.length;
i++) {var marker = markers[i];
var marker = new google.maps.Marker({position: {lat: parseFloat(marker.lat), lng: parseFloat(marker.lng)}, map: map, icon: image, shape: {coords: [1, 1, 1, 20, 18, 20, 18, 1], type: 'poly'}, title: marker.name});
}}
我们将在地图中获得以下输出:
【如何使用PHP,MySQL从一组坐标(经度和纬度)中查找最近的位置】现在, 一切正常, 地图正常, 标记在正确的位置, 但是现在, 我们需要根据我们的位置(Bucaramanga)和特定的距离半径对它们进行过滤。我们不会在本文中介绍如何使用JavaScript过滤它们, 而仅在服务器端进行过滤, 因此你可以自行决定如何稍后在前端中显示它们。
2.了解我们需要做什么 首先, 我们需要了解我们将在数据库中进行理论上的操作。以下模式展示了我们需要完成以完成任务的两个问题, 其中包括我们将搜索一个圆形区域, 该圆形区域由我们将其称为搜索半径的某个距离定义:
知道初始位置和其他坐标之间的距离是未知的:
- 我们如何从起点定义搜索半径?
- 我们如何知道位置在搜索半径内?
- 拉特:7.08594109039762
- lng:286.95225338731285
<
?php /** * Method to find the distance between 2 locations from its coordinates. * * @param latitude1 LAT from point A * @param longitude1 LNG from point A * @param latitude2 LAT from point A * @param longitude2 LNG from point A * * @return Float Distance in Kilometers. */function getDistanceBetweenPointsNew($latitude1, $longitude1, $latitude2, $longitude2, $unit = 'Mi') {$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 'Mi': break;
case 'Km' : $distance = $distance * 1.609344;
}return (round($distance, 2));
}
这就是我们基本上要做的, 以便从它们的坐标知道2个位置之间的距离, 例如Bucaramanga之间的距离:
- 拉特:7.08594109039762
- lng:286.95225338731285
- 拉特:7.88475514
- lng:-72.49432589
// Outputs: 107.76, distance in km between the given coordinatesecho getDistanceBetweenPointsNew(7.08594109039762, 286.95225338731285, 7.88475514, -72.49432589, 'Km');
了解了这一点, 我们将对SQL进行相同的操作, 这将在查询中为我们提供一个新列, 即距离, 该列包含来自给定坐标的值。如果你以公里或英里为单位, 则实现此目的的SQL查询将有所不同:
A.搜索公里
--- Where: --- $LATITUDE = the latitude of the start point e.g 7.08594109039762;
--- $LONGITUDE = the longitude of the start point e.g 286.95225338731285;
--- $DISTANCE_KILOMETERS = your radius of search in Kilometers e.g 150SELECT * FROM (SELECT *, (((acos(sin(( $LATITUDE * pi() / 180))*sin(( `latitud_fieldname` * pi() / 180)) + cos(( $LATITUDE * pi() /180 ))*cos(( `latitud_fieldname` * pi() / 180)) * cos((( $LONGITUDE - `longitude_fieldname`) * pi()/180)))) * 180/pi()) * 60 * 1.1515 * 1.609344)as distance FROM `myTable`) myTableWHERE distance <
= $DISTANCE_KILOMETERSLIMIT 15;
B.英里搜索
--- Where: --- $LATITUDE = the latitude of the start point e.g 7.08594109039762;
--- $LONGITUDE = the longitude of the start point e.g 286.95225338731285;
--- $DISTANCE_MILES = your radius of search in Miles e.g 150SELECT * FROM (SELECT *, (((acos(sin(( $LATITUDE * pi() / 180))*sin(( `latitud_fieldname` * pi() / 180)) + cos(( $LATITUDE * pi() /180 ))*cos(( `latitud_fieldname` * pi() / 180)) * cos((( $LONGITUDE - `longitude_fieldname`) * pi()/180)))) * 180/pi()) * 60 * 1.1515)as distance FROM `myTable`) myTableWHERE distance <
= $DISTANCE_MILESLIMIT 15;
4.测试查询 现在我们有了搜索半径距离, 我们最终可以测试查询以替换值并简单地运行它(在屏幕快照中, 我们使用140.85而不是150, 但基本相同):
现在, 使用给定的值, 我们的查询总共以图形和数学方式完全匹配了3个与搜索匹配的位置。你最终可以使用PHP运行查询, 以根据需要处理结果:
<
?php$servername = "localhost";
$username = "root";
$password = "";
$dbname = "test";
// Create connection$conn = new mysqli($servername, $username, $password, $dbname);
mysqli_set_charset($conn, "utf8");
// Check connectionif ($conn->
connect_error) {die("Connection failed: " . $conn->
connect_error);
}// Bucaramanga Coordinates$lat = 7.08594109039762;
$lon = 286.95225338731285;
// Only show places within 100km$distance = 150;
$lat = mysqli_real_escape_string($conn, $lat);
$lon = mysqli_real_escape_string($conn, $lon);
$distance = mysqli_real_escape_string($conn, $distance);
$query = <
<
<
EOFSELECT * FROM (SELECT *, (((acos(sin(( $lat * pi() / 180))*sin(( `lat` * pi() / 180)) + cos(( $lat * pi() /180 ))*cos(( `lat` * pi() / 180)) * cos((( $lon - `lng`) * pi()/180)))) * 180/pi()) * 60 * 1.1515 * 1.609344)as distance FROM `markers`) markersWHERE distance <
= $distanceLIMIT 15;
EOF;
$result = $conn->
query($query);
if ($result->
num_rows >
0) {// output data of each rowwhile($row = $result->
fetch_assoc()) {echo $row["name"] . "<
br>
";
}}// Outputs:// Barrancabermeja// Cúcuta// San Gil
编码愉快!
推荐阅读
- 如何在JavaScript中使用Fabric.js创建自己的T恤设计器
- 如何使用CoconutBattery 3确定Mac的生产年份
- 如何使用Android Five Stars库向Android应用程序添加”为我的应用评分”对话框
- Android的演变(从开始到2019年的旅程)
- 常见的Java学习错误以及如何解决它们
- 如何在Java中操作KeePass数据库(kdbx)
- 如何使用ACE Editor将文本插入特定位置
- 如何在Laravel 5.4中实现PHP调试栏
- Linux基础_李孟_新浪博客