Your IP : 172.70.127.68


Current Path : /var/www/element/data/www/revenuestory.ru/bitrix/modules/location/lib/geometry/type/
Upload File :
Current File : /var/www/element/data/www/revenuestory.ru/bitrix/modules/location/lib/geometry/type/polygon.php

<?php

namespace Bitrix\Location\Geometry\Type;

class Polygon extends Collection
{
	/**
	 * @inherit
	 */
	public function contains(BaseGeometry $geometry): ?bool
	{
		if (!$geometry instanceof Point)
		{
			return null;
		}

		if (!isset($this->components[0]))
		{
			return null;
		}

		/** @var LineString $outerRing */
		$outerRing = $this->components[0];
		if (!$this->isPointInsideClosedRing($outerRing, $geometry))
		{
			return false;
		}

		$innerRings = array_slice($this->components, 1);
		foreach ($innerRings as $innerRing)
		{
			if ($this->isPointInsideClosedRing($innerRing, $geometry))
			{
				return false;
			}
		}

		return true;
	}

	/**
	 * @param LineString $lineString
	 * @param Point $point
	 * @return bool
	 *
	 * @see https://github.com/mjaschen/phpgeo
	 */
	private function isPointInsideClosedRing(LineString $lineString, Point $point): bool
	{
		$polygonContainsPoint = false;

		$componentsCount = $lineString->getComponentsCount();

		$lineStringPoints = $lineString->getComponents();
		$lineStringLats = [];
		$lineStringLngs = [];

		/** @var Point $point */
		foreach ($lineStringPoints as $lineStringPoint)
		{
			$lineStringLats[] = $lineStringPoint->getLat();
			$lineStringLngs[] = $lineStringPoint->getLng();
		}

		for ($node = 0, $altNode = $componentsCount - 1; $node < $componentsCount; $altNode = $node++)
		{
			$condition = ($lineStringLngs[$node] > $point->getLng()) !== ($lineStringLngs[$altNode] > $point->getLng())
				&& ($point->getLat() < ($lineStringLats[$altNode] - $lineStringLats[$node])
					* ($point->getLng() - $lineStringLngs[$node])
					/ ($lineStringLngs[$altNode] - $lineStringLngs[$node]) + $lineStringLats[$node]);

			if ($condition)
			{
				$polygonContainsPoint = !$polygonContainsPoint;
			}
		}

		return $polygonContainsPoint;
	}
}