文档章节

php计算经纬度是否在区域内

o
 osc_o9u1um45
发布于 07/01 11:15
字数 786
阅读 17
收藏 0

精选30+云产品,助力企业轻松上云!>>>

<?php

namespace lib;

/**
* Description of Area
*
* @author lsf
*/
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;
}
}



 

o
粉丝 0
博文 48
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。

暂无文章

switch linux mint 20 apt repository to tsinghua' mirrors

edit file /etc/apt/sources.list.d/cat official-package-repositories.list lwk@qwfys:/etc/apt/sources.list.d$ lltotal 12drwxr-xr-x 2 root root 4096 Jul 5 20:01 ./drwxr-xr-x 7 ......

qwfys
10分钟前
0
0
面试系列之C++的对象布局【建议收藏】

我们都知道C++多态是通过虚函数表来实现的,那具体是什么样的大家清楚吗?开篇依旧提出来几个问题: 普通类对象是什么布局? 带虚函数的类对象是什么布局? 单继承下不含有覆盖函数的类对象是...

伊牙牙嘿哈哈
35分钟前
17
0
OpenCV开发笔记(六十六):红胖子8分钟带你总结形态学操作-膨胀、腐蚀、开运算、闭运算、梯度、顶帽、黑帽(图文并茂+浅显易懂+程序源码)

若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062 本文章博客地址:h...

红模仿_红胖子
39分钟前
12
0
base 64编码用于什么? - What is base 64 encoding used for?

问题: I've heard people talking about "base 64 encoding" here and there. 我听说有人在这里和那里谈论“base 64编码”。 What is it used for? 它是干什么用的? 解决方案: 参考一: ......

技术盛宴
44分钟前
17
0
2020阿里巴巴官方最新Redis开发规范!

本文主要介绍在使用阿里云Redis的开发规范,从下面几个方面进行说明。 键值设计 命令使用 客户端使用 相关工具 通过本文的介绍可以减少使用Redis过程带来的问题。 一、键值设计 1、key名设计...

北柠Java
51分钟前
26
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部