• 判断一个点是否在某个区域内。百度,高德,腾讯都能用。(php版)


    <?php
    	// *** 配置文件(表示区域的三维数组)其内的点,必须按顺时针方向依次给出!
    	$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)
    		),
    		//大悦城店
    		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)
    		),
    		//安贞店
    		5 => array(
    			array('x'=>116.372171,'y'=>39.993161),
    			array('x'=>116.443676,'y'=>39.994985),
    			array('x'=>116.448419,'y'=>39.993548),
    			array('x'=>116.43807, 'y'=>39.97735),
    			array('x'=>116.438789,'y'=>39.9656),
    			array('x'=>116.440298,'y'=>39.955839),
    			array('x'=>116.42262, 'y'=>39.955673),
    			array('x'=>116.378531,'y'=>39.954815),
    			array('x'=>116.377704,'y'=>39.963941),
    			array('x'=>116.368003,'y'=>39.96383),
    			array('x'=>116.367679,'y'=>39.973341),
    			array('x'=>116.361247,'y'=>39.973479),
    			array('x'=>116.360529,'y'=>39.987025),
    			array('x'=>116.37235, 'y'=>39.987716)  
    		),
    		//三元桥
    		6 => array(
    			array('x'=>116.283706,'y'=>40.114137  ),    
    			array('x'=>116.354995,'y'=>40.121613  ),    
    			array('x'=>116.369081,'y'=>40.114661  ),    
    			array('x'=>116.37871, 'y'=>40.114772  ),   
    			array('x'=>116.380435,'y'=>40.106826  ),    
    			array('x'=>116.385897,'y'=>40.107543  ),    
    			array('x'=>116.389346,'y'=>40.07782   ),   
    			array('x'=>116.370949,'y'=>40.075998  ),    
    			array('x'=>116.37174, 'y'=>40.05739   ),  
    			array('x'=>116.325746,'y'=>40.042643  )  
    		),
    		//团结湖
    		7 => array(
    			array('x'=>116.43189, 'y'=>39.955341),
    			array('x'=>116.440316,'y'=>39.955396),
    			array('x'=>116.438394,'y'=>39.977225),
    			array('x'=>116.442849,'y'=>39.984116),
    			array('x'=>116.467876,'y'=>39.969194),
    			array('x'=>116.476608,'y'=>39.976797),
    			array('x'=>116.494969,'y'=>39.963637),
    			array('x'=>116.496999,'y'=>39.914179),
    			array('x'=>116.433902,'y'=>39.914511)
    		),
    		//劲松店
    		8 => array(
    			array('x'=>116.4053,  'y'=>39.90632  ),
    			array('x'=>116.495418,'y'=>39.911412 ),   
    			array('x'=>116.495418,'y'=>39.87709  ),  
    			array('x'=>116.491322,'y'=>39.854717 ),   
    			array('x'=>116.462432,'y'=>39.851892 ),   
    			array('x'=>116.421362,'y'=>39.852141 ),   
    			array('x'=>116.420895,'y'=>39.863412 ),   
    			array('x'=>116.406809,'y'=>39.863412 ),   
    			array('x'=>116.406881,'y'=>39.863357 )  
    		),
    		//黄村店
    		9 => array(
    			array('x'=>116.280184,'y'=>39.776406 ),  
    			array('x'=>116.314751,'y'=>39.788383 ),  
    			array('x'=>116.337586,'y'=>39.805041 ),  
    			array('x'=>116.353252,'y'=>39.804487 ),  
    			array('x'=>116.356001,'y'=>39.794703 ),  
    			array('x'=>116.364912,'y'=>39.799138 ),  
    			array('x'=>116.367787,'y'=>39.783836 ),  
    			array('x'=>116.378495,'y'=>39.781507 ),  
    			array('x'=>116.383094,'y'=>39.766479 ),  
    			array('x'=>116.388628,'y'=>39.76426  ), 
    			array('x'=>116.387478,'y'=>39.749616 ),  
    			array('x'=>116.383238,'y'=>39.748507 ),  
    			array('x'=>116.385178,'y'=>39.728255 ),  
    			array('x'=>116.352408,'y'=>39.727423 ),  
    			array('x'=>116.335592,'y'=>39.705888 ),  
    			array('x'=>116.301726,'y'=>39.697727 )  
    		)
    	);
    /*
    	*** 配置文件(表示区域的三维数组)其内的点,必须按顺时针方向依次给出!
    	*** 确定一点是否在一区域(多边形)内:
    		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; $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;
    	}
     
    	/*
    		检测一个点,是否在区域内
    		返回结果:
    			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);
    var_dump($area->checkPoint(116.531748,39.944229));
    ?>
    

      

    https://blog.csdn.net/u014290054/article/details/47418065

  • 相关阅读:
    快速排序算法图文详解(模版使用)
    数据库中事务和隔离级别解析
    详解对象的创建,布局,定位,存活判断
    SpringCloud-Ribbon:认识并配置负载均衡
    SpringCloud-Feign:接口式微服务调用
    SpringCloud-Eureka(3)集群配置和了解CAP原则
    SpringCloud-Eureka(2)服务注册与信息配置
    SpringCloud-Eureka(1)认识Eureka和初步配置
    Promise
    es6
  • 原文地址:https://www.cnblogs.com/lxwphp/p/10784922.html
Copyright © 2020-2023  润新知