From 39d06b5ddc0a91e9c3dc7a2233ac9d5f36222dde Mon Sep 17 00:00:00 2001 From: Patrick Hayes Date: Tue, 12 Apr 2011 18:55:46 -0700 Subject: [PATCH] Adding GPX adapter --- geoPHP.inc | 13 ++- lib/adapters/GPX.class.php | 176 +++++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 lib/adapters/GPX.class.php diff --git a/geoPHP.inc b/geoPHP.inc index 3efcefac..99a4cd46 100644 --- a/geoPHP.inc +++ b/geoPHP.inc @@ -7,15 +7,21 @@ * file that was distributed with this source code. */ +// Geometry Loader (Depreciated) include_once("lib/GeometryLoader.class.php"); -include_once("lib/adapters/GeoAdapter.class.php"); + +// Adapters +include_once("lib/adapters/GeoAdapter.class.php"); // Abtract class include_once("lib/adapters/GeoJSON.class.php"); include_once("lib/adapters/WKT.class.php"); include_once("lib/adapters/KML.class.php"); +include_once("lib/adapters/GPX.class.php"); include_once("lib/adapters/GoogleGeocode.class.php"); -include_once("lib/geometry/Geometry.class.php"); + +// Geometries +include_once("lib/geometry/Geometry.class.php"); // Abtract class include_once("lib/geometry/Point.class.php"); -include_once("lib/geometry/Collection.class.php"); +include_once("lib/geometry/Collection.class.php"); // Abtract class include_once("lib/geometry/LineString.class.php"); include_once("lib/geometry/MultiPoint.class.php"); include_once("lib/geometry/LinearRing.class.php"); @@ -61,6 +67,7 @@ class geoPHP { 'wkt' => 'WKT', 'json' => 'GeoJSON', 'kml' => 'KML', + 'gpx' => 'GPX', 'google_geocode' => 'GoogleGeocode', ); } diff --git a/lib/adapters/GPX.class.php b/lib/adapters/GPX.class.php new file mode 100644 index 00000000..4d66dc2d --- /dev/null +++ b/lib/adapters/GPX.class.php @@ -0,0 +1,176 @@ +geomFromText($gpx); + } + + /** + * Serialize geometries into a KML string. + * + * @param Geometry $geometry + * + * @return string The KML string representation of the input geometries + */ + public function write(Geometry $geometry) + { + return $this->geometryToGPX($geometry); + } + + public function geomFromText($text) { + // Change to lower-case and strip all CDATA + $text = strtolower($text); + $text = preg_replace('//s','',$text); + + // Load into DOMDOcument + $xmlobj = new DOMDocument(); + $xmlobj->loadXML($text); + if ($xmlobj === false) { + throw new Exception("Invalid GPX: ". $text); + } + + $this->xmlobj = $xmlobj; + try { + $geom = $this->geomFromXML(); + } catch(InvalidText $e) { + throw new Exception("Cannot Read Geometry From GPX: ". $text); + } catch(Exception $e) { + throw $e; + } + + return $geom; + } + + protected function geomFromXML() { + $geometries = array(); + $geometries = array_merge($geometries, $this->parseWaypoints()); + $geometries = array_merge($geometries, $this->parseTracks()); + $geometries = array_merge($geometries, $this->parseRoutes()); + + if (empty($geometries)) { + throw new Exception("Invalid / Empty GPX"); + } + + return geoPHP::geometryReduce($geometries); + } + + protected function childElements($xml, $nodename = '') { + $children = array(); + foreach ($xml->childNodes as $child) { + if ($child->nodeName == $nodename) { + $children[] = $child; + } + } + return $children; + } + + protected function parseWaypoints() { + $points = array(); + $wpt_elements = $this->xmlobj->getElementsByTagName('wpt'); + foreach ($wpt_elements as $wpt) { + $lat = $wpt->attributes->getNamedItem("lat")->nodeValue; + $lon = $wpt->attributes->getNamedItem("lon")->nodeValue; + $points[] = new Point($lon, $lat); + } + return $points; + } + + protected function parseTracks() { + $lines = array(); + $trk_elements = $this->xmlobj->getElementsByTagName('trk'); + foreach ($trk_elements as $trk) { + $components = array(); + foreach ($this->childElements($trk, 'trkseg') as $trkseg) { + foreach ($this->childElements($trkseg, 'trkpt') as $trkpt) { + $lat = $trkpt->attributes->getNamedItem("lat")->nodeValue; + $lon = $trkpt->attributes->getNamedItem("lon")->nodeValue; + $components[] = new Point($lon, $lat); + } + } + $lines[] = new LineString($components); + } + return $lines; + } + + protected function parseRoutes() { + $lines = array(); + $rte_elements = $this->xmlobj->getElementsByTagName('rte'); + foreach ($rte_elements as $rte) { + $components = array(); + foreach ($this->childElements($rte, 'rtept') as $rtept) { + $lat = $rtept->attributes->getNamedItem("lat")->nodeValue; + $lon = $rtept->attributes->getNamedItem("lon")->nodeValue; + $components[] = new Point($lon, $lat); + } + $lines[] = new LineString($components); + } + return $lines; + } + + private function geometryToGPX($geom) { + $type = strtolower($geom->getGeomType()); + switch ($type) { + case 'point': + return $this->pointToGPX($geom); + break; + case 'linestring': + case 'linearring': + return $this->linestringToGPX($geom); + break; + case 'polygon': + case 'multipoint': + case 'multilinestring': + case 'multipolygon': + case 'geometrycollection': + return $this->collectionToGPX($geom); + break; + } + } + + private function pointToGPX($geom) { + return ''; + } + + private function linestringToGPX($geom) { + $gpx = ''; + + foreach ($geom->getComponents() as $comp) { + $gpx .= ''; + } + + $gpx .= ''; + + return $gpx; + } + + public function collectionToGPX($geom) { + $gpx = ''; + $components = $geom->getComponents(); + foreach ($geom->getComponents() as $comp) { + $gpx .= $this->geometryToGPX($comp); + } + + return $gpx; + } + +}