根据经纬度判断坐标点在哪个区域范围内(高德可用 别的没有测试)

 $area = array(
        0 => array(
            array('x'=>115.5225419, 'y'=>38.2166756),
            array('x'=>115.4841541, 'y'=>38.2174511),
            array('x'=>115.4828238,'y'=>38.2300603),
            array('x'=>116.448455,'y'=>40.050818),
            array('x'=>116.448275,'y'=>40.038307),
            array('x'=>116.441448,'y'=>40.038418),
            array('x'=>116.436058,'y'=>40.038804),
            array('x'=>116.417302,'y'=>40.039136),
            array('x'=>116.414822,'y'=>40.039384),
            array('x'=>116.412738,'y'=>40.039329),
            array('x'=>116.407672,'y'=>40.039329),
            array('x'=>116.388628,'y'=>40.085162),
            array('x'=>116.383633,'y'=>40.084997)
        ),
        1 => array(
            array('x'=>116.358804,'y'=>40.028474),
            array('x'=>116.41608, 'y'=>40.02875),
            array('x'=>116.41723, 'y'=>40.038915),
            array('x'=>116.447988,'y'=>40.037921),
            array('x'=>116.447844,'y'=>40.026761),
            array('x'=>116.455821,'y'=>40.024164),
            array('x'=>116.446281,'y'=>39.994736),
            array('x'=>116.443532,'y'=>39.995372),
            array('x'=>116.376267,'y'=>39.993493),
            array('x'=>116.375908,'y'=>40.000015),
            array('x'=>116.372027,'y'=>39.999904),
            array('x'=>116.371452,'y'=>40.007366),
            array('x'=>116.359451,'y'=>40.006758)
        ),
        2 => array(
            array('x'=>116.46387, 'y'=>40.021125),
            array('x'=>116.484495,'y'=>40.020462),
            array('x'=>116.515684,'y'=>39.995151),
            array('x'=>116.51519, 'y'=>39.976137),
            array('x'=>116.491906,'y'=>39.972985),
            array('x'=>116.476239,'y'=>39.977298),
            array('x'=>116.467472,'y'=>39.96917),
            array('x'=>116.443325,'y'=>39.984817),
            array('x'=>116.449506,'y'=>39.993109),
            array('x'=>116.446357,'y'=>39.994736),
            array('x'=>116.456037,'y'=>40.024109)
        ),
        3 => array(
            array('x'=>116.496424,'y'=>39.96253),
            array('x'=>116.479527,'y'=>39.975491),
            array('x'=>116.492921,'y'=>39.972491),
            array('x'=>116.508533,'y'=>39.974454),
            array('x'=>116.535231,'y'=>39.980225),
            array('x'=>116.553485,'y'=>39.975691),
            array('x'=>116.564624,'y'=>39.975028),
            array('x'=>116.571307,'y'=>39.972097),
            array('x'=>116.571666,'y'=>39.946989),
            array('x'=>116.547736,'y'=>39.947763),
            array('x'=>116.549245,'y'=>39.936755),
            array('x'=>116.564624,'y'=>39.937142),
            array('x'=>116.569367,'y'=>39.92995),
            array('x'=>116.570085,'y'=>39.915175),
            array('x'=>116.496424,'y'=>39.914843)
        ),	
        4 => array(
            array('x'=>116.24763, 'y'=>39.978677),
            array('x'=>116.280975,'y'=>39.976244),
            array('x'=>116.322872,'y'=>39.991226),
            array('x'=>116.323231,'y'=>39.986859),
            array('x'=>116.339975,'y'=>39.986859),
            array('x'=>116.340263,'y'=>39.982215),
            array('x'=>116.346443,'y'=>39.98216),
            array('x'=>116.354492,'y'=>39.963415),
            array('x'=>116.361822,'y'=>39.963637),
            array('x'=>116.362397,'y'=>39.957664),
            array('x'=>116.37792, 'y'=>39.958106),
            array('x'=>116.37138, 'y'=>39.929728),
            array('x'=>116.367068,'y'=>39.929341),
            array('x'=>116.366637,'y'=>39.924361),
            array('x'=>116.37138, 'y'=>39.924361),
            array('x'=>116.369655,'y'=>39.913626),
            array('x'=>116.362325,'y'=>39.912962),
            array('x'=>116.363188,'y'=>39.903774),
            array('x'=>116.317194,'y'=>39.902999),
            array('x'=>116.259415,'y'=>39.902778)
        ),
)
$area = new Area($newarea);
$scale = $area->checkPoint(115.4898400,38.2338860); 

在area中判断:

<?php

class Area {
    protected $config = null;

    // 包含每个区域的四边形
    protected $rectangles = null;

    // 每个区域(多边形)的所有边
    protected $lines = null;

    // 要判断的点的x, y坐标
    protected $_x = null;
    protected $_y = null;

    public function __construct($config){
        $this->config = $config;
        $this->initRectangles();
        $this->initLines();
    }

    /*
        获取包含每个配送区域的四边形
    */
    private function initRectangles(){
        foreach ($this->config as $k => $v) {
            $this->rectangles[$k]['minX'] = $this->getMinXInEachConfig($k);
            $this->rectangles[$k]['minY'] = $this->getMinYInEachConfig($k);
            $this->rectangles[$k]['maxX'] = $this->getMaxXInEachConfig($k);
            $this->rectangles[$k]['maxY'] = $this->getMaxYInEachConfig($k);
        }
    }

