[Mapbender-commits] r1901 - trunk/mapbender/http/classes

svn_mapbender at osgeo.org svn_mapbender at osgeo.org
Thu Dec 6 08:52:38 EST 2007


Author: christoph
Date: 2007-12-06 08:52:38 -0500 (Thu, 06 Dec 2007)
New Revision: 1901

Added:
   trunk/mapbender/http/classes/class_kml_ows.php
Log:
new kml class

Copied: trunk/mapbender/http/classes/class_kml_ows.php (from rev 1738, trunk/mapbender/http/classes/class_kml.php)
===================================================================
--- trunk/mapbender/http/classes/class_kml_ows.php	                        (rev 0)
+++ trunk/mapbender/http/classes/class_kml_ows.php	2007-12-06 13:52:38 UTC (rev 1901)
@@ -0,0 +1,1143 @@
+<?php
+# $Id: class_wmc.php,v 1.31 2006/03/16 14:49:30 c_baudson Exp $
+# http://www.mapbender.org/index.php/class_wmc.php
+# Copyright (C) 2002 CCGIS 
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+session_start();
+mb_internal_encoding("UTF-8");
+
+require_once("../../conf/mapbender.conf");
+require_once("../classes/class_mb_exception.php");
+require_once("../extensions/JSON.php");
+
+/**
+ * Represents a polygon, consisting of 1 outerboundary and 0..n inner boundaries 
+ */
+class KMLPolygon {
+	var $outerBoundary;
+	var $innerBoundaryArray = array();
+	
+	public function __construct ($aLinearRing) {
+		$this->outerBoundary = $aLinearRing;
+	}
+
+	public function __toString() {
+		$str = "Polygon:\n";
+		$str .= "OuterBoundary:\n" . $this->outerBoundary;
+		for ($i=0; $i < count($this->innerBoundaryArray); $i++) {
+			$str .= "InnerBoundary #" . $i . ":\n";
+			$str .= $this->innerBoundaryArray[$i];
+		}
+		return $str;
+	}
+	
+	/**
+	 * Exports the geometry to a JS format (geometryArray), see geometry.js
+	 * 
+	 * This should be replaced by something JSON-like in the future.
+	 */
+	public function toGeoJSON () {
+		$str = "";
+		if ($this->outerBoundary !== null) {
+			$str .= "{\"type\": \"Polygon\", \"coordinates\": [";
+			$str .= $this->outerBoundary->toGeoJSON();
+			
+			$numberOfInnerBoundaries = count($this->innerBoundaryArray);
+			if ($numberOfInnerBoundaries > 0) {
+				$str .= ", ";
+				for ($i=0; $i < $numberOfInnerBoundaries; $i++) {
+					if ($i > 0) {
+						$str .= ",";
+					}
+					$str .= $this->innerBoundaryArray[$i]->toGeoJSON();
+				}
+			}
+			$str .= "]";
+			$str .= "}";
+		}
+		else {
+			$e = new mb_exception("KMLPoint: toGeoJSON: this point is null.");
+		}
+		return $str;
+	}
+
+	public function appendInnerBoundary ($aLinearRing) {
+		array_push($this->innerBoundaryArray, $aLinearRing);
+	}
+}
+
+/**
+ * Represents a linear ring, consisting of an array of points. 
+ * I guess the first and last point must be identical.
+ */
+class KMLLinearRing {
+	var $pointArray = array();
+	
+	public function __construct ($geometryString) {
+		// KML 2.2
+		if (preg_match("/,/", $geometryString)) {
+			$pointArray = explode(" ", $geometryString);
+			for ($i=0; $i < count($pointArray); $i++) {
+				/*
+				 * Some KMLs have a lot of whitespaces; this "if" is an
+				 * ugly hack to prevent adding empty points
+				 */
+				if (preg_match("/,/", $pointArray[$i])) {
+					$aPoint = explode(",", $pointArray[$i]);
+					// ignore altitude
+					$point = array("x" => $aPoint[0], "y" => $aPoint[1]);
+					array_push($this->pointArray, $point);
+				}
+			}
+		}
+		else {
+			$pointArray = explode(" ", $geometryString);
+			for ($i=0; $i < count($pointArray); $i+=2) {
+				/*
+				 * Some KMLs have a lot of whitespaces; this "if" is an
+				 * ugly hack to prevent adding empty points
+				 */
+				if ($pointArray[$i] && $pointArray[$i+1]) {
+					// ignore altitude
+					$point = array("x" => $pointArray[$i], "y" => $pointArray[$i+1]);
+					array_push($this->pointArray, $point);
+				}
+			}
+		}
+	}
+
+	public function __toString() {
+		$str = "LinearRing:\n";
+		for ($i=0; $i < count($this->pointArray); $i++) {
+			$str .= "Point #" . $i . ": (" . $this->pointArray[$i]["x"] . ", " . $this->pointArray[$i]["y"] . ")\n";
+		}
+		return $str;
+	}
+
+	/**
+	 * Exports the geometry to a JS format (geometryArray), see geometry.js
+	 * 
+	 * This should be replaced by something JSON-like in the future.
+	 */
+	public function toGeoJSON () {
+		$numberOfPoints = count($this->pointArray);
+		$str = "";
+		if ($numberOfPoints > 0) {
+			$str .= "[";
+			for ($i=0; $i < $numberOfPoints; $i++) {
+				if ($i > 0) {
+					$str .= ",";
+				}
+				$str .= "[".$this->pointArray[$i]["x"].",".$this->pointArray[$i]["y"]."]";
+			}
+			$str .= "]";
+		}
+		else {
+			$e = new mb_exception("KMLPoint: toGeoJSON: this point is null.");
+		}
+		return $str;
+	}
+}
+
+/**
+ * Represents a linestring, consisting of an array of points. 
+ */
+class KMLLine {
+	var $pointArray = array();
+	
+	public function __construct ($geometryString) {
+		// KML 2.2
+		if (preg_match("/,/", $geometryString)) {
+			$pointArray = explode(" ", $geometryString);
+			for ($i=0; $i < count($pointArray); $i++) {
+				/*
+				 * Some KMLs have a lot of whitespaces; this "if" is an
+				 * ugly hack to prevent adding empty points
+				 */
+				if (preg_match("/,/", $pointArray[$i])) {
+					$aPoint = explode(",", $pointArray[$i]);
+					// ignore altitude
+					$point = array("x" => $aPoint[0], "y" => $aPoint[1]);
+					array_push($this->pointArray, $point);
+				}
+			}
+		}
+		else {
+			$pointArray = explode(" ", $geometryString);
+			for ($i=0; $i < count($pointArray); $i+=2) {
+				/*
+				 * Some KMLs have a lot of whitespaces; this "if" is an
+				 * ugly hack to prevent adding empty points
+				 */
+				if ($pointArray[$i] && $pointArray[$i+1]) {
+					// ignore altitude
+					$point = array("x" => $pointArray[$i], "y" => $pointArray[$i+1]);
+					array_push($this->pointArray, $point);
+				}
+			}
+		}
+	}
+
+	public function __toString() {
+		$str = "LineString:\n";
+		for ($i=0; $i < count($this->pointArray); $i++) {
+			$str .= "Point #" . $i . ": (" . $this->pointArray[$i]["x"] . ", " . $this->pointArray[$i]["y"] . ")\n";
+		}
+		return $str;
+	}
+
+	/**
+	 * Exports the geometry to a JS format (geometryArray), see geometry.js
+	 * 
+	 * This should be replaced by something JSON-like in the future.
+	 */
+	public function toGeoJSON () {
+		$numberOfPoints = count($this->pointArray);
+		$str = "";
+		if ($numberOfPoints > 0) {
+			$str .= "{\"type\": \"LineString\", \"coordinates\":[";
+			for ($i=0; $i < $numberOfPoints; $i++) {
+				if ($i > 0) {
+					$str .= ",";
+				}
+				$str .= "[".$this->pointArray[$i]["x"].",".$this->pointArray[$i]["y"]."]";
+			}
+			$str .= "]}";
+		}
+		else {
+			$e = new mb_exception("KMLPoint: toGeoJSON: this point is null.");
+		}
+		return $str;
+	}
+}
+
+/**
+ * Represents a point, consisting of a single point geometry. 
+ */
+class KMLPoint {
+	var $point;
+	
+	public function __construct ($geometryString) {
+		// KML 2.2
+		if (preg_match("/,/", $geometryString)) {
+			$aPoint = explode(",", $geometryString);
+			// ignore altitude
+			$this->point = array("x" => $aPoint[0], "y" => $aPoint[1]);
+		}
+		else {
+			$aPoint = explode(" ", $geometryString);
+			// ignore altitude
+			$this->point = array("x" => $aPoint[0], "y" => $aPoint[1]);
+		}
+	}
+
+	public function __toString() {
+		$str = "Point: (" . $this->point["x"] . ", " . $this->point["y"] . ")\n";
+		return $str;
+	}
+
+	/**
+	 * Exports the geometry to a JS format (geometryArray), see geometry.js
+	 * 
+	 * This should be replaced by something JSON-like in the future.
+	 */
+	public function toGeoJSON () {
+		$str = "";
+		if ($this->point !== null) {
+			$str .= "{\"type\": \"Point\", \"coordinates\": [".$this->point["x"].",".$this->point["y"]."]}";
+		}
+		else {
+			$e = new mb_exception("KMLPoint: toGeoJSON: this point is null.");
+		}
+		return $str;
+	}
+}
+
+/**
+ * Represents a multigeometry, consisting of an array of geometries 
+ * (KMLPoint, KMLPolygon, KMLLinestring and KMLMultigeometry allowed)
+ */
+class KMLMultiGeometry {
+	var $geometryArray = array();
+	
+	public function __construct () {
+		
+	}
+	
+	public function __toString() {
+		$str = "";
+		for ($i=0; $i < count($this->geometryArray); $i++) {
+			$str .= "Geometry #" . $i . ":\n" . $this->geometryArray[$i];
+		}
+		return $str;
+	}
+	
+	/**
+	 * Exports the geometry to a JS format (geometryArray), see geometry.js
+	 * TODO: RETURNS "", AS NOT IMPLEMENTED IN geometry.js!!!!!!!!!!!!!!!!!
+	 */
+	public function toGeoJSON () {
+		$str = "";
+		$numberOfGeometries = count($this->geometryArray);
+		if ($numberOfGeometries > 0) {
+			$str .= "{\"type\": \"GeometryCollection\", \"geometries\": [";
+			for ($i=0; $i < $numberOfGeometries; $i++) {
+				if ($i > 0) {
+					$str .= ",";
+				}
+				$str .= $this->geometryArray[$i]->toGeoJSON();
+			}
+			$str .= "]}";
+			return $str;
+		}
+		else {
+			$e = new mb_exception("KMLMultiGeometry: toGeoJSON: this geometryArray is empty.");
+		}
+		return $str;;
+	}
+
+	public function append ($aGeometry) {
+		array_push($this->geometryArray, $aGeometry);
+	}
+}
+
+/**
+ * A Placemark consists of a geometry
+ * (KMLPoint, KMLPolygon, KMLLinestring and KMLMultigeometry allowed)
+ */
+class KMLPlacemark {
+	var $geometry;
+	private $properties = array();
+
+	public function __construct ($aGeometry) {
+		$this->geometry = $aGeometry;
+	}
+	
+	public function __toString () {
+		return "" . $this->geometry; 
+	}
+	
+	/**
+	 * deprecated
+	 */
+	public function getName () {
+		return $this->name;
+	}
+	
+	/**
+	 * deprecated
+	 */
+	public function setName ($aName) {
+		$this->name = $aName;
+	}
+
+	public function setProperty ($key, $value) {
+		// TODO: keys are unique, may be not intended in KML OWS5
+		$this->properties[$key] = $value;
+	}
+	
+	public function getProperties () {
+		return $this->properties;
+	}	
+	
+	/**
+	 * Exports the geometry to a JS format (geometryArray), see geometry.js
+	 */
+	public function toGeoJSON () {
+		$str = "";
+		if ($this->geometry !== null) {
+			$str .= "{\"type\":\"Feature\", \"id\":\"id". time() ."\", ";
+			$str .= "\"geometry\": ";
+			$str .= $this->geometry->toGeoJSON();
+			$str .= ", \"properties\": {";
+			$cnt = 0;
+			foreach ($this->properties as $key => $value) {
+				if ($cnt > 0) {
+					$str .= ",";
+				}
+				$str .= "\"" . $key . "\":\"" . $value . "\"";
+				$cnt ++;
+			}
+			$str .= "}}";
+		}
+		else {
+			$e = new mb_exception("KMLPlacemark: toGeoJSON: this geometry is null!");
+		}
+		return $str;
+	}
+}
+
+/**
+ * Allows parsing a KML file, extracting the placemarks.
+ */
+class KML {
+
+	var $kml;
+	var $id;
+	var $placemarkArray = array();
+					
+	public function __construct() {
+	} 
+
+	/**
+	 * parses an incoming KML and stores it in the database
+	 */
+	public function parseKml ($kml) {
+		$this->kml = $kml;
+		
+		if (!$this->storeInDb()) {
+			return false;
+		}
+		$this->createObjFromKML($kml);
+		return true;
+	}
+	
+	public function getKmlDocument ($kmlId) {
+		$con = db_connect(DBSERVER,OWNER,PW);
+		db_select_db(DB,$con);
+		//get KML from database (check if user is allowed to access)
+# for now, do not restrict access 
+#		$sql = "SELECT kml_doc FROM gui_kml WHERE kml_id = $1 AND fkey_mb_user_id = $2 AND fkey_gui_id = $3 LIMIT 1";
+		$sql = "SELECT kml_doc FROM gui_kml WHERE kml_id = $1 LIMIT 1";
+#		$v = array($kmlId, $_SESSION["mb_user_id"], $_SESSION["mb_user_gui"]);
+#		$t = array("i", "i", "s");
+		$v = array($kmlId);
+		$t = array("i");
+		$result = db_prep_query($sql, $v, $t);
+		$row = db_fetch_array($result);
+		if ($row) {
+			return $row["kml_doc"];
+		}
+		return null;
+	}
+	
+	public function updateKml ($kmlId, $placemarkId, $geoJSON) {
+		$kmlFromDb = $this->getKmlDocument($kmlId);
+		 
+		if ($kmlFromDb !== NULL) {
+			// load the KML from the database in the DOM object
+#			$kmlDoc = simplexml_load_string($kmlFromDb);			
+			$kmlDoc_DOM = new DOMDocument("1.0");
+			$kmlDoc_DOM->encoding = CHARSET;
+			$kmlDoc_DOM->preserveWhiteSpace = false;
+			$kmlDoc_DOM->loadXML($kmlFromDb); 
+
+#			$e = new mb_exception("xmlBEGIN:" . $kmlFromDb . ":xmlEND");
+#			echo CHARSET;
+#			echo "...." . $kmlFromDb . "....";
+#			print_r($kmlDoc);
+#			print_r($kmlDoc_DOM);die;
+
+			//gload ihe geoJSON
+			$json = new Services_JSON();
+			$geoObj = $json->decode($geoJSON);
+
+			// construct an array that holds all metadata of the placemark
+			$metadataObj = $geoObj->properties;
+			
+			// construct an array that holds all geometries of the placemark
+			$geometryObj = $geoObj->geometry;
+			$geometryType = $geometryObj->type;
+			if ($geometryType == "GeometryCollection") {
+				$geometryArray = $geometryObj->geometries;
+			}
+			else if ($geometryType == "Point" || $geometryType == "LineString" || $geometryType == "Polygon") {
+				$geometryArray = array($geometryObj);
+			}
+			else {
+				$e = new mb_exception("class_kml: Invalid geometry type " . $geometryType);
+				return false;
+			}
+
+			//
+			// apply the changes
+			//
+			
+#			$currentPlacemarkArray = $kmlDoc->xpath("//Placemark");
+			$currentPlacemarkArray = $kmlDoc_DOM->getElementsByTagName("Placemark");
+#			$currentPlacemark = $currentPlacemarkArray[$placemarkId]; 
+			$currentPlacemark = $currentPlacemarkArray->item($placemarkId);
+
+			#print_r($currentPlacemark);die;
+			if ($currentPlacemark) {
+				$metadataUpdateSuccessful = $this->updateMetadata($currentPlacemark, $metadataObj);
+				$geometryUpdateSuccessful = $this->updateGeometries($currentPlacemark, $geometryArray);
+			}
+			else {
+				$e = new mb_exception("class_kml.php: updateKml: placemark " . $placemarkId . " not found in KML " . $kmlId . ".");
+				return false;
+			}
+
+			if ($metadataUpdateSuccessful && $geometryUpdateSuccessful) {
+				$updatedKml = $kmlDoc_DOM->saveXML();
+
+				$sql = "UPDATE gui_kml SET kml_doc = $1 WHERE kml_id = $2";
+				$v = array($updatedKml, $kmlId);
+				$t = array("s", "i");
+				$result = db_prep_query($sql, $v, $t);
+				if (!$result) {
+					$e = new mb_exception("class_kml: kml update failed! " . db_error());
+					return false;
+				}
+			}
+			else {
+				if (!$metadataUpdateSuccessful) {
+					$e = new mb_exception("class_kml: Updating the metadata failed, no database update.");
+				}
+				if (!$geometryUpdateSuccessful) {
+					$e = new mb_exception("class_kml: Updating the geometries failed, no database update.");
+				}
+				return false;
+			}
+		}
+		else {
+			$e = new mb_exception("class_kml: No KML found in database, no database update. " . db_error());
+			return false;
+		}
+		return true;
+	}
+
+	private function sepNameSpace($s){
+		$c = mb_strpos($s,":"); 
+		if($c>0){
+			return mb_substr($s,$c+1);
+		}
+		else{
+			return $s;
+		}		
+	}
+
+	private function updateGeometries($currentPlacemark, $geometryArray) {
+		$cnt = 0; 
+		$childNodes = $currentPlacemark->childNodes;
+
+		foreach ($childNodes as $childNode) {
+			$name = $childNode->nodeName;
+			if ( in_array($name, array("Point","LineString","Polygon"))) {
+				$returnValue = $this->updateGeometry($childNode, $geometryArray[$cnt]);
+				if (!$returnValue) {
+					return false;
+				}
+				$cnt ++;
+			}
+			else if ($name == "MultiGeometry") {
+				return $this->updateGeometries($childNode, $geometryArray);
+			}
+		}
+		return true;
+	}
+	
+	private function updateGeometry ($currentNode, $geometry) {
+		$json = new Services_JSON();
+		$currentNode_SimpleXML = simplexml_import_dom($currentNode);
+
+		$currentTypeXml = mb_strtoupper($currentNode->nodeName);
+		$currentTypeGeoJson = mb_strtoupper($geometry->type);  
+
+		if ($currentTypeGeoJson != $currentTypeXml) {
+			$e = new mb_exception("class_kml: geometry type mismatch: geoJSON: " . $currentTypeGeoJson . "; XML: " . $currentTypeXml);
+			return false;
+		}
+		if ($currentTypeXml == "POLYGON") {
+			// GML 3
+			$gmlNode = $currentNode_SimpleXML->{"exterior"}->{"LinearRing"}->{"posList"};
+			$kmlNode = $currentNode_SimpleXML->{"outerBoundaryIs"}->{"LinearRing"}->{"coordinates"};
+			if ($gmlNode->asXML()) {
+				$currentNode_SimpleXML->{"exterior"}->{"LinearRing"}->{"posList"} = preg_replace("/,/", " ", preg_replace("/\[|\]/", "", $json->encode($geometry->coordinates)));
+#				echo "updated polygon (KML OWS)\n";
+			}
+			// KML 2.2
+			else if ($kmlNode->asXML()) {
+				$currentNode_SimpleXML->{"outerBoundaryIs"}->{"LinearRing"}->{"coordinates"} = preg_replace("/\],/", " ", preg_replace("/\][^,]|\[/", "", $json->encode($geometry->coordinates)));
+#				echo "updated polygon (KML 2.2)\n";
+			}
+		}
+		elseif ($currentTypeXml == "POINT") {
+			$gmlNode = $currentNode_SimpleXML->{"pos"};
+			$kmlNode = $currentNode_SimpleXML->{"coordinates"};
+
+			// GML 3
+			if ($gmlNode->asXML()) {
+				$currentNode_SimpleXML->{"pos"} = preg_replace("/,/", " ", preg_replace("/\[|\]/", "", $json->encode($geometry->coordinates)));
+#				$nodeInDom = dom_import_simplexml($currentNode_SimpleXML->{"pos"});
+#				echo "nodevalue pre:" . $nodeInDom->nodeValue;
+#				echo "updated point (KML OWS)\n";
+			}
+			// KML 2.2
+			else if ($kmlNode->asXML()) {
+				$currentNode_SimpleXML->{"coordinates"} = preg_replace("/\[|\]/", "", $json->encode($geometry->coordinates));
+#				echo "updated point (KML 2.2)\n";
+			}
+		}
+		elseif ($currentTypeXml == "LINESTRING") {
+			$gmlNode = $currentNode_SimpleXML->{"posList"};
+			$kmlNode = $currentNode_SimpleXML->{"coordinates"};
+
+			// GML 3
+			if ($gmlNode->asXML()) {
+				$currentNode_SimpleXML->{"posList"} = preg_replace("/,/", " ", preg_replace("/\[|\]/", "", $json->encode($geometry->coordinates)));
+#				echo "updated linestring (KML OWS)\n";
+			}
+			// KML 2.2
+			else if ($kmlNode->asXML()) {
+				$currentNode_SimpleXML->{"coordinates"} = preg_replace("/\[|\]/", "", $json->encode($geometry->coordinates));
+#				echo "updated linestring (KML 2.2)\n";
+			}
+		}
+		return true;
+	}
+
+	private function updateMetadata($currentPlacemark, $metadataObj) {
+		$currentPlacemark_SimpleXML = simplexml_import_dom($currentPlacemark);
+#		print_r($currentPlacemark_SimpleXML);
+		$extendedDataNode = $currentPlacemark_SimpleXML->{"ExtendedData"};
+#		print_r($extendedDataNode);die;
+		if ($extendedDataNode) {
+#echo "extended data\n";
+			// Either, data is within a SCHEMADATA tag...
+			$simpleDataNodes = $extendedDataNode->{"SchemaData"}->{"SimpleData"};
+			if ($simpleDataNodes) {
+#				print_r($simpleDataNodes);
+				foreach ($simpleDataNodes as $simpleDataNode) {
+					$tmp = dom_import_simplexml($simpleDataNode);					
+					$name = $tmp->getAttribute("name");
+#$name = $simpleDataNode->attributes()->name;
+#print_r($simpleDataNode);
+#echo "attrib: " . $simpleDataNode->attributes() . "\n";
+#echo "name: " . $name . "\n";
+					// if there is a metadata entry, update it
+					if (isset($metadataObj->$name)) {
+#						$tmp = dom_import_simplexml($simpleDataNode);
+						$tmp->nodeValue = $metadataObj->$name;
+#echo "setting: " . $tmp->nodeValue . "\n";
+					}										
+				}
+			}
+
+			// ...or within a DATA tag
+			$dataNodes = $extendedDataNode->{"Data"};
+			if ($dataNodes) {
+#				print_r($metadataObj);
+#echo "data nodes\n";
+				foreach ($dataNodes as $dataNode) {
+					$tmp = dom_import_simplexml($dataNode);
+					$name = $tmp->getAttribute("name");
+#echo "data node: " . $name . "\n";
+					// if there is a metadata entry, update it
+					if (isset($metadataObj->$name)) {
+						$tmp->nodeValue = $metadataObj->$name;
+#echo "set to " . $dataNode->nodeValue . "\n";
+					}										
+				}
+			}
+			return true;
+		}
+#		echo "false";
+		return false;
+	}
+	
+	/**
+	 * Store this KML in the database.
+	 */
+	private function storeInDb () {
+		$con = db_connect(DBSERVER,OWNER,PW);
+		db_select_db(DB,$con);
+
+		$sql  = "INSERT INTO gui_kml ";
+		$sql .= "(fkey_mb_user_id, fkey_gui_id, kml_doc, kml_name, kml_description, kml_timestamp) ";
+		$sql .= "VALUES ";
+		$sql .= "($1, $2, $3, $4, $5, $6)";
+		$v = array ($_SESSION["mb_user_id"], $_SESSION["mb_user_gui"], $this->kml, "name", "description", time());
+		$t = array ("i", "s", "s", "s", "s", "s");
+		$res = db_prep_query($sql, $v, $t);
+		if (!$res) {
+			$e = new mb_exception("class_kml.php: storeInDb: failed to store KML in database: " . db_error());
+			return false;
+		}
+
+		$this->id = db_insert_id($con, "gui_kml", "kml_id");
+		return true;
+	}
+
+	public function __toString() {
+		$str = "";
+		for ($i=0; $i < count($this->placemarkArray); $i++) {
+			$str .= "Placemark #" . $i . ":\n " . $this->placemarkArray[$i] . "\n\n"; 
+		}
+		return $str;
+	}
+	
+	public function toGeoJSON() {
+		$str = "";
+		$numberOfPlacemarks = count($this->placemarkArray);
+		if ($numberOfPlacemarks > 0) {
+			$str .= "{\"type\": \"FeatureCollection\", \"features\": [";
+			for ($i=0; $i < $numberOfPlacemarks; $i++) {
+				if ($i > 0) {
+					$str .= ",";
+				}	
+				$str .= $this->placemarkArray[$i]->toGeoJSON();
+			}
+			$str .= "]}";
+		}
+		else {
+			$e = new mb_exception("KML: toGeoJSON: this placemarkArray is empty!");
+		}
+		return $str;
+	}
+
+	/**
+	 * Parses the given KML and extracts its placemarks 
+	 */
+	private function createObjFromKML() {
+		$parser = new KmlOwsParser($this);
+		$this->placemarkArray = $parser->placemarkArray; 
+		return true;
+	}
+
+/*	
+	function createObjFromDB($kml_id) {
+		$this->kml_id = $kml_id;
+
+		$sql = "SELECT kml FROM mb_meetingpoint WHERE mb_meetingpoint_id = $1";
+		$v = array($kml_id);
+		$t = array('s');
+		$res = db_prep_query($sql, $v, $t);
+		$row = db_fetch_array($res);
+		return $this->createObjFromKML($row['kml']);
+	}
+
+	function createKMLFromObj(){
+		$kml = "";
+		$kml .= "<?xml version=\"1.0\" encoding=\"".CHARSET."\"?>\n";
+		$kml .= "<kml xmlns=\"http://earth.google.com/kml/2.0\">\n";
+		$kml .= "<Placemark>\n";
+		$kml .= "\t<description>" . $this->description . "</description>\n";
+		$kml .= "\t<name>" . $this->title . "</name>\n";
+		$kml .= "\t<LookAt>\n";
+		$kml .= "\t\t<longitude>" . $this->x . "</longitude>\n";
+		$kml .= "\t\t<latitude>" . $this->y . "</latitude>\n";
+		$kml .= "\t\t<range>" . $this->lookAt_range . "</range>\n";
+		$kml .= "\t\t<tilt>" . $this->lookAt_tilt . "</tilt>\n";
+		$kml .= "\t\t<heading>" . $this->lookAt_heading . "</heading>\n";
+		$kml .= "\t</LookAt>\n";
+		$kml .= "\t<visibility>0</visibility>\n";
+		$kml .= "\t<Style>\n";
+		$kml .= "\t\t<IconStyle>\n";
+		$kml .= "\t\t\t<Icon>\n";
+		$kml .= "\t\t\t\t<href>" . $this->icon . "</href>\n";
+		$kml .= "\t\t\t</Icon>\n";
+		$kml .= "\t\t</IconStyle>\n";
+		$kml .= "\t</Style>\n";
+		$kml .= "\t<Point>\n";
+		$kml .= "\t\t<extrude>1</extrude>\n";
+		$kml .= "\t\t<coordinates>" . $this->x . "," . $this->y . "</coordinates>\n";
+		$kml .= "\t</Point>\n";
+		$kml .= "</Placemark>\n";
+		$kml .= "</kml>";
+		
+		$this->kml = $kml;
+		
+		return $kml;
+	}
+*/
+} 
+
+class KmlOwsParser {
+	var $placemarkArray = array();
+	
+	public function __construct($kmlObj) {
+		
+		$doc = new DOMDocument("1.0");
+		$doc->preserveWhiteSpace = false;
+		$doc->loadXML($kmlObj->kml);
+#		print_r($doc);
+#		$doc_db = new DOMDocument("1.0");
+#		$doc_db->preserveWhiteSpace = false;
+#		$doc_db->loadXML($kmlObj->getKmlDocument($kmlObj->id));
+#		print_r($doc_db);
+#		$e = new mb_exception("Vergleich:" . strcmp($doc->saveXML(), $doc_db->saveXML()));
+#die;
+		/*
+		 * Get geometry information only, store it in placemarkArray
+		 */
+		$placemarkTagArray = $doc->getElementsByTagName("Placemark");
+		
+		if (count($placemarkTagArray) > 0) {
+			$id = 0;
+			
+			foreach ($placemarkTagArray as $node) {
+	
+				$geometryArray = $this->getGeometryArrayFromPlacemarkOrMultigeometryNode($node);
+				$metadataArray = $this->getMetadataFromPlacemarkNode($node);
+				
+				/*
+				 * For a placemark, the geometryArray should only contain 1 geometry!
+				 */
+				for ($i=0; $i < count($geometryArray); $i++) {
+					$currentPlacemark = new KMLPlacemark($geometryArray[$i]);
+					
+					foreach ($metadataArray as $key => $value) {
+						$currentPlacemark->setProperty($key, $value);
+					}
+					$currentPlacemark->setProperty("Mapbender:kml", true);
+					$currentPlacemark->setProperty("Mapbender:name", "unknown");
+					$currentPlacemark->setProperty("Mapbender:id", $kmlObj->id);
+					$currentPlacemark->setProperty("Mapbender:placemarkId", $id);
+					array_push($this->placemarkArray, $currentPlacemark);
+				}
+				$id ++;		    
+			}
+		}
+		else {
+			$e = new mb_exception("class_kml.php: KMLOWSParser: No placemarks found in KML.");
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Returns an associative array, containing metadata
+	 */
+	private function getMetadataFromPlacemarkNode ($node) {
+	    $children = $node->childNodes;
+	    
+	    $metadataArray = array();
+	    
+		// search "ExtendedData" tag
+		foreach ($children as $child) {
+			if (mb_strtoupper($this->sepNameSpace($child->nodeName)) == "EXTENDEDDATA") {  
+				$extendedDataNode = $child;
+				$extDataChildren = $extendedDataNode->childNodes; 
+				
+				// search "Data" or "SchemaData" tag
+				foreach ($extDataChildren as $extDataChild) {
+					if (mb_strtoupper($this->sepNameSpace($extDataChild->nodeName)) == "SCHEMADATA") {
+						$simpleDataNode = $extDataChild->firstChild;
+						while ($simpleDataNode !== NULL) {
+							if (mb_strtoupper($this->sepNameSpace($simpleDataNode->nodeName)) == "SIMPLEDATA") {
+								$name = $simpleDataNode->getAttribute("name");
+								$value = $simpleDataNode->nodeValue;
+								$metadataArray[$name] = $value;
+							}
+							$simpleDataNode = $simpleDataNode->nextSibling;
+						}
+					}
+					if (mb_strtoupper($this->sepNameSpace($extDataChild->nodeName)) == "DATA") {
+						$dataNode = $extDataChild;
+						$name = $dataNode->getAttribute("name");
+#						$dataChildren = $dataNode->childNodes;
+#						foreach ($dataChildren as $dataChild) {
+#							if (mb_strtoupper($this->sepNameSpace($extDataChild->nodeName)) == "VALUE") {
+#								$metadataArray[$name] = $dataChild->nodeValue;
+#							}					
+#						}
+						$metadataArray[$name] = $dataNode->nodeValue;
+					}
+				}
+			}
+		}
+		return $metadataArray;		
+	}
+	
+	/**
+	 * Given a "Point" node, this function returns the geometry (KMLPoint)
+	 * from within the node.
+	 */
+	private function getGeometryFromPointNode ($node) {
+		$coordinatesNode = $this->getCoordinatesNode($node);
+		$geomString = $coordinatesNode->nodeValue;
+		return new KMLPoint($geomString);
+	}
+	
+	/**
+	 * Given a "LineString" node, this function returns the geometry (KMLLine)
+	 * from within the node.
+	 */
+	private function getGeometryFromLinestringNode ($node) {
+		$coordinatesNode = $this->getCoordinatesNode($node);
+		$geomString = $coordinatesNode->nodeValue;
+		return new KMLLine($geomString);
+	}
+	
+	/**
+	 * Given a "Polygon" node, this function returns the geometry (KMLPolygon)
+	 * from within the node.
+	 */
+	private function getGeometryFromPolygonNode ($node) {
+		$polygon = null;
+
+	    $children = $node->childNodes;
+	    
+		// create new KMLPolygon
+		foreach ($children as $child) {
+			if (mb_strtoupper($this->sepNameSpace($child->nodeName)) == "EXTERIOR" || 
+				mb_strtoupper($this->sepNameSpace($child->nodeName)) == "OUTERBOUNDARYIS") {
+				// create a new Linear Ring
+				$outerBoundary = $this->getGeometryFromLinearRingNode($child);
+				$polygon = new KMLPolygon($outerBoundary);
+			}
+		}
+		
+		if ($polygon !== null) {
+			// append inner boundaries to KMLPolygon
+			foreach ($children as $child) {
+				if (mb_strtoupper($this->sepNameSpace($child->nodeName)) == "INTERIOR" || 
+					mb_strtoupper($this->sepNameSpace($child->nodeName)) == "INNERBOUNDARYIS") {
+					// create a new Linear Ring
+					$innerBoundary = $this->getGeometryFromLinearRingNode($child);
+					$polygon->appendInnerBoundary($innerBoundary);
+				}
+			}
+		}
+		return $polygon;
+	}
+	
+	/**
+	 * Given a "OuterBoundaryIs" or "InnerBoundaryIs" node, this function 
+	 * returns the geometry (KMLLinearRing) within the child node named "linearring"
+	 */
+	private function getGeometryFromLinearRingNode ($node) {
+	    $children = $node->childNodes;
+		foreach($children as $child) {
+			if (mb_strtoupper($this->sepNameSpace($child->nodeName)) == "LINEARRING") {
+				$coordinatesNode = $this->getCoordinatesNode($child);
+				$geomString = $coordinatesNode->nodeValue;
+				return new KMLLinearRing($geomString);
+			}
+		}
+		return null;
+	}
+	
+	/**
+	 * Checks if the child nodes of a given KML node contains any geometries and
+	 * returns an array of geometries (KMLPoint, KMLPolygon, KMLLinestring and KMLMultigeometry)
+	 */
+	private function getGeometryArrayFromPlacemarkOrMultigeometryNode ($node) {
+	    $geometryArray = array();
+	    
+	    $children = $node->childNodes;
+		foreach($children as $child) {
+			if (mb_strtoupper($this->sepNameSpace($child->nodeName)) == "POINT") {
+				array_push($geometryArray, $this->getGeometryFromPointNode($child));
+			}
+			elseif (mb_strtoupper($this->sepNameSpace($child->nodeName)) == "POLYGON") {
+				array_push($geometryArray, $this->getGeometryFromPolygonNode($child));
+			}
+			elseif (mb_strtoupper($this->sepNameSpace($child->nodeName)) == "LINESTRING") {
+				array_push($geometryArray, $this->getGeometryFromLinestringNode($child));
+			}
+			elseif (mb_strtoupper($this->sepNameSpace($child->nodeName)) == "MULTIGEOMETRY") {
+				$geometryArray = $this->getGeometryArrayFromPlacemarkOrMultigeometryNode($child);
+				$multigeometry = new KMLMultiGeometry();
+				
+				for ($i=0; $i < count($geometryArray); $i++) {
+					$multigeometry->append($geometryArray[$i]);	
+				}
+				array_push($geometryArray, $multigeometry);
+			}
+		}
+		return $geometryArray;
+	}
+
+	/**
+	 * Returns the child node with node name "coordinates" of a given KML node.
+	 * If no node is found, null is returned.
+	 */
+	private function getCoordinatesNode ($node) {
+	    $children = $node->childNodes;
+		foreach($children as $child) {
+			if (mb_strtoupper($this->sepNameSpace($child->nodeName)) == "POSLIST" || 
+				mb_strtoupper($this->sepNameSpace($child->nodeName)) == "POS" || 
+				mb_strtoupper($this->sepNameSpace($child->nodeName)) == "COORDINATES") {
+				return $child;
+			}
+		}
+		return null;
+	}
+
+	private function sepNameSpace($s){
+		$c = mb_strpos($s,":"); 
+		if($c>0){
+			return mb_substr($s,$c+1);
+		}
+		else{
+			return $s;
+		}		
+	}
+}
+
+/**
+ * not used in OGC KML Mapbender project, may be buggy
+ */
+class Kml22Parser {
+	public function __construct($kml) {
+		$doc = new DOMDocument("1.0");
+		$doc->preserveWhiteSpace = false;
+		$doc->loadXML($kml);
+
+		/*
+		 * Get geometry information only, store it in placemarkArray
+		 */
+		$placemarkTagArray = $doc->getElementsByTagName("Placemark");
+		
+		foreach ($placemarkTagArray as $node) {
+
+			$geometryArray = $this->getGeometryArrayFromPlacemarkOrMultigeometryNode($node);
+			
+			/*
+			 * For a placemark, the geometryArray should only contain 1 geometry!
+			 */
+			for ($i=0; $i < count($geometryArray); $i++) {
+				$currentPlacemark = new KMLPlacemark($geometryArray[$i]);
+				$currentPlacemark->setName($this->getNameFromPlacemarkNode($node));
+				array_push($this->placemarkArray, $currentPlacemark);
+			}		    
+		}
+//		print_r($this->placemarkArray);
+	}
+
+	/**
+	 * Given a "Point" node, this function returns the geometry (KMLPoint)
+	 * from within the node.
+	 */
+	private function getGeometryFromPointNode ($node) {
+		$coordinatesNode = $this->getCoordinatesNode($node);
+		$geomString = $coordinatesNode->nodeValue;
+		return new KMLPoint($geomString);
+	}
+	
+	/**
+	 * Given a "LineString" node, this function returns the geometry (KMLLine)
+	 * from within the node.
+	 */
+	private function getGeometryFromLinestringNode ($node) {
+		$coordinatesNode = $this->getCoordinatesNode($node);
+		$geomString = $coordinatesNode->nodeValue;
+		return new KMLLine($geomString);
+	}
+	
+	/**
+	 * Given a "Polygon" node, this function returns the geometry (KMLPolygon)
+	 * from within the node.
+	 */
+	private function getGeometryFromPolygonNode ($node) {
+		$polygon = null;
+
+	    $children = $node->childNodes;
+	    
+		// create new KMLPolygon
+		foreach ($children as $child) {
+			if (mb_strtoupper($child->nodeName) == "OUTERBOUNDARYIS") {
+				// create a new Linear Ring
+				$outerBoundary = $this->getGeometryFromLinearRingNode($child);
+				$polygon = new KMLPolygon($outerBoundary);
+			}
+		}
+		
+		if ($polygon !== null) {
+			// append inner boundaries to KMLPolygon
+			foreach ($children as $child) {
+				if (mb_strtoupper($child->nodeName) == "INNERBOUNDARYIS") {
+					// create a new Linear Ring
+					$innerBoundary = $this->getGeometryFromLinearRingNode($child);
+					$polygon->appendInnerBoundary($innerBoundary);
+				}
+			}
+		}
+		return $polygon;
+	}
+	
+	/**
+	 * Given a "OuterBoundaryIs" or "InnerBoundaryIs" node, this function 
+	 * returns the geometry (KMLLinearRing) within the child node named "linearring"
+	 */
+	private function getGeometryFromLinearRingNode ($node) {
+	    $children = $node->childNodes;
+		foreach($children as $child) {
+			if (mb_strtoupper($child->nodeName) == "LINEARRING") {
+				$coordinatesNode = $this->getCoordinatesNode($child);
+				$geomString = $coordinatesNode->nodeValue;
+				return new KMLLinearRing($geomString);
+			}
+		}
+		return null;
+	}
+	
+	/**
+	 * Checks if the child nodes of a given KML node contains any geometries and
+	 * returns an array of geometries (KMLPoint, KMLPolygon, KMLLinestring and KMLMultigeometry)
+	 */
+	private function getGeometryArrayFromPlacemarkOrMultigeometryNode ($node) {
+	    $geometryArray = array();
+	    
+	    $children = $node->childNodes;
+		foreach($children as $child) {
+			if (mb_strtoupper($child->nodeName) == "POINT") {
+				array_push($geometryArray, $this->getGeometryFromPointNode($child));
+			}
+			elseif (mb_strtoupper($child->nodeName) == "POLYGON") {
+				array_push($geometryArray, $this->getGeometryFromPolygonNode($child));
+			}
+			elseif (mb_strtoupper($child->nodeName) == "LINESTRING") {
+				array_push($geometryArray, $this->getGeometryFromLinestringNode($child));
+			}
+			elseif (mb_strtoupper($child->nodeName) == "MULTIGEOMETRY") {
+				$geometryArray = $this->getGeometryArrayFromPlacemarkOrMultigeometryNode($child);
+				$multigeometry = new KMLMultiGeometry();
+				
+				for ($i=0; $i < count($geometryArray); $i++) {
+					$multigeometry->append($geometryArray[$i]);	
+				}
+				array_push($geometryArray, $multigeometry);
+			}
+		}
+		return $geometryArray;
+	}
+	
+	/**
+	 * Returns the name of the placemark from the placemark node
+	 */
+	function getNameFromPlacemarkNode($node) {
+	    $name = "new";
+	    
+	    $children = $node->childNodes;
+		foreach($children as $child) {
+			if (mb_strtoupper($child->nodeName) == "NAME") {
+				$name = $child->nodeValue;
+			}
+		}
+		return $name;
+	}
+	
+	/**
+	 * Returns the child node with node name "coordinates" of a given KML node.
+	 * If no node is found, null is returned.
+	 */
+	private function getCoordinatesNode ($node) {
+	    $children = $node->childNodes;
+		foreach($children as $child) {
+			if (mb_strtoupper($child->nodeName) == "COORDINATES") {
+				return $child;
+			}
+		}
+		return null;
+	}
+}
+
+// end class
+?>



More information about the Mapbender_commits mailing list