melder/vendor/Shapefile/Geometry/GeometryCollection.php

183 lines
5.5 KiB
PHP
Raw 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
* @version 3.3.0
* @license MIT
* @link https://gasparesganga.com/labs/php-shapefile/
*/
namespace Shapefile\Geometry;
use Shapefile\Shapefile;
use Shapefile\ShapefileException;
/**
* Abstract base class for all Geometry Collections.
* It defines some common public methods and some helper protected functions.
*/
abstract class GeometryCollection extends Geometry
{
/**
* @var \Shapefile\Geometry\Geometry[] The actual geometries in the collection.
* They are enforced to be all of the same type by addGeometry() method.
*/
protected $geometries = [];
/////////////////////////////// ABSTRACT ///////////////////////////////
/**
* Gets the class name of the base geometries in the collection.
*
* @return string
*/
abstract protected function getCollectionClass();
/////////////////////////////// PUBLIC ///////////////////////////////
/**
* Constructor.
*
* @param \Shapefile\Geometry\Geometry[] $geometries Optional array of geometries to initialize the collection.
*/
public function __construct(array $geometries = null)
{
if ($geometries !== null) {
foreach ($geometries as $Geometry) {
$this->addGeometry($Geometry);
}
}
}
public function getBoundingBox()
{
if ($this->isEmpty()) {
return null;
}
$ret = $this->getCustomBoundingBox();
if (!$ret) {
$is_z = $this->isZ();
$is_m = $this->isM();
foreach ($this->geometries as $Geometry) {
$bbox = $Geometry->getBoundingBox();
if (!$ret) {
$ret = $bbox;
} elseif ($bbox) {
if ($bbox['xmin'] < $ret['xmin']) {
$ret['xmin'] = $bbox['xmin'];
}
if ($bbox['xmax'] > $ret['xmax']) {
$ret['xmax'] = $bbox['xmax'];
}
if ($bbox['ymin'] < $ret['ymin']) {
$ret['ymin'] = $bbox['ymin'];
}
if ($bbox['ymax'] > $ret['ymax']) {
$ret['ymax'] = $bbox['ymax'];
}
if ($is_z) {
if ($bbox['zmin'] < $ret['zmin']) {
$ret['zmin'] = $bbox['zmin'];
}
if ($bbox['zmax'] > $ret['zmax']) {
$ret['zmax'] = $bbox['zmax'];
}
}
if ($is_m) {
if ($ret['mmin'] === false || $bbox['mmin'] < $ret['mmin']) {
$ret['mmin'] = $bbox['mmin'];
}
if ($ret['mmax'] === false || $bbox['mmax'] > $ret['mmax']) {
$ret['mmax'] = $bbox['mmax'];
}
}
}
}
}
return $ret;
}
/////////////////////////////// PROTECTED ///////////////////////////////
/**
* Adds a Geometry to the collection.
* It enforces all geometries to be of the same type.
*
* @param \Shapefile\Geometry\Geometry $Geometry
*
* @return self Returns $this to provide a fluent interface.
*/
protected function addGeometry(Geometry $Geometry)
{
if (!is_a($Geometry, $this->getCollectionClass())) {
throw new ShapefileException(Shapefile::ERR_INPUT_GEOMETRY_TYPE_NOT_VALID, $this->getCollectionClass());
}
if (!$Geometry->isEmpty()) {
if ($this->isEmpty()) {
$this->setFlagEmpty(false);
$this->setFlagZ($Geometry->isZ());
$this->setFlagM($Geometry->isM());
} else {
if ($this->isZ() !== $Geometry->isZ() || $this->isM() !== $Geometry->isM()) {
throw new ShapefileException(Shapefile::ERR_GEOM_MISMATCHED_DIMENSIONS);
}
}
$this->geometries[] = $Geometry;
}
return $this;
}
/**
* Gets a Geometry at specified index from the collection.
*
* @param int $index The index of the Geometry.
*
* @return \Shapefile\Geometry\Geometry
*/
protected function getGeometry($index)
{
if (!isset($this->geometries[$index])) {
throw new ShapefileException(Shapefile::ERR_INPUT_GEOMETRY_INDEX_NOT_VALID, $index);
}
return $this->geometries[$index];
}
/**
* Gets all the geometries in the collection.
*
* @return \Shapefile\Geometry\Geometry[]
*/
protected function getGeometries()
{
return $this->geometries;
}
/**
* Gets the number of geometries in the collection.
*
* @return int
*/
protected function getNumGeometries()
{
return count($this->geometries);
}
/**
* Reverses the order of geometries in the collection.
*
* @return self Returns $this to provide a fluent interface.
*/
protected function reverseGeometries()
{
$this->geometries = array_reverse($this->geometries);
return $this;
}
}