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


    地理位置搜寻
    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
     
    ?>
  • 相关阅读:
    Redis的发布订阅
    Redis的事务
    Redis的持久化下
    Redis的持久化上
    Redis数据类型之Redis有序集合Zset(sorted set
    Redis数据类型之Redis哈希(Hash)
    Redis数据类型之Redis集合(Set)
    LeetCode#53-最大子序和
    LeetCode#442-数组中的重复数据
    LeetCode#1014-最佳观光组合
  • 原文地址:https://www.cnblogs.com/ouruola863/p/9205336.html
Copyright © 2020-2023  润新知