    /*
        初始化每个区域(多边形)的边(线段:直线的一部分【限制x或者y坐标范围】)
        n 个顶点构成的多边形,有 n-1 条边
    */
    private function initLines(){
        foreach ($this->config as $k => $v) {
            $pointNum = count($v);        // 区域的顶点个数
            $lineNum = $pointNum - 1;     // 区域的边条数
            for($i=0; $i<$lineNum; $i++){
                // y=kx+b : k
                if($this->config[$k][$i]['x'] - $this->config[$k][$i+1]['x'] == 0) $this->lines[$k][$i]['k'] = 0;
                else $this->lines[$k][$i]['k'] =
                    ($this->config[$k][$i]['y'] - $this->config[$k][$i+1]['y'])/($this->config[$k][$i]['x'] - $this->config[$k][$i+1]['x']);
                // y=kx+b : b
                $this->lines[$k][$i]['b'] = $this->config[$k][$i+1]['y'] - $this->lines[$k][$i]['k'] * $this->config[$k][$i+1]['x'];
                $this->lines[$k][$i]['lx'] = min($this->config[$k][$i]['x'], $this->config[$k][$i+1]['x']);
                $this->lines[$k][$i]['rx'] = max($this->config[$k][$i]['x'], $this->config[$k][$i+1]['x']);
            }
            $pointNum-=1;
            if($this->config[$k][$pointNum]['x'] - $this->config[$k][0]['x'] == 0) $this->lines[$k][$pointNum]['k'] = 0;
            else $this->lines[$k][$pointNum]['k'] =
                ($this->config[$k][$pointNum]['y'] - $this->config[$k][0]['y'])/($this->config[$k][$pointNum]['x'] - $this->config[$k][0]['x']);
            // y=kx+b : b
            $this->lines[$k][$pointNum]['b'] = $this->config[$k][0]['y'] - $this->lines[$k][$pointNum]['k'] * $this->config[$k][0]['x'];
            $this->lines[$k][$pointNum]['lx'] = min($this->config[$k][$pointNum]['x'], $this->config[$k][0]['x']);
            $this->lines[$k][$pointNum]['rx'] = max($this->config[$k][$pointNum]['x'], $this->config[$k][0]['x']);
        }
    }

    /*
        获取一组坐标中,x坐标最小值
    */
    private function getMinXInEachConfig($index){
        $minX = 200;
        foreach ($this->config[$index] as $k => $v) {
            if($v['x'] < $minX){
                $minX = $v['x'];
            }
        }
        return $minX;
    }

    /*
        获取一组坐标中,y坐标最小值
    */
    private function getMinYInEachConfig($index){
        $minY = 200;
        foreach ($this->config[$index] as $k => $v) {
            if($v['y'] < $minY){
                $minY = $v['y'];
            }
        }
        return $minY;
    }

    /*
        获取一组坐标中,x坐标最大值
    */
    public function getMaxXInEachConfig($index){
        $maxX = 0;
        foreach ($this->config[$index] as $k => $v) {
            if($v['x'] > $maxX){
                $maxX = $v['x'];
            }
        }
        return $maxX;
    }

    /*
        获取一组坐标中,y坐标最大值
    */
    public function getMaxYInEachConfig($index){
        $maxY = 0;
        foreach ($this->config[$index] as $k => $v) {
            if($v['y'] > $maxY){
                $maxY = $v['y'];
            }
        }
        return $maxY;
    }

    /*
        获取 y=y0 与特定区域的所有边的交点,并去除和顶点重复的,再将交点分为左和右两部分
    */
    private function getCrossPointInCertainConfig($index){
        $crossPoint = null;
        foreach ($this->lines[$index] as $k => $v) {
            if($v['k'] == 0) return true;
            $x0 = ($this->_y - $v['b']) / $v['k'];    // 交点x坐标
            if($x0 == $this->_x) return true;        // 点在边上
            if($x0 > $v['lx'] && $x0 < $v['rx']){
                if($x0 < $this->_x) $crossPoint['left'][] = $x0;
                if($x0 > $this->_x) $crossPoint['right'][] = $x0;
            }
        }
        return $crossPoint;
    }

    protected function inPoint($k, $x, $y) {
        $in  = false;
        $p   = $this->config[$k];
        $num = count($p);

        for ($i = 0, $j = $num - 1; $i < $num; $j = $i++) {
            if (
                ($p[$i]['y'] > $y) !== ($p[$j]['y'] > $y)
                && $x < ($p[$j]['x'] - $p[$i]['x']) * ($y - $p[$i]['y']) / ($p[$j]['y'] - $p[$i]['y']) + $p[$i]['x']
            ) {
                $in = !$in;
            }
        }

        return $in;
    }

    /*
        检测一个点,是否在区域内
        返回结果:
            return === false : 点不在区域内
            return 0, 1, 2, 3 ... 点所在的区域编号(配置文件中的区域编号。)
    */
    public function checkPoint($x, $y){
        $this->_x = $x;
        $this->_y = $y;


        $contain = [];
        foreach ($this->rectangles as $k => $v) {
            if($x > $v['maxX'] || $x < $v['minX'] || $y > $v['maxY'] || $y < $v['minY']){
                continue;
            }elseif($this->inPoint($k, $x, $y)){
                array_push($contain, $k);
            }
        }

        return $contain;

    }
}

因为我这个可能会有重叠的 所以返回的是个一位数组。

这个是在别人的基础上修改的    目前测试的正确的。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值