Skip to content

Commit 29fd6d9

Browse files
committed
GeoJSON and KML can now deal with empty geometries
1 parent 54eab05 commit 29fd6d9

File tree

2 files changed

+62
-58
lines changed

2 files changed

+62
-58
lines changed

lib/adapters/GeoJSON.class.php

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
33
* GeoJSON class : a geojson reader/writer.
4-
*
4+
*
55
* Note that it will always return a GeoJSON geometry. This
66
* means that if you pass it a feature, it will return the
77
* geometry of that feature strip everything else.
@@ -25,7 +25,7 @@ public function read($input) {
2525
if (!is_string($input->type)) {
2626
throw new Exception('Invalid JSON');
2727
}
28-
28+
2929
// Check to see if it's a FeatureCollection
3030
if ($input->type == 'FeatureCollection') {
3131
$geoms = array();
@@ -34,31 +34,26 @@ public function read($input) {
3434
}
3535
return geoPHP::geometryReduce($geoms);
3636
}
37-
37+
3838
// Check to see if it's a Feature
3939
if ($input->type == 'Feature') {
4040
return $this->read($input->geometry);
4141
}
42-
42+
4343
// It's a geometry - process it
4444
return $this->objToGeom($input);
4545
}
46-
46+
4747
private function objToGeom($obj) {
4848
$type = $obj->type;
49-
49+
5050
if ($type == 'GeometryCollection') {
5151
return $this->objToGeometryCollection($obj);
5252
}
53-
else {
54-
if (empty($obj->coordinates)) {
55-
throw new Exception ('Invalid GeoJSON: missing coordinates');
56-
}
57-
$method = 'arrayTo' . $type;
58-
return $this->$method($obj->coordinates);
59-
}
53+
$method = 'arrayTo' . $type;
54+
return $this->$method($obj->coordinates);
6055
}
61-
56+
6257
private function arrayToPoint($array) {
6358
return new Point($array[0], $array[1]);
6459
}
@@ -102,7 +97,7 @@ private function arrayToMultiPolygon($array) {
10297
}
10398
return new MultiPolygon($polys);
10499
}
105-
100+
106101
private function objToGeometryCollection($obj) {
107102
$geoms = array();
108103
if (empty($obj->geometries)) {
@@ -113,7 +108,7 @@ private function objToGeometryCollection($obj) {
113108
}
114109
return new GeometryCollection($geoms);
115110
}
116-
111+
117112
/**
118113
* Serializes an object into a geojson string
119114
*
@@ -130,7 +125,7 @@ public function write(Geometry $geometry, $return_array = FALSE) {
130125
return json_encode($this->getArray($geometry));
131126
}
132127
}
133-
128+
134129
public function getArray($geometry) {
135130
if ($geometry->getGeomType() == 'GeometryCollection') {
136131
$component_array = array();

lib/adapters/KML.class.php

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
/**
1212
* PHP Geometry/KML encoder/decoder
1313
*
14-
* Mainly inspired/adapted from OpenLayers( http://www.openlayers.org )
14+
* Mainly inspired/adapted from OpenLayers( http://www.openlayers.org )
1515
* Openlayers/format/WKT.js
1616
*
1717
* @package sfMapFishPlugin
@@ -33,7 +33,7 @@ class KML extends GeoAdapter
3333
public function read($kml) {
3434
return $this->geomFromText($kml);
3535
}
36-
36+
3737
/**
3838
* Serialize geometries into a KML string.
3939
*
@@ -44,24 +44,24 @@ public function read($kml) {
4444
public function write(Geometry $geometry, $namespace = FALSE) {
4545
if ($namespace) {
4646
$this->namespace = $namespace;
47-
$this->nss = $namespace.':';
47+
$this->nss = $namespace.':';
4848
}
4949
return $this->geometryToKML($geometry);
5050
}
51-
51+
5252
public function geomFromText($text) {
53-
53+
5454
// Change to lower-case and strip all CDATA
5555
$text = mb_strtolower($text, mb_detect_encoding($text));
5656
$text = preg_replace('/<!\[cdata\[(.*?)\]\]>/s','',$text);
57-
57+
5858
// Load into DOMDOcument
5959
$xmlobj = new DOMDocument();
6060
@$xmlobj->loadXML($text);
6161
if ($xmlobj === false) {
6262
throw new Exception("Invalid KML: ". $text);
6363
}
64-
64+
6565
$this->xmlobj = $xmlobj;
6666
try {
6767
$geom = $this->geomFromXML();
@@ -73,7 +73,7 @@ public function geomFromText($text) {
7373

7474
return $geom;
7575
}
76-
76+
7777
protected function geomFromXML() {
7878
$geometries = array();
7979
$geom_types = geoPHP::geometryList();
@@ -98,24 +98,26 @@ protected function geomFromXML() {
9898
$geometries[] = $this->$function($this->xmlobj->documentElement);
9999
}
100100
}
101-
return geoPHP::geometryReduce($geometries);
101+
return geoPHP::geometryReduce($geometries);
102102
}
103-
103+
104104
protected function childElements($xml, $nodename = '') {
105105
$children = array();
106-
foreach ($xml->childNodes as $child) {
107-
if ($child->nodeName == $nodename) {
108-
$children[] = $child;
106+
if ($xml->childNodes) {
107+
foreach ($xml->childNodes as $child) {
108+
if ($child->nodeName == $nodename) {
109+
$children[] = $child;
110+
}
109111
}
110112
}
111113
return $children;
112114
}
113-
115+
114116
protected function parsePoint($xml) {
115117
$coordinates = $this->_extractCoordinates($xml);
116118
return new Point($coordinates[0][0],$coordinates[0][1]);
117119
}
118-
120+
119121
protected function parseLineString($xml) {
120122
$coordinates = $this->_extractCoordinates($xml);
121123
$point_array = array();
@@ -124,20 +126,20 @@ protected function parseLineString($xml) {
124126
}
125127
return new LineString($point_array);
126128
}
127-
129+
128130
protected function parsePolygon($xml) {
129131
$components = array();
130-
132+
131133
$outer_boundary_element_a = $this->childElements($xml, 'outerboundaryis');
132134
$outer_boundary_element = $outer_boundary_element_a[0];
133135
$outer_ring_element_a = $this->childElements($outer_boundary_element, 'linearring');
134136
$outer_ring_element = $outer_ring_element_a[0];
135137
$components[] = $this->parseLineString($outer_ring_element);
136-
138+
137139
if (count($components) != 1) {
138140
throw new Exception("Invalid KML");
139141
}
140-
142+
141143
$inner_boundary_element_a = $this->childElements($xml, 'innerboundaryis');
142144
if (count($inner_boundary_element_a)) {
143145
foreach ($inner_boundary_element_a as $inner_boundary_element) {
@@ -146,10 +148,10 @@ protected function parsePolygon($xml) {
146148
}
147149
}
148150
}
149-
151+
150152
return new Polygon($components);
151153
}
152-
154+
153155
protected function parseGeometryCollection($xml) {
154156
$components = array();
155157
$geom_types = geoPHP::geometryList();
@@ -162,14 +164,11 @@ protected function parseGeometryCollection($xml) {
162164
}
163165
return new GeometryCollection($components);
164166
}
165-
167+
166168
protected function _extractCoordinates($xml) {
167169
$coord_elements = $this->childElements($xml, 'coordinates');
168-
if (!count($coord_elements)) {
169-
throw new Exception('Bad KML: Missing coordinate element');
170-
}
171170
$coordinates = array();
172-
$coord_sets = explode(' ',$coord_elements[0]->nodeValue);
171+
$coord_sets = explode(' ', $coord_elements[0]->nodeValue);
173172
foreach ($coord_sets as $set_string) {
174173
$set_string = trim($set_string);
175174
if ($set_string) {
@@ -179,10 +178,10 @@ protected function _extractCoordinates($xml) {
179178
}
180179
}
181180
}
182-
181+
183182
return $coordinates;
184183
}
185-
184+
186185
private function geometryToKML($geom) {
187186
$type = strtolower($geom->getGeomType());
188187
switch ($type) {
@@ -212,28 +211,38 @@ private function linestringToKML($geom, $type = FALSE) {
212211
if (!$type) {
213212
$type = $geom->getGeomType();
214213
}
215-
216-
$str = '<'.$this->nss . $type .'><'.$this->nss.'coordinates>';
217-
$i=0;
218-
foreach ($geom->getComponents() as $comp) {
219-
if ($i != 0) $str .= ' ';
220-
$str .= $comp->getX() .','. $comp->getY();
221-
$i++;
214+
215+
$str = '<'.$this->nss . $type .'>';
216+
217+
if (!$geom->isEmpty()) {
218+
$str .= '<'.$this->nss.'coordinates>';
219+
$i=0;
220+
foreach ($geom->getComponents() as $comp) {
221+
if ($i != 0) $str .= ' ';
222+
$str .= $comp->getX() .','. $comp->getY();
223+
$i++;
224+
}
225+
226+
$str .= '</'.$this->nss.'coordinates>';
222227
}
223228

224-
return $str .'</'.$this->nss.'coordinates></'. $this->nss . $type .'>';
229+
$str .= '</'. $this->nss . $type .'>';
230+
231+
return $str;
225232
}
226233

227234
public function polygonToKML($geom) {
228235
$components = $geom->getComponents();
229-
$str = '<'.$this->nss.'outerBoundaryIs>' . $this->linestringToKML($components[0], 'LinearRing') . '</'.$this->nss.'outerBoundaryIs>';
230-
foreach (array_slice($components, 1) as $comp) {
231-
$str .= '<'.$this->nss.'innerBoundaryIs>' . $this->linestringToKML($comp) . '</'.$this->nss.'innerBoundaryIs>';
236+
if (!empty($components)) {
237+
$str = '<'.$this->nss.'outerBoundaryIs>' . $this->linestringToKML($components[0], 'LinearRing') . '</'.$this->nss.'outerBoundaryIs>';
238+
foreach (array_slice($components, 1) as $comp) {
239+
$str .= '<'.$this->nss.'innerBoundaryIs>' . $this->linestringToKML($comp) . '</'.$this->nss.'innerBoundaryIs>';
240+
}
232241
}
233-
242+
234243
return '<'.$this->nss.'Polygon>'. $str .'</'.$this->nss.'Polygon>';
235244
}
236-
245+
237246
public function collectionToKML($geom) {
238247
$components = $geom->getComponents();
239248
$str = '<'.$this->nss.'MultiGeometry>';

0 commit comments

Comments
 (0)