<?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; } }