/*---------------- FILE HEADER --------------------------------------- This file is part of Geoide. Copyright (C) 2005-2006 by: IDgis B.V. http://www.idgis.nl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Herman Assink IDgis bv P.O. Box 15 7450 AA Holten The Netherlands E-Mail: herman.assink@idgis.nl * @version 1.4.0 * @author IDgis team * ------------------------------------------------------------------------*/ import nl.idgis.giclient.geoma.Envelope; import nl.idgis.giclient.geoma.Geometry; import nl.idgis.giclient.geoma.GeometryCollection; import nl.idgis.giclient.geoma.GeometryTools; import nl.idgis.giclient.geoma.LinearRing; import nl.idgis.giclient.geoma.LineString; import nl.idgis.giclient.geoma.MultiLineString; import nl.idgis.giclient.geoma.MultiPoint; import nl.idgis.giclient.geoma.MultiPolygon; import nl.idgis.giclient.geoma.Point; import nl.idgis.giclient.geoma.Polygon; import nl.idgis.giclient.gis.Feature; import nl.idgis.giclient.gis.Layer; import nl.idgis.giclient.util.XMLTools; import nl.idgis.giclient.gis.SelectableLayer; class nl.idgis.giclient.geoma.GMLFactory { static function createGML(features:Array):XML { if (features == null) { // EXCEPTION return null; } var gml:XML = new XML(); gml.docTypeDecl = ""; var featureCollectionNode:XMLNode = gml.createElement("gml:FeatureCollection"); gml.appendChild(featureCollectionNode); featureCollectionNode.attributes["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance"; featureCollectionNode.attributes["xmlns:xlink"] = "http://www.w3.org/1999/xlink"; featureCollectionNode.attributes["xmlns:gml"] = "http://www.opengis.net/gml"; var boundedByNode:XMLNode = gml.createElement("gml:boundedBy"); featureCollectionNode.appendChild(boundedByNode); var boxNode:XMLNode = gml.createElement("gml:box"); boundedByNode.appendChild(boxNode); var feature:Feature = null; var geometry:Geometry = null; var layer:SelectableLayer = null; var featureTypeName:String = null; var id:String = null; var geometryColumn:String = null; var envelope:Envelope = null; var envelopes:Array = new Array(); for (var i:Number = 0; i < features.length; i++) { var idPrefix:String = ""; if (features[i] instanceof Feature) { feature = Feature(features[i]); geometry = feature.getGeometry(); layer = SelectableLayer(feature.getLayer()); id = feature.getID(); idPrefix = layer.getFeatureIdPrefix(); geometryColumn = layer.getFeatureType().getDefaultGeometryProperty().getName(); var colonPos = geometryColumn.lastIndexOf(":"); if (colonPos > -1) { //remove namespace prefix (app) geometryColumn = geometryColumn.substr(colonPos + 1); } var pointPos = geometryColumn.lastIndexOf("."); //assume that the prefix of geocolumn is featuretypename if (pointPos > -1) { featureTypeName = geometryColumn.substr(0, pointPos); } else { featureTypeName = layer.getName(); geometryColumn = featureTypeName + "." + geometryColumn; } envelope = feature.getEnvelope(); } else if (features[i] instanceof Geometry){ geometry = Geometry(features[i]); featureTypeName = "SELECT_POLYGON"; id = String(i + 1); geometryColumn = "SELECT_POLYGON.GEOMETRY"; envelope = geometry.getEnvelope(); } else { // EXCEPTION return null; } var featureMemberNode:XMLNode = gml.createElement("gml:featureMember"); featureCollectionNode.appendChild(featureMemberNode); var featureNode:XMLNode = gml.createElement(featureTypeName); featureMemberNode.appendChild(featureNode); featureNode.attributes["fid"] = id; var idNode:XMLNode = gml.createElement(featureTypeName + ".NR"); featureNode.appendChild(idNode); var id_nr:String = id; if (id.substr(0,idPrefix.length) == idPrefix) { //strip id prefix added by WFS id_nr = id.substr(idPrefix.length); } var idTextNode:XMLNode = gml.createTextNode(id_nr); idNode.appendChild(idTextNode); var geometryNode:XMLNode = createGeometryNode(geometryColumn, geometry,null); // return empty node if geometry == null/NullGeometry featureNode.appendChild(geometryNode); envelopes.push(envelope); } var envelopesEnvelope:Envelope = GeometryTools.getEnvelope(envelopes); // Retrieves the bounding envelope for the geometries of all features. var envCoords:Array = null; if (envelopesEnvelope != null) { envCoords = envelopesEnvelope.getCoords(); } var coordsNode:XMLNode = createCoordsNode(envCoords); boxNode.appendChild(coordsNode); return gml; } static function createEmptyFC():XML{ var gml:XML = new XML(); gml.docTypeDecl = ""; var featureCollectionNode:XMLNode = gml.createElement("gml:FeatureCollection"); gml.appendChild(featureCollectionNode); featureCollectionNode.attributes["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance"; featureCollectionNode.attributes["xmlns:xlink"] = "http://www.w3.org/1999/xlink"; featureCollectionNode.attributes["xmlns:gml"] = "http://www.opengis.net/gml"; return gml; } // NOT USED??!! static private function createEnvelopeNode(envelope:Envelope):XMLNode { var gml:XML = new XML(); var envelopeNode:XMLNode = gml.createElement("ENVELOPE"); var minNode:XMLNode = gml.createElement("MIN"); envelopeNode.appendChild(minNode); var minXNode:XMLNode = gml.createElement("X"); minNode.appendChild(minXNode); var minYNode:XMLNode = gml.createElement("Y"); minNode.appendChild(minYNode); var minXTextNode:XMLNode = gml.createTextNode(String(envelope.getMinX())); minXNode.appendChild(minXTextNode); var minYTextNode:XMLNode = gml.createTextNode(String(envelope.getMinY())); minYNode.appendChild(minYTextNode); var maxNode:XMLNode = gml.createElement("MAX"); envelopeNode.appendChild(maxNode); var maxXNode:XMLNode = gml.createElement("X"); maxNode.appendChild(maxXNode); var maxYNode:XMLNode = gml.createElement("Y"); maxNode.appendChild(maxYNode); var maxXTextNode:XMLNode = gml.createTextNode(String(envelope.getMaxX())); maxXNode.appendChild(maxXTextNode); var maxYTextNode:XMLNode = gml.createTextNode(String(envelope.getMaxY())); maxYNode.appendChild(maxYTextNode); return envelopeNode; } static function createGeometryNode(geometryColumnName:String, geometry:Geometry, srs:String):XMLNode { var xml:XML = new XML(); var geometryColumnNode:XMLNode = xml.createElement(geometryColumnName); var geometryNode:XMLNode = createGMLNode(geometry); var srsName:String = null; if (srs == null){ //TODO:srsName is the srs of the activeMap srsName = "EPSG:28992"; } else { srsName = srs; } if (geometryNode != null) { geometryNode.attributes["srsName"] = srsName; geometryColumnNode.appendChild(geometryNode); } return geometryColumnNode; } static function createGMLNode(geometry:Geometry):XMLNode { return doCreateGMLNode(geometry, true); } static function doCreateGMLNode(geometry:Geometry, top:Boolean):XMLNode { var xml:XML = new XML(); var geometryNode:XMLNode = null; if (geometry instanceof GeometryCollection) { var geometryNodeName:String = null; var memberNodeName:String = null; if (geometry instanceof MultiPoint) { geometryNodeName = "gml:MultiPoint"; memberNodeName = "gml:pointMember"; } else if (geometry instanceof MultiLineString) { geometryNodeName = "gml:MultiLineString"; memberNodeName = "gml:lineStringMember"; } else if (geometry instanceof MultiPolygon) { geometryNodeName = "gml:MultiPolygon"; memberNodeName = "gml:polygonMember"; } geometryNode = xml.createElement(geometryNodeName); var geometryMembers:Array = geometry.getGeometries(); var memberNode:XMLNode = null; for (var i:Number = 0; i < geometryMembers.length; i++) { memberNode = xml.createElement(memberNodeName); geometryNode.appendChild(memberNode); memberNode.appendChild(doCreateGMLNode(Geometry(geometryMembers[i]), false)); } } else if (geometry instanceof Point) { var point:Point = Point(geometry); geometryNode = xml.createElement("gml:Point"); var coords:Array = point.getCoords(); var coordsNode:XMLNode = createCoordsNode(coords); geometryNode.appendChild(coordsNode); } else if (geometry instanceof LineString) { var lineString:LineString = LineString(geometry); if (geometry instanceof LinearRing) { geometryNode = xml.createElement("gml:LinearRing"); } else { geometryNode = xml.createElement("gml:LineString"); } var coords:Array = lineString.getCoords(); var coordsNode:XMLNode = createCoordsNode(coords); geometryNode.appendChild(coordsNode); } else if (geometry instanceof Polygon) { var polygon:Polygon = Polygon(geometry); geometryNode = xml.createElement("gml:Polygon"); var boundaryNode:XMLNode = null; var linearRingNode:XMLNode = null; var linearRings:Array = polygon.getGeometries(); for (var i:Number = 0; i < linearRings.length; i++) { if (i == 0) { boundaryNode = xml.createElement("gml:outerBoundaryIs");; } else { boundaryNode = xml.createElement("gml:innerBoundaryIs");; } geometryNode.appendChild(boundaryNode); linearRingNode = doCreateGMLNode(LinearRing(linearRings[i]), false); boundaryNode.appendChild(linearRingNode); } } geometryNode.attributes["xmlns:gml"] = "http://www.opengis.net/gml"; if(top) { geometryNode.attributes["srsName"] = geometry.getSRS(); } return geometryNode; } static private function createCoordsNode(coords:Array):XMLNode { var xml:XML = new XML(); var coordsNode:XMLNode = xml.createElement("gml:coordinates"); coordsNode.attributes["ts"] = " "; coordsNode.attributes["decimal"] = "."; coordsNode.attributes["cs"] = ","; var coordsString:String = ""; if (coords != null) { //return empty node if coords == null for (var i:Number = 0; i < coords.length; i++) { if (i > 0) { coordsString += " "; } coordsString += (coords[i].x + "," + coords[i].y); } } var coordsTextNode:XMLNode = xml.createTextNode(coordsString); coordsNode.appendChild(coordsTextNode); return coordsNode; } static function parseGML(geometryNode:XMLNode):Geometry { return doParseGML(geometryNode, null); } static function doParseGML(geometryNode:XMLNode, parentSrs:String):Geometry { var geometryMemberNodes:Array = null; var geometryMemberNode:XMLNode = null; var geometries:Array = null; var outerBoundaryNode:XMLNode = null; var innerBoundaryNodes:Array = null; var linearRingNode:XMLNode = null; var coordinatePairsString:String = null; var coordinatesNode:XMLNode = null; var cs:String = null; var ts:String = null; var coordinatePairs:Array = null; var coordinates:Array = null; var x:Number = 0; var y:Number = 0; var points:Array = null; var geometry:Geometry = null; var membersNode:XMLNode = null; var geometryNodes:Array = null; var srsName:String = XMLTools.getStringValue("srsName", geometryNode); if(srsName == null) { srsName = parentSrs; } if (geometryNode.nodeName.indexOf("gml:Multi") == 0) { if (geometryNode.nodeName == "gml:MultiPoint") { geometryMemberNodes = XMLTools.getChildNodes("gml:pointMember", geometryNode); } else if (geometryNode.nodeName == "gml:MultiCurve") { geometryMemberNodes = XMLTools.getChildNodes("gml:curveMember", geometryNode); } else if (geometryNode.nodeName == "gml:MultiLineString") { geometryMemberNodes = XMLTools.getChildNodes("gml:lineStringMember", geometryNode); } else if (geometryNode.nodeName == "gml:MultiPolygon") { geometryMemberNodes = XMLTools.getChildNodes("gml:polygonMember", geometryNode); } else if (geometryNode.nodeName == "gml:MultiSurface") { geometryMemberNodes = XMLTools.getChildNodes("gml:surfaceMember", geometryNode); } if (geometryMemberNodes == null) { //to be compatible with previous gml version geometryMemberNodes = XMLTools.getChildNodes("gml:geometryMember", geometryNode); } if (geometryMemberNodes.length == 0) { //throw new Error("No geometry members found in MultiGeometry"); if (geometryNode.nodeName == "gml:MultiPoint") { membersNode = XMLTools.getChild("gml:pointMembers", geometryNode); } else if (geometryNode.nodeName == "gml:MultiCurve") { membersNode = XMLTools.getChild("gml:curveMembers", geometryNode); } else if (geometryNode.nodeName == "gml:MultiLineString") { membersNode = XMLTools.getChild("gml:lineStringMembers", geometryNode); } else if (geometryNode.nodeName == "gml:MultiPolygon") { membersNode = XMLTools.getChild("gml:polygonMembers", geometryNode); } else if (geometryNode.nodeName == "gml:MultiSurface") { membersNode = XMLTools.getChild("gml:surfaceMembers", geometryNode); } if(membersNode != null) { if (geometryNode.nodeName == "gml:MultiPoint") { geometryNodes = XMLTools.getChildNodes("gml:Point", membersNode); } else if (geometryNode.nodeName == "gml:MultiCurve") { geometryNodes = XMLTools.getChildNodes("gml:Curve", membersNode); } else if (geometryNode.nodeName == "gml:MultiLineString") { geometryNodes = XMLTools.getChildNodes("gml:LineString", membersNode); } else if (geometryNode.nodeName == "gml:MultiPolygon") { geometryNodes = XMLTools.getChildNodes("gml:Polygon", membersNode); } else if (geometryNode.nodeName == "gml:MultiSurface") { geometryNodes = XMLTools.getChildNodes("gml:Surface", membersNode); } geometries = new Array(); for(var i:Number = 0; i < geometryNodes.length; i++) { geometries.push(doParseGML(geometryNodes[i], srsName)); } } } else { geometries = new Array(); for (var i:Number = 0; i < geometryMemberNodes.length; i++) { geometryMemberNode = XMLNode(geometryMemberNodes[i]); geometries.push(doParseGML(geometryMemberNode.firstChild, srsName)); } } if (geometryNode.nodeName == "gml:MultiPoint") { geometry = new MultiPoint(srsName, geometries); } else if (geometryNode.nodeName == "gml:MultiCurve") { geometry = new MultiLineString(srsName, geometries); } else if (geometryNode.nodeName == "gml:MultiLineString") { geometry = new MultiLineString(srsName, geometries); } else if (geometryNode.nodeName == "gml:MultiPolygon") { geometry = new MultiPolygon(srsName, geometries); } else if (geometryNode.nodeName == "gml:MultiSurface") { //TODO add class MultiSurface //geometry = new MultiSurface(geometries); geometry = new MultiPolygon(srsName, geometries); } } else if (geometryNode.nodeName == "gml:Point") { coordinatesNode = XMLTools.getChild("gml:coordinates", geometryNode); if (coordinatesNode != null) { coordinatePairsString = XMLTools.getStringValue("gml:coordinates", geometryNode); cs = XMLTools.getStringValue("cs", coordinatesNode); coordinates = coordinatePairsString.split(cs); } else { coordinatePairsString = XMLTools.getStringValue("gml:pos", geometryNode); coordinates = coordinatePairsString.split(" "); } x = Number(coordinates[0]); y = Number(coordinates[1]); geometry = new Point(srsName, x, y); } else if (geometryNode.nodeName == "gml:LinearRing") { coordinatePairsString = XMLTools.getStringValue("gml:coordinates", geometryNode); coordinatesNode = XMLTools.getChild("gml:coordinates", geometryNode); cs = XMLTools.getStringValue("cs", coordinatesNode); ts = XMLTools.getStringValue("ts", coordinatesNode); coordinatePairs = coordinatePairsString.split(ts); points = new Array(); for (var j:Number = 0; j < coordinatePairs.length; j++) { if (j < coordinatePairs.length - 1) { coordinates = coordinatePairs[j].split(cs); x = Number(coordinates[0]); y = Number(coordinates[1]); points.push(new Point(srsName, x, y)); } else { points.push(points[0]); } } geometry = new LinearRing(srsName, points); } else if (geometryNode.nodeName == "gml:LineString") { coordinatePairsString = XMLTools.getStringValue("gml:coordinates", geometryNode); coordinatesNode = XMLTools.getChild("gml:coordinates", geometryNode); cs = XMLTools.getStringValue("cs", coordinatesNode); ts = XMLTools.getStringValue("ts", coordinatesNode); coordinatePairs = coordinatePairsString.split(ts); points = new Array(); for (var j:Number = 0; j < coordinatePairs.length; j++) { coordinates = coordinatePairs[j].split(cs); x = Number(coordinates[0]); y = Number(coordinates[1]); points.push(new Point(srsName, x, y)); } geometry = new LineString(srsName, points); } else if (geometryNode.nodeName == "gml:Polygon") { outerBoundaryNode = XMLTools.getChild("gml:outerBoundaryIs", geometryNode); linearRingNode = XMLTools.getChild("gml:LinearRing", outerBoundaryNode); geometry = new Polygon(srsName, LinearRing(doParseGML(linearRingNode, srsName))); innerBoundaryNodes = XMLTools.getChildNodes("gml:innerBoundaryIs", geometryNode); for (var j:Number = 0; j < innerBoundaryNodes.length; j++) { linearRingNode = XMLTools.getChild("gml:LinearRing", innerBoundaryNodes[j]); Polygon(geometry).addInteriorRing(LinearRing(doParseGML(linearRingNode, srsName))); } } else if (geometryNode.nodeName == "gml:Curve") { var segmentsNode:XMLNode = XMLTools.getChild("gml:segments", geometryNode); var lineStringSegments:Array = XMLTools.getChildNodes("gml:LineStringSegment", segmentsNode); points = new Array(); for(var i:Number = 0; i < lineStringSegments.length; i++) { var posList:String = XMLTools.getStringValue("gml:posList", lineStringSegments[i]); var coordSkip:Number = XMLTools.getNumberValue("srsDimension", XMLTools.getChild("gml:posList", lineStringSegments[i])) - 2; coordinates = posList.split(" "); for(var j:Number = 0; j < coordinates.length; j++) { x = Number(coordinates[j++]); y = Number(coordinates[j]); j += coordSkip; points.push(new Point(srsName, x, y)); } } geometry = new LineString(srsName, points); } else if (geometryNode.nodeName == "gml:Surface") { var patchesNode:XMLNode = XMLTools.getChild("gml:patches", geometryNode); var polygonNodes:Array = XMLTools.getChildNodes("gml:PolygonPatch", patchesNode); var polygons:Array = new Array(); for(var i:Number = 0; i < polygonNodes.length; i++) { var exteriorNode:XMLNode = XMLTools.getChild("gml:exterior", polygonNodes[i]); var interiorNodes:Array = XMLTools.getChildNodes("gml:interior", polygonNodes[i]); var linearRings:Array = XMLTools.getChildNodes("gml:LinearRing", exteriorNode); points = new Array(); for(var j:Number = 0; j < linearRings.length; j++) { var posList:String = XMLTools.getStringValue("gml:posList", linearRings[j]); var coordSkip:Number = XMLTools.getNumberValue("srsDimension", XMLTools.getChild("gml:posList", linearRings[j])) - 2; coordinates = posList.split(" "); for(var k:Number = 0; k < coordinates.length - 2; k++) { x = Number(coordinates[k++]); y = Number(coordinates[k]); k += coordSkip; points.push(new Point(srsName, x, y)); } } points.push(points[0]); var polygon:Polygon = new Polygon(srsName, new LinearRing(srsName, points)); polygons.push(polygon); for(var j:Number = 0; j < interiorNodes.length; j++) { linearRings = XMLTools.getChildNodes("gml:LinearRing", interiorNodes[j]); points = new Array(); for(var k:Number = 0; k < linearRings.length; k++) { var posList:String = XMLTools.getStringValue("gml:posList", linearRings[j]); var coordSkip:Number = XMLTools.getNumberValue("srsDimension", XMLTools.getChild("gml:posList", linearRings[j])) - 2; coordinates = posList.split(" "); for(var l:Number = 0; l < coordinates.length - 2; l++) { x = Number(coordinates[l++]); y = Number(coordinates[l]); l += coordSkip; points.push(new Point(srsName, x, y)); } } points.push(points[0]); polygon.addInteriorRing(new LinearRing(srsName, points)); } } if(polygons.length == 1) { geometry = polygons[0]; } else if(polygons.length > 1) { geometry = new MultiPolygon(srsName, polygons); } } return geometry; } }