From 9ecfc61fb5d103543ca10f6aa4ef9b4171dc0907 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 3 Feb 2009 19:49:06 +0000 Subject: [PATCH] Changes to GML 2 and 3. GML 3 now supports gml:Curve, gml:Surface, and the multis - with options to write the deprecated elements. Now reading boundedBy on features as geometry.bounds. Corrected lowerCorner and upperCorner elements. Added ability to build without the old gml parser. r=ahocevar,adube (closes #1918) git-svn-id: http://svn.openlayers.org/trunk/openlayers@8808 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- lib/OpenLayers/Format/GML/Base.js | 57 +++++++-- lib/OpenLayers/Format/GML/v3.js | 190 ++++++++++++++++++++++++++++-- tests/Format/GML/cases.js | 5 + tests/Format/GML/v2.html | 2 +- tests/Format/GML/v3.html | 178 +++++++++++++++++++++++++--- 5 files changed, 395 insertions(+), 37 deletions(-) diff --git a/lib/OpenLayers/Format/GML/Base.js b/lib/OpenLayers/Format/GML/Base.js index ad80778dd9..ce0401a57f 100644 --- a/lib/OpenLayers/Format/GML/Base.js +++ b/lib/OpenLayers/Format/GML/Base.js @@ -7,6 +7,14 @@ * @requires OpenLayers/Format/GML.js */ +/** + * Though required in the full build, if the GML format is excluded, we set + * the namespace here. + */ +if(!OpenLayers.Format.GML) { + OpenLayers.Format.GML = {}; +} + /** * Class: OpenLayers.Format.GML.Base * Superclass for GML parsers. @@ -79,6 +87,13 @@ OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, { */ xy: true, + /** + * Property: geometryTypes + * {Object} Maps OpenLayers geometry class names to GML element names. + * Use before accessing this property. + */ + geometryTypes: null, + /** * Property: regExes * Compiled regular expressions for manipulating strings. @@ -108,6 +123,7 @@ OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, { initialize: function(options) { OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); this.setNamespace("feature", options.featureNS); + this.setGeometryTypes(); }, /** @@ -168,6 +184,16 @@ OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, { "featureMembers": function(node, obj) { this.readChildNodes(node, obj); }, + "name": function(node, obj) { + obj.name = this.getChildValue(node); + }, + "boundedBy": function(node, obj) { + var container = {}; + this.readChildNodes(node, container); + if(container.components && container.components.length > 0) { + obj.bounds = container.components[0]; + } + }, "Point": function(node, container) { var obj = {points: []}; this.readChildNodes(node, obj); @@ -314,6 +340,10 @@ OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, { "_typeName": function(node, obj) { var container = {components: [], attributes: {}}; this.readChildNodes(node, container); + // look for common gml namespaced elements + if(container.name) { + container.attributes.name = container.name; + } var feature = new OpenLayers.Feature.Vector( container.components[0], container.attributes ); @@ -327,7 +357,10 @@ OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, { feature.geometry.transform( this.externalProjection, this.internalProjection ); - } + } + if(container.bounds) { + feature.geometry.bounds = container.bounds; + } obj.features.push(feature); }, "_geometry": function(node, obj) { @@ -499,17 +532,19 @@ OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, { }, /** - * Property: geometryTypes - * {Object} Maps OpenLayers geometry class names to GML element names. + * Function: setGeometryTypes + * Sets the mapping. */ - geometryTypes: { - "OpenLayers.Geometry.Point": "Point", - "OpenLayers.Geometry.MultiPoint": "MultiPoint", - "OpenLayers.Geometry.LineString": "LineString", - "OpenLayers.Geometry.MultiLineString": "MultiLineString", - "OpenLayers.Geometry.Polygon": "Polygon", - "OpenLayers.Geometry.MultiPolygon": "MultiPolygon", - "OpenLayers.Geometry.Collection": "GeometryCollection" + setGeometryTypes: function() { + this.geometryTypes = { + "OpenLayers.Geometry.Point": "Point", + "OpenLayers.Geometry.MultiPoint": "MultiPoint", + "OpenLayers.Geometry.LineString": "LineString", + "OpenLayers.Geometry.MultiLineString": "MultiLineString", + "OpenLayers.Geometry.Polygon": "Polygon", + "OpenLayers.Geometry.MultiPolygon": "MultiPolygon", + "OpenLayers.Geometry.Collection": "GeometryCollection" + }; }, CLASS_NAME: "OpenLayers.Format.GML.Base" diff --git a/lib/OpenLayers/Format/GML/v3.js b/lib/OpenLayers/Format/GML/v3.js index f4f5335271..1c158b7aa7 100644 --- a/lib/OpenLayers/Format/GML/v3.js +++ b/lib/OpenLayers/Format/GML/v3.js @@ -22,6 +22,46 @@ OpenLayers.Format.GML.v3 = OpenLayers.Class(OpenLayers.Format.GML.Base, { */ schemaLocation: "http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd", + /** + * Property: curve + * {Boolean} Write gml:Curve instead of gml:LineString elements. This also + * affects the elements in multi-part geometries. Default is false. + * To write gml:Curve elements instead of gml:LineString, set curve + * to true in the options to the contstructor (cannot be changed after + * instantiation). + */ + curve: false, + + /** + * Property: multiCurve + * {Boolean} Write gml:MultiCurve instead of gml:MultiLineString. Since + * the latter is deprecated in GML 3, the default is true. To write + * gml:MultiLineString instead of gml:MultiCurve, set multiCurve to + * false in the options to the constructor (cannot be changed after + * instantiation). + */ + multiCurve: true, + + /** + * Property: surface + * {Boolean} Write gml:Surface instead of gml:Polygon elements. This also + * affects the elements in multi-part geometries. Default is false. + * To write gml:Surface elements instead of gml:Polygon, set surface + * to true in the options to the contstructor (cannot be changed after + * instantiation). + */ + surface: false, + + /** + * Property: multiSurface + * {Boolean} Write gml:multiSurface instead of gml:MultiPolygon. Since + * the latter is deprecated in GML 3, the default is true. To write + * gml:MultiPolygon instead of gml:multiSurface, set multiSurface to + * false in the options to the constructor (cannot be changed after + * instantiation). + */ + multiSurface: true, + /** * Constructor: OpenLayers.Format.GML.v3 * Create a parser for GML v3. @@ -52,6 +92,26 @@ OpenLayers.Format.GML.v3 = OpenLayers.Class(OpenLayers.Format.GML.Base, { "featureMembers": function(node, obj) { this.readChildNodes(node, obj); }, + "Curve": function(node, container) { + var obj = {points: []}; + this.readChildNodes(node, obj); + if(!container.components) { + container.components = []; + } + container.components.push( + new OpenLayers.Geometry.LineString(obj.points) + ); + }, + "segments": function(node, obj) { + this.readChildNodes(node, obj); + }, + "LineStringSegment": function(node, container) { + var obj = {}; + this.readChildNodes(node, obj); + if(obj.points) { + Array.prototype.push.apply(container.points, obj.points); + } + }, "pos": function(node, obj) { var str = this.getChildValue(node).replace( this.regExes.trimSpace, "" @@ -90,6 +150,15 @@ OpenLayers.Format.GML.v3 = OpenLayers.Class(OpenLayers.Format.GML.Base, { } obj.points = points; }, + "Surface": function(node, obj) { + this.readChildNodes(node, obj); + }, + "patches": function(node, obj) { + this.readChildNodes(node, obj); + }, + "PolygonPatch": function(node, obj) { + this.readers.gml.Polygon.apply(this, [node, obj]); + }, "exterior": function(node, container) { var obj = {}; this.readChildNodes(node, obj); @@ -100,6 +169,18 @@ OpenLayers.Format.GML.v3 = OpenLayers.Class(OpenLayers.Format.GML.Base, { this.readChildNodes(node, obj); container.inner.push(obj.components[0]); }, + "MultiCurve": function(node, container) { + var obj = {components: []}; + this.readChildNodes(node, obj); + if(obj.components.length > 0) { + container.components = [ + new OpenLayers.Geometry.MultiLineString(obj.components) + ]; + } + }, + "curveMember": function(node, obj) { + this.readChildNodes(node, obj); + }, "MultiSurface": function(node, container) { var obj = {components: []}; this.readChildNodes(node, obj); @@ -141,12 +222,12 @@ OpenLayers.Format.GML.v3 = OpenLayers.Class(OpenLayers.Format.GML.Base, { }, "lowerCorner": function(node, container) { var obj = {}; - this.readChildNodes(node, obj); + this.readers.gml.pos.apply(this, [node, obj]); container.points[0] = obj.points[0]; }, "upperCorner": function(node, container) { var obj = {}; - this.readChildNodes(node, obj); + this.readers.gml.pos.apply(this, [node, obj]); container.points[1] = obj.points[0]; } }, OpenLayers.Format.GML.Base.prototype.readers["gml"]), @@ -215,6 +296,21 @@ OpenLayers.Format.GML.v3 = OpenLayers.Class(OpenLayers.Format.GML.Base, { this.writeNode("posList", geometry.components, node); return node; }, + "Curve": function(geometry) { + var node = this.createElementNSPlus("gml:Curve"); + this.writeNode("segments", geometry, node); + return node; + }, + "segments": function(geometry) { + var node = this.createElementNSPlus("gml:segments"); + this.writeNode("LineStringSegment", geometry, node); + return node; + }, + "LineStringSegment": function(geometry) { + var node = this.createElementNSPlus("gml:LineStringSegment"); + this.writeNode("posList", geometry.components, node); + return node; + }, "posList": function(points) { // only 2d for simple features profile var len = points.length; @@ -232,6 +328,28 @@ OpenLayers.Format.GML.v3 = OpenLayers.Class(OpenLayers.Format.GML.Base, { value: parts.join(" ") }); }, + "Surface": function(geometry) { + var node = this.createElementNSPlus("gml:Surface"); + this.writeNode("patches", geometry, node); + return node; + }, + "patches": function(geometry) { + var node = this.createElementNSPlus("gml:patches"); + this.writeNode("PolygonPatch", geometry, node); + return node; + }, + "PolygonPatch": function(geometry) { + var node = this.createElementNSPlus("gml:PolygonPatch", { + attributes: {interpolation: "planar"} + }); + this.writeNode("exterior", geometry.components[0], node); + for(var i=1, len=geometry.components.length; i mapping. + */ + setGeometryTypes: function() { + this.geometryTypes = { + "OpenLayers.Geometry.Point": "Point", + "OpenLayers.Geometry.MultiPoint": "MultiPoint", + "OpenLayers.Geometry.LineString": (this.curve === true) ? "Curve": "LineString", + "OpenLayers.Geometry.MultiLineString": (this.multiCurve === false) ? "MultiLineString" : "MultiCurve", + "OpenLayers.Geometry.Polygon": (this.surface === true) ? "Surface" : "Polygon", + "OpenLayers.Geometry.MultiPolygon": (this.multiSurface === false) ? "MultiPolygon" : "MultiSurface", + "OpenLayers.Geometry.Collection": "GeometryCollection" + }; + }, CLASS_NAME: "OpenLayers.Format.GML.v3" diff --git a/tests/Format/GML/cases.js b/tests/Format/GML/cases.js index 214e84fd71..258c570416 100644 --- a/tests/Format/GML/cases.js +++ b/tests/Format/GML/cases.js @@ -209,14 +209,19 @@ var cases = { OpenLayers.Util.extend(cases, { "v3/point.xml": cases["v2/point-coordinates.xml"], "v3/linestring.xml": cases["v2/linestring-coordinates.xml"], + "v3/curve.xml": cases["v2/linestring-coordinates.xml"], "v3/polygon.xml": cases["v2/polygon-coordinates.xml"], + "v3/surface.xml": cases["v2/polygon-coordinates.xml"], "v3/multipoint-singular.xml": cases["v2/multipoint-coordinates.xml"], "v3/multipoint-plural.xml": cases["v2/multipoint-coordinates.xml"], "v3/multilinestring-singular.xml": cases["v2/multilinestring-coordinates.xml"], "v3/multilinestring-plural.xml": cases["v2/multilinestring-coordinates.xml"], + "v3/multicurve-singular.xml": cases["v2/multilinestring-coordinates.xml"], + "v3/multicurve-curve.xml": cases["v2/multilinestring-coordinates.xml"], "v3/multipolygon-singular.xml": cases["v2/multipolygon-coordinates.xml"], "v3/multipolygon-plural.xml": cases["v2/multipolygon-coordinates.xml"], "v3/multisurface-singular.xml": cases["v2/multipolygon-coordinates.xml"], "v3/multisurface-plural.xml": cases["v2/multipolygon-coordinates.xml"], + "v3/multisurface-surface.xml": cases["v2/multipolygon-coordinates.xml"], "v3/envelope.xml": cases["v2/box-coordinates.xml"] }); \ No newline at end of file diff --git a/tests/Format/GML/v2.html b/tests/Format/GML/v2.html index 6684883ab8..730e7eaf41 100644 --- a/tests/Format/GML/v2.html +++ b/tests/Format/GML/v2.html @@ -599,7 +599,7 @@ -->
diff --git a/tests/Format/GML/v3.html b/tests/Format/GML/v3.html index e24a2fb0a8..d8f1003494 100644 --- a/tests/Format/GML/v3.html +++ b/tests/Format/GML/v3.html @@ -10,11 +10,14 @@ "v2/linestring-coord.xml", "v2/linestring-coordinates.xml", "v2/multipoint-coord.xml", "v2/multipoint-coordinates.xml", "v2/multilinestring-coord.xml", "v2/multilinestring-coordinates.xml", - "v3/point.xml", "v3/linestring.xml", "v3/polygon.xml", + "v3/point.xml", "v3/linestring.xml", "v3/curve.xml", + "v3/polygon.xml", "v3/surface.xml", "v3/multipoint-singular.xml", "v3/multipoint-plural.xml", "v3/multilinestring-singular.xml", "v3/multilinestring-plural.xml", + "v3/multicurve-singular.xml", "v3/multicurve-curve.xml", "v3/multipolygon-singular.xml", "v3/multipolygon-plural.xml", - "v3/multisurface-singular.xml", "v3/multisurface-plural.xml" + "v3/multisurface-singular.xml", "v3/multisurface-plural.xml", + "v3/multisurface-surface.xml" ]; var len = files.length; @@ -88,29 +91,41 @@ function test_writeNode_geometry(t) { // we only care to write the 'pos' and 'posList' variants of GML 3 - conforming with simple features profile var files = [ - "v3/point.xml", - "v3/linestring.xml", - "v3/polygon.xml", - "v3/multipoint-singular.xml", - "v3/multilinestring-singular.xml", - "v3/multipolygon-singular.xml" + {path: "v3/point.xml"}, + {path: "v3/linestring.xml"}, + {path: "v3/curve.xml", options: {curve: true}}, + {path: "v3/polygon.xml"}, + {path: "v3/surface.xml", options: {surface: true}}, + {path: "v3/multipoint-singular.xml"}, + {path: "v3/multilinestring-singular.xml", options: {multiCurve: false}}, + {path: "v3/multicurve-singular.xml"}, + {path: "v3/multicurve-curve.xml", options: {curve: true}}, + {path: "v3/multipolygon-singular.xml", options: {multiSurface: false}}, + {path: "v3/multisurface-singular.xml"}, + {path: "v3/multisurface-surface.xml", options: {surface: true}} ]; var len = files.length; t.plan(len); - var format = new OpenLayers.Format.GML.v3({ + var defaults = { featureType: "feature", featureNS: "http://example.com/feature", srsName: "foo" // GML geometry collections require srsName, we only write if provided - }); - var file, geom, doc, node; + }; + + var format, options, file, geom, doc, node; for(var i=0; i
+
+
+
+
+