From 97e55039ea059c6673c06abc68c5d5457ccc0682 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sun, 1 Mar 2009 05:40:21 +0000 Subject: [PATCH] Adding support for reading and writing spatial filters with Within, Contains, and Intersects elements. Thanks pvalsecc for the original patch. r=ahocevar (closes #1959) git-svn-id: http://svn.openlayers.org/trunk/openlayers@8921 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- lib/OpenLayers/Filter/Spatial.js | 4 + lib/OpenLayers/Format/Filter/v1.js | 74 +++++++++++---- lib/OpenLayers/Format/Filter/v1_0_0.js | 29 ++++++ lib/OpenLayers/Format/Filter/v1_1_0.js | 28 ++++++ tests/Format/Filter/v1.html | 126 +++++++++++++++++++++++++ tests/Format/Filter/v1_0_0.html | 76 ++++++++++++++- tests/Format/Filter/v1_1_0.html | 35 +++++++ tests/list-tests.html | 1 + 8 files changed, 356 insertions(+), 17 deletions(-) create mode 100644 tests/Format/Filter/v1.html diff --git a/lib/OpenLayers/Filter/Spatial.js b/lib/OpenLayers/Filter/Spatial.js index 8a2604370a..f5e5e7b7a7 100644 --- a/lib/OpenLayers/Filter/Spatial.js +++ b/lib/OpenLayers/Filter/Spatial.js @@ -24,6 +24,8 @@ OpenLayers.Filter.Spatial = OpenLayers.Class(OpenLayers.Filter, { * - OpenLayers.Filter.Spatial.BBOX * - OpenLayers.Filter.Spatial.INTERSECTS * - OpenLayers.Filter.Spatial.DWITHIN + * - OpenLayers.Filter.Spatial.WITHIN + * - OpenLayers.Filter.Spatial.CONTAINS */ type: null, @@ -107,3 +109,5 @@ OpenLayers.Filter.Spatial = OpenLayers.Class(OpenLayers.Filter, { OpenLayers.Filter.Spatial.BBOX = "BBOX"; OpenLayers.Filter.Spatial.INTERSECTS = "INTERSECTS"; OpenLayers.Filter.Spatial.DWITHIN = "DWITHIN"; +OpenLayers.Filter.Spatial.WITHIN = "WITHIN"; +OpenLayers.Filter.Spatial.CONTAINS = "CONTAINS"; diff --git a/lib/OpenLayers/Format/Filter/v1.js b/lib/OpenLayers/Format/Filter/v1.js index c81654623d..31966c115e 100644 --- a/lib/OpenLayers/Format/Filter/v1.js +++ b/lib/OpenLayers/Format/Filter/v1.js @@ -178,11 +178,49 @@ OpenLayers.Format.Filter.v1 = OpenLayers.Class(OpenLayers.Format.XML, { }, "UpperBoundary": function(node, filter) { filter.upperBoundary = this.readOgcExpression(node); + }, + "Intersects": function(node, obj) { + this.readSpatial(node, obj, OpenLayers.Filter.Spatial.INTERSECTS); + }, + "Within": function(node, obj) { + this.readSpatial(node, obj, OpenLayers.Filter.Spatial.WITHIN); + }, + "Contains": function(node, obj) { + this.readSpatial(node, obj, OpenLayers.Filter.Spatial.CONTAINS); + }, + "DWithin": function(node, obj) { + this.readSpatial(node, obj, OpenLayers.Filter.Spatial.DWITHIN); + }, + "Distance": function(node, obj) { + obj.distance = parseInt(this.getChildValue(node)); + obj.distanceUnits = node.getAttribute("units"); } - } }, + /** + * Method: readSpatial + * + * Read a {} filter. + * + * Parameters: + * node - {DOMElement} A DOM element that contains an ogc:expression. + * obj - {Object} The target object. + * type - {String} One of the OpenLayers.Filter.Spatial.* constants. + * + * Returns: + * {} The created filter. + */ + readSpatial: function(node, obj, type) { + var filter = new OpenLayers.Filter.Spatial({ + type: type + }); + this.readChildNodes(node, filter); + filter.value = filter.components[0]; + delete filter.components; + obj.filters.push(filter); + }, + /** * Method: readOgcExpression * Limited support for OGC expressions. @@ -343,29 +381,31 @@ OpenLayers.Format.Filter.v1 = OpenLayers.Class(OpenLayers.Format.XML, { this.writeNode("Literal", filter.upperBoundary, node); return node; }, + "INTERSECTS": function(filter) { + return this.writeSpatial(filter, "Intersects"); + }, + "WITHIN": function(filter) { + return this.writeSpatial(filter, "Within"); + }, + "CONTAINS": function(filter) { + return this.writeSpatial(filter, "Contains"); + }, "DWITHIN": function(filter) { - var node = this.createElementNSPlus("ogc:DWithin"); - this.writeNode("PropertyName", filter, node); - var child = this.writeNode("feature:_geometry", filter.value); - node.appendChild(child.firstChild); + var node = this.writeSpatial(filter, "DWithin"); this.writeNode("Distance", filter, node); return node; }, - "INTERSECTS": function(filter) { - var node = this.createElementNSPlus("ogc:Intersects"); - this.writeNode("PropertyName", filter, node); - var child = this.writeNode("feature:_geometry", filter.value); - node.appendChild(child.firstChild); - return node; - }, "Distance": function(filter) { - return this.createElementNSPlus("ogc:Distance", - {attributes: {units: filter.distanceUnits}, - value: filter.distance}); + return this.createElementNSPlus("ogc:Distance", { + attributes: { + units: filter.distanceUnits + }, + value: filter.distance + }); } } }, - + /** * Method: getFilterType */ @@ -396,6 +436,8 @@ OpenLayers.Format.Filter.v1 = OpenLayers.Class(OpenLayers.Format.XML, { "~": "PropertyIsLike", "BBOX": "BBOX", "DWITHIN": "DWITHIN", + "WITHIN": "WITHIN", + "CONTAINS": "CONTAINS", "INTERSECTS": "INTERSECTS" }, diff --git a/lib/OpenLayers/Format/Filter/v1_0_0.js b/lib/OpenLayers/Format/Filter/v1_0_0.js index a10ed50755..6024836fe7 100644 --- a/lib/OpenLayers/Format/Filter/v1_0_0.js +++ b/lib/OpenLayers/Format/Filter/v1_0_0.js @@ -111,6 +111,35 @@ OpenLayers.Format.Filter.v1_0_0 = OpenLayers.Class( }, + /** + * Method: writeSpatial + * + * Read a {} filter and converts it into XML. + * + * Parameters: + * filter - {} The filter. + * name - {String} Name of the generated XML element. + * + * Returns: + * {DOMElement} The created XML element. + */ + writeSpatial: function(filter, name) { + var node = this.createElementNSPlus("ogc:"+name); + this.writeNode("PropertyName", filter, node); + var child; + if(filter.value instanceof OpenLayers.Geometry) { + child = this.writeNode("feature:_geometry", filter.value).firstChild; + } else { + child = this.writeNode("gml:Box", filter.value); + } + if(filter.projection) { + child.setAttribute("srsName", filter.projection); + } + node.appendChild(child); + return node; + }, + + CLASS_NAME: "OpenLayers.Format.Filter.v1_0_0" }); \ No newline at end of file diff --git a/lib/OpenLayers/Format/Filter/v1_1_0.js b/lib/OpenLayers/Format/Filter/v1_1_0.js index 9042503630..1d0bfca30a 100644 --- a/lib/OpenLayers/Format/Filter/v1_1_0.js +++ b/lib/OpenLayers/Format/Filter/v1_1_0.js @@ -125,6 +125,34 @@ OpenLayers.Format.Filter.v1_1_0 = OpenLayers.Class( "feature": OpenLayers.Format.GML.v3.prototype.writers["feature"] }, + /** + * Method: writeSpatial + * + * Read a {} filter and converts it into XML. + * + * Parameters: + * filter - {} The filter. + * name - {String} Name of the generated XML element. + * + * Returns: + * {DOMElement} The created XML element. + */ + writeSpatial: function(filter, name) { + var node = this.createElementNSPlus("ogc:"+name); + this.writeNode("PropertyName", filter, node); + var child; + if(filter.value instanceof OpenLayers.Geometry) { + child = this.writeNode("feature:_geometry", filter.value).firstChild; + } else { + child = this.writeNode("gml:Envelope", filter.value); + } + if(filter.projection) { + child.setAttribute("srsName", filter.projection); + } + node.appendChild(child); + return node; + }, + CLASS_NAME: "OpenLayers.Format.Filter.v1_1_0" }); \ No newline at end of file diff --git a/tests/Format/Filter/v1.html b/tests/Format/Filter/v1.html new file mode 100644 index 0000000000..5471717387 --- /dev/null +++ b/tests/Format/Filter/v1.html @@ -0,0 +1,126 @@ + + + + + + + + diff --git a/tests/Format/Filter/v1_0_0.html b/tests/Format/Filter/v1_0_0.html index b268392267..8aab3d76ac 100644 --- a/tests/Format/Filter/v1_0_0.html +++ b/tests/Format/Filter/v1_0_0.html @@ -77,7 +77,81 @@ t.xml_eq(node, out, "bbox correctly written"); } - + + function test_DWithin(t) { + + t.plan(6); + + var str = + '' + + '' + + 'Geometry' + + '' + + '2488789,289552' + + '' + + '1000' + + '' + + ''; + + var format = new OpenLayers.Format.Filter.v1_0_0(); + var filter = new OpenLayers.Filter.Spatial({ + type: OpenLayers.Filter.Spatial.DWITHIN, + property: "Geometry", + value: new OpenLayers.Geometry.Point(2488789,289552), + distance: 1000, + distanceUnits: "m" + }); + + // test writing + var node = format.write(filter); + t.xml_eq(node, str, "filter correctly written"); + + // test reading + var doc = (new OpenLayers.Format.XML).read(str); + var got = format.read(doc.firstChild); + t.eq(got.type, filter.type, "read correct type"); + t.eq(got.property, filter.property, "read correct property"); + t.geom_eq(got.value, filter.value, "read correct value"); + t.eq(got.distance, filter.distance, "read correct distance"); + t.eq(got.distanceUnits, filter.distanceUnits, "read correct distance units"); + + } + + function test_Intersects(t) { + + t.plan(4); + + var str = + '' + + '' + + 'Geometry' + + '' + + '-180,-90 180,90' + + '' + + '' + + ''; + + var format = new OpenLayers.Format.Filter.v1_0_0(); + var filter = new OpenLayers.Filter.Spatial({ + type: OpenLayers.Filter.Spatial.INTERSECTS, + property: "Geometry", + value: new OpenLayers.Bounds(-180, -90, 180, 90), + projection: "EPSG:4326" + }); + + // test writing + var node = format.write(filter); + t.xml_eq(node, str, "filter correctly written"); + + // test reading + var doc = (new OpenLayers.Format.XML).read(str); + var got = format.read(doc.firstChild); + t.eq(got.type, filter.type, "read correct type"); + t.eq(got.property, filter.property, "read correct property"); + t.eq(got.value.toArray(), filter.value.toArray(), "read correct value"); + + } + diff --git a/tests/Format/Filter/v1_1_0.html b/tests/Format/Filter/v1_1_0.html index cef81ec19c..0fc479940f 100644 --- a/tests/Format/Filter/v1_1_0.html +++ b/tests/Format/Filter/v1_1_0.html @@ -167,6 +167,41 @@ t.xml_eq(node, out, "bbox correctly written"); } + function test_Intersects(t) { + + t.plan(4); + + var str = + '' + + '' + + 'Geometry' + + '' + + '-180 -90' + + '180 90' + + '' + + '' + + ''; + + var format = new OpenLayers.Format.Filter.v1_1_0(); + var filter = new OpenLayers.Filter.Spatial({ + type: OpenLayers.Filter.Spatial.INTERSECTS, + property: "Geometry", + value: new OpenLayers.Bounds(-180, -90, 180, 90), + projection: "EPSG:4326" + }); + + // test writing + var node = format.write(filter); + t.xml_eq(node, str, "filter correctly written"); + + // test reading + var doc = (new OpenLayers.Format.XML).read(str); + var got = format.read(doc.firstChild); + t.eq(got.type, filter.type, "read correct type"); + t.eq(got.property, filter.property, "read correct property"); + t.eq(got.value.toArray(), filter.value.toArray(), "read correct value"); + + } diff --git a/tests/list-tests.html b/tests/list-tests.html index 9ef7db977f..d4bb353606 100644 --- a/tests/list-tests.html +++ b/tests/list-tests.html @@ -52,6 +52,7 @@
  • Format/SLD.html
  • Format/SLD/v1_0_0.html
  • Format/Filter.html
  • +
  • Format/Filter/v1.html
  • Format/Filter/v1_0_0.html
  • Format/Filter/v1_1_0.html
  • Format/WFSDescribeFeatureType.html