1<?php
2/**
3 * GeoJSON class : a geojson reader/writer.
4 *
5 * Note that it will always return a GeoJSON geometry. This
6 * means that if you pass it a feature, it will return the
7 * geometry of that feature strip everything else.
8 */
9class GeoJSON extends GeoAdapter
10{
11  /**
12   * Given an object or a string, return a Geometry
13   *
14   * @param mixed $input The GeoJSON string or object
15   *
16   * @return object Geometry
17   */
18  public function read($input) {
19    if (is_string($input)) {
20      $input = json_decode($input);
21    }
22    if (!is_object($input)) {
23      throw new Exception('Invalid JSON');
24    }
25    if (!is_string($input->type)) {
26      throw new Exception('Invalid JSON');
27    }
28
29    // Check to see if it's a FeatureCollection
30    if ($input->type == 'FeatureCollection') {
31      $geoms = array();
32      foreach ($input->features as $feature) {
33        $geoms[] = $this->read($feature);
34      }
35      return geoPHP::geometryReduce($geoms);
36    }
37
38    // Check to see if it's a Feature
39    if ($input->type == 'Feature') {
40      return $this->read($input->geometry);
41    }
42
43    // It's a geometry - process it
44    return $this->objToGeom($input);
45  }
46
47  private function objToGeom($obj) {
48    $type = $obj->type;
49
50    if ($type == 'GeometryCollection') {
51      return $this->objToGeometryCollection($obj);
52    }
53    $method = 'arrayTo' . $type;
54    return $this->$method($obj->coordinates);
55  }
56
57  private function arrayToPoint($array) {
58    if (!empty($array)) {
59      return new Point($array[0], $array[1]);
60    }
61    else {
62      return new Point();
63    }
64  }
65
66  private function arrayToLineString($array) {
67    $points = array();
68    foreach ($array as $comp_array) {
69      $points[] = $this->arrayToPoint($comp_array);
70    }
71    return new LineString($points);
72  }
73
74  private function arrayToPolygon($array) {
75    $lines = array();
76    foreach ($array as $comp_array) {
77      $lines[] = $this->arrayToLineString($comp_array);
78    }
79    return new Polygon($lines);
80  }
81
82  private function arrayToMultiPoint($array) {
83    $points = array();
84    foreach ($array as $comp_array) {
85      $points[] = $this->arrayToPoint($comp_array);
86    }
87    return new MultiPoint($points);
88  }
89
90  private function arrayToMultiLineString($array) {
91    $lines = array();
92    foreach ($array as $comp_array) {
93      $lines[] = $this->arrayToLineString($comp_array);
94    }
95    return new MultiLineString($lines);
96  }
97
98  private function arrayToMultiPolygon($array) {
99    $polys = array();
100    foreach ($array as $comp_array) {
101      $polys[] = $this->arrayToPolygon($comp_array);
102    }
103    return new MultiPolygon($polys);
104  }
105
106  private function objToGeometryCollection($obj) {
107    $geoms = array();
108    if (empty($obj->geometries)) {
109      throw new Exception('Invalid GeoJSON: GeometryCollection with no component geometries');
110    }
111    foreach ($obj->geometries as $comp_object) {
112      $geoms[] = $this->objToGeom($comp_object);
113    }
114    return new GeometryCollection($geoms);
115  }
116
117  /**
118   * Serializes an object into a geojson string
119   *
120   *
121   * @param Geometry $obj The object to serialize
122   *
123   * @return string The GeoJSON string
124   */
125  public function write(Geometry $geometry, $return_array = FALSE) {
126    if ($return_array) {
127      return $this->getArray($geometry);
128    }
129    else {
130      return json_encode($this->getArray($geometry));
131    }
132  }
133
134  public function getArray($geometry) {
135    if ($geometry->getGeomType() == 'GeometryCollection') {
136      $component_array = array();
137      foreach ($geometry->components as $component) {
138        $component_array[] = array(
139          'type' => $component->geometryType(),
140          'coordinates' => $component->asArray(),
141        );
142      }
143      return array(
144        'type'=> 'GeometryCollection',
145        'geometries'=> $component_array,
146      );
147    }
148    else return array(
149      'type'=> $geometry->getGeomType(),
150      'coordinates'=> $geometry->asArray(),
151    );
152  }
153}
154
155
156