博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

PHP GPS_tool GPS工具类

Posted on 2020-06-15 09:21  PHP-张工  阅读(421)  评论(0编辑  收藏  举报
<?php

// 地球赤道半径
define('EARTH_RADIUS', 6378137);
define('PI', pi());

///# GPS工具类 zjfree@2017-03-29
class GpsTool
{
    private static function get_rad($d)
    {
        return $d * PI / 180.0;
    }

    /// 获取两个GPS距离
    public static function get_distance($gps1, $gps2)
    {
        $radLat1 = self::get_rad($gps1['lat']);
        $radLat2 = self::get_rad($gps2['lat']);

        $a = $radLat1 - $radLat2;
        $b = self::get_rad($gps1['lon']) - self::get_rad($gps2['lon']);

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

        $s = round($s * EARTH_RADIUS, 2);

        return $s;
    }

    /// GPS向指定方向移动指定距离
    public static function go_angle($gps, $deg, $dist)
    {
        // 经纬度比例
        $rate = cos($gps['lat'] * PI / 180);

        // 1纬度多少米
        $lat_meter = 111111;

        $r = $deg * PI / 180.0;

        $x = sin($r) * $dist;
        $y = cos($r) * $dist;

        $x = $x / $lat_meter / $rate;
        $y = $y / $lat_meter;

        $new_gps = array(
            'lon' => round($gps['lon'] + $x, 8),
            'lat' => round($gps['lat'] + $y, 8),
        );

        return $new_gps;
    }

    /// 判断GPS是否在指定区域内
    public static function check_in_area($gps, $gps_list)
    {
        $px = $gps['lon'];
        $py = $gps['lat'];
        $flag = false;
        
        for($i = 0, $l = count($gps_list), $j = $l - 1; $i < $l; $j = $i, $i++) 
        {
            $sx = $gps_list[$i]['lon'];
            $sy = $gps_list[$i]['lat'];
            $tx = $gps_list[$j]['lon'];
            $ty = $gps_list[$j]['lat'];
        
            // 点与多边形顶点重合
            if(($sx === $px && $sy === $py) || ($tx === $px && $ty === $py)) {
                return true;
            }
        
            // 判断线段两端点是否在射线两侧
            if(($sy < $py && $ty >= $py) || ($sy >= $py && $ty < $py)) {
                // 线段上与射线 Y 坐标相同的点的 X 坐标
                $x = $sx + ($py - $sy) * ($tx - $sx) / ($ty - $sy);
            
                // 点在多边形的边上
                if($x === $px) {
                    return true;
                }
            
                // 射线穿过多边形的边界
                if($x > $px) {
                    $flag = !$flag;
                }
            }
        }
        
        // 射线穿过多边形边界的次数为奇数时点在多边形内
        return $flag;
    }
}