php xy轴点图demo_php实现 计算坐标点在某区域

项目需求:通过地图坐标和区域坐标点集合 判断当前坐标是否在坐标点集合区域中

$area[array] 区域坐标点集合数组

$area = array(//天通苑店

0 => array(array('x'=>116.38295, 'y'=>40.09416),

array('x'=>116.44037, 'y'=>40.095898),

array('x'=>116.448275,'y'=>40.083313),

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)

),);

/**

* 验证坐标点是否在某区域内

* @author xiaoliang <1058436713@qq.com>

* Class validationMap

*/

class InareaAction extends CommonAction {

// 一个表示区域的三维数组

public $config = null;

// 包含每个区域的四边形

public $rectangles = null;

// 每个区域(多边形)的所有边

public $lines = null;

// 要判断的点的x, y坐标

public $_x = null;

public $_y = null;

public function __construct($config){

$this->config = $config;

$this->initRectangles();

$this->initLines();

}

/*

获取包含每个配送区域的四边形

*/

public 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 条边

*/

public function initLines(){

foreach ($this->config as $k => $v) {

$pointNum = count($v);// 区域的顶点个数

$lineNum = $pointNum - 1; // 区域的边条数

for($i=0; $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坐标最小值

*/

public function getMinXInEachConfig($index){

$minX = 200;

foreach ($this->config[$index] as $k => $v) {

if($v['x'] < $minX){

$minX = $v['x'];

}

}

return $minX;

}

/*

获取一组坐标中,y坐标最小值

*/

public 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 与特定区域的所有边的交点,并去除和顶点重复的,再将交点分为左和右两部分

*/

public 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;

}

/*

检测一个点,是否在区域内

返回结果:

return === false : 点不在区域内

return 0, 1, 2, 3 ... 点所在的区域编号(配置文件中的区域编号。)

*/

public function checkPoint($x, $y){

$this->_x = $x;

$this->_y = $y;

$contain = null;

foreach ($this->rectangles as $k => $v) {

if($x > $v['maxX'] || $x < $v['minX'] || $y > $v['maxY'] || $y < $v['minY']){

continue;

}else{

$contain = $k;

break;

}

}

if($contain === null) return false;

$crossPoint = $this->getCrossPointInCertainConfig($contain);

if($crossPoint === true) return $contain;

if(count($crossPoint['left'])%2 == 1 && count($crossPoint['right'])%2 == 1) return $contain;

return false;

}

}

//实例化对象

$area = new Area($area);

//判断坐标点是否在区域中 如果坐标点在某一区域返回区域编号 否则返回false;

var_dump($area->checkPoint(116.531748,39.944229))

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值