melder/vendor/Shapefile/Geometry/Point.php

313 lines
7.3 KiB
PHP
Raw Permalink Normal View History

2024-02-16 15:35:01 +01:00
<?php
/**
* PHP Shapefile - PHP library to read and write ESRI Shapefiles, compatible with WKT and GeoJSON
*
* @package Shapefile
* @author Gaspare Sganga
2024-03-13 12:03:56 +01:00
* @version 4.0.0dev
2024-02-16 15:35:01 +01:00
* @license MIT
* @link https://gasparesganga.com/labs/php-shapefile/
*/
namespace Shapefile\Geometry;
use Shapefile\Shapefile;
use Shapefile\ShapefileException;
/**
* Point Geometry.
*
* - Array: [
* [x] => float
* [y] => float
* [z] => float
* [m] => float/bool
* ]
*
* - WKT:
* POINT [Z][M] (x y z m)
*
*
* - GeoJSON:
* {
* "type": "Point" / "PointM"
* "coordinates": [x, y, z] / [x, y, m] / [x, y, z, m]
* }
*/
class Point extends Geometry
{
/**
* WKT and GeoJSON basetypes
*/
const WKT_BASETYPE = 'POINT';
const GEOJSON_BASETYPE = 'Point';
/**
* @var float|null X coordinate
*/
private $x = null;
/**
* @var float|null Y coordinate
*/
private $y = null;
/**
* @var floa|null Z coordinate
*/
private $z = null;
/**
* @var float|bool|null M coordinate
*/
private $m = null;
/////////////////////////////// PUBLIC ///////////////////////////////
/**
* Constructor.
*
* @param float $x X coordinate
* @param float $y Y coordinate
* @param float $z Z coordinate
* @param float|bool $m M coordinate
*/
public function __construct($x = null, $y = null, $z = null, $m = null)
{
$this->init($x, $y, $z, $m);
}
public function initFromArray($array)
{
$this->checkInit();
$this->init(
isset($array['x']) ? $array['x'] : null,
isset($array['y']) ? $array['y'] : null,
isset($array['z']) ? $array['z'] : null,
isset($array['m']) ? $array['m'] : null
);
return $this;
}
public function initFromWKT($wkt)
{
$this->checkInit();
$wkt = $this->wktSanitize($wkt);
if (!$this->wktIsEmpty($wkt)) {
$coordinates = $this->wktParseCoordinates(
$this->wktExtractData($wkt),
$this->wktIsZ($wkt),
$this->wktIsM($wkt)
);
$this->init($coordinates['x'], $coordinates['y'], $coordinates['z'], $coordinates['m']);
}
return $this;
}
public function initFromGeoJSON($geojson)
{
$this->checkInit();
$geojson = $this->geojsonSanitize($geojson);
if ($geojson !== null) {
2024-03-13 12:03:56 +01:00
$coordinates = $this->geojsonParseCoordinates($geojson['coordinates'], $geojson['flag_m']);
2024-02-16 15:35:01 +01:00
$this->init($coordinates['x'], $coordinates['y'], $coordinates['z'], $coordinates['m']);
}
return $this;
}
public function getArray()
{
if ($this->isEmpty()) {
return null;
}
$ret = [
'x' => $this->x,
'y' => $this->y,
];
if ($this->isZ()) {
$ret['z'] = $this->z;
}
if ($this->isM()) {
$ret['m'] = $this->m;
}
return $ret;
}
public function getWKT()
{
$ret = $this->wktInitializeOutput();
if (!$this->isEmpty()) {
$ret .= '(' . implode(' ', $this->getRawArray()) . ')';
}
return $ret;
}
public function getGeoJSON($flag_bbox = false, $flag_feature = false)
{
if ($this->isEmpty()) {
return 'null';
}
return $this->geojsonPackOutput($this->getRawArray(), $flag_bbox, $flag_feature);
}
public function getBoundingBox()
{
if ($this->isEmpty()) {
return null;
}
$ret = $this->getCustomBoundingBox();
if (!$ret) {
$ret = [
'xmin' => $this->x,
'xmax' => $this->x,
'ymin' => $this->y,
'ymax' => $this->y,
];
if ($this->isZ()) {
$ret['zmin'] = $this->z;
$ret['zmax'] = $this->z;
}
if ($this->isM()) {
$ret['mmin'] = $this->m;
$ret['mmax'] = $this->m;
}
}
return $ret;
}
public function getSHPBasetype()
{
return Shapefile::SHAPE_TYPE_POINT;
}
/**
* Gets X coordinate
*
* @return float
*/
public function getX()
{
return $this->x;
}
/**
* Gets Y coordinate
*
* @return float
*/
public function getY()
{
return $this->y;
}
/**
* Gets Z coordinate
*
* @return float
*/
public function getZ()
{
return $this->z;
}
/**
* Gets M coordinate
*
* @return float
*/
public function getM()
{
return $this->m;
}
/**
* @internal
*
* Gets an indexed array of coordinates.
* This is not actually for public use, rather it is used by other classes in the library.
*
* @return array
*/
public function getRawArray()
{
$ret = [];
if (!$this->isEmpty()) {
$ret[] = $this->x;
$ret[] = $this->y;
if ($this->isZ()) {
$ret[] = $this->z;
}
if ($this->isM()) {
$ret[] = $this->m === false ? 0 : $this->m ;
}
}
return $ret;
}
/****************************** PROTECTED ******************************/
protected function getWKTBasetype()
{
return static::WKT_BASETYPE;
}
protected function getGeoJSONBasetype()
{
return static::GEOJSON_BASETYPE;
}
/****************************** PRIVATE ******************************/
/**
* Initializes Geometry with coordinates.
*
* @param float $x X coordinate
* @param float $y Y coordinate
* @param float $z Z coordinate
* @param float|bool $m M coordinate
*
* @return self Returns $this to provide a fluent interface.
*/
private function init($x = null, $y = null, $z = null, $m = null)
{
if ($x === null xor $y === null) {
throw new ShapefileException(Shapefile::ERR_GEOM_POINT_NOT_VALID);
}
if ($x !== null && $y !== null) {
$this->x = $this->validateCoordValue($x);
$this->y = $this->validateCoordValue($y);
$this->setFlagEmpty(false);
if ($z !== null) {
$this->z = $this->validateCoordValue($z);
$this->setFlagZ(true);
}
if ($m !== null) {
$this->m = ($m === false) ? $m : $this->validateCoordValue($m);
$this->setFlagM(true);
}
}
return $this;
}
/**
* Validates a coordinate value.
*
* @param float $value Coordinate value
*
* @return float
*/
private function validateCoordValue($value)
{
if (!is_numeric($value)) {
throw new ShapefileException(Shapefile::ERR_GEOM_COORD_VALUE_NOT_VALID, $value);
}
return floatval($value);
}
}