计算机与数学是息息相关的,计算机模型中无时无刻不体现数学的理念。例如余弦定理用来求两个文案的相似度。今天我这里解决的问题也与数学有关。实际需求是这样的,在项目当中,需要人工在百度地图中划分配送区域,要求划分出来的区域不能是杂乱无章的,即线段与线段之间不能相穿。当时接到这个需求有点懵逼,如何是好,开完会坐下来,慢慢画图发现划出的图形只要是凹凸多边形即可,突然茅塞顿开,问题迎刃而解,因为规则的凹凸多边形的顶点数与边数相等,根据这段理念简单写了一段验证,结果验证无误。
用对象的方式实现代码逻辑:
<?php
/**
* 平面点
*
* Class Point2D
*/
class Point2D
{
public $x;
public $y;
public function __construct($x, $y)
{
$this->x = $x;
$this->y = $y;
}
public function __toString()
{
return "({$this->x}, {$this->y})";
}
}
/**
* 平面线
*
* Class Line2D
*/
class Line2D
{
/**
* @var Point2D
*/
public $p1;
/**
* @var Point2D
*/
public $p2;
public function __construct(Point2D $p1, Point2D $p2)
{
$this->p1 = $p1;
$this->p2 = $p2;
}
public function __toString()
{
return "({$this->p1}, {$this->p2})";
}
}
/**
* 平面向量
*
* Class Vector
*/
class Vector extends Line2D
{
/**
* 向量
*
* @var Point2D
*/
public $v;
public function __construct(Point2D $p1, Point2D $p2)
{
parent::__construct($p1, $p2);
$this->v = new Point2D($p2->x - $p1->x, $p2->y - $p1->y);
}
public function __toString()
{
return "({$this->p1}->{$this->p2})";
}
/**
* 向量叉积
*
* @param Vector $v1
* @param Vector $v2
* @return Vector
*/
public static function mul(Vector $v1, Vector $v2)
{
return $v1->v->x * $v2->v->y - $v2->v->x * $v1->v->y;
}
}
public function checkMapIsRegular($aPoint)
{
$aFormatPoint = array();
$aFormatLine = array();
try {
if ($aPoint) {
//拆分出坐标点,初始化坐标对象
foreach ($aPoint as $item) {
list($pointX,$pointY) = explode(',' ,$item);
$aFormatPoint[] = array('x' => $pointX, 'y' => $pointY);
}
//按顺序构成矢量线
$index = count($aFormatPoint) - 1;
foreach ($aFormatPoint as $key=>$point) {
$aFormatLine[]['start'] = $point;
if ($index == $key) {
$aFormatLine[$key]['end'] = $aFormatPoint[0];
} else {
$aFormatLine[$key]['end'] = $aFormatPoint[$key+1];
}
}
$aOutPoint = $aFormatLine;
$edgeCount = 0;
$vertexCount = count($aOutPoint);
array_shift($aFormatLine);
//两两求交点
foreach ($aOutPoint as $key=>$aLine) {
if (empty($aFormatLine)) {
continue;
}
foreach ($aFormatLine as $innerKey => $aInnerLine) {
//初始化坐标对象
$oAPointStart = new Point2D($aOutPoint[$key]['start']['x'],$aOutPoint[$key]['start']['y']);
$oAPointEnd = new Point2D($aOutPoint[$key]['end']['x'],$aOutPoint[$key]['end']['y']);
$oBPointStart = new Point2D($aFormatLine[$innerKey]['start']['x'],$aFormatLine[$innerKey]['start']['y']);
$oBPointEnd = new Point2D($aFormatLine[$innerKey]['end']['x'],$aFormatLine[$innerKey]['end']['y']);
//两两画出矢量线
$vector = new Vector($oAPointStart, $oAPointEnd);
$vABStart = new Vector($oAPointStart, $oBPointStart);
$vABEnd = new Vector($oAPointStart, $oBPointEnd);
$isInterSect1 = false;
$isInterSect2 = false;
if (Vector::mul($vABStart, $vector) * Vector::mul($vABEnd, $vector) <= 0) {
$isInterSect1 = true;
}
$oppositeVector = new Vector($oBPointStart, $oAPointStart);
$oVABStart = new Vector($oBPointStart, $oAPointEnd);
$oVABEnd = new Vector($oBPointStart, $oBPointEnd);
if (Vector::mul($oppositeVector, $oVABEnd) * Vector::mul($oVABStart, $oVABEnd) <= 0) {
$isInterSect2 = true;
}
if ($isInterSect1 && $isInterSect2) {
$edgeCount += 1;
}
}
array_shift($aFormatLine);
}
}
if ($edgeCount == $vertexCount) {
return true;
} else {
return false;
}
}catch (\Exception $e) {
return $e->getMessage();
}
}
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。