<?php # $Id: class_wfs.php 3094 2008-10-01 13:52:35Z christoph $ # http://www.mapbender.org/index.php/class_wfs.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. require_once(dirname(__FILE__)."/../../core/globalSettings.php"); require_once(dirname(__FILE__)."/../classes/class_gml_factory.php"); require_once(dirname(__FILE__)."/../classes/class_gml_3.php"); require_once(dirname(__FILE__)."/../classes/class_connector.php"); require_once(dirname(__FILE__)."/../classes/class_administration.php"); /** * Creates GML 3 objects from a GML documents. * * @return Gml_3 */ class Gml_3_Factory extends GmlFactory { /** * Creates a GML object from a GeoJSON (http://www.geojson.org) String * * @return Gml_3 * @param $geoJson String */ public function createFromGeoJson ($geoJson) { $gml3 = new Gml_3(); return parent::createFromGeoJson($geoJson, $gml3); } /** * Creates GML 3 objects from GML documents. * * @return Gml_3 * @param $xml String */ public function createFromXml ($xml, $wfsConf) { $gml3 = new Gml_3(); return parent::createFromXml($xml, $wfsConf, $gml3); } public static function getDimensionFromNode ($domNode) { if (!$domNode->hasAttribute("srsDimension")) { return 2; } $dim = intval($domNode->getAttribute("srsDimension"), 10); if (2 == $dim || 3 == $dim) { return $dim; } return 2; } function findNameSpace($s){ list($ns,$FeaturePropertyName) = split(":",$s); $nodeName = array('ns' => $ns, 'value' => $FeaturePropertyName); return $nodeName; } public static function parsePoint ($domNode) { $gmlPoint = new GmlPoint(); $currentSibling = $domNode->firstChild; while ($currentSibling) { $coordArray = explode(" ", $currentSibling->nodeValue); $gmlPoint->setPoint($coordArray[0], $coordArray[1]); $currentSibling = $currentSibling->nextSibling; } return $gmlPoint; } public static function parseLine ($domNode) { $gmlLine = new GmlLine(); $currentSibling = $domNode->firstChild; while ($currentSibling) { $dim = self::getDimensionFromNode($currentSibling); $coordArray = explode(' ', trim($currentSibling->nodeValue)); for ($i = 0; $i < count($coordArray); $i += $dim) { $x = $coordArray[$i]; $y = $coordArray[$i+1]; $gmlLine->addPoint($x, $y); } $currentSibling = $currentSibling->nextSibling; } return $gmlLine; } public static function parsePolygon ($domNode) { $gmlPolygon = new GmlPolygon(); $simpleXMLNode = simplexml_import_dom($domNode); $simpleXMLNode->registerXPathNamespace('gml', 'http://www.opengis.net/gml'); $allCoords = $simpleXMLNode->xpath("gml:exterior/gml:LinearRing/gml:posList"); $cnt=0; foreach ($allCoords as $Coords) { $coordsDom = dom_import_simplexml($Coords); $dim = self::getDimensionFromNode($coordsDom); $coordArray = explode(' ', trim($coordsDom->nodeValue)); for ($i = 0; $i < count($coordArray); $i += $dim) { $x = $coordArray[$i]; $y = $coordArray[$i+1]; $gmlPolygon->addPoint($x, $y); } $cnt++; } $innerRingNodeArray = $simpleXMLNode->xpath("gml:innerBoundaryIs/gml:LinearRing"); if ($innerRingNodeArray) { $ringCount = 0; foreach ($innerRingNodeArray as $ringNode) { $coordinates = $ringNode->xpath("gml:coordinates"); foreach ($coordinates as $coordinate) { $coordsDom = dom_import_simplexml($coordinate); $dim = self::getDimensionFromNode($coordsDom); $coordArray = explode(' ', trim($coordsDom->nodeValue)); for ($i = 0; $i < count($coordArray); $i += $dim) { $x = $coordArray[$i]; $y = $coordArray[$i+1]; $gmlPolygon->addPointToRing($ringCount, $x, $y); } } $ringCount++; } } return $gmlPolygon; } public static function parseMultiLine ($domNode) { $gmlMultiLine = new GmlMultiLine(); $simpleXMLNode = simplexml_import_dom($domNode); $simpleXMLNode->registerXPathNamespace('gml', 'http://www.opengis.net/gml'); $allCoords = $simpleXMLNode->xpath("gml:lineStringMember/gml:LineString/gml:posList"); if (count($allCoords) === 0) { $allCoords = $simpleXMLNode->xpath("gml:lineStringMembers/gml:LineString/gml:posList"); } $cnt=0; foreach ($allCoords as $Coords) { $gmlMultiLine->lineArray[$cnt] = array(); $coordsDom = dom_import_simplexml($Coords); $dim = self::getDimensionFromNode($coordsDom); $coordArray = explode(' ', trim($coordsDom->nodeValue)); for ($i = 0; $i < count($coordArray); $i += $dim) { $x = $coordArray[$i]; $y = $coordArray[$i+1]; $gmlMultiLine->addPoint($x, $y, $cnt); } $cnt++; } return $gmlMultiLine; } public static function parseMultiPoint ($domNode) { $gmlMultiPoint = new GmlMultiPoint(); $simpleXMLNode = simplexml_import_dom($domNode); $simpleXMLNode->registerXPathNamespace('gml', 'http://www.opengis.net/gml'); $allCoords = $simpleXMLNode->xpath("gml:pointMember/gml:Point/gml:pos"); if (count($allCoords) === 0) { $allCoords = $simpleXMLNode->xpath("gml:pointMembers/gml:Point/gml:pos"); } foreach ($allCoords as $Coords) { $coordsDom = dom_import_simplexml($Coords); $dim = self::getDimensionFromNode($coordsDom); $coordArray = explode(' ', trim($coordsDom->nodeValue)); for ($i = 0; $i < count($coordArray); $i += $dim) { $x = $coordArray[$i]; $y = $coordArray[$i+1]; $gmlMultiPoint->addPoint($x, $y); break; } } return $gmlMultiPoint; } public static function parseMultiCurve ($domNode) { $gmlMultiLine = new GmlMultiLine(); $simpleXMLNode = simplexml_import_dom($domNode); $simpleXMLNode->registerXPathNamespace('gml', 'http://www.opengis.net/gml'); $allCoords = $simpleXMLNode->xpath("gml:curveMembers/gml:LineString/gml:posList"); if (count($allCoords) === 0) { $allCoords = $simpleXMLNode->xpath("gml:curveMember/gml:LineString/gml:posList"); } $cnt=0; foreach ($allCoords as $Coords) { $gmlMultiLine->lineArray[$cnt] = array(); $coordsDom = dom_import_simplexml($Coords); $dim = self::getDimensionFromNode($coordsDom); $coordArray = explode(' ', trim($coordsDom->nodeValue)); for ($i = 0; $i < count($coordArray); $i += $dim) { $x = $coordArray[$i]; $y = $coordArray[$i+1]; $gmlMultiLine->addPoint($x, $y, $cnt); } $cnt++; } return $gmlMultiLine; } public static function parseMultiPolygon ($domNode) { $gmlMultiPolygon = new GmlMultiPolygon(); $simpleXMLNode = simplexml_import_dom($domNode); $simpleXMLNode->registerXPathNamespace('gml', 'http://www.opengis.net/gml'); $allPolygons = $simpleXMLNode->xpath("gml:surfaceMember/gml:Polygon"); if (count($allPolygons) === 0) { $allPolygons = $simpleXMLNode->xpath("gml:surfaceMembers/gml:Polygon"); } $cnt=0; foreach ($allPolygons as $polygon) { $allCoords = $polygon->xpath("gml:exterior/gml:LinearRing/gml:posList"); $gmlMultiPolygon->polygonArray[$cnt] = array(); foreach ($allCoords as $Coords) { $coordsDom = dom_import_simplexml($Coords); $dim = self::getDimensionFromNode($coordsDom); $coordArray = explode(' ', trim($coordsDom->nodeValue)); for ($i = 0; $i < count($coordArray); $i += $dim) { $x = $coordArray[$i]; $y = $coordArray[$i+1]; $gmlMultiPolygon->addPoint($x, $y, $cnt); } } $gmlMultiPolygon->innerRingArray[$cnt] = array(); $innerRingNodeArray = $polygon->xpath("gml:interior"); if ($innerRingNodeArray) { $ringCount = 0; foreach ($innerRingNodeArray as $ringNode) { $currentRingNode = $ringNode->xpath("gml:LinearRing"); foreach ($currentRingNode as $node) { $coordinates = $node->xpath("gml:posList"); foreach ($coordinates as $coordinate) { $coordsDom = dom_import_simplexml($coordinate); $dim = self::getDimensionFromNode($coordsDom); $coordArray = explode(' ', trim($coordsDom->nodeValue)); for ($i = 0; $i < count($coordArray); $i += $dim) { $x = $coordArray[$i]; $y = $coordArray[$i+1]; $gmlMultiPolygon->addPointToRing($cnt, $ringCount, $x, $y); } } $ringCount++; } } } $cnt++; // new mb_exception("create multipolygon " . serialize($gmlMultiPolygon->innerRingArray)); } return $gmlMultiPolygon; } /** * Parses the feature segment of a GML and stores the geometry in the * $geometry variable of the class. * * Example of a feature segment of a GML. * * <gml:featureMember> * <ms:my_polygons gml:id="my_polygons.624"> * <gml:boundedBy> * <gml:Envelope srsName="epsg:4326"> * <gml:lowerCorner>39.700000 29.400000</gml:lowerCorner> * <gml:upperCorner>46.400000 35.400000</gml:upperCorner> * </gml:Envelope> * </gml:boundedBy> * <ms:the_geom> * <gml:MultiSurface srsName="epsg:4326"> * <gml:surfaceMembers> * <gml:Polygon> * <gml:exterior> * <gml:LinearRing> * <gml:posList srsDimension="2"> * 43.200000 35.400000 * 46.400000 31.700000 * 44.100000 31.000000 * 41.700000 29.400000 * 39.700000 31.400000 * 43.300000 32.300000 * 43.200000 35.400000 * </gml:posList> * </gml:LinearRing> * </gml:exterior> * </gml:Polygon> * </gml:surfaceMembers> * </gml:MultiSurface> * </ms:the_geom> * <ms:oid>16752039</ms:oid> * <ms:gid>624</ms:gid> * <ms:name>inter_08</ms:name> * <ms:angle/> * <ms:annotation/> * <ms:style>3</ms:style> * </ms:my_polygons> * </gml:featureMember> * * @return void * @param $domNode DOMNodeObject the feature tag of the GML * (<gml:featureMember> in the above example) */ protected function parseFeature($domNode, $feature, $wfsConf) { $geomFeaturetypeElement = $wfsConf->getGeometryColumnName(); $feature->fid = $domNode->getAttribute("gml:id"); $currentSibling = $domNode->firstChild; while ($currentSibling) { $name = $currentSibling->nodeName; $value = $currentSibling->nodeValue; $namespace = $this->findNameSpace($name); $ns = $namespace['ns']; $columnName = $namespace['value']; $isGeomColumn = ($geomFeaturetypeElement == null || $columnName == $geomFeaturetypeElement); // check if this node is a geometry node. // however, even if it is a property node, // it has a child node, the text node! // So we might need to do something more // sophisticated here... if ($currentSibling->hasChildNodes() && $isGeomColumn){ $geomNode = $currentSibling->firstChild; $geomType = $geomNode->nodeName; if ($geomNode->hasAttribute("srsName")) { $srs = $geomNode->getAttribute("srsName"); } switch ($geomType) { case "gml:Polygon" :// untested! $feature->geometry = self::parsePolygon($geomNode); if ($feature->geometry->isEmpty()) { $feature->geometry = Gml_2_Factory::parsePolygon($geomNode); } $feature->geometry->srs = $srs; break; case "gml:LineString" :// untested! $feature->geometry = self::parseLine($geomNode); if ($feature->geometry->isEmpty()) { $feature->geometry = Gml_2_Factory::parseLine($geomNode); } $feature->geometry->srs = $srs; break; case "gml:Point" : $feature->geometry = self::parsePoint($geomNode); if ($feature->geometry->isEmpty()) { $feature->geometry = Gml_2_Factory::parsePoint($geomNode); } $feature->geometry->srs = $srs; break; case "gml:MultiPoint" : $feature->geometry = self::parseMultiPoint($geomNode); if ($feature->geometry->isEmpty()) { $feature->geometry = Gml_2_Factory::parseMultiPoint($geomNode); } $feature->geometry->srs = $srs; break; case "gml:MultiLineString" : new mb_exception("found multilinestring"); $feature->geometry = self::parseMultiLine($geomNode); if ($feature->geometry->isEmpty()) { $feature->geometry = Gml_2_Factory::parseMultiLine($geomNode); } $feature->geometry->srs = $srs; break; case "gml:MultiCurve" : $feature->geometry = self::parseMultiCurve($geomNode); if ($feature->geometry->isEmpty()) { $feature->geometry = Gml_2_Factory::parseMultiLine($geomNode); } $feature->geometry->srs = $srs; break; case "gml:MultiSurface" : $feature->geometry = self::parseMultiPolygon($geomNode); if ($feature->geometry->isEmpty()) { $feature->geometry = Gml_2_Factory::parseMultiPolygon($geomNode); } $feature->geometry->srs = $srs; break; default: $feature->properties[$columnName] = $value; break; } } else { if ($currentSibling->hasChildNodes() && $currentSibling->firstChild instanceof DOMText) { $feature->properties[$columnName] = $value; } } $currentSibling = $currentSibling->nextSibling; } } } ?>