/var/www/vhosts/nabawater/common/helpers
Edit: /var/www/vhosts/nabawater/common/helpers/GeoMetricHelper.php (5514B)
*/
class GeoMetricHelper
{
const SHAPE_TYPE_CIRCLE = 'circle';
const SHAPE_TYPE_POLYGON = 'polygon';
const EARTH_RADIUS = 6371;
/**
* To hold the center of circle's geo points in [latitude, longitude] format
* @var array
*/
private $centerPoint;
/**
* Radius of the circle
* @var double
*/
private $radius;
/**
* To hold the point to check whether the point exits inside the circle.
* which is in [latitude, longitude] format
* @var array
*/
private $point;
/**
* @var
*/
private $shapeType;
/**
* @var
*/
private $shapePoints;
/**
* Holds the instance of GeoMetricHelper to keep the data in the object
* @var GeoMetricHelper
*/
private static $instance;
/**
* Returns the instance of GeoMetricHelper from $instance variable
* @return self
*/
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Sets the given $latitude and $longitude as circle's center point
*
* @param $latitude
* @param $longitude
* @internal param mixed $centerPoint
*/
public function setCenterPoint($latitude, $longitude)
{
$this->centerPoint = [$latitude, $longitude];
return $this;
}
/**
* @param double $radius in meter
*/
public function setRadius($radius)
{
$this->radius = $radius;
return $this;
}
/**
* Sets the given $latitude and $longitude as point to check
* @param $latitude
* @param $longitude
* @internal param array $point
* @return GeoMetricHelper
*/
public function setPoint($latitude, $longitude)
{
$this->point = [$latitude, $longitude];
return $this;
}
/**
* @return bool
*
* @link https://stackoverflow.com/a/12440017/5798881
*/
public function isPointInsideCircle()
{
list($circleLat, $circleLon) = $this->centerPoint;
list($pointLat, $pointLon) = $this->point;
$dLat = deg2rad($pointLat - $circleLat);
$dLon = deg2rad($pointLon - $circleLon);
$a = sin($dLat / 2) * sin($dLat / 2) + cos(deg2rad($circleLat)) * cos(deg2rad($pointLat)) * sin($dLon / 2) * sin($dLon / 2);
$c = 2 * asin(sqrt($a));
return self::EARTH_RADIUS * $c <= $this->radius;
}
/**
* @param $shapePoints
* @return $this
*/
public function setShapePoints($shapePoints)
{
$this->shapePoints = $shapePoints;
return $this;
}
/**
* @param $shapeType
* @return $this
*/
public function setShapeType($shapeType)
{
$this->shapeType = $shapeType;
return $this;
}
/**
* @return int
* @throws InvalidConfigException
*/
public function isPointInsidePolygon()
{
if ($this->shapeType !== self::SHAPE_TYPE_POLYGON) {
throw new InvalidConfigException('Invalid `$shapeType` configuration');
}
if (!is_array($this->shapePoints) || $this->shapePoints === []) {
throw new InvalidConfigException('Invalid `$shapeType` configuration');
}
if ($this->point === null || $this->point === [] || count($this->point) !== 2) {
throw new InvalidConfigException('Invalid `$shapeType` configuration');
}
$shapePoints = $this->shapePoints;
if ($shapePoints[0] !== $shapePoints[count($shapePoints) - 1]) {
$shapePoints[count($shapePoints)] = $shapePoints[0];
}
$j = 0;
$oddNodes = false;
list($y, $x) = $this->point;
$n = count($shapePoints);
for ($i = 0; $i < $n; $i++) {
$j++;
if ($j === $n) {
$j = 0;
}
if ((($shapePoints[$i][0] < $y) && ($shapePoints[$j][0] >= $y)) || (($shapePoints[$j][0] < $y) && ($shapePoints[$i][0] >=
$y))) {
if ($shapePoints[$i][1] + ($y - $shapePoints[$i][0]) / ($shapePoints[$j][0] - $shapePoints[$i][0]) * ($shapePoints[$j][1] -
$shapePoints[$i][1]) < $x) {
$oddNodes = !$oddNodes;
}
}
}
return $oddNodes ? 1 : 0;
}
/**
*
* @return bool
*/
public function isPointInsideGeoMetric()
{
if ($this->shapeType == self::SHAPE_TYPE_POLYGON) {
return $this->isPointInsidePolygon();
}
return $this->isPointInsideCircle();
}
public function NewisPointInsideCircle()
{
list($circleLat, $circleLon) = $this->centerPoint;
list($pointLat, $pointLon) = $this->point;
$dLat = deg2rad($pointLat - $circleLat);
$dLon = deg2rad($pointLon - $circleLon);
$a = sin($dLat / 2) * sin($dLat / 2) + cos(deg2rad($circleLat)) * cos(deg2rad($pointLat)) * sin($dLon / 2) * sin($dLon / 2);
$c = 2 * asin(sqrt($a));
$re = self::EARTH_RADIUS * $c;
$rad = $this->radius/1000;
return self::EARTH_RADIUS * $c <= $rad;
}
}