From 567a9d7a5a046af3437b1914f938eebbc160561a Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Tue, 31 Mar 2015 11:56:52 +0200 Subject: [PATCH 1/4] Make ol.geom.Geometry inherit from ol.Object This will allow storing per-geometry properties. --- src/ol/geom/geometry.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ol/geom/geometry.js b/src/ol/geom/geometry.js index c1ff3da2c9..30ecaa7247 100644 --- a/src/ol/geom/geometry.js +++ b/src/ol/geom/geometry.js @@ -2,7 +2,7 @@ goog.provide('ol.geom.Geometry'); goog.provide('ol.geom.GeometryType'); goog.require('goog.functions'); -goog.require('ol.Observable'); +goog.require('ol.Object'); goog.require('ol.extent'); goog.require('ol.proj'); @@ -50,7 +50,7 @@ ol.geom.GeometryLayout = { * Base class for vector geometries. * * @constructor - * @extends {ol.Observable} + * @extends {ol.Object} * @fires change Triggered when the geometry changes. * @api stable */ @@ -89,7 +89,7 @@ ol.geom.Geometry = function() { this.simplifiedGeometryRevision = 0; }; -goog.inherits(ol.geom.Geometry, ol.Observable); +goog.inherits(ol.geom.Geometry, ol.Object); /** From ea8ee16f49312d33e95f11e45dea431ef941f04b Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Tue, 31 Mar 2015 14:07:04 +0200 Subject: [PATCH 2/4] Fix return type of ol.xml.pushParseAndPop --- src/ol/xml.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/xml.js b/src/ol/xml.js index 908e6bbb9e..996678c857 100644 --- a/src/ol/xml.js +++ b/src/ol/xml.js @@ -679,7 +679,7 @@ ol.xml.parseNode = function(parsersNS, node, objectStack, opt_this) { * @param {Node} node Node. * @param {Array.<*>} objectStack Object stack. * @param {*=} opt_this The object to use as `this`. - * @return {T|undefined} Object. + * @return {T} Object. * @template T */ ol.xml.pushParseAndPop = function( From 5bd63f7e2ccbd77fef4e6de3730980ecf6d36318 Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Mon, 30 Mar 2015 20:21:01 +0200 Subject: [PATCH 3/4] Parse KML extrude and altitudeMode of simple geometries Point, LineString and Polygon are handled. LinearRing properties are not handled. An 'extrude' boolean property is set in the geometry properties. An 'altitudeMode' string property is set in the geometry properties. --- src/ol/format/kmlformat.js | 28 +++++++++++++++++++++++++++ test/spec/ol/format/kmlformat.test.js | 12 ++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/ol/format/kmlformat.js b/src/ol/format/kmlformat.js index 841914cc94..8ad3401b7c 100644 --- a/src/ol/format/kmlformat.js +++ b/src/ol/format/kmlformat.js @@ -802,11 +802,15 @@ ol.format.KML.readLineString_ = function(node, objectStack) { 'node.nodeType should be ELEMENT'); goog.asserts.assert(node.localName == 'LineString', 'localName should be LineString'); + var properties = ol.xml.pushParseAndPop(/** @type {Object} */ ({}), + ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_, node, + objectStack); var flatCoordinates = ol.format.KML.readFlatCoordinatesFromNode_(node, objectStack); if (goog.isDef(flatCoordinates)) { var lineString = new ol.geom.LineString(null); lineString.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates); + lineString.setProperties(properties); return lineString; } else { return undefined; @@ -825,12 +829,16 @@ ol.format.KML.readLinearRing_ = function(node, objectStack) { 'node.nodeType should be ELEMENT'); goog.asserts.assert(node.localName == 'LinearRing', 'localName should be LinearRing'); + var properties = ol.xml.pushParseAndPop(/** @type {Object} */ ({}), + ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_, node, + objectStack); var flatCoordinates = ol.format.KML.readFlatCoordinatesFromNode_(node, objectStack); if (goog.isDef(flatCoordinates)) { var polygon = new ol.geom.Polygon(null); polygon.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates, [flatCoordinates.length]); + polygon.setProperties(properties); return polygon; } else { return undefined; @@ -920,6 +928,9 @@ ol.format.KML.readPoint_ = function(node, objectStack) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT, 'node.nodeType should be ELEMENT'); goog.asserts.assert(node.localName == 'Point', 'localName should be Point'); + var properties = ol.xml.pushParseAndPop(/** @type {Object} */ ({}), + ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_, node, + objectStack); var flatCoordinates = ol.format.KML.readFlatCoordinatesFromNode_(node, objectStack); if (goog.isDefAndNotNull(flatCoordinates)) { @@ -927,6 +938,7 @@ ol.format.KML.readPoint_ = function(node, objectStack) { goog.asserts.assert(flatCoordinates.length == 3, 'flatCoordinates should have a length of 3'); point.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates); + point.setProperties(properties); return point; } else { return undefined; @@ -945,6 +957,9 @@ ol.format.KML.readPolygon_ = function(node, objectStack) { 'node.nodeType should be ELEMENT'); goog.asserts.assert(node.localName == 'Polygon', 'localName should be Polygon'); + var properties = ol.xml.pushParseAndPop(/** @type {Object} */ ({}), + ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_, node, + objectStack); var flatLinearRings = ol.xml.pushParseAndPop( /** @type {Array.>} */ ([null]), ol.format.KML.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack); @@ -960,6 +975,7 @@ ol.format.KML.readPolygon_ = function(node, objectStack) { } polygon.setFlatCoordinates( ol.geom.GeometryLayout.XYZ, flatCoordinates, ends); + polygon.setProperties(properties); return polygon; } else { return undefined; @@ -1266,6 +1282,18 @@ ol.format.KML.EXTENDED_DATA_PARSERS_ = ol.xml.makeParsersNS( }); +/** + * @const + * @type {Object.>} + * @private + */ +ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_ = ol.xml.makeParsersNS( + ol.format.KML.NAMESPACE_URIS_, { + 'extrude': ol.xml.makeObjectPropertySetter(ol.format.XSD.readBoolean), + 'altitudeMode': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString) + }); + + /** * @const * @type {Object.>} diff --git a/test/spec/ol/format/kmlformat.test.js b/test/spec/ol/format/kmlformat.test.js index 1aca2f4053..db7e21423b 100644 --- a/test/spec/ol/format/kmlformat.test.js +++ b/test/spec/ol/format/kmlformat.test.js @@ -133,6 +133,8 @@ describe('ol.format.KML', function() { ' ' + ' ' + ' 1,2,3' + + ' 0' + + ' absolute' + ' ' + ' ' + ''; @@ -143,6 +145,8 @@ describe('ol.format.KML', function() { var g = f.getGeometry(); expect(g).to.be.an(ol.geom.Point); expect(g.getCoordinates()).to.eql([1, 2, 3]); + expect(g.get('extrude')).to.be(false); + expect(g.get('altitudeMode')).to.be('absolute'); }); it('can transform and read Point geometries', function() { @@ -338,6 +342,8 @@ describe('ol.format.KML', function() { ' ' + ' ' + ' 1,2,3 4,5,6' + + ' 0' + + ' absolute' + ' ' + ' ' + ''; @@ -348,6 +354,8 @@ describe('ol.format.KML', function() { var g = f.getGeometry(); expect(g).to.be.an(ol.geom.LineString); expect(g.getCoordinates()).to.eql([[1, 2, 3], [4, 5, 6]]); + expect(g.get('extrude')).to.be(false); + expect(g.get('altitudeMode')).to.be('absolute'); }); it('can write XY LineString geometries', function() { @@ -540,6 +548,8 @@ describe('ol.format.KML', function() { '' + ' ' + ' ' + + ' 0' + + ' absolute' + ' ' + ' ' + ' 0,0,1 0,5,1 5,5,2 5,0,3' + @@ -556,6 +566,8 @@ describe('ol.format.KML', function() { expect(g).to.be.an(ol.geom.Polygon); expect(g.getCoordinates()).to.eql( [[[0, 0, 1], [0, 5, 1], [5, 5, 2], [5, 0, 3]]]); + expect(g.get('extrude')).to.be(false); + expect(g.get('altitudeMode')).to.be('absolute'); }); it('can write XY Polygon geometries', function() { From f25302f8b749ed2d9c32d3d92c52bf049058c4ae Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Tue, 31 Mar 2015 15:14:12 +0200 Subject: [PATCH 4/4] Parse KML extrude and altitudeMode from multi geometries Handle MultiPoint, MultiLineString, MultiPolygon. LinearRing properties are not handled. An 'extrude' boolean array property is set in the geometry properties. An 'altitudeMode' string array property is set in the geometry properties. --- src/ol/format/kmlformat.js | 34 +++++++++++++++++++++++++++ test/spec/ol/format/kmlformat.test.js | 32 +++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/src/ol/format/kmlformat.js b/src/ol/format/kmlformat.js index 8ad3401b7c..5036018c9d 100644 --- a/src/ol/format/kmlformat.js +++ b/src/ol/format/kmlformat.js @@ -897,14 +897,17 @@ ol.format.KML.readMultiGeometry_ = function(node, objectStack) { } var multiPoint = new ol.geom.MultiPoint(null); multiPoint.setFlatCoordinates(layout, flatCoordinates); + ol.format.KML.setCommonGeometryProperties_(multiPoint, geometries); return multiPoint; } else if (type == ol.geom.GeometryType.LINE_STRING) { var multiLineString = new ol.geom.MultiLineString(null); multiLineString.setLineStrings(geometries); + ol.format.KML.setCommonGeometryProperties_(multiLineString, geometries); return multiLineString; } else if (type == ol.geom.GeometryType.POLYGON) { var multiPolygon = new ol.geom.MultiPolygon(null); multiPolygon.setPolygons(geometries); + ol.format.KML.setCommonGeometryProperties_(multiPolygon, geometries); return multiPolygon; } else if (type == ol.geom.GeometryType.GEOMETRY_COLLECTION) { return new ol.geom.GeometryCollection(geometries); @@ -1026,6 +1029,37 @@ ol.format.KML.readStyle_ = function(node, objectStack) { }; +/** + * Reads an array of geometries and creates arrays for common geometry + * properties. Then sets them to the multi geometry. + * @param {ol.geom.MultiPoint|ol.geom.MultiLineString|ol.geom.MultiPolygon} + * multiGeometry + * @param {Array.} geometries + * @private + */ +ol.format.KML.setCommonGeometryProperties_ = function(multiGeometry, + geometries) { + var ii = geometries.length; + var extrudes = new Array(geometries.length); + var altitudeModes = new Array(geometries.length); + var geometry, i, hasExtrude, hasAltitudeMode; + hasExtrude = hasAltitudeMode = false; + for (i = 0; i < ii; ++i) { + geometry = geometries[i]; + extrudes[i] = geometry.get('extrude'); + altitudeModes[i] = geometry.get('altitudeMode'); + hasExtrude = hasExtrude || goog.isDef(extrudes[i]); + hasAltitudeMode = hasAltitudeMode || goog.isDef(altitudeModes[i]); + } + if (hasExtrude) { + multiGeometry.set('extrude', extrudes); + } + if (hasAltitudeMode) { + multiGeometry.set('altitudeMode', altitudeModes); + } +}; + + /** * @param {Node} node Node. * @param {Array.<*>} objectStack Object stack. diff --git a/test/spec/ol/format/kmlformat.test.js b/test/spec/ol/format/kmlformat.test.js index db7e21423b..6050a7976f 100644 --- a/test/spec/ol/format/kmlformat.test.js +++ b/test/spec/ol/format/kmlformat.test.js @@ -754,9 +754,13 @@ describe('ol.format.KML', function() { ' ' + ' ' + ' 1,2,3' + + ' 0' + + ' absolute' + ' ' + ' ' + ' 4,5,6' + + ' 1' + + ' clampToGround' + ' ' + ' ' + ' ' + @@ -768,6 +772,14 @@ describe('ol.format.KML', function() { var g = f.getGeometry(); expect(g).to.be.an(ol.geom.MultiPoint); expect(g.getCoordinates()).to.eql([[1, 2, 3], [4, 5, 6]]); + expect(g.get('extrude')).to.be.an('array'); + expect(g.get('extrude')).to.have.length(2); + expect(g.get('extrude')[0]).to.be(false); + expect(g.get('extrude')[1]).to.be(true); + expect(g.get('altitudeMode')).to.be.an('array'); + expect(g.get('altitudeMode')).to.have.length(2); + expect(g.get('altitudeMode')[0]).to.be('absolute'); + expect(g.get('altitudeMode')[1]).to.be('clampToGround'); }); it('can write MultiPoint geometries', function() { @@ -802,6 +814,8 @@ describe('ol.format.KML', function() { ' ' + ' ' + ' ' + + ' 0' + + ' absolute' + ' 1,2,3 4,5,6' + ' ' + ' ' + @@ -818,6 +832,14 @@ describe('ol.format.KML', function() { expect(g).to.be.an(ol.geom.MultiLineString); expect(g.getCoordinates()).to.eql( [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]); + expect(g.get('extrude')).to.be.an('array'); + expect(g.get('extrude')).to.have.length(2); + expect(g.get('extrude')[0]).to.be(false); + expect(g.get('extrude')[1]).to.be(undefined); + expect(g.get('altitudeMode')).to.be.an('array'); + expect(g.get('altitudeMode')).to.have.length(2); + expect(g.get('altitudeMode')[0]).to.be('absolute'); + expect(g.get('altitudeMode')[1]).to.be(undefined); }); it('can write MultiLineString geometries', function() { @@ -852,6 +874,8 @@ describe('ol.format.KML', function() { ' ' + ' ' + ' ' + + ' 0' + + ' absolute' + ' ' + ' ' + ' 0,0,0 0,1,0 1,1,0 1,0,0' + @@ -877,6 +901,14 @@ describe('ol.format.KML', function() { expect(g.getCoordinates()).to.eql( [[[[0, 0, 0], [0, 1, 0], [1, 1, 0], [1, 0, 0]]], [[[3, 0, 0], [3, 1, 0], [4, 1, 0], [4, 0, 0]]]]); + expect(g.get('extrude')).to.be.an('array'); + expect(g.get('extrude')).to.have.length(2); + expect(g.get('extrude')[0]).to.be(false); + expect(g.get('extrude')[1]).to.be(undefined); + expect(g.get('altitudeMode')).to.be.an('array'); + expect(g.get('altitudeMode')).to.have.length(2); + expect(g.get('altitudeMode')[0]).to.be('absolute'); + expect(g.get('altitudeMode')[1]).to.be(undefined); }); it('can write MultiPolygon geometries', function() {