You are here

abstract class Collection in geoPHP 8

Same name and namespace in other branches
  1. 7 geoPHP/lib/geometry/Collection.class.php \Collection

Collection: Abstract class for compound geometries

A geometry is a collection if it is made up of other component geometries. Therefore everything but a Point is a Collection. For example a LingString is a collection of Points. A Polygon is a collection of LineStrings etc.

Hierarchy

Expanded class hierarchy of Collection

File

geoPHP/lib/geometry/Collection.class.php, line 11

View source
abstract class Collection extends Geometry {
  public $components = array();

  /**
   * Constructor: Checks and sets component geometries
   *
   * @param array $components array of geometries
   */
  public function __construct($components = array()) {
    if (!is_array($components)) {
      throw new Exception("Component geometries must be passed as an array");
    }
    foreach ($components as $component) {
      if ($component instanceof Geometry) {
        $this->components[] = $component;
      }
      else {
        throw new Exception("Cannot create a collection with non-geometries");
      }
    }
  }

  /**
   * Returns Collection component geometries
   *
   * @return array
   */
  public function getComponents() {
    return $this->components;
  }
  public function centroid() {
    if ($this
      ->isEmpty()) {
      return NULL;
    }
    if ($this
      ->geos()) {
      $geos_centroid = $this
        ->geos()
        ->centroid();
      if ($geos_centroid
        ->typeName() == 'Point') {
        return geoPHP::geosToGeometry($this
          ->geos()
          ->centroid());
      }
    }

    // As a rough estimate, we say that the centroid of a colletion is the centroid of it's envelope
    // @@TODO: Make this the centroid of the convexHull
    // Note: Outside of polygons, geometryCollections and the trivial case of points, there is no standard on what a "centroid" is
    $centroid = $this
      ->envelope()
      ->centroid();
    return $centroid;
  }
  public function getBBox() {
    if ($this
      ->isEmpty()) {
      return NULL;
    }
    if ($this
      ->geos()) {
      $envelope = $this
        ->geos()
        ->envelope();
      if ($envelope
        ->typeName() == 'Point') {
        return geoPHP::geosToGeometry($envelope)
          ->getBBOX();
      }
      $geos_ring = $envelope
        ->exteriorRing();
      return array(
        'maxy' => $geos_ring
          ->pointN(3)
          ->getY(),
        'miny' => $geos_ring
          ->pointN(1)
          ->getY(),
        'maxx' => $geos_ring
          ->pointN(1)
          ->getX(),
        'minx' => $geos_ring
          ->pointN(3)
          ->getX(),
      );
    }

    // Go through each component and get the max and min x and y
    $i = 0;
    foreach ($this->components as $component) {
      $component_bbox = $component
        ->getBBox();

      // On the first run through, set the bbox to the component bbox
      if ($i == 0) {
        $maxx = $component_bbox['maxx'];
        $maxy = $component_bbox['maxy'];
        $minx = $component_bbox['minx'];
        $miny = $component_bbox['miny'];
      }

      // Do a check and replace on each boundary, slowly growing the bbox
      $maxx = $component_bbox['maxx'] > $maxx ? $component_bbox['maxx'] : $maxx;
      $maxy = $component_bbox['maxy'] > $maxy ? $component_bbox['maxy'] : $maxy;
      $minx = $component_bbox['minx'] < $minx ? $component_bbox['minx'] : $minx;
      $miny = $component_bbox['miny'] < $miny ? $component_bbox['miny'] : $miny;
      $i++;
    }
    return array(
      'maxy' => $maxy,
      'miny' => $miny,
      'maxx' => $maxx,
      'minx' => $minx,
    );
  }
  public function asArray() {
    $array = array();
    foreach ($this->components as $component) {
      $array[] = $component
        ->asArray();
    }
    return $array;
  }
  public function area() {
    if ($this
      ->geos()) {
      return $this
        ->geos()
        ->area();
    }
    $area = 0;
    foreach ($this->components as $component) {
      $area += $component
        ->area();
    }
    return $area;
  }

  // By default, the boundary of a collection is the boundary of it's components
  public function boundary() {
    if ($this
      ->isEmpty()) {
      return new LineString();
    }
    if ($this
      ->geos()) {
      return $this
        ->geos()
        ->boundary();
    }
    $components_boundaries = array();
    foreach ($this->components as $component) {
      $components_boundaries[] = $component
        ->boundary();
    }
    return geoPHP::geometryReduce($components_boundaries);
  }
  public function numGeometries() {
    return count($this->components);
  }

  // Note that the standard is 1 based indexing
  public function geometryN($n) {
    $n = intval($n);
    if (array_key_exists($n - 1, $this->components)) {
      return $this->components[$n - 1];
    }
    else {
      return NULL;
    }
  }
  public function length() {
    $length = 0;
    foreach ($this->components as $delta => $component) {
      $length += $component
        ->length();
    }
    return $length;
  }
  public function greatCircleLength($radius = 6378137) {
    $length = 0;
    foreach ($this->components as $component) {
      $length += $component
        ->greatCircleLength($radius);
    }
    return $length;
  }
  public function haversineLength() {
    $length = 0;
    foreach ($this->components as $component) {
      $length += $component
        ->haversineLength();
    }
    return $length;
  }
  public function dimension() {
    $dimension = 0;
    foreach ($this->components as $component) {
      if ($component
        ->dimension() > $dimension) {
        $dimension = $component
          ->dimension();
      }
    }
    return $dimension;
  }

