判斷點是否在多邊形區域內外
阿新 • • 發佈:2020-09-12
原理:
根據數學知識的射線法,射線與幾何多邊形相交的點的個數為奇數則是在幾何內部,偶數在外部;
程式碼:
安裝:
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 */ publicfunction 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 Fairy\Boundary; use Fairy\Point; $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) ? '內' : '外';
參考: