123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- <?php
- /*
- * Copyright (c) Patrick Hayes
- *
- * This code is open-source and licenced under the Modified BSD License.
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- /**
- * PHP Geometry/GPX encoder/decoder
- */
- class GPX extends GeoAdapter
- {
- private $namespace = FALSE;
- private $nss = ''; // Name-space string. eg 'georss:'
- /**
- * Read GPX string into geometry objects
- *
- * @param string $gpx A GPX string
- *
- * @return Geometry|GeometryCollection
- */
- public function read($gpx) {
- return $this->geomFromText($gpx);
- }
- /**
- * Serialize geometries into a GPX string.
- *
- * @param Geometry $geometry
- *
- * @return string The GPX string representation of the input geometries
- */
- public function write(Geometry $geometry, $namespace = FALSE) {
- if ($geometry->isEmpty()) return NULL;
- if ($namespace) {
- $this->namespace = $namespace;
- $this->nss = $namespace.':';
- }
- return '<'.$this->nss.'gpx creator="geoPHP" version="1.0">'.$this->geometryToGPX($geometry).'</'.$this->nss.'gpx>';
- }
-
- public function geomFromText($text) {
- // Change to lower-case and strip all CDATA
- $text = strtolower($text);
- $text = preg_replace('/<!\[cdata\[(.*?)\]\]>/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);
- }
- }
- if ($components) {$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;
- }
-
- protected function geometryToGPX($geom) {
- $type = strtolower($geom->getGeomType());
- switch ($type) {
- case 'point':
- return $this->pointToGPX($geom);
- break;
- case 'linestring':
- 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 '<'.$this->nss.'wpt lat="'.$geom->getY().'" lon="'.$geom->getX().'" />';
- }
-
- private function linestringToGPX($geom) {
- $gpx = '<'.$this->nss.'trk><'.$this->nss.'trkseg>';
-
- foreach ($geom->getComponents() as $comp) {
- $gpx .= '<'.$this->nss.'trkpt lat="'.$comp->getY().'" lon="'.$comp->getX().'" />';
- }
-
- $gpx .= '</'.$this->nss.'trkseg></'.$this->nss.'trk>';
-
- return $gpx;
- }
-
- public function collectionToGPX($geom) {
- $gpx = '';
- $components = $geom->getComponents();
- foreach ($geom->getComponents() as $comp) {
- $gpx .= $this->geometryToGPX($comp);
- }
-
- return $gpx;
- }
- }
|