1. 程式人生 > 實用技巧 >判斷點是否在多邊形區域內外

判斷點是否在多邊形區域內外

原理:

根據數學知識的射線法,射線與幾何多邊形相交的點的個數為奇數則是在幾何內部,偶數在外部;

程式碼:

安裝:

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 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) ? '內' : '外';

參考:

https://stackoverflow.com/questions/8721406/how-to-determine-if-a-point-is-inside-a-2d-convex-polygon

https://www.cnblogs.com/lxwphp/p/10784592.html