原理:
根据数学知识的射线法,射线与几何多边形相交的点的个数为奇数则是在几何内部,偶数在外部;
代码:
安装:
composer require cshaptx4869/boundary
代码示例:
Point.php
<?php namespace Fairy; class Point { public $x; public $y; public function __construct(float $x, float $y) { $this->x = $x; $this->y = $y; } }
Boundary.php
<?php namespace Fairy; class Boundary { private $latitude = 'latitude'; private $longitude = 'longitude'; private static $instance = null; private function __construct() { } private function __clone() { } private function __wakeup() { } /** * @return Boundary */ public static function getInstance() { if (is_null(static::$instance)) { static::$instance = new static(); } return static::$instance; } /** * 设置纬度名 * @param string $key * @return $this */ public function latitudeKey(string $key) { $this->latitude = $key; return $this; } /** * 设置经度名 * @param string $key * @return $this */ public function longitudeKey(string $key) { $this->longitude = $key; return $this; } /** * 检查坐标范围点格式 * @param array $points * @return bool */ public function checkPointRange(array $points) { foreach ($points as $point) { if (!isset($point[$this->latitude]) || !isset($point[$this->longitude])) { return false; } } return true; } /** * 如果给定的点包含在边界内,则返回true * @param Point $point * @param array $points * @return bool */ public function contains(Point $point, array $points) { if (!$this->checkPointRange($points)) { throw new InvalidArgumentException('points data invalid'); } $pointNum = count($points); $result = false; for ($i = 0, $j = $pointNum - 1; $i < $pointNum; $j = $i++) { if ( ($points[$i][$this->longitude] > $point->y) != ($points[$j][$this->longitude] > $point->y) && ($point->x < ($points[$j][$this->latitude] - $points[$i][$this->latitude]) * ($point->y - $points[$i][$this->longitude]) / ($points[$j][$this->longitude] - $points[$i][$this->longitude]) + $points[$i][$this->latitude] ) ) { $result = !$result; } } return $result; } }
run.php
<?php require './vendor/autoload.php'; use FairyBoundary; use FairyPoint; $points = [ ['x' => 9.4, 'y' => 12.04], ['x' => 6.68, 'y' => 8.61], ['x' => 9.05, 'y' => 6.06], ['x' => 6.24, 'y' => 3.87], ['x' => 10.02, 'y' => 2.55], ['x' => 14.06, 'y' => 4.13], ['x' => 4.13, 'y' => 7.56], ['x' => 11.69, 'y' => 8.35], ]; // 9.97, 4.96 在内 // 15.73, 5.62 在外 echo Boundary::getInstance() ->latitudeKey('x') ->longitudeKey('y') ->contains(new Point(9.97, 4.96), $points) ? '内' : '外';
参考: