PHP实现搜索地理位置及计算两点地理位置间距离的实例


Posted in PHP onJanuary 08, 2016

地理位置搜寻
LBS,存储每个地点的经纬度坐标,搜寻附近的地点,建立地理位置索引可提高查询效率。
mongodb地理位置索引,2d和2dsphere,对应平面和球面。

1.创建lbs集合存放地点坐标

use lbs; 
 
db.lbs.insert( 
  { 
    loc:{ 
      type: "Point", 
      coordinates: [113.332264, 23.156206] 
    }, 
    name: "广州东站" 
  } 
) 
 
db.lbs.insert( 
  { 
    loc:{ 
      type: "Point", 
      coordinates: [113.330611, 23.147234] 
    }, 
    name: "林和西" 
  } 
) 
 
db.lbs.insert( 
  { 
    loc:{ 
      type: "Point", 
      coordinates: [113.328095, 23.165376] 
    }, 
    name: "天平架" 
  } 
)

2.创建地理位置索引

db.lbs.ensureIndex( 
  { 
    loc: "2dsphere" 
  } 
)

3.查询附近的坐标
当前位置为:时代广场,
坐标:

113.323568, 23.146436

搜寻附近一公里内的点,由近到远排序

db.lbs.find( 
  { 
    loc: { 
      $near:{ 
        $geometry:{ 
          type: "Point", 
          coordinates: [113.323568, 23.146436] 
        }, 
        $maxDistance: 1000 
      } 
    } 
  } 
)

搜寻结果:

{ "_id" : ObjectId("556a651996f1ac2add8928fa"), "loc" : { "type" : "Point", "coordinates" : [ 113.330611, 23.147234 ] }, "name" : "林和西" } 

php代码如下:

<?php 
// 连接mongodb 
function conn($dbhost, $dbname, $dbuser, $dbpasswd){ 
  $server = 'mongodb://'.$dbuser.':'.$dbpasswd.'@'.$dbhost.'/'.$dbname; 
  try{ 
    $conn = new MongoClient($server); 
    $db = $conn->selectDB($dbname); 
  } catch (MongoException $e){ 
    throw new ErrorException('Unable to connect to db server. Error:' . $e->getMessage(), 31); 
  } 
  return $db; 
} 
 
// 插入坐标到mongodb 
function add($dbconn, $tablename, $longitude, $latitude, $name){ 
  $index = array('loc'=>'2dsphere'); 
  $data = array( 
      'loc' => array( 
          'type' => 'Point', 
          'coordinates' => array(doubleval($longitude), doubleval($latitude)) 
      ), 
      'name' => $name 
  ); 
  $coll = $dbconn->selectCollection($tablename); 
  $coll->ensureIndex($index); 
  $result = $coll->insert($data, array('w' => true)); 
  return (isset($result['ok']) && !empty($result['ok'])) ? true : false; 
} 
 
// 搜寻附近的坐标 
function query($dbconn, $tablename, $longitude, $latitude, $maxdistance, $limit=10){ 
  $param = array( 
    'loc' => array( 
      '$nearSphere' => array( 
        '$geometry' => array( 
          'type' => 'Point', 
          'coordinates' => array(doubleval($longitude), doubleval($latitude)),  
        ), 
        '$maxDistance' => $maxdistance*1000 
      ) 
    ) 
  ); 
 
  $coll = $dbconn->selectCollection($tablename); 
  $cursor = $coll->find($param); 
  $cursor = $cursor->limit($limit); 
   
  $result = array(); 
  foreach($cursor as $v){ 
    $result[] = $v; 
  }  
 
  return $result; 
} 
 
$db = conn('localhost','lbs','root','123456'); 
 
// 随机插入100条坐标纪录 
for($i=0; $i<100; $i++){ 
  $longitude = '113.3'.mt_rand(10000, 99999); 
  $latitude = '23.15'.mt_rand(1000, 9999); 
  $name = 'name'.mt_rand(10000,99999); 
  add($db, 'lbs', $longitude, $latitude, $name); 
} 
 
// 搜寻一公里内的点 
$longitude = 113.323568; 
$latitude = 23.146436; 
$maxdistance = 1; 
$result = query($db, 'lbs', $longitude, $latitude, $maxdistance); 
print_r($result); 
?>

演示php代码,首先需要在mongodb的lbs中创建用户和执行auth。方法如下:

use lbs; 
db.createUser( 
  { 
    "user":"root", 
    "pwd":"123456", 
    "roles":[] 
  } 
) 
 
db.auth( 
  { 
    "user":"root", 
    "pwd":"123456" 
  } 
)

计算两点地理坐标的距离
功能:根据圆周率和地球半径系数与两点坐标的经纬度,计算两点之间的球面距离。

获取两点坐标距离:

<?php
/**
 * 计算两点地理坐标之间的距离
 * @param Decimal $longitude1 起点经度
 * @param Decimal $latitude1 起点纬度
 * @param Decimal $longitude2 终点经度 
 * @param Decimal $latitude2 终点纬度
 * @param Int   $unit    单位 1:米 2:公里
 * @param Int   $decimal  精度 保留小数位数
 * @return Decimal
 */
