判断一个点是否在某个区域内。百度,高德,腾讯都能用。(php版)
程序员文章站
2024-01-19 20:34:04
...
废话不多说,直接来代码:
array( 0 => array('x' => 116.383698,'y' => 40.08427 ), 1 => array('x' => 116.382836,'y' => 40.095917), 2 => array('x' => 116.397927,'y' => 40.097462), 3 => array('x' => 116.419774,'y' => 40.111314), 4 => array('x' => 116.446256,'y' => 40.106016), 5 => array('x' => 116.448556,'y' => 40.089293), 6 => array('x' => 116.44331, 'y' => 40.061302), 7 => array('x' => 116.428146,'y' => 40.060197), 8 => array('x' => 116.418445,'y' => 40.074664), 9 => array('x' => 116.418876,'y' => 40.080406) ), //亚运村 1 => array( 0 => array('x' => 116.355096,'y' => 40.028575), 1 => array('x' => 116.442268,'y' => 40.027691), 2 => array('x' => 116.462605,'y' => 40.021834), 3 => array('x' => 116.455671,'y' => 40.003709), 4 => array('x' => 116.442735,'y' => 39.984804), 5 => array('x' => 116.423188,'y' => 39.995086), 6 => array('x' => 116.360594,'y' => 39.992378), 7 => array('x' => 116.359588,'y' => 40.003653), 8 => array('x' => 116.34561, 'y' => 40.014319) ), //望京店 2 => array( 0 => array('x' => 116.462605,'y' => 40.021834), 1 => array('x' => 116.454952,'y' => 40.000393), 2 => array('x' => 116.450568,'y' => 39.994644), 3 => array('x' => 116.490597,'y' => 39.968549), 4 => array('x' => 116.506982,'y' => 39.976815), 5 => array('x' => 116.525235,'y' => 39.983616), 6 => array('x' => 116.517618,'y' => 39.994838), 7 => array('x' => 116.493112,'y' => 40.019044), 8 => array('x' => 116.489087,'y' => 40.021088), 9 => array('x' => 116.467241,'y' => 40.020923) ), //大悦城店 3 => array( 0 => array('x' => 116.507036,'y' => 39.976801), 1 => array('x' => 116.525163,'y' => 39.98363), 2 => array('x' => 116.563611,'y' => 39.97235), 3 => array('x' => 116.571803,'y' => 39.975336), 4 => array('x' => 116.576475,'y' => 39.968093), 5 => array('x' => 116.565479,'y' => 39.96707), 6 => array('x' => 116.563683,'y' => 39.964415), 7 => array('x' => 116.544136,'y' => 39.953907), 8 => array('x' => 116.549741,'y' => 39.939968), 9 => array('x' => 116.55046, 'y' => 39.922485), 10 => array('x' => 116.555275,'y' => 39.899738), 11 => array('x' => 116.496561,'y' => 39.899351), 12 => array('x' => 116.496777,'y' => 39.915789), 13 => array('x' => 116.468391,'y' => 39.929401), 14 => array('x' => 116.469253,'y' => 39.9442), 15 => array('x' => 116.466235,'y' => 39.95417) ), //北洼路 4 => array( 0 => array('x' => 116.34561, 'y' => 40.014319), 1 => array('x' => 116.359588,'y' => 40.003653), 2 => array('x' => 116.362822,'y' => 39.935722), 3 => array('x' => 116.259912,'y' => 39.935777), 4 => array('x' => 116.259337,'y' => 39.953423), 5 => array('x' => 116.253228,'y' => 39.968245), 6 => array('x' => 116.254809,'y' => 39.975433), 7 => array('x' => 116.281902,'y' => 39.975765), 8 => array('x' => 116.281759,'y' => 39.998541), 9 => array('x' => 116.306336,'y' => 40.013408) ), //安贞店 5 => array( 0 => array('x' => 116.360809,'y' => 39.992267), 1 => array('x' => 116.385459,'y' => 39.992986), 2 => array('x' => 116.422972,'y' => 39.995086), 3 => array('x' => 116.442232,'y' => 39.984915), 4 => array('x' => 116.429727,'y' => 39.964678), 5 => array('x' => 116.414492,'y' => 39.95959), 6 => array('x' => 116.414923,'y' => 39.955166), 7 => array('x' => 116.378847,'y' => 39.953617), 8 => array('x' => 116.362606,'y' => 39.94875) ), //三元桥 6 => array( 0 => array('x' => 116.450065,'y' => 39.994036), 1 => array('x' => 116.490165,'y' => 39.967719), 2 => array('x' => 116.469181,'y' => 39.955995), 3 => array('x' => 116.447047,'y' => 39.95334), 4 => array('x' => 116.438711,'y' => 39.946814), 5 => array('x' => 116.415426,'y' => 39.946924), 6 => array('x' => 116.41442, 'y' => 39.959424), 7 => array('x' => 116.429943,'y' => 39.96407) ), //团结湖 7 => array( 0 => array('x' => 116.423547,'y' => 39.955), 1 => array('x' => 116.468965,'y' => 39.956216), 2 => array('x' => 116.493399,'y' => 39.963627), 3 => array('x' => 116.496705,'y' => 39.960862), 4 => array('x' => 116.496418,'y' => 39.913174), 5 => array('x' => 116.424409,'y' => 39.908414) ), //劲松店 8 => array( 0 => array('x' => 116.390777,'y' => 39.905702), 1 => array('x' => 116.496418,'y' => 39.913008), 2 => array('x' => 116.496418,'y' => 39.899614), 3 => array('x' => 116.52387, 'y' => 39.89906), 4 => array('x' => 116.520277,'y' => 39.859415), 5 => array('x' => 116.500155,'y' => 39.84457), 6 => array('x' => 116.489806,'y' => 39.850553), 7 => array('x' => 116.478164,'y' => 39.842797), 8 => array('x' => 116.467528,'y' => 39.838808), 9 => array('x' => 116.411977,'y' => 39.838531), 10 => array('x' => 116.410037,'y' => 39.852824), 11 => array('x' => 116.407018,'y' => 39.852159), 12 => array('x' => 116.406659,'y' => 39.863458), 13 => array('x' => 116.393436,'y' => 39.863292) ), //黄村店 9 => array( 0 => array('x' => 116.350533,'y' => 39.8377), 1 => array('x' => 116.358438,'y' => 39.822961), 2 => array('x' => 116.370511,'y' => 39.824181), 3 => array('x' => 116.374536,'y' => 39.800792), 4 => array('x' => 116.372236,'y' => 39.799239), 5 => array('x' => 116.374248,'y' => 39.785712), 6 => array('x' => 116.390633,'y' => 39.787597), 7 => array('x' => 116.396095,'y' => 39.786155), 8 => array('x' => 116.398323,'y' => 39.771073), 9 => array('x' => 116.385531,'y' => 39.768355), 10 => array('x' => 116.349527,'y' => 39.768771), 11 => array('x' => 116.356605,'y' => 39.748636), 12 => array('x' => 116.339178,'y' => 39.74933), 13 => array('x' => 116.336771,'y' => 39.748387), 14 => array('x' => 116.324895,'y' => 39.754225), 15 => array('x' => 116.307935,'y' => 39.780957), 16 => array('x' => 116.311313,'y' => 39.791326), 17 => array('x' => 116.306785,'y' => 39.790882), 18 => array('x' => 116.309085,'y' => 39.809785) ) );/* *** 配置文件(表示区域的三维数组)其内的点,必须按顺时针方向依次给出! *** 确定一点是否在一区域(多边形)内: 1:过这一点(x0, y0),画一水平线(y=y0),与多边形的所有边进行交点判断。 2:获取交点集(其中不含多边形的顶点) 3:若该点(x0, y0)的左侧和右侧交点个数均为奇数个,则该点在区域(多边形)内。否则:不在。 *** 返回结果: return === false : 点不在区域内 return 0, 1, 2, 3 ... 点所在的区域编号(配置文件中的区域编号。) *** Author : Guojunzhou / Eric *** Main : php20141104@163.com */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; $iconfig[$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'] = $this->getMinXInEachConfig($k); $this->lines[$k][$i]['rx'] = $this->getMaxXInEachConfig($k); } } } /* 获取一组坐标中,x坐标最小值 */ private function getMinXInEachConfig($index){ $minX = 200; foreach ($this->config[$index] as $k => $v) { if($v['x'] config[$index] as $k => $v) { if($v['y'] 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) { $x0 = ($this->_y - $v['b']) / $v['k']; // 交点x坐标 if($x0 == $this->_x) return true; // 点在边上 if($x0 _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['maxY'] || $y 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);var_dump($area->checkPoint(116.309085,39.809785));?>
版权声明:本文为博主原创文章,未经博主允许不得转载。