欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

判断一个点是否在某个区域内。百度,高德,腾讯都能用。(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));?>


版权声明:本文为博主原创文章,未经博主允许不得转载。