function getDistance($longitude1, $latitude1, $longitude2, $latitude2, $unit=2, $decimal=2){

  $EARTH_RADIUS = 6370.996; // 地球半径系数
  $PI = 3.1415926;

  $radLat1 = $latitude1 * $PI / 180.0;
  $radLat2 = $latitude2 * $PI / 180.0;

  $radLng1 = $longitude1 * $PI / 180.0;
  $radLng2 = $longitude2 * $PI /180.0;

  $a = $radLat1 - $radLat2;
  $b = $radLng1 - $radLng2;

  $distance = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1) * cos($radLat2) * pow(sin($b/2),2)));
  $distance = $distance * $EARTH_RADIUS * 1000;

  if($unit==2){
    $distance = $distance / 1000;
  }

  return round($distance, $decimal);

}

// 起点坐标
$longitude1 = 113.330405;
$latitude1 = 23.147255;

// 终点坐标
$longitude2 = 113.314271;
$latitude2 = 23.1323;

$distance = getDistance($longitude1, $latitude1, $longitude2, $latitude2, 1);
echo $distance.'m'; // 2342.38m

$distance = getDistance($longitude1, $latitude1, $longitude2, $latitude2, 2);
echo $distance.'km'; // 2.34km

?>
PHP 相关文章推荐
真正面向对象编程:PHP5.01发布
Oct 09 PHP
php面向对象全攻略 (六)__set() __get() __isset() __unset()的用法
Sep 30 PHP
zen cart新进商品的随机排序修改方法
Sep 10 PHP
for循环连续求和、九九乘法表代码
Feb 20 PHP
php添加文章时生成静态HTML文章的实现代码
Feb 17 PHP
PHP函数microtime()用法与说明
Dec 04 PHP
在html文件中也可以执行php语句的方法
Apr 09 PHP
Thinkphp框架开发移动端接口(1)
Aug 18 PHP
php版阿里大于(阿里大鱼)短信发送实例详解
Nov 30 PHP
PHP实现对xml进行简单的增删改查(CRUD)操作示例
May 19 PHP
PHP实现的多维数组排序算法分析
Feb 10 PHP
Laravel框架Eloquent ORM删除数据操作示例
Dec 03 PHP
PHP使用数组依次替换字符串中匹配项
Jan 08 #PHP
PHP 7.0.2 正式版发布
Jan 08 #PHP
深入浅析php中sprintf与printf函数的用法及区别
Jan 08 #PHP
PHP中each与list用法分析
Jan 08 #PHP
PHP中list()函数用法实例简析
Jan 08 #PHP
PHP图像裁剪缩略裁切类源码及使用方法
Jan 07 #PHP
PHP中substr_count()函数获取子字符串出现次数的方法
Jan 07 #PHP
You might like
关于时间计算的结总
2006/12/06 PHP
用ADODB来让PHP操作ACCESS数据库的方法
2006/12/31 PHP
PHP校验ISBN码的函数代码
2011/01/17 PHP
PHP得到mssql的存储过程的输出参数功能实现
2012/11/23 PHP
php从文件夹随机读取文件的方法
2015/06/01 PHP
WordPress迁移时一些常见问题的解决方法整理
2015/11/24 PHP
ThinkPHP3.2.2实现持久登录(记住我)功能的方法
2016/05/16 PHP
laravel5.1 ajax post 传值_token示例
2019/10/24 PHP
破除网页鼠标右键被禁用的绝招大全
2006/12/27 Javascript
javascript 字符串连接的性能问题(多浏览器)
2008/11/18 Javascript
javascript获取作用在元素上面的样式属性代码
2012/09/20 Javascript
js和as的稳定传值问题解决
2013/07/14 Javascript
如何实现textarea里的不同文本显示不同颜色
2014/01/20 Javascript
一个JS函数搞定网页标题(title)闪动效果
2014/05/13 Javascript
JavaScript编写推箱子游戏
2015/07/07 Javascript
jquery实现两边飘浮可关闭的对联广告
2015/11/27 Javascript
JQuery实现简单的服务器轮询效果实例
2016/03/31 Javascript
Vue.js每天必学之指令系统与自定义指令
2016/09/07 Javascript
JS获取IE版本号与HTML设置IE文档模式的方法
2016/10/09 Javascript
angular4中关于表单的校验示例
2017/10/16 Javascript
浅谈Node.js爬虫之网页请求模块
2018/01/11 Javascript
vue.js实现三级菜单效果
2019/10/19 Javascript
使用python的chardet库获得文件编码并修改编码
2014/01/22 Python
Python中的迭代器与生成器高级用法解析
2016/06/28 Python
pandas数据集的端到端处理
2019/02/18 Python
在django admin详情表单显示中添加自定义控件的实现
2020/03/11 Python
Python连接mysql方法及常用参数
2020/09/01 Python
谈一谈HTML5本地存储技术
2016/03/02 HTML / CSS
生物化学研究助理员求职信
2013/10/09 职场文书
初中生学习的自我评价
2013/11/14 职场文书
中小学生学籍证明
2014/10/25 职场文书
社区党风廉政建设调研报告
2015/01/01 职场文书
干部考核工作总结
2015/08/12 职场文书
班级管理经验交流材料
2015/11/02 职场文书
python机器学习实现oneR算法(以鸢尾data为例)
2022/03/03 Python
oracle设置密码复杂度及设置超时退出的功能
2022/06/28 Oracle