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;
+ }
+
+}