[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