  // A collection is empty if it has no components OR all it's components are empty
  public function isEmpty() {
    if (!count($this->components)) {
      return TRUE;
    }
    else {
      foreach ($this->components as $component) {
        if (!$component
          ->isEmpty()) {
          return FALSE;
        }
      }
      return TRUE;
    }
  }
  public function numPoints() {
    $num = 0;
    foreach ($this->components as $component) {
      $num += $component
        ->numPoints();
    }
    return $num;
  }
  public function getPoints() {
    $points = array();
    foreach ($this->components as $component) {
      $points = array_merge($points, $component
        ->getPoints());
    }
    return $points;
  }
  public function equals($geometry) {
    if ($this
      ->geos()) {
      return $this
        ->geos()
        ->equals($geometry
        ->geos());
    }

    // To test for equality we check to make sure that there is a matching point
    // in the other geometry for every point in this geometry.
    // This is slightly more strict than the standard, which
    // uses Within(A,B) = true and Within(B,A) = true
    // @@TODO: Eventually we could fix this by using some sort of simplification
    // method that strips redundant vertices (that are all in a row)
    $this_points = $this
      ->getPoints();
    $other_points = $geometry
      ->getPoints();

    // First do a check to make sure they have the same number of vertices
    if (count($this_points) != count($other_points)) {
      return FALSE;
    }
    foreach ($this_points as $point) {
      $found_match = FALSE;
      foreach ($other_points as $key => $test_point) {
        if ($point
          ->equals($test_point)) {
          $found_match = TRUE;
          unset($other_points[$key]);
          break;
        }
      }
      if (!$found_match) {
        return FALSE;
      }
    }

    // All points match, return TRUE
    return TRUE;
  }
  public function isSimple() {
    if ($this
      ->geos()) {
      return $this
        ->geos()
        ->isSimple();
    }

    // A collection is simple if all it's components are simple
    foreach ($this->components as $component) {
      if (!$component
        ->isSimple()) {
        return FALSE;
      }
    }
    return TRUE;
  }
  public function explode() {
    $parts = array();
    foreach ($this->components as $component) {
      $parts = array_merge($parts, $component
        ->explode());
    }
    return $parts;
  }

  // Not valid for this geometry type
  // --------------------------------
  public function x() {
    return NULL;
  }
  public function y() {
    return NULL;
  }
  public function startPoint() {
    return NULL;
  }
  public function endPoint() {
    return NULL;
  }
  public function isRing() {
    return NULL;
  }
  public function isClosed() {
    return NULL;
  }
  public function pointN($n) {
    return NULL;
  }
  public function exteriorRing() {
    return NULL;
  }
  public function numInteriorRings() {
    return NULL;
  }
  public function interiorRingN($n) {
    return NULL;
  }
  public function pointOnSurface() {
    return NULL;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
Collection::$components public property
Collection::area public function Overrides Geometry::area 2
Collection::asArray public function Overrides Geometry::asArray 1
Collection::boundary public function Overrides Geometry::boundary 2
Collection::centroid public function Overrides Geometry::centroid 1
Collection::dimension public function Overrides Geometry::dimension 2
Collection::endPoint public function Overrides Geometry::endPoint 1
Collection::equals public function Overrides Geometry::equals
Collection::explode public function Overrides Geometry::explode 2
Collection::exteriorRing public function Overrides Geometry::exteriorRing 1
Collection::geometryN public function Overrides Geometry::geometryN
Collection::getBBox public function Overrides Geometry::getBBox
Collection::getComponents public function Returns Collection component geometries
Collection::getPoints public function Overrides Geometry::getPoints
Collection::greatCircleLength public function Overrides Geometry::greatCircleLength 1
Collection::haversineLength public function Overrides Geometry::haversineLength 1
Collection::interiorRingN public function Overrides Geometry::interiorRingN 1
Collection::isClosed public function Overrides Geometry::isClosed 2
Collection::isEmpty public function Overrides Geometry::isEmpty
Collection::isRing public function Overrides Geometry::isRing 1
Collection::isSimple public function Overrides Geometry::isSimple 4
Collection::length public function Overrides Geometry::length 2
Collection::numGeometries public function Overrides Geometry::numGeometries
Collection::numInteriorRings public function Overrides Geometry::numInteriorRings 1
Collection::numPoints public function Overrides Geometry::numPoints 2
Collection::pointN public function Overrides Geometry::pointN 1
Collection::pointOnSurface public function Overrides Geometry::pointOnSurface
Collection::startPoint public function Overrides Geometry::startPoint 1
Collection::x public function Overrides Geometry::x
Collection::y public function Overrides Geometry::y
Collection::__construct public function Constructor: Checks and sets component geometries 1
Geometry::$geom_type protected property 7
Geometry::$geos private property
Geometry::$srid protected property
Geometry::asBinary public function
Geometry::asText public function
Geometry::buffer public function
Geometry::checkValidity public function
Geometry::contains public function
Geometry::convexHull public function
Geometry::coordinateDimension public function
Geometry::coveredBy public function
Geometry::covers public function
Geometry::crosses public function
Geometry::difference public function
Geometry::disjoint public function
Geometry::distance public function
Geometry::envelope public function
Geometry::equalsExact public function
Geometry::geometryType public function
Geometry::geos public function
Geometry::getArea public function
Geometry::getCentroid public function
Geometry::getGeomType public function
Geometry::getGeos public function
Geometry::getSRID public function
Geometry::getX public function
Geometry::getY public function
Geometry::hasZ public function
Geometry::hausdorffDistance public function
Geometry::intersection public function
Geometry::intersects public function
Geometry::is3D public function
Geometry::isMeasured public function
Geometry::m public function
Geometry::out public function
Geometry::overlaps public function
Geometry::project public function
Geometry::relate public function
Geometry::setGeos public function
Geometry::setSRID public function
Geometry::simplify public function
Geometry::SRID public function
Geometry::symDifference public function
Geometry::touches public function
Geometry::union public function
Geometry::within public function
Geometry::z public function 1