From c0aa50abfcc5fd0d2b09b91af656f5b7878e4ba0 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Mon, 25 Feb 2013 10:30:04 +0100 Subject: [PATCH 01/41] Split TouchRotateAndZoom interaction. Split TouchRotateAndZoom interaction into two new interaction: TouchRotate and TouchZoom. --- src/objectliterals.exports | 3 +- ...teraction.js => touchrotateinteraction.js} | 44 +++------ src/ol/interaction/touchzoominteraction.js | 98 +++++++++++++++++++ src/ol/map.js | 17 +++- test/spec/ol/map.test.js | 3 +- 5 files changed, 126 insertions(+), 39 deletions(-) rename src/ol/interaction/{touchrotateandzoominteraction.js => touchrotateinteraction.js} (69%) create mode 100644 src/ol/interaction/touchzoominteraction.js diff --git a/src/objectliterals.exports b/src/objectliterals.exports index 4af5ad024f..a990d913c6 100644 --- a/src/objectliterals.exports +++ b/src/objectliterals.exports @@ -13,7 +13,8 @@ @exportObjectLiteralProperty ol.MapOptions.shiftDragZoom boolean|undefined @exportObjectLiteralProperty ol.MapOptions.target Element|string @exportObjectLiteralProperty ol.MapOptions.touchPan boolean|undefined -@exportObjectLiteralProperty ol.MapOptions.touchRotateZoom boolean|undefined +@exportObjectLiteralProperty ol.MapOptions.touchRotate boolean|undefined +@exportObjectLiteralProperty ol.MapOptions.touchZoom boolean|undefined @exportObjectLiteralProperty ol.MapOptions.view ol.IView|undefined @exportObjectLiteralProperty ol.MapOptions.zoomControl boolean|undefined @exportObjectLiteralProperty ol.MapOptions.zoomDelta number|undefined diff --git a/src/ol/interaction/touchrotateandzoominteraction.js b/src/ol/interaction/touchrotateinteraction.js similarity index 69% rename from src/ol/interaction/touchrotateandzoominteraction.js rename to src/ol/interaction/touchrotateinteraction.js index d06d6ee93d..1253866fdc 100644 --- a/src/ol/interaction/touchrotateandzoominteraction.js +++ b/src/ol/interaction/touchrotateinteraction.js @@ -1,6 +1,6 @@ // FIXME works for View2D only -goog.provide('ol.interaction.TouchRotateAndZoom'); +goog.provide('ol.interaction.TouchRotate'); goog.require('goog.asserts'); goog.require('ol.View'); @@ -12,8 +12,10 @@ goog.require('ol.interaction.Touch'); /** * @constructor * @extends {ol.interaction.Touch} + * @param {number=} opt_threshold Minimal angle to start a rotation. + * Default to 0.3 (radian). */ -ol.interaction.TouchRotateAndZoom = function() { +ol.interaction.TouchRotate = function(opt_threshold) { goog.base(this); @@ -23,12 +25,6 @@ ol.interaction.TouchRotateAndZoom = function() { */ this.lastAngle_; - /** - * @private - * @type {number|undefined} - */ - this.lastDistance_; - /** * @private * @type {boolean} @@ -45,23 +41,20 @@ ol.interaction.TouchRotateAndZoom = function() { * @private * @type {number} */ - this.rotationThreshold_ = 0.3; + this.threshold_ = goog.isDef(opt_threshold) ? opt_threshold : 0.3; }; -goog.inherits(ol.interaction.TouchRotateAndZoom, ol.interaction.Touch); +goog.inherits(ol.interaction.TouchRotate, ol.interaction.Touch); /** * @inheritDoc */ -ol.interaction.TouchRotateAndZoom.prototype.handleTouchMove = +ol.interaction.TouchRotate.prototype.handleTouchMove = function(mapBrowserEvent) { goog.asserts.assert(this.targetTouches.length >= 2); - var scaleDelta = 1.0; var rotationDelta = 0.0; - var centroid = ol.interaction.Touch.centroid(this.targetTouches); - var touch0 = this.targetTouches[0]; var touch1 = this.targetTouches[1]; var dx = touch0.clientX - touch1.clientX; @@ -72,19 +65,11 @@ ol.interaction.TouchRotateAndZoom.prototype.handleTouchMove = touch1.clientY - touch0.clientY, touch1.clientX - touch0.clientX); - // distance between touches - var distance = Math.sqrt(dx * dx + dy * dy); - - if (goog.isDef(this.lastDistance_)) { - scaleDelta = this.lastDistance_ / distance; - } - this.lastDistance_ = distance; - if (goog.isDef(this.lastAngle_)) { var delta = angle - this.lastAngle_; this.rotationDelta_ += delta; if (!this.rotating_ && - Math.abs(this.rotationDelta_) > this.rotationThreshold_) { + Math.abs(this.rotationDelta_) > this.threshold_) { this.rotating_ = true; } rotationDelta = delta; @@ -94,17 +79,15 @@ ol.interaction.TouchRotateAndZoom.prototype.handleTouchMove = var map = mapBrowserEvent.map; var view = map.getView(); - // rotate / scale anchor point. + // rotate anchor point. // FIXME: should be the intersection point between the lines: // touch0,touch1 and previousTouch0,previousTouch1 var viewportPosition = goog.style.getClientPosition(map.getViewport()); + var centroid = ol.interaction.Touch.centroid(this.targetTouches); centroid.x -= viewportPosition.x; centroid.y -= viewportPosition.y; var anchor = map.getCoordinateFromPixel(centroid); - // scale, bypass the resolution constraint - view.zoom_(map, view.getResolution() * scaleDelta, anchor); - // rotate if (this.rotating_) { view.rotate(map, view.getRotation() + rotationDelta, anchor); @@ -115,13 +98,11 @@ ol.interaction.TouchRotateAndZoom.prototype.handleTouchMove = /** * @inheritDoc */ -ol.interaction.TouchRotateAndZoom.prototype.handleTouchEnd = +ol.interaction.TouchRotate.prototype.handleTouchEnd = function(mapBrowserEvent) { if (this.targetTouches.length < 2) { var map = mapBrowserEvent.map; var view = map.getView(); - // take the resolution constraint into account - view.zoomToResolution(map, view.getResolution()); view.setHint(ol.ViewHint.PANNING, -1); return false; } else { @@ -133,11 +114,10 @@ ol.interaction.TouchRotateAndZoom.prototype.handleTouchEnd = /** * @inheritDoc */ -ol.interaction.TouchRotateAndZoom.prototype.handleTouchStart = +ol.interaction.TouchRotate.prototype.handleTouchStart = function(mapBrowserEvent) { if (this.targetTouches.length >= 2) { var view = mapBrowserEvent.map.getView(); - this.lastDistance_ = undefined; this.lastAngle_ = undefined; this.rotating_ = false; this.rotationDelta_ = 0.0; diff --git a/src/ol/interaction/touchzoominteraction.js b/src/ol/interaction/touchzoominteraction.js new file mode 100644 index 0000000000..3d5bd178ae --- /dev/null +++ b/src/ol/interaction/touchzoominteraction.js @@ -0,0 +1,98 @@ +// FIXME works for View2D only + +goog.provide('ol.interaction.TouchZoom'); + +goog.require('goog.asserts'); +goog.require('ol.View'); +goog.require('ol.ViewHint'); +goog.require('ol.interaction.Touch'); + + + +/** + * @constructor + * @extends {ol.interaction.Touch} + */ +ol.interaction.TouchZoom = function() { + + goog.base(this); + + /** + * @private + * @type {number|undefined} + */ + this.lastDistance_; + +}; +goog.inherits(ol.interaction.TouchZoom, ol.interaction.Touch); + + +/** + * @inheritDoc + */ +ol.interaction.TouchZoom.prototype.handleTouchMove = + function(mapBrowserEvent) { + goog.asserts.assert(this.targetTouches.length >= 2); + var scaleDelta = 1.0; + + var touch0 = this.targetTouches[0]; + var touch1 = this.targetTouches[1]; + var dx = touch0.clientX - touch1.clientX; + var dy = touch0.clientY - touch1.clientY; + + // distance between touches + var distance = Math.sqrt(dx * dx + dy * dy); + + if (goog.isDef(this.lastDistance_)) { + scaleDelta = this.lastDistance_ / distance; + } + this.lastDistance_ = distance; + + var map = mapBrowserEvent.map; + var view = map.getView(); + + // scale anchor point. + var viewportPosition = goog.style.getClientPosition(map.getViewport()); + var centroid = ol.interaction.Touch.centroid(this.targetTouches); + centroid.x -= viewportPosition.x; + centroid.y -= viewportPosition.y; + var anchor = map.getCoordinateFromPixel(centroid); + + // scale, bypass the resolution constraint + view.zoom_(map, view.getResolution() * scaleDelta, anchor); + +}; + + +/** + * @inheritDoc + */ +ol.interaction.TouchZoom.prototype.handleTouchEnd = + function(mapBrowserEvent) { + if (this.targetTouches.length < 2) { + var map = mapBrowserEvent.map; + var view = map.getView(); + // take the resolution constraint into account + view.zoomToResolution(map, view.getResolution()); + view.setHint(ol.ViewHint.PANNING, -1); + return false; + } else { + return true; + } +}; + + +/** + * @inheritDoc + */ +ol.interaction.TouchZoom.prototype.handleTouchStart = + function(mapBrowserEvent) { + if (this.targetTouches.length >= 2) { + var view = mapBrowserEvent.map.getView(); + this.lastDistance_ = undefined; + view.setHint(ol.ViewHint.PANNING, 1); + return true; + } else { + return false; + } +}; diff --git a/src/ol/map.js b/src/ol/map.js index ad1fa4d8c0..1a16c95136 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -55,7 +55,8 @@ goog.require('ol.interaction.KeyboardPan'); goog.require('ol.interaction.KeyboardZoom'); goog.require('ol.interaction.MouseWheelZoom'); goog.require('ol.interaction.TouchPan'); -goog.require('ol.interaction.TouchRotateAndZoom'); +goog.require('ol.interaction.TouchRotate'); +goog.require('ol.interaction.TouchZoom'); goog.require('ol.interaction.condition'); goog.require('ol.layer.Layer'); goog.require('ol.renderer.Map'); @@ -967,10 +968,16 @@ ol.Map.createInteractions_ = function(mapOptions) { interactions.push(new ol.interaction.TouchPan()); } - var touchRotateZoom = goog.isDef(mapOptions.touchRotateZoom) ? - mapOptions.touchRotateZoom : true; - if (touchRotateZoom) { - interactions.push(new ol.interaction.TouchRotateAndZoom()); + var touchRotate = goog.isDef(mapOptions.touchRotate) ? + mapOptions.touchRotate : true; + if (touchRotate) { + interactions.push(new ol.interaction.TouchRotate()); + } + + var touchZoom = goog.isDef(mapOptions.touchZoom) ? + mapOptions.touchZoom : true; + if (touchZoom) { + interactions.push(new ol.interaction.TouchZoom()); } var dragPan = goog.isDef(mapOptions.dragPan) ? diff --git a/test/spec/ol/map.test.js b/test/spec/ol/map.test.js index db5ed7f546..43cda9f703 100644 --- a/test/spec/ol/map.test.js +++ b/test/spec/ol/map.test.js @@ -79,7 +79,8 @@ describe('ol.Map', function() { mouseWheelZoom: false, shiftDragZoom: false, touchPan: false, - touchRotateZoom: false + touchRotate: false, + touchZoom: false }; }); From 585c397a0f449814e7b0f342fc5e9da7b2831d37 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Mon, 25 Feb 2013 16:01:22 +0100 Subject: [PATCH 02/41] Reset position on touch end --- src/ol/interaction/touchpaninteraction.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ol/interaction/touchpaninteraction.js b/src/ol/interaction/touchpaninteraction.js index 0c21c78c4b..4d033932e9 100644 --- a/src/ol/interaction/touchpaninteraction.js +++ b/src/ol/interaction/touchpaninteraction.js @@ -87,6 +87,7 @@ ol.interaction.TouchPan.prototype.handleTouchEnd = } return false; } else { + this.lastCentroid = null; return true; } }; From 20e8eab142bddac143fa3b5904f3dcd96fed73af Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Tue, 26 Feb 2013 09:46:24 +0100 Subject: [PATCH 03/41] Add missing 'protected' comment for targetTouches prop. --- src/ol/interaction/touchinteraction.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ol/interaction/touchinteraction.js b/src/ol/interaction/touchinteraction.js index c71d5997de..1e96fe7ecb 100644 --- a/src/ol/interaction/touchinteraction.js +++ b/src/ol/interaction/touchinteraction.js @@ -31,6 +31,7 @@ ol.interaction.Touch = function() { /** * @type {Array.} + * @protected */ this.targetTouches = []; From 3b74f72c5656c17b2854481d4d8a35212706fa33 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Tue, 26 Feb 2013 10:52:53 +0100 Subject: [PATCH 04/41] Add optional kinetic parameter. --- src/ol/interaction/touchpaninteraction.js | 18 +++++++++++------- src/ol/map.js | 3 ++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/ol/interaction/touchpaninteraction.js b/src/ol/interaction/touchpaninteraction.js index 4d033932e9..69bad9a186 100644 --- a/src/ol/interaction/touchpaninteraction.js +++ b/src/ol/interaction/touchpaninteraction.js @@ -1,5 +1,4 @@ // FIXME works for View2D only -// FIXME opt_kinetic param goog.provide('ol.interaction.TouchPan'); goog.require('goog.asserts'); @@ -16,16 +15,17 @@ goog.require('ol.interaction.Touch'); /** * @constructor * @extends {ol.interaction.Touch} + * @param {ol.Kinetic=} opt_kinetic Kinetic object. */ -ol.interaction.TouchPan = function() { +ol.interaction.TouchPan = function(opt_kinetic) { goog.base(this); /** * @private - * @type {ol.Kinetic} + * @type {ol.Kinetic|undefined} */ - this.kinetic_ = new ol.Kinetic(-0.005, 0.05, 100); + this.kinetic_ = opt_kinetic; /** * @private @@ -49,7 +49,9 @@ ol.interaction.TouchPan.prototype.handleTouchMove = function(mapBrowserEvent) { goog.asserts.assert(this.targetTouches.length >= 1); var centroid = ol.interaction.Touch.centroid(this.targetTouches); if (!goog.isNull(this.lastCentroid)) { - this.kinetic_.update(centroid.x, centroid.y); + if (this.kinetic_) { + this.kinetic_.update(centroid.x, centroid.y); + } var deltaX = this.lastCentroid.x - centroid.x; var deltaY = centroid.y - this.lastCentroid.y; var view = mapBrowserEvent.map.getView(); @@ -72,7 +74,7 @@ ol.interaction.TouchPan.prototype.handleTouchEnd = var view = map.getView(); if (this.targetTouches.length == 0) { view.setHint(ol.ViewHint.PANNING, -1); - if (this.kinetic_.end()) { + if (this.kinetic_ && this.kinetic_.end()) { var distance = this.kinetic_.getDistance(); var angle = this.kinetic_.getAngle(); var center = view.getCenter(); @@ -108,7 +110,9 @@ ol.interaction.TouchPan.prototype.handleTouchStart = view.setCenter(mapBrowserEvent.frameState.view2DState.center); this.kineticPreRenderFn_ = null; } - this.kinetic_.begin(); + if (this.kinetic_) { + this.kinetic_.begin(); + } view.setHint(ol.ViewHint.PANNING, 1); return true; } else { diff --git a/src/ol/map.js b/src/ol/map.js index 1a16c95136..1b47a05f98 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -965,7 +965,8 @@ ol.Map.createInteractions_ = function(mapOptions) { var touchPan = goog.isDef(mapOptions.touchPan) ? mapOptions.touchPan : true; if (touchPan) { - interactions.push(new ol.interaction.TouchPan()); + interactions.push(new ol.interaction.TouchPan( + new ol.Kinetic(-0.005, 0.05, 100))); } var touchRotate = goog.isDef(mapOptions.touchRotate) ? From 66d4c4415949d774dc3c38b679ec8859c0f6e942 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Sun, 3 Mar 2013 10:08:55 +0100 Subject: [PATCH 05/41] Rename ol.ViewHint.PANNING to ol.ViewHint.INTERACTING --- src/ol/interaction/dragpaninteraction.js | 4 ++-- src/ol/interaction/touchpaninteraction.js | 4 ++-- src/ol/interaction/touchrotateinteraction.js | 4 ++-- src/ol/interaction/touchzoominteraction.js | 4 ++-- src/ol/renderer/canvas/canvasimagelayerrenderer.js | 2 +- src/ol/renderer/dom/domimagelayerrenderer.js | 2 +- src/ol/renderer/dom/domtilelayerrenderer.js | 2 +- src/ol/renderer/webgl/webglimagelayerrenderer.js | 2 +- src/ol/view.js | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/ol/interaction/dragpaninteraction.js b/src/ol/interaction/dragpaninteraction.js index 4281be71fb..4827c92e2f 100644 --- a/src/ol/interaction/dragpaninteraction.js +++ b/src/ol/interaction/dragpaninteraction.js @@ -80,7 +80,7 @@ ol.interaction.DragPan.prototype.handleDragEnd = function(mapBrowserEvent) { var map = mapBrowserEvent.map; var view = map.getView(); - view.setHint(ol.ViewHint.PANNING, -1); + view.setHint(ol.ViewHint.INTERACTING, -1); if (this.kinetic_ && this.kinetic_.end()) { var distance = this.kinetic_.getDistance(); @@ -111,7 +111,7 @@ ol.interaction.DragPan.prototype.handleDragStart = function(mapBrowserEvent) { } var map = mapBrowserEvent.map; map.requestRenderFrame(); - map.getView().setHint(ol.ViewHint.PANNING, 1); + map.getView().setHint(ol.ViewHint.INTERACTING, 1); return true; } else { return false; diff --git a/src/ol/interaction/touchpaninteraction.js b/src/ol/interaction/touchpaninteraction.js index 69bad9a186..452c43159a 100644 --- a/src/ol/interaction/touchpaninteraction.js +++ b/src/ol/interaction/touchpaninteraction.js @@ -73,7 +73,7 @@ ol.interaction.TouchPan.prototype.handleTouchEnd = var map = mapBrowserEvent.map; var view = map.getView(); if (this.targetTouches.length == 0) { - view.setHint(ol.ViewHint.PANNING, -1); + view.setHint(ol.ViewHint.INTERACTING, -1); if (this.kinetic_ && this.kinetic_.end()) { var distance = this.kinetic_.getDistance(); var angle = this.kinetic_.getAngle(); @@ -113,7 +113,7 @@ ol.interaction.TouchPan.prototype.handleTouchStart = if (this.kinetic_) { this.kinetic_.begin(); } - view.setHint(ol.ViewHint.PANNING, 1); + view.setHint(ol.ViewHint.INTERACTING, 1); return true; } else { return false; diff --git a/src/ol/interaction/touchrotateinteraction.js b/src/ol/interaction/touchrotateinteraction.js index 1253866fdc..1ce5d02a77 100644 --- a/src/ol/interaction/touchrotateinteraction.js +++ b/src/ol/interaction/touchrotateinteraction.js @@ -103,7 +103,7 @@ ol.interaction.TouchRotate.prototype.handleTouchEnd = if (this.targetTouches.length < 2) { var map = mapBrowserEvent.map; var view = map.getView(); - view.setHint(ol.ViewHint.PANNING, -1); + view.setHint(ol.ViewHint.INTERACTING, -1); return false; } else { return true; @@ -121,7 +121,7 @@ ol.interaction.TouchRotate.prototype.handleTouchStart = this.lastAngle_ = undefined; this.rotating_ = false; this.rotationDelta_ = 0.0; - view.setHint(ol.ViewHint.PANNING, 1); + view.setHint(ol.ViewHint.INTERACTING, 1); return true; } else { return false; diff --git a/src/ol/interaction/touchzoominteraction.js b/src/ol/interaction/touchzoominteraction.js index 3d5bd178ae..9087c5f3b4 100644 --- a/src/ol/interaction/touchzoominteraction.js +++ b/src/ol/interaction/touchzoominteraction.js @@ -74,7 +74,7 @@ ol.interaction.TouchZoom.prototype.handleTouchEnd = var view = map.getView(); // take the resolution constraint into account view.zoomToResolution(map, view.getResolution()); - view.setHint(ol.ViewHint.PANNING, -1); + view.setHint(ol.ViewHint.INTERACTING, -1); return false; } else { return true; @@ -90,7 +90,7 @@ ol.interaction.TouchZoom.prototype.handleTouchStart = if (this.targetTouches.length >= 2) { var view = mapBrowserEvent.map.getView(); this.lastDistance_ = undefined; - view.setHint(ol.ViewHint.PANNING, 1); + view.setHint(ol.ViewHint.INTERACTING, 1); return true; } else { return false; diff --git a/src/ol/renderer/canvas/canvasimagelayerrenderer.js b/src/ol/renderer/canvas/canvasimagelayerrenderer.js index 61eb2b898d..fa62818db7 100644 --- a/src/ol/renderer/canvas/canvasimagelayerrenderer.js +++ b/src/ol/renderer/canvas/canvasimagelayerrenderer.js @@ -78,7 +78,7 @@ ol.renderer.canvas.ImageLayer.prototype.renderFrame = var hints = frameState.viewHints; - if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.PANNING]) { + if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { image = imageSource.getImage(frameState.extent, viewResolution); if (!goog.isNull(image)) { var imageState = image.getState(); diff --git a/src/ol/renderer/dom/domimagelayerrenderer.js b/src/ol/renderer/dom/domimagelayerrenderer.js index 7190d8c268..769b944848 100644 --- a/src/ol/renderer/dom/domimagelayerrenderer.js +++ b/src/ol/renderer/dom/domimagelayerrenderer.js @@ -66,7 +66,7 @@ ol.renderer.dom.ImageLayer.prototype.renderFrame = var hints = frameState.viewHints; - if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.PANNING]) { + if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { var image_ = imageSource.getImage(frameState.extent, viewResolution); if (!goog.isNull(image_)) { var imageState = image_.getState(); diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index 9b5dd26b32..0477bde451 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -200,7 +200,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = } } else { if (!frameState.viewHints[ol.ViewHint.ANIMATING] && - !frameState.viewHints[ol.ViewHint.PANNING]) { + !frameState.viewHints[ol.ViewHint.INTERACTING]) { tileLayerZ.removeTilesOutsideExtent(frameState.extent); } } diff --git a/src/ol/renderer/webgl/webglimagelayerrenderer.js b/src/ol/renderer/webgl/webglimagelayerrenderer.js index 5d0341f3c1..545547d198 100644 --- a/src/ol/renderer/webgl/webglimagelayerrenderer.js +++ b/src/ol/renderer/webgl/webglimagelayerrenderer.js @@ -159,7 +159,7 @@ ol.renderer.webgl.ImageLayer.prototype.renderFrame = var hints = frameState.viewHints; - if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.PANNING]) { + if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { var image_ = imageSource.getImage(frameState.extent, viewResolution); if (!goog.isNull(image_)) { var imageState = image_.getState(); diff --git a/src/ol/view.js b/src/ol/view.js index f9303af991..61fba43f46 100644 --- a/src/ol/view.js +++ b/src/ol/view.js @@ -11,7 +11,7 @@ goog.require('ol.Object'); */ ol.ViewHint = { ANIMATING: 0, - PANNING: 1 + INTERACTING: 1 }; From c72877b33b0f0707c39145a8379ef2432e1a641f Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Thu, 21 Feb 2013 13:52:29 +0100 Subject: [PATCH 06/41] Listen to both click and touchend events --- src/ol/control/zoomcontrol.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/ol/control/zoomcontrol.js b/src/ol/control/zoomcontrol.js index 1f5354e3dd..ffacacf55f 100644 --- a/src/ol/control/zoomcontrol.js +++ b/src/ol/control/zoomcontrol.js @@ -6,7 +6,6 @@ goog.require('goog.dom'); goog.require('goog.dom.TagName'); goog.require('goog.events'); goog.require('goog.events.EventType'); -goog.require('ol.BrowserFeature'); goog.require('ol.control.Control'); @@ -24,20 +23,23 @@ ol.control.ZOOM_DURATION = 250; */ ol.control.Zoom = function(zoomOptions) { - var eventType = ol.BrowserFeature.HAS_TOUCH ? - goog.events.EventType.TOUCHEND : goog.events.EventType.CLICK; - var inElement = goog.dom.createDom(goog.dom.TagName.A, { 'href': '#zoomIn', 'class': 'ol-zoom-in' }); - goog.events.listen(inElement, eventType, this.handleIn_, false, this); + goog.events.listen(inElement, [ + goog.events.EventType.TOUCHEND, + goog.events.EventType.CLICK + ], this.handleIn_, false, this); var outElement = goog.dom.createDom(goog.dom.TagName.A, { 'href': '#zoomOut', 'class': 'ol-zoom-out' }); - goog.events.listen(outElement, eventType, this.handleOut_, false, this); + goog.events.listen(outElement, [ + goog.events.EventType.TOUCHEND, + goog.events.EventType.CLICK + ], this.handleOut_, false, this); var element = goog.dom.createDom( goog.dom.TagName.DIV, 'ol-zoom ol-unselectable', inElement, outElement); From 0a80feccfc215b91a00ed8ce7da3863929caccc2 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Thu, 21 Feb 2013 14:45:58 +0100 Subject: [PATCH 07/41] Allow touch event (touchstart) to fire click events --- src/ol/mapbrowserevent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/mapbrowserevent.js b/src/ol/mapbrowserevent.js index 792585eff0..e86b83728d 100644 --- a/src/ol/mapbrowserevent.js +++ b/src/ol/mapbrowserevent.js @@ -201,7 +201,7 @@ ol.MapBrowserEventHandler.prototype.click_ = function(browserEvent) { newEvent = new ol.MapBrowserEvent( ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, browserEvent); this.dispatchEvent(newEvent); - } else if (type == goog.events.EventType.CLICK) { + } else { newEvent = new ol.MapBrowserEvent( ol.MapBrowserEvent.EventType.CLICK, this.map_, browserEvent); this.dispatchEvent(newEvent); From 0df692e159a57593028eb2b114380e64b39ae801 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sun, 3 Mar 2013 17:57:30 +0100 Subject: [PATCH 08/41] Lint in the tests --- test/spec/ol/extent.test.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/spec/ol/extent.test.js b/test/spec/ol/extent.test.js index e3f0f4a321..11431db798 100644 --- a/test/spec/ol/extent.test.js +++ b/test/spec/ol/extent.test.js @@ -52,17 +52,17 @@ describe('ol.Extent', function() { expect(extent.containsCoordinate( new ol.Coordinate(3, 1))).toBeFalsy(); expect(extent.containsCoordinate( - new ol.Coordinate(3, 5))).toBeFalsy(); + new ol.Coordinate(3, 5))).toBeFalsy(); expect(extent.containsCoordinate( - new ol.Coordinate(4, 1))).toBeFalsy(); + new ol.Coordinate(4, 1))).toBeFalsy(); expect(extent.containsCoordinate( - new ol.Coordinate(4, 2))).toBeFalsy(); + new ol.Coordinate(4, 2))).toBeFalsy(); expect(extent.containsCoordinate( - new ol.Coordinate(4, 3))).toBeFalsy(); + new ol.Coordinate(4, 3))).toBeFalsy(); expect(extent.containsCoordinate( - new ol.Coordinate(4, 4))).toBeFalsy(); + new ol.Coordinate(4, 4))).toBeFalsy(); expect(extent.containsCoordinate( - new ol.Coordinate(4, 5))).toBeFalsy(); + new ol.Coordinate(4, 5))).toBeFalsy(); }); }); }); From d754c34a04b88e8c6490926b7716d6418437cbef Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Sun, 3 Mar 2013 17:37:15 +0100 Subject: [PATCH 09/41] Better indentation for wms capabilities example --- examples/wms-capabilities.html | 2 +- examples/wms-capabilities.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/wms-capabilities.html b/examples/wms-capabilities.html index c119fdc92e..3fde09bcf8 100644 --- a/examples/wms-capabilities.html +++ b/examples/wms-capabilities.html @@ -35,7 +35,7 @@ wms capabilities example -
+

     

WMS GetCapabilities parsing example

diff --git a/examples/wms-capabilities.js b/examples/wms-capabilities.js index 09d8ed7061..8566372599 100644 --- a/examples/wms-capabilities.js +++ b/examples/wms-capabilities.js @@ -13,7 +13,8 @@ xhr.open('GET', url, true); xhr.onload = function() { if (xhr.status == 200) { result = parser.read(xhr.responseXML); - document.getElementById('log').innerHTML = window.JSON.stringify(result); + document.getElementById('log').innerHTML = + window.JSON.stringify(result, undefined, 2); } }; xhr.send(); From 7a5e6a06d8d957b8170b306b011f7857c6fb297e Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sun, 3 Mar 2013 19:27:57 +0100 Subject: [PATCH 10/41] Make transform functions work with arrays Instead of working with ol.Coordinate instances, transform functions work with arrays. This is in anticipation of using transform functions to transform large arrays of vertex coordinate values. The ol.projection.transform and ol.projection.transformWithCodes are slightly more convenient functions for dealing with ol.Coordinate instances. Whether we make this more consistent with the use of functions returned by ol.projection.getTransform is up for discussion. --- src/ol/control/mousepositioncontrol.js | 4 +- src/ol/extent.js | 10 ++-- src/ol/geolocation.js | 15 +++--- src/ol/projection.js | 56 ++++++++++++++------- src/ol/projection/epsg3857.js | 55 +++++++++++++++------ src/ol/transformfunction.js | 8 +-- test/spec/ol/extent.test.js | 4 +- test/spec/ol/projection.test.js | 68 +++++++++++++++++++++++--- 8 files changed, 163 insertions(+), 57 deletions(-) diff --git a/src/ol/control/mousepositioncontrol.js b/src/ol/control/mousepositioncontrol.js index 09abf92d4b..0f3cfb9400 100644 --- a/src/ol/control/mousepositioncontrol.js +++ b/src/ol/control/mousepositioncontrol.js @@ -8,6 +8,7 @@ goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.events.EventType'); goog.require('goog.style'); +goog.require('ol.Coordinate'); goog.require('ol.CoordinateFormatType'); goog.require('ol.MapEvent'); goog.require('ol.MapEventType'); @@ -177,7 +178,8 @@ ol.control.MousePosition.prototype.updateHTML_ = function(pixel) { var map = this.getMap(); var coordinate = map.getCoordinateFromPixel(pixel); if (!goog.isNull(coordinate)) { - coordinate = this.transform_(coordinate); + var output = this.transform_([coordinate.x, coordinate.y]); + coordinate = new ol.Coordinate(output[0], output[1]); if (goog.isDef(this.coordinateFormat_)) { html = this.coordinateFormat_(coordinate); } else { diff --git a/src/ol/extent.js b/src/ol/extent.js index 3606dfc63c..0edfa2a8ca 100644 --- a/src/ol/extent.js +++ b/src/ol/extent.js @@ -108,8 +108,10 @@ ol.Extent.prototype.getTopRight = function() { * @return {ol.Extent} Extent. */ ol.Extent.prototype.transform = function(transformFn) { - var a = transformFn(new ol.Coordinate(this.minX, this.minY)); - var b = transformFn(new ol.Coordinate(this.maxX, this.maxY)); - return new ol.Extent(Math.min(a.x, b.x), Math.min(a.y, b.y), - Math.max(a.x, b.x), Math.max(a.y, b.y)); + var input = [this.minX, this.minY, this.maxX, this.maxY]; + var output = transformFn(input, 2); + return new ol.Extent(Math.min(output[0], output[2]), + Math.min(output[1], output[3]), + Math.max(output[0], output[2]), + Math.max(output[1], output[3])); }; diff --git a/src/ol/geolocation.js b/src/ol/geolocation.js index 201257e2eb..69052832b2 100644 --- a/src/ol/geolocation.js +++ b/src/ol/geolocation.js @@ -76,11 +76,12 @@ ol.Geolocation.prototype.disposeInternal = function() { ol.Geolocation.prototype.handleProjectionChanged_ = function() { var projection = this.getProjection(); if (goog.isDefAndNotNull(projection)) { - this.transformCoords_ = ol.projection.getTransform( + this.transformFn_ = ol.projection.getTransform( ol.projection.getFromCode('EPSG:4326'), projection); if (!goog.isNull(this.position_)) { + var output = this.transformFn_([this.position_.x, this.position_.y]); this.set(ol.GeolocationProperty.POSITION, - this.transformCoords_(this.position_)); + new ol.Coordinate(output[0], output[1])); } } }; @@ -108,8 +109,9 @@ ol.Geolocation.prototype.positionChange_ = function(position) { this.set(ol.GeolocationProperty.HEADING, goog.isNull(coords.heading) ? undefined : goog.math.toRadians(coords.heading)); this.position_ = new ol.Coordinate(coords.longitude, coords.latitude); + var output = this.transformFn_([coords.longitude, coords.latitude]); this.set(ol.GeolocationProperty.POSITION, - this.transformCoords_(this.position_)); + new ol.Coordinate(output[0], output[1])); this.set(ol.GeolocationProperty.SPEED, goog.isNull(coords.speed) ? undefined : coords.speed); }; @@ -230,7 +232,8 @@ goog.exportProperty( /** * @private - * @param {ol.Coordinate} coordinate Coordinate. - * @return {ol.Coordinate} Coordinate. + * @param {Array.} input Input coordinate values. + * @param {number=} opt_dimension Dimension (default is 2). + * @return {Array.} Output coordinate values. */ -ol.Geolocation.prototype.transformCoords_ = goog.functions.identity; +ol.Geolocation.prototype.transformFn_ = goog.functions.identity; diff --git a/src/ol/projection.js b/src/ol/projection.js index 6c1e321f14..80e8c1dbe2 100644 --- a/src/ol/projection.js +++ b/src/ol/projection.js @@ -397,14 +397,29 @@ ol.projection.getTransform = function(source, destination) { var destinationProj4jsProj = proj4jsDestination.getProj4jsProj(); transform = /** - * @param {ol.Coordinate} coordinate Coordinate. - * @return {ol.Coordinate} Coordinate. + * @param {Array.} input Input coordinate values. + * @param {number=} opt_dimension Dimension. + * @return {Array.} Output coordinate values. */ - function(coordinate) { - var proj4jsPoint = new Proj4js.Point(coordinate.x, coordinate.y); - proj4jsPoint = Proj4js.transform( - sourceProj4jsProj, destinationProj4jsProj, proj4jsPoint); - return new ol.Coordinate(proj4jsPoint.x, proj4jsPoint.y); + function(input, opt_dimension) { + var length = input.length, + dimension = goog.isDef(opt_dimension) ? opt_dimension : 2, + output, proj4jsPoint; + if (dimension > 2) { + // preserve values beyond second dimension + output = input.slice(); + } else { + output = new Array(length); + } + goog.asserts.assert(output.length % dimension === 0); + for (var i = 0; i < length; i += dimension) { + proj4jsPoint = new Proj4js.Point(input[i], input[i + 1]); + proj4jsPoint = Proj4js.transform( + sourceProj4jsProj, destinationProj4jsProj, proj4jsPoint); + output[i] = proj4jsPoint.x; + output[i + 1] = proj4jsPoint.y; + } + return output; }; ol.projection.addTransform(source, destination, transform); } @@ -418,7 +433,7 @@ ol.projection.getTransform = function(source, destination) { /** * Given the projection codes this method searches for a transformation function - * to convert coordinate from the source projection to the destination + * to convert a coordinates array from the source projection to the destination * projection. * * @param {string} sourceCode Source code. @@ -433,20 +448,23 @@ ol.projection.getTransformFromCodes = function(sourceCode, destinationCode) { /** - * @param {ol.Coordinate} point Point. - * @return {ol.Coordinate} Unaltered point (same reference). + * @param {Array.} input Input coordinate array. + * @param {number=} opt_dimension Dimension. + * @return {Array.} Input coordinate array (same array as input). */ -ol.projection.identityTransform = function(point) { - return point; +ol.projection.identityTransform = function(input, opt_dimension) { + return input; }; /** - * @param {ol.Coordinate} point Point. - * @return {ol.Coordinate} Equal point (different reference). + * @param {Array.} input Input coordinate array. + * @param {number=} opt_dimension Dimension. + * @return {Array.} Output coordinate array (new array, same coordinate + * values). */ -ol.projection.cloneTransform = function(point) { - return new ol.Coordinate(point.x, point.y); +ol.projection.cloneTransform = function(input, opt_dimension) { + return input.slice(); }; @@ -460,7 +478,8 @@ ol.projection.cloneTransform = function(point) { */ ol.projection.transform = function(point, source, destination) { var transformFn = ol.projection.getTransform(source, destination); - return transformFn(point); + var output = transformFn([point.x, point.y]); + return new ol.Coordinate(output[0], output[1]); }; @@ -474,5 +493,6 @@ ol.projection.transformWithCodes = function(point, sourceCode, destinationCode) { var transformFn = ol.projection.getTransformFromCodes( sourceCode, destinationCode); - return transformFn(point); + var output = transformFn([point.x, point.y]); + return new ol.Coordinate(output[0], output[1]); }; diff --git a/src/ol/projection/epsg3857.js b/src/ol/projection/epsg3857.js index 991eca5410..2050aca7d2 100644 --- a/src/ol/projection/epsg3857.js +++ b/src/ol/projection/epsg3857.js @@ -1,7 +1,6 @@ goog.provide('ol.projection.EPSG3857'); goog.require('goog.array'); -goog.require('ol.Coordinate'); goog.require('ol.Extent'); goog.require('ol.Projection'); goog.require('ol.ProjectionUnits'); @@ -73,26 +72,52 @@ ol.projection.EPSG3857.PROJECTIONS = goog.array.map( /** * Transformation from EPSG:4326 to EPSG:3857. * - * @param {ol.Coordinate} point Point. - * @return {ol.Coordinate} Point. + * @param {Array.} input Input array of coordinate values. + * @param {number=} opt_dimension Dimension (default is 2). + * @return {Array.} Output array of coordinate values. */ -ol.projection.EPSG3857.fromEPSG4326 = function(point) { - var x = ol.projection.EPSG3857.RADIUS * Math.PI * point.x / 180; - var y = ol.projection.EPSG3857.RADIUS * - Math.log(Math.tan(Math.PI * (point.y + 90) / 360)); - return new ol.Coordinate(x, y); +ol.projection.EPSG3857.fromEPSG4326 = function(input, opt_dimension) { + var length = input.length, + dimension = goog.isDef(opt_dimension) ? opt_dimension : 2, + output; + if (dimension > 2) { + // preserve values beyond second dimension + output = input.slice(); + } else { + output = new Array(length); + } + goog.asserts.assert(output.length % dimension === 0); + for (var i = 0; i < length; i += dimension) { + output[i] = ol.projection.EPSG3857.RADIUS * Math.PI * input[i] / 180; + output[i + 1] = ol.projection.EPSG3857.RADIUS * + Math.log(Math.tan(Math.PI * (input[i + 1] + 90) / 360)); + } + return output; }; /** * Transformation from EPSG:3857 to EPSG:4326. * - * @param {ol.Coordinate} point Point. - * @return {ol.Coordinate} Point. + * @param {Array.} input Input array of coordinate values. + * @param {number=} opt_dimension Dimension (default is 2). + * @return {Array.} Output array of coordinate values. */ -ol.projection.EPSG3857.toEPSG4326 = function(point) { - var x = 180 * point.x / (ol.projection.EPSG3857.RADIUS * Math.PI); - var y = 360 * Math.atan( - Math.exp(point.y / ol.projection.EPSG3857.RADIUS)) / Math.PI - 90; - return new ol.Coordinate(x, y); +ol.projection.EPSG3857.toEPSG4326 = function(input, opt_dimension) { + var length = input.length, + dimension = goog.isDef(opt_dimension) ? opt_dimension : 2, + output; + if (dimension > 2) { + // preserve values beyond second dimension + output = input.slice(); + } else { + output = new Array(length); + } + goog.asserts.assert(output.length % dimension === 0); + for (var i = 0; i < length; i += dimension) { + output[i] = 180 * input[i] / (ol.projection.EPSG3857.RADIUS * Math.PI); + output[i + 1] = 360 * Math.atan( + Math.exp(input[i + 1] / ol.projection.EPSG3857.RADIUS)) / Math.PI - 90; + } + return output; }; diff --git a/src/ol/transformfunction.js b/src/ol/transformfunction.js index a8be2c0f28..65b5a6c585 100644 --- a/src/ol/transformfunction.js +++ b/src/ol/transformfunction.js @@ -1,9 +1,11 @@ goog.provide('ol.TransformFunction'); -goog.require('ol.Coordinate'); - /** - * @typedef {function(ol.Coordinate): ol.Coordinate} + * A transform function accepts an array of input coordinate values and an + * optional dimension (default should be 2). The function transforms the + * coordinate values and returns an array of the same length as the input. + * + * @typedef {function(Array., number=): Array.} */ ol.TransformFunction; diff --git a/test/spec/ol/extent.test.js b/test/spec/ol/extent.test.js index 11431db798..9cd1ba3c40 100644 --- a/test/spec/ol/extent.test.js +++ b/test/spec/ol/extent.test.js @@ -84,8 +84,8 @@ describe('ol.Extent', function() { }); it('takes arbitrary function', function() { - var transformFn = function(coordinate) { - return new ol.Coordinate(-coordinate.x, -coordinate.y); + var transformFn = function(input) { + return [-input[0], -input[1], -input[2], -input[3]]; }; var sourceExtent = new ol.Extent(-15, -30, 45, 60); var destinationExtent = sourceExtent.transform(transformFn); diff --git a/test/spec/ol/projection.test.js b/test/spec/ol/projection.test.js index 42b3f09fc2..a840a6f0f4 100644 --- a/test/spec/ol/projection.test.js +++ b/test/spec/ol/projection.test.js @@ -155,10 +155,22 @@ describe('ol.projection', function() { var transform = ol.projection.getTransform(sm, gg); expect(typeof transform).toBe('function'); - var coordinate = transform(new ol.Coordinate(-12000000, 5000000)); + var output = transform([-12000000, 5000000]); - expect(coordinate.x).toRoughlyEqual(-107.79783409434258, 1e-9); - expect(coordinate.y).toRoughlyEqual(40.91627447067577, 1e-9); + expect(output[0]).toRoughlyEqual(-107.79783409434258, 1e-9); + expect(output[1]).toRoughlyEqual(40.91627447067577, 1e-9); + }); + + it('works for longer arrays', function() { + var transform = ol.projection.getTransform(sm, gg); + expect(typeof transform).toBe('function'); + + var output = transform([-12000000, 5000000, -12000000, 5000000]); + + expect(output[0]).toRoughlyEqual(-107.79783409434258, 1e-9); + expect(output[1]).toRoughlyEqual(40.91627447067577, 1e-9); + expect(output[2]).toRoughlyEqual(-107.79783409434258, 1e-9); + expect(output[3]).toRoughlyEqual(40.91627447067577, 1e-9); }); }); @@ -177,14 +189,54 @@ describe('ol.projection', function() { 'GOOGLE', 'EPSG:4326'); expect(typeof transform).toBe('function'); - var coordinate = transform( - new ol.Coordinate(-626172.13571216376, 6887893.4928337997)); + var output = transform([-626172.13571216376, 6887893.4928337997]); - expect(coordinate.x).toRoughlyEqual(-5.625, 1e-9); - expect(coordinate.y).toRoughlyEqual(52.4827802220782, 1e-9); + expect(output[0]).toRoughlyEqual(-5.625, 1e-9); + expect(output[1]).toRoughlyEqual(52.4827802220782, 1e-9); }); + it('works for longer arrays of coordinate values', function() { + var transform = ol.projection.getTransformFromCodes( + 'GOOGLE', 'EPSG:4326'); + expect(typeof transform).toBe('function'); + + var output = transform([ + -626172.13571216376, 6887893.4928337997, + -12000000, 5000000, + -626172.13571216376, 6887893.4928337997 + ]); + + expect(output[0]).toRoughlyEqual(-5.625, 1e-9); + expect(output[1]).toRoughlyEqual(52.4827802220782, 1e-9); + expect(output[2]).toRoughlyEqual(-107.79783409434258, 1e-9); + expect(output[3]).toRoughlyEqual(40.91627447067577, 1e-9); + expect(output[4]).toRoughlyEqual(-5.625, 1e-9); + expect(output[5]).toRoughlyEqual(52.4827802220782, 1e-9); + }); + + it('accepts a dimension', function() { + var transform = ol.projection.getTransformFromCodes( + 'GOOGLE', 'EPSG:4326'); + expect(typeof transform).toBe('function'); + + var dimension = 3; + var output = transform([ + -626172.13571216376, 6887893.4928337997, 100, + -12000000, 5000000, 200, + -626172.13571216376, 6887893.4928337997, 300 + ], dimension); + + expect(output[0]).toRoughlyEqual(-5.625, 1e-9); + expect(output[1]).toRoughlyEqual(52.4827802220782, 1e-9); + expect(output[2]).toBe(100); + expect(output[3]).toRoughlyEqual(-107.79783409434258, 1e-9); + expect(output[4]).toRoughlyEqual(40.91627447067577, 1e-9); + expect(output[5]).toBe(200); + expect(output[6]).toRoughlyEqual(-5.625, 1e-9); + expect(output[7]).toRoughlyEqual(52.4827802220782, 1e-9); + expect(output[8]).toBe(300); + }); }); describe('ol.projection.removeTransform()', function() { @@ -195,7 +247,7 @@ describe('ol.projection', function() { it('removes functions cached by addTransform', function() { var foo = new ol.Projection('foo', units, extent); var bar = new ol.Projection('bar', units, extent); - var transform = function() {}; + var transform = function(intput, dimension) {return input}; ol.projection.addTransform(foo, bar, transform); expect(ol.projection.transforms_).not.toBeUndefined(); expect(ol.projection.transforms_.foo).not.toBeUndefined(); From 337fd11a05dc188cfc2162cf47c1cf3c667c4647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Sun, 3 Mar 2013 19:38:25 +0100 Subject: [PATCH 11/41] Load the examples using PhantomJS This commit adds a check-examples target to check that the hosted examples load without errors. --- bin/check-example.js | 30 ++++++++++++++++++++++++++++++ build.py | 13 ++++++++++++- build/ol-simple.json | 10 ++++++++++ build/ol-whitespace.json | 11 +++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 bin/check-example.js diff --git a/bin/check-example.js b/bin/check-example.js new file mode 100644 index 0000000000..7995118519 --- /dev/null +++ b/bin/check-example.js @@ -0,0 +1,30 @@ +// +// A PhantomJS script used to check that the hosted examples load +// without errors. This script is executed by the build tool's +// check-examples target. +// +var args = require('system').args; +if (args.length != 2) { + phantom.exit(2); +} +var examplePath = args[1]; +var page = require('webpage').create(); +page.onError = function(msg, trace) { + var msgStack = ['JavaScript ERROR: ' + msg]; + if (trace) { + msgStack.push('TRACE:'); + trace.forEach(function(t) { + msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function + '")' : '')); + }); + } + console.error(msgStack.join('\n')); + phantom.exit(1); +}; +page.open(examplePath, function(s) { + var exitCode = 0; + if (s != 'success') { + exitCode = 1; + console.error('PAGE LOAD ERROR'); + } + phantom.exit(exitCode); +}); diff --git a/build.py b/build.py index 3305910d45..61fd01419a 100755 --- a/build.py +++ b/build.py @@ -95,7 +95,7 @@ def report_sizes(t): virtual('all', 'build-all', 'build', 'examples', 'precommit') -virtual('precommit', 'lint', 'build-all', 'test', 'build', 'build-examples', 'doc') +virtual('precommit', 'lint', 'build-all', 'test', 'build', 'build-examples', 'check-examples', 'doc') virtual('build', 'build/ol.css', 'build/ol.js', 'build/ol-simple.js', 'build/ol-whitespace.js') @@ -356,6 +356,17 @@ def hostexamples(t): t.cp('examples/example-list.js', 'examples/example-list.xml', 'examples/Jugl.js', 'build/gh-pages/%(BRANCH)s/examples/') +@target('check-examples', 'hostexamples', phony=True) +def check_examples(t): + directory = 'build/gh-pages/%(BRANCH)s/' + examples = ['build/gh-pages/%(BRANCH)s/' + e for e in EXAMPLES] + all_examples = examples + \ + [e + '?mode=simple' for e in examples] + \ + [e + '?mode=whitespace' for e in examples] + for example in all_examples: + t.run('%(PHANTOMJS)s', 'bin/check-example.js', example) + + @target(PROJ4JS, PROJ4JS_ZIP) def proj4js(t): from zipfile import ZipFile diff --git a/build/ol-simple.json b/build/ol-simple.json index 27a982ee23..63fd1b7108 100644 --- a/build/ol-simple.json +++ b/build/ol-simple.json @@ -1,5 +1,15 @@ { + // If ambiguate-properties and disambiguate-properties are set to true + // we get function names like "ol_control_Control_prototype$setMap" in + // the compiled code when using the SIMPLE compilation. It looks like + // "ambiguate-properties" and "disambiguate-properties" are only + // appropriate for ADVANCED compilation. + + "ambiguate-properties": false, + + "disambiguate-properties": false, + "id": "ol-simple", "externs": [ diff --git a/build/ol-whitespace.json b/build/ol-whitespace.json index 83294ee47c..95fd632611 100644 --- a/build/ol-whitespace.json +++ b/build/ol-whitespace.json @@ -2,6 +2,17 @@ "id": "ol-whitespace", + // If ambiguate-properties and disambiguate-properties are set to true + // we get function names like "ol_control_Control_prototype$setMap" in + // the compiled code when using the SIMPLE compilation. It looks like + // "ambiguate-properties" and "disambiguate-properties" are only + // appropriate for ADVANCED compilation. To be sure we also don't + // set them for WHITESPACE. + + "ambiguate-properties": false, + + "disambiguate-properties": false, + "externs": [ "externs/bingmaps.js", "externs/proj4js.js", From 5202281ce8d05cd97ef25bf664863ec9c8a91197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Sun, 3 Mar 2013 19:41:10 +0100 Subject: [PATCH 12/41] Remove references to goog in epsg-4326 example --- examples/epsg-4326.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/examples/epsg-4326.js b/examples/epsg-4326.js index 27fc69913b..9acf4517f8 100644 --- a/examples/epsg-4326.js +++ b/examples/epsg-4326.js @@ -1,6 +1,3 @@ -goog.require('goog.debug.Console'); -goog.require('goog.debug.Logger'); -goog.require('goog.debug.Logger.Level'); goog.require('ol.Collection'); goog.require('ol.Coordinate'); goog.require('ol.Map'); @@ -11,11 +8,6 @@ goog.require('ol.projection'); goog.require('ol.source.TiledWMS'); -if (goog.DEBUG) { - goog.debug.Console.autoInstall(); - goog.debug.Logger.getLogger('ol').setLevel(goog.debug.Logger.Level.INFO); -} - var epsg4326 = ol.projection.getFromCode('EPSG:4326'); // We give the single image source a set of resolutions. This prevents the From 26cf882d68afc3c724f12a2f73c489049ebbc0d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Sun, 3 Mar 2013 19:42:25 +0100 Subject: [PATCH 13/41] Make createLayerRenderer always return a renderer --- src/ol/renderer/maprenderer.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ol/renderer/maprenderer.js b/src/ol/renderer/maprenderer.js index d3cceb36d1..dfd69e5464 100644 --- a/src/ol/renderer/maprenderer.js +++ b/src/ol/renderer/maprenderer.js @@ -119,7 +119,9 @@ ol.renderer.Map.prototype.calculateMatrices2D = function(frameState) { * @protected * @return {ol.renderer.Layer} layerRenderer Layer renderer. */ -ol.renderer.Map.prototype.createLayerRenderer = goog.functions.NULL; +ol.renderer.Map.prototype.createLayerRenderer = function(layer) { + return new ol.renderer.Layer(this, layer); +}; /** From 40bde4056b76cb2fe8000619fe95de51fa3152c3 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sun, 3 Mar 2013 20:24:14 +0100 Subject: [PATCH 14/41] Accept a destination array for transforms This allows in-place transforms. --- src/ol/extent.js | 10 ++++----- src/ol/geolocation.js | 1 + src/ol/projection.js | 26 +++++++++++++--------- src/ol/projection/epsg3857.js | 39 +++++++++++++++++++-------------- src/ol/transformfunction.js | 9 ++++---- test/spec/ol/projection.test.js | 19 ++++++++++++++-- 6 files changed, 67 insertions(+), 37 deletions(-) diff --git a/src/ol/extent.js b/src/ol/extent.js index 0edfa2a8ca..5595382e7c 100644 --- a/src/ol/extent.js +++ b/src/ol/extent.js @@ -109,9 +109,9 @@ ol.Extent.prototype.getTopRight = function() { */ ol.Extent.prototype.transform = function(transformFn) { var input = [this.minX, this.minY, this.maxX, this.maxY]; - var output = transformFn(input, 2); - return new ol.Extent(Math.min(output[0], output[2]), - Math.min(output[1], output[3]), - Math.max(output[0], output[2]), - Math.max(output[1], output[3])); + input = transformFn(input, input, 2); + return new ol.Extent(Math.min(input[0], input[2]), + Math.min(input[1], input[3]), + Math.max(input[0], input[2]), + Math.max(input[1], input[3])); }; diff --git a/src/ol/geolocation.js b/src/ol/geolocation.js index 69052832b2..bb90723f15 100644 --- a/src/ol/geolocation.js +++ b/src/ol/geolocation.js @@ -233,6 +233,7 @@ goog.exportProperty( /** * @private * @param {Array.} input Input coordinate values. + * @param {Array.=} opt_output Output array of coordinate values. * @param {number=} opt_dimension Dimension (default is 2). * @return {Array.} Output coordinate values. */ diff --git a/src/ol/projection.js b/src/ol/projection.js index 80e8c1dbe2..86ac70b6a5 100644 --- a/src/ol/projection.js +++ b/src/ol/projection.js @@ -398,20 +398,24 @@ ol.projection.getTransform = function(source, destination) { transform = /** * @param {Array.} input Input coordinate values. + * @param {Array.=} opt_output Output array of coordinates. * @param {number=} opt_dimension Dimension. * @return {Array.} Output coordinate values. */ - function(input, opt_dimension) { + function(input, opt_output, opt_dimension) { var length = input.length, - dimension = goog.isDef(opt_dimension) ? opt_dimension : 2, - output, proj4jsPoint; - if (dimension > 2) { - // preserve values beyond second dimension - output = input.slice(); - } else { - output = new Array(length); + dimension = opt_dimension > 1 ? opt_dimension : 2, + output = opt_output; + if (!goog.isDef(output)) { + if (dimension > 2) { + // preserve values beyond second dimension + output = input.slice(); + } else { + output = new Array(length); + } } goog.asserts.assert(output.length % dimension === 0); + var proj4jsPoint; for (var i = 0; i < length; i += dimension) { proj4jsPoint = new Proj4js.Point(input[i], input[i + 1]); proj4jsPoint = Proj4js.transform( @@ -449,21 +453,23 @@ ol.projection.getTransformFromCodes = function(sourceCode, destinationCode) { /** * @param {Array.} input Input coordinate array. + * @param {Array.=} opt_output Output array of coordinate values. * @param {number=} opt_dimension Dimension. * @return {Array.} Input coordinate array (same array as input). */ -ol.projection.identityTransform = function(input, opt_dimension) { +ol.projection.identityTransform = function(input, opt_output, opt_dimension) { return input; }; /** * @param {Array.} input Input coordinate array. + * @param {Array.=} opt_output Output array of coordinate values. * @param {number=} opt_dimension Dimension. * @return {Array.} Output coordinate array (new array, same coordinate * values). */ -ol.projection.cloneTransform = function(input, opt_dimension) { +ol.projection.cloneTransform = function(input, opt_output, opt_dimension) { return input.slice(); }; diff --git a/src/ol/projection/epsg3857.js b/src/ol/projection/epsg3857.js index 2050aca7d2..0d183c3e66 100644 --- a/src/ol/projection/epsg3857.js +++ b/src/ol/projection/epsg3857.js @@ -73,18 +73,22 @@ ol.projection.EPSG3857.PROJECTIONS = goog.array.map( * Transformation from EPSG:4326 to EPSG:3857. * * @param {Array.} input Input array of coordinate values. + * @param {Array.=} opt_output Output array of coordinate values. * @param {number=} opt_dimension Dimension (default is 2). * @return {Array.} Output array of coordinate values. */ -ol.projection.EPSG3857.fromEPSG4326 = function(input, opt_dimension) { +ol.projection.EPSG3857.fromEPSG4326 = function( + input, opt_output, opt_dimension) { var length = input.length, - dimension = goog.isDef(opt_dimension) ? opt_dimension : 2, - output; - if (dimension > 2) { - // preserve values beyond second dimension - output = input.slice(); - } else { - output = new Array(length); + dimension = opt_dimension > 1 ? opt_dimension : 2, + output = opt_output; + if (!goog.isDef(output)) { + if (dimension > 2) { + // preserve values beyond second dimension + output = input.slice(); + } else { + output = new Array(length); + } } goog.asserts.assert(output.length % dimension === 0); for (var i = 0; i < length; i += dimension) { @@ -100,18 +104,21 @@ ol.projection.EPSG3857.fromEPSG4326 = function(input, opt_dimension) { * Transformation from EPSG:3857 to EPSG:4326. * * @param {Array.} input Input array of coordinate values. + * @param {Array.=} opt_output Output array of coordinate values. * @param {number=} opt_dimension Dimension (default is 2). * @return {Array.} Output array of coordinate values. */ -ol.projection.EPSG3857.toEPSG4326 = function(input, opt_dimension) { +ol.projection.EPSG3857.toEPSG4326 = function(input, opt_output, opt_dimension) { var length = input.length, - dimension = goog.isDef(opt_dimension) ? opt_dimension : 2, - output; - if (dimension > 2) { - // preserve values beyond second dimension - output = input.slice(); - } else { - output = new Array(length); + dimension = opt_dimension > 1 ? opt_dimension : 2, + output = opt_output; + if (!goog.isDef(output)) { + if (dimension > 2) { + // preserve values beyond second dimension + output = input.slice(); + } else { + output = new Array(length); + } } goog.asserts.assert(output.length % dimension === 0); for (var i = 0; i < length; i += dimension) { diff --git a/src/ol/transformfunction.js b/src/ol/transformfunction.js index 65b5a6c585..b5fb315d69 100644 --- a/src/ol/transformfunction.js +++ b/src/ol/transformfunction.js @@ -2,10 +2,11 @@ goog.provide('ol.TransformFunction'); /** - * A transform function accepts an array of input coordinate values and an - * optional dimension (default should be 2). The function transforms the - * coordinate values and returns an array of the same length as the input. + * A transform function accepts an array of input coordinate values, an optional + * output array, and an optional dimension (default should be 2). The function + * transforms the input coordinate values, populates the output array, and + * returns the output array. * - * @typedef {function(Array., number=): Array.} + * @typedef {function(Array., Array.=, number=): Array.} */ ol.TransformFunction; diff --git a/test/spec/ol/projection.test.js b/test/spec/ol/projection.test.js index a840a6f0f4..5a217e0f40 100644 --- a/test/spec/ol/projection.test.js +++ b/test/spec/ol/projection.test.js @@ -215,6 +215,21 @@ describe('ol.projection', function() { expect(output[5]).toRoughlyEqual(52.4827802220782, 1e-9); }); + it('accepts an optional destination array', function() { + var transform = ol.projection.getTransformFromCodes( + 'EPSG:3857', 'EPSG:4326'); + var input = [-12000000, 5000000]; + var output = []; + + var got = transform(input, output); + expect(got).toBe(output); + + expect(output[0]).toRoughlyEqual(-107.79783409434258, 1e-9); + expect(output[1]).toRoughlyEqual(40.91627447067577, 1e-9); + + expect(input).toEqual([-12000000, 5000000]); + }); + it('accepts a dimension', function() { var transform = ol.projection.getTransformFromCodes( 'GOOGLE', 'EPSG:4326'); @@ -225,7 +240,7 @@ describe('ol.projection', function() { -626172.13571216376, 6887893.4928337997, 100, -12000000, 5000000, 200, -626172.13571216376, 6887893.4928337997, 300 - ], dimension); + ], undefined, dimension); expect(output[0]).toRoughlyEqual(-5.625, 1e-9); expect(output[1]).toRoughlyEqual(52.4827802220782, 1e-9); @@ -247,7 +262,7 @@ describe('ol.projection', function() { it('removes functions cached by addTransform', function() { var foo = new ol.Projection('foo', units, extent); var bar = new ol.Projection('bar', units, extent); - var transform = function(intput, dimension) {return input}; + var transform = function(input, output, dimension) {return input}; ol.projection.addTransform(foo, bar, transform); expect(ol.projection.transforms_).not.toBeUndefined(); expect(ol.projection.transforms_.foo).not.toBeUndefined(); From f7a895a8236c0eb773993df87e1dd021546aa28d Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Sun, 3 Mar 2013 19:54:21 +0100 Subject: [PATCH 15/41] Remove unused tileGrid.getTileSize() call. --- src/ol/renderer/dom/domtilelayerrenderer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index 9b5dd26b32..402b3edfaa 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -138,7 +138,6 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = /** @type {Object.} */ var newTileLayerZKeys = {}; - var tileSize = tileGrid.getTileSize(); var iz, tileCoordKey, tileCoordOrigin, tileLayerZ, tileLayerZKey, tilesToDraw; for (iz = 0; iz < zs.length; ++iz) { tileLayerZKey = zs[iz]; From 7c440d087f0eb616917a443c9857f8a0d0a40515 Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Sun, 3 Mar 2013 20:32:39 +0100 Subject: [PATCH 16/41] Ensure we cannot set both origin and origins in the tilegrid --- src/ol/tilegrid/tilegrid.js | 3 +++ test/spec/ol/tilegrid.test.js | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/ol/tilegrid/tilegrid.js b/src/ol/tilegrid/tilegrid.js index 7b65dd5cdb..52d449d084 100644 --- a/src/ol/tilegrid/tilegrid.js +++ b/src/ol/tilegrid/tilegrid.js @@ -58,6 +58,9 @@ ol.tilegrid.TileGrid = function(tileGridOptions) { this.origins_ = tileGridOptions.origins; goog.asserts.assert(this.origins_.length == this.resolutions_.length); } + goog.asserts.assert( + (goog.isNull(this.origin_) && !goog.isNull(this.origins_)) || + (!goog.isNull(this.origin_) && goog.isNull(this.origins_))); /** * @private diff --git a/test/spec/ol/tilegrid.test.js b/test/spec/ol/tilegrid.test.js index 1c93439115..bb118dd1d8 100644 --- a/test/spec/ol/tilegrid.test.js +++ b/test/spec/ol/tilegrid.test.js @@ -68,6 +68,20 @@ describe('ol.tilegrid.TileGrid', function() { }); }); + describe('create with both origin and multiple origins', function() { + it('throws an exception', function() { + expect(function() { + return new ol.tilegrid.TileGrid({ + resolutions: [100, 50, 25, 10], + extent: extent, + origins: [origin, origin, origin, origin], + origin: origin, + tileSize: tileSize + }); + }).toThrow(); + }); + }); + describe('create with too few origins', function() { it('throws an exception', function() { expect(function() { From 2816e3256cf213716109f16e990557c63c2ebd85 Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Sun, 3 Mar 2013 20:37:45 +0100 Subject: [PATCH 17/41] Add support for multiple tileSizes in the tilegrid. This is needed by WMTS. --- src/objectliterals.exports | 1 + .../canvas/canvastilelayerrenderer.js | 2 +- src/ol/renderer/dom/domtilelayerrenderer.js | 2 +- .../renderer/webgl/webgltilelayerrenderer.js | 2 +- src/ol/source/debugtilesource.js | 2 +- src/ol/source/tiledwmssource.js | 3 -- src/ol/tilegrid/tilegrid.js | 37 +++++++++++++++---- src/ol/tileurlfunction.js | 6 ++- 8 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/objectliterals.exports b/src/objectliterals.exports index 3e0d0e4f1a..8e817820f2 100644 --- a/src/objectliterals.exports +++ b/src/objectliterals.exports @@ -134,6 +134,7 @@ @exportObjectLiteralProperty ol.tilegrid.TileGridOptions.origins Array.|undefined @exportObjectLiteralProperty ol.tilegrid.TileGridOptions.resolutions !Array. @exportObjectLiteralProperty ol.tilegrid.TileGridOptions.tileSize ol.Size|undefined +@exportObjectLiteralProperty ol.tilegrid.TileGridOptions.tileSizes Array.|undefined @exportObjectLiteral ol.tilegrid.XYZOptions @exportObjectLiteralProperty ol.tilegrid.XYZOptions.maxZoom number diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index 8204edcf33..617a1e2e65 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -91,8 +91,8 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = var tileSource = tileLayer.getTileSource(); var tileSourceKey = goog.getUid(tileSource).toString(); var tileGrid = tileSource.getTileGrid(); - var tileSize = tileGrid.getTileSize(); var z = tileGrid.getZForResolution(view2DState.resolution); + var tileSize = tileGrid.getTileSize(z); var tileResolution = tileGrid.getResolution(z); var tileRange = tileGrid.getTileRangeForExtentAndResolution( frameState.extent, tileResolution); diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index 402b3edfaa..f51382b4d9 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -292,7 +292,7 @@ ol.renderer.dom.TileLayerZ_.prototype.addTile = function(tile) { if (tileCoordKey in this.tiles_) { return; } - var tileSize = this.tileGrid_.getTileSize(); + var tileSize = this.tileGrid_.getTileSize(tileCoord.z); var image = tile.getImage(this); var style = image.style; style.position = 'absolute'; diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 9b75e0d0b1..f2a0219586 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -299,7 +299,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = } else { var tileRangeSize = tileRange.getSize(); - var tileSize = tileGrid.getTileSize(); + var tileSize = tileGrid.getTileSize(z); var maxDimension = Math.max( tileRangeSize.width * tileSize.width, diff --git a/src/ol/source/debugtilesource.js b/src/ol/source/debugtilesource.js index 8cd712d584..e553081ae3 100644 --- a/src/ol/source/debugtilesource.js +++ b/src/ol/source/debugtilesource.js @@ -33,7 +33,7 @@ ol.DebugTile_ = function(tileCoord, tileGrid) { * @private * @type {ol.Size} */ - this.tileSize_ = tileGrid.getTileSize(); + this.tileSize_ = tileGrid.getTileSize(tileCoord.z); /** * @private diff --git a/src/ol/source/tiledwmssource.js b/src/ol/source/tiledwmssource.js index c3e3838b98..9c7eb5ec8c 100644 --- a/src/ol/source/tiledwmssource.js +++ b/src/ol/source/tiledwmssource.js @@ -46,9 +46,6 @@ ol.source.TiledWMS = function(tiledWMSOptions) { 'FORMAT': 'image/png', 'TRANSPARENT': true }; - var tileSize = tileGrid.getTileSize(); - baseParams['WIDTH'] = tileSize.width; - baseParams['HEIGHT'] = tileSize.height; baseParams[version >= '1.3' ? 'CRS' : 'SRS'] = projection.getCode(); goog.object.extend(baseParams, tiledWMSOptions.params); diff --git a/src/ol/tilegrid/tilegrid.js b/src/ol/tilegrid/tilegrid.js index 52d449d084..415557d93e 100644 --- a/src/ol/tilegrid/tilegrid.js +++ b/src/ol/tilegrid/tilegrid.js @@ -62,13 +62,27 @@ ol.tilegrid.TileGrid = function(tileGridOptions) { (goog.isNull(this.origin_) && !goog.isNull(this.origins_)) || (!goog.isNull(this.origin_) && goog.isNull(this.origins_))); + /** + * @private + * @type {Array.} + */ + this.tileSizes_ = null; + if (goog.isDef(tileGridOptions.tileSizes)) { + this.tileSizes_ = tileGridOptions.tileSizes; + goog.asserts.assert(this.tileSizes_.length == this.resolutions_.length); + } + /** * @private * @type {ol.Size} */ this.tileSize_ = goog.isDef(tileGridOptions.tileSize) ? tileGridOptions.tileSize : - new ol.Size(ol.DEFAULT_TILE_SIZE, ol.DEFAULT_TILE_SIZE); + goog.isNull(this.tileSizes_) ? + new ol.Size(ol.DEFAULT_TILE_SIZE, ol.DEFAULT_TILE_SIZE) : null; + goog.asserts.assert( + (goog.isNull(this.tileSize_) && !goog.isNull(this.tileSizes_)) || + (!goog.isNull(this.tileSize_) && goog.isNull(this.tileSizes_))); }; @@ -117,7 +131,7 @@ ol.tilegrid.TileGrid.prototype.getOrigin = function(z) { ol.tilegrid.TileGrid.prototype.getPixelBoundsForTileCoordAndResolution = function(tileCoord, resolution) { var scale = resolution / this.getResolution(tileCoord.z); - var tileSize = this.getTileSize(); + var tileSize = this.getTileSize(tileCoord.z); tileSize = new ol.Size(tileSize.width / scale, tileSize.height / scale); var minX, maxX, minY, maxY; @@ -155,7 +169,7 @@ ol.tilegrid.TileGrid.prototype.getResolutions = function() { ol.tilegrid.TileGrid.prototype.getTileRangeExtent = function(z, tileRange) { var origin = this.getOrigin(z); var resolution = this.getResolution(z); - var tileSize = this.tileSize_; + var tileSize = this.getTileSize(z); var minX = origin.x + tileRange.minX * tileSize.width * resolution; var minY = origin.y + tileRange.minY * tileSize.height * resolution; var maxX = origin.x + (tileRange.maxX + 1) * tileSize.width * resolution; @@ -197,7 +211,7 @@ ol.tilegrid.TileGrid.prototype.getTileRangeForExtentAndZ = function(extent, z) { ol.tilegrid.TileGrid.prototype.getTileCoordCenter = function(tileCoord) { var origin = this.getOrigin(tileCoord.z); var resolution = this.getResolution(tileCoord.z); - var tileSize = this.tileSize_; + var tileSize = this.getTileSize(tileCoord.z); var x = origin.x + (tileCoord.x + 0.5) * tileSize.width * resolution; var y = origin.y + (tileCoord.y + 0.5) * tileSize.height * resolution; return new ol.Coordinate(x, y); @@ -211,7 +225,7 @@ ol.tilegrid.TileGrid.prototype.getTileCoordCenter = function(tileCoord) { ol.tilegrid.TileGrid.prototype.getTileCoordExtent = function(tileCoord) { var origin = this.getOrigin(tileCoord.z); var resolution = this.getResolution(tileCoord.z); - var tileSize = this.tileSize_; + var tileSize = this.getTileSize(tileCoord.z); var minX = origin.x + tileCoord.x * tileSize.width * resolution; var minY = origin.y + tileCoord.y * tileSize.height * resolution; var maxX = minX + tileSize.width * resolution; @@ -249,7 +263,7 @@ ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndResolution_ = function( var z = this.getZForResolution(resolution); var scale = resolution / this.getResolution(z); var origin = this.getOrigin(z); - var tileSize = this.getTileSize(); + var tileSize = this.getTileSize(z); var x = scale * (coordinate.x - origin.x) / (resolution * tileSize.width); var y = scale * (coordinate.y - origin.y) / (resolution * tileSize.height); @@ -289,10 +303,17 @@ ol.tilegrid.TileGrid.prototype.getTileCoordResolution = function(tileCoord) { /** + * @param {number} z Z. * @return {ol.Size} Tile size. */ -ol.tilegrid.TileGrid.prototype.getTileSize = function() { - return this.tileSize_; +ol.tilegrid.TileGrid.prototype.getTileSize = function(z) { + if (!goog.isNull(this.tileSize_)) { + return this.tileSize_; + } else { + goog.asserts.assert(!goog.isNull(this.tileSizes_)); + goog.asserts.assert(0 <= z && z < this.tileSizes_.length); + return this.tileSizes_[z]; + } }; diff --git a/src/ol/tileurlfunction.js b/src/ol/tileurlfunction.js index e5e3dfc3e6..d64c57ec9e 100644 --- a/src/ol/tileurlfunction.js +++ b/src/ol/tileurlfunction.js @@ -86,7 +86,11 @@ ol.TileUrlFunction.createBboxParam = var bboxValues = axisOrientation.substr(0, 2) == 'ne' ? [tileExtent.minY, tileExtent.minX, tileExtent.maxY, tileExtent.maxX] : [tileExtent.minX, tileExtent.minY, tileExtent.maxX, tileExtent.maxY]; - return goog.uri.utils.appendParam(baseUrl, 'BBOX', bboxValues.join(',')); + var tileSize = tileGrid.getTileSize(tileCoord.z); + return goog.uri.utils.appendParams(baseUrl, + 'BBOX', bboxValues.join(','), + 'HEIGHT', tileSize.height, + 'WIDTH', tileSize.width); } }; }; From bf325c38b44671deacafcb1ab735004906bfe422 Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Sun, 3 Mar 2013 20:38:40 +0100 Subject: [PATCH 18/41] Fix tests related to createBboxParam. --- test/spec/ol/tileurlfunction.test.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/spec/ol/tileurlfunction.test.js b/test/spec/ol/tileurlfunction.test.js index b11180f811..62f245f5c9 100644 --- a/test/spec/ol/tileurlfunction.test.js +++ b/test/spec/ol/tileurlfunction.test.js @@ -75,7 +75,8 @@ describe('ol.TileUrlFunction', function() { var tileCoord = new ol.TileCoord(1, 0, 0); var tileUrl = tileUrlFunction(tileCoord); var expected = 'http://wms?foo=bar&BBOX=-20037508.342789244' + - '%2C20037508.342789244%2C0%2C40075016.68557849'; + '%2C20037508.342789244%2C0%2C40075016.68557849' + + '&HEIGHT=256&WIDTH=256'; expect(tileUrl).toEqual(expected); }); it('creates expected URL respecting axis orientation', function() { @@ -85,7 +86,8 @@ describe('ol.TileUrlFunction', function() { var tileCoord = new ol.TileCoord(1, 0, 0); var tileUrl = tileUrlFunction(tileCoord); var expected = 'http://wms?foo=bar&BBOX=20037508.342789244' + - '%2C-20037508.342789244%2C40075016.68557849%2C0'; + '%2C-20037508.342789244%2C40075016.68557849%2C0' + + '&HEIGHT=256&WIDTH=256'; expect(tileUrl).toEqual(expected); }); }); From 93131d610518ec0438682b2186ebf7b3ec15caa1 Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Sun, 3 Mar 2013 20:39:22 +0100 Subject: [PATCH 19/41] Add some tests for the multiple tileSizes in tilegrid. --- test/spec/ol/tilegrid.test.js | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/test/spec/ol/tilegrid.test.js b/test/spec/ol/tilegrid.test.js index bb118dd1d8..3c24a17167 100644 --- a/test/spec/ol/tilegrid.test.js +++ b/test/spec/ol/tilegrid.test.js @@ -108,6 +108,59 @@ describe('ol.tilegrid.TileGrid', function() { }); }); + describe('create with multiple tileSizes', function() { + it('does not throw an exception', function() { + expect(function() { + return new ol.tilegrid.TileGrid({ + resolutions: [100, 50, 25, 10], + extent: extent, + tileSizes: [tileSize, tileSize, tileSize, tileSize], + origin: origin + }); + }).not.toThrow(); + }); + }); + + describe('create with both tileSize and multiple tileSizes', function() { + it('throws an exception', function() { + expect(function() { + return new ol.tilegrid.TileGrid({ + resolutions: [100, 50, 25, 10], + extent: extent, + tileSizes: [tileSize, tileSize, tileSize, tileSize], + tileSize: tileSize, + origin: origin + }); + }).toThrow(); + }); + }); + + describe('create with too few tileSizes', function() { + it('throws an exception', function() { + expect(function() { + return new ol.tilegrid.TileGrid({ + resolutions: [100, 50, 25, 10], + extent: extent, + tileSizes: [tileSize, tileSize, tileSize], + origin: origin + }); + }).toThrow(); + }); + }); + + describe('create with too many tileSizes', function() { + it('throws an exception', function() { + expect(function() { + return new ol.tilegrid.TileGrid({ + resolutions: [100, 50, 25, 10], + extent: extent, + tileSizes: [tileSize, tileSize, tileSize, tileSize, tileSize], + origin: origin + }); + }).toThrow(); + }); + }); + describe('createForProjection', function() { it('allows easier creation of a tile grid', function() { From e9fa08fccb436184de499a367f7bd13a8239f8bf Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sun, 3 Mar 2013 20:53:13 +0100 Subject: [PATCH 20/41] Use in-place transforms where possible --- src/ol/control/mousepositioncontrol.js | 5 +++-- src/ol/geolocation.js | 10 ++++++---- src/ol/projection.js | 19 ++++++++++++++++++- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/ol/control/mousepositioncontrol.js b/src/ol/control/mousepositioncontrol.js index 0f3cfb9400..60a667f4a0 100644 --- a/src/ol/control/mousepositioncontrol.js +++ b/src/ol/control/mousepositioncontrol.js @@ -178,8 +178,9 @@ ol.control.MousePosition.prototype.updateHTML_ = function(pixel) { var map = this.getMap(); var coordinate = map.getCoordinateFromPixel(pixel); if (!goog.isNull(coordinate)) { - var output = this.transform_([coordinate.x, coordinate.y]); - coordinate = new ol.Coordinate(output[0], output[1]); + var vertex = [coordinate.x, coordinate.y]; + vertex = this.transform_(vertex, vertex); + coordinate = new ol.Coordinate(vertex[0], vertex[1]); if (goog.isDef(this.coordinateFormat_)) { html = this.coordinateFormat_(coordinate); } else { diff --git a/src/ol/geolocation.js b/src/ol/geolocation.js index bb90723f15..5920f92328 100644 --- a/src/ol/geolocation.js +++ b/src/ol/geolocation.js @@ -79,9 +79,10 @@ ol.Geolocation.prototype.handleProjectionChanged_ = function() { this.transformFn_ = ol.projection.getTransform( ol.projection.getFromCode('EPSG:4326'), projection); if (!goog.isNull(this.position_)) { - var output = this.transformFn_([this.position_.x, this.position_.y]); + var vertex = [this.position_.x, this.position_.y]; + vertex = this.transformFn_(vertex, vertex, 2); this.set(ol.GeolocationProperty.POSITION, - new ol.Coordinate(output[0], output[1])); + new ol.Coordinate(vertex[0], vertex[1])); } } }; @@ -109,9 +110,10 @@ ol.Geolocation.prototype.positionChange_ = function(position) { this.set(ol.GeolocationProperty.HEADING, goog.isNull(coords.heading) ? undefined : goog.math.toRadians(coords.heading)); this.position_ = new ol.Coordinate(coords.longitude, coords.latitude); - var output = this.transformFn_([coords.longitude, coords.latitude]); + var vertex = [coords.longitude, coords.latitude]; + vertex = this.transformFn_(vertex, vertex, 2); this.set(ol.GeolocationProperty.POSITION, - new ol.Coordinate(output[0], output[1])); + new ol.Coordinate(vertex[0], vertex[1])); this.set(ol.GeolocationProperty.SPEED, goog.isNull(coords.speed) ? undefined : coords.speed); }; diff --git a/src/ol/projection.js b/src/ol/projection.js index 86ac70b6a5..30cc5deb2c 100644 --- a/src/ol/projection.js +++ b/src/ol/projection.js @@ -458,6 +458,14 @@ ol.projection.getTransformFromCodes = function(sourceCode, destinationCode) { * @return {Array.} Input coordinate array (same array as input). */ ol.projection.identityTransform = function(input, opt_output, opt_dimension) { + if (goog.isDef(opt_output) && input !== opt_output) { + // TODO: consider making this a warning instead + goog.asserts.assert(false, 'This should not be used internally.'); + for (var i = 0, ii = input.length; i < ii; ++i) { + opt_output[i] = input[i]; + } + input = opt_output; + } return input; }; @@ -470,7 +478,16 @@ ol.projection.identityTransform = function(input, opt_output, opt_dimension) { * values). */ ol.projection.cloneTransform = function(input, opt_output, opt_dimension) { - return input.slice(); + var output; + if (goog.isDef(opt_output)) { + for (var i = 0, ii = input.length; i < ii; ++i) { + opt_output[i] = input[i]; + } + output = opt_output; + } else { + output = input.slice(); + } + return output; }; From 684ea356733afac752a04213e56f928b5148eeca Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Sun, 3 Mar 2013 16:17:38 +0100 Subject: [PATCH 21/41] Add sphere with radius equal to the semi-major axis of the WGS84 ellipsoid --- src/ol/sphere/wgs84.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/ol/sphere/wgs84.js diff --git a/src/ol/sphere/wgs84.js b/src/ol/sphere/wgs84.js new file mode 100644 index 0000000000..e30aafeb4b --- /dev/null +++ b/src/ol/sphere/wgs84.js @@ -0,0 +1,10 @@ +goog.provide('ol.sphere.WGS84'); + +goog.require('ol.Sphere'); + + +/** + * A sphere with radius equal to the semi-major axis of the WGS84 ellipsoid. + * @const {ol.Sphere} + */ +ol.sphere.WGS84 = new ol.Sphere(6378137); From e6f08df72caaeb3b5ebf306a7ee81a0abe076cc3 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Sun, 3 Mar 2013 17:14:35 +0100 Subject: [PATCH 22/41] Add the normal sphere --- src/ol/sphere/normal.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/ol/sphere/normal.js diff --git a/src/ol/sphere/normal.js b/src/ol/sphere/normal.js new file mode 100644 index 0000000000..e07bf000b4 --- /dev/null +++ b/src/ol/sphere/normal.js @@ -0,0 +1,10 @@ +goog.provide('ol.sphere.NORMAL'); + +goog.require('ol.Sphere'); + + +/** + * The normal sphere. + * @const {ol.Sphere} + */ +ol.sphere.NORMAL = new ol.Sphere(6370997); From d3e49d0a19368fdf7214006ac0158ef18b03c6fb Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Sun, 3 Mar 2013 17:15:56 +0100 Subject: [PATCH 23/41] Add ol.Projection.getPointResolution --- src/ol/projection.exports | 1 + src/ol/projection.js | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/ol/projection.exports b/src/ol/projection.exports index 613ac99a3c..e82e78498f 100644 --- a/src/ol/projection.exports +++ b/src/ol/projection.exports @@ -2,6 +2,7 @@ @exportProperty ol.Projection.prototype.getAxisOrientation @exportProperty ol.Projection.prototype.getCode @exportProperty ol.Projection.prototype.getExtent +@exportProperty ol.Projection.prototype.getPointResolution @exportProperty ol.Projection.prototype.getUnits @exportSymbol ol.ProjectionUnits diff --git a/src/ol/projection.js b/src/ol/projection.js index 30cc5deb2c..f55f4ba45e 100644 --- a/src/ol/projection.js +++ b/src/ol/projection.js @@ -85,6 +85,14 @@ ol.Projection.prototype.getExtent = function() { }; +/** + * @param {number} resolution Resolution. + * @param {ol.Coordinate} point Point. + * @return {number} Point resolution. + */ +ol.Projection.prototype.getPointResolution = goog.abstractMethod; + + /** * @return {ol.ProjectionUnits} Units. */ From 98d7391024cc032f15f5f2e4e3b85ab51c4a54ff Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Sun, 3 Mar 2013 17:17:13 +0100 Subject: [PATCH 24/41] Implement getPointResolution for EPSG:3587 --- src/ol/projection/epsg3857.js | 10 +++++ test/spec/ol/projection.epsg3857.test.js | 49 ++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 test/spec/ol/projection.epsg3857.test.js diff --git a/src/ol/projection/epsg3857.js b/src/ol/projection/epsg3857.js index 0d183c3e66..93a99f8a62 100644 --- a/src/ol/projection/epsg3857.js +++ b/src/ol/projection/epsg3857.js @@ -4,6 +4,7 @@ goog.require('goog.array'); goog.require('ol.Extent'); goog.require('ol.Projection'); goog.require('ol.ProjectionUnits'); +goog.require('ol.math'); goog.require('ol.projection'); @@ -128,3 +129,12 @@ ol.projection.EPSG3857.toEPSG4326 = function(input, opt_output, opt_dimension) { } return output; }; + + +/** + * @inheritDoc + */ +ol.projection.EPSG3857.prototype.getPointResolution = + function(resolution, point) { + return resolution / ol.math.cosh(point.y / ol.projection.EPSG3857.RADIUS); +}; diff --git a/test/spec/ol/projection.epsg3857.test.js b/test/spec/ol/projection.epsg3857.test.js new file mode 100644 index 0000000000..51f72444ec --- /dev/null +++ b/test/spec/ol/projection.epsg3857.test.js @@ -0,0 +1,49 @@ +goog.provide('ol.test.projection.EPSG3857'); + + +describe('ol.projection.EPSG3857', function() { + + describe('getPointResolution', function() { + + it('returns the correct point scale at the equator', function() { + // @see http://msdn.microsoft.com/en-us/library/aa940990.aspx + var epsg3857 = ol.projection.getFromCode('EPSG:3857'); + var resolution = 19.11; + var point = new ol.Coordinate(0, 0); + expect(epsg3857.getPointResolution(resolution, point)). + toRoughlyEqual(19.11, 1e-1); + }); + + it('returns the correct point scale at the latitude of Toronto', + function() { + // @see http://msdn.microsoft.com/en-us/library/aa940990.aspx + var epsg3857 = ol.projection.getFromCode('EPSG:3857'); + var epsg4326 = ol.projection.getFromCode('EPSG:4326'); + var resolution = 19.11; + var point = ol.projection.transform( + new ol.Coordinate(0, 43.65), epsg4326, epsg3857); + expect(epsg3857.getPointResolution(resolution, point)). + toRoughlyEqual(19.11 * Math.cos(Math.PI * 43.65 / 180), 1e-9); + }); + + it('returns the correct point scale at various latitudes', function() { + // @see http://msdn.microsoft.com/en-us/library/aa940990.aspx + var epsg3857 = ol.projection.getFromCode('EPSG:3857'); + var epsg4326 = ol.projection.getFromCode('EPSG:4326'); + var resolution = 19.11; + var latitude; + for (latitude = 0; latitude < 90; ++latitude) { + var point = ol.projection.transform( + new ol.Coordinate(0, latitude), epsg4326, epsg3857); + expect(epsg3857.getPointResolution(resolution, point)). + toRoughlyEqual(19.11 * Math.cos(Math.PI * latitude / 180), 1e-9); + } + }); + + }); + +}); + + +goog.require('ol.Coordinate'); +goog.require('ol.projection.EPSG3857'); From 343768df6ac2108e8a3ca1a8ad854317c4059132 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Sun, 3 Mar 2013 17:17:33 +0100 Subject: [PATCH 25/41] Implement getPointResolution for EPSG:4326 --- src/ol/projection/epsg4326.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ol/projection/epsg4326.js b/src/ol/projection/epsg4326.js index 05b2c760d7..1c5d7215aa 100644 --- a/src/ol/projection/epsg4326.js +++ b/src/ol/projection/epsg4326.js @@ -41,3 +41,12 @@ ol.projection.EPSG4326.PROJECTIONS = [ new ol.projection.EPSG4326('urn:ogc:def:crs:EPSG:6.6:4326', 'neu'), new ol.projection.EPSG4326('urn:ogc:def:crs:OGC:1.3:CRS84') ]; + + +/** + * @inheritDoc + */ +ol.projection.EPSG4326.prototype.getPointResolution = + function(resolution, point) { + return resolution; +}; From a8760108d4e519190d344f83537342d5c1f00f30 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Sun, 3 Mar 2013 17:19:18 +0100 Subject: [PATCH 26/41] Estimate point resolution for Proj4js projections --- src/ol/projection.js | 40 +++++++++++++++++++++++++++++++++ test/spec/ol/projection.test.js | 30 +++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/ol/projection.js b/src/ol/projection.js index f55f4ba45e..0969b45882 100644 --- a/src/ol/projection.js +++ b/src/ol/projection.js @@ -8,6 +8,7 @@ goog.require('goog.object'); goog.require('ol.Coordinate'); goog.require('ol.Extent'); goog.require('ol.TransformFunction'); +goog.require('ol.sphere.NORMAL'); /** @@ -129,10 +130,49 @@ ol.Proj4jsProjection_ = function(code, proj4jsProj) { */ this.proj4jsProj_ = proj4jsProj; + /** + * @private + * @type {?ol.TransformFunction} + */ + this.toEPSG4326_ = null; + }; goog.inherits(ol.Proj4jsProjection_, ol.Projection); +/** + * @inheritDoc + */ +ol.Proj4jsProjection_.prototype.getPointResolution = + function(resolution, point) { + if (this.getUnits() == ol.ProjectionUnits.DEGREES) { + return resolution; + } else { + // Estimate point resolution by transforming the center pixel to EPSG:4326, + // measuring its width and height on the normal sphere, and taking the + // average of the width and height. + if (goog.isNull(this.toEPSG4326_)) { + this.toEPSG4326_ = ol.projection.getTransform( + this, ol.projection.getProj4jsProjectionFromCode_('EPSG:4326')); + } + var vertices = [ + point.x - resolution / 2, point.y, + point.x + resolution / 2, point.y, + point.x, point.y - resolution / 2, + point.x, point.y + resolution / 2 + ]; + vertices = this.toEPSG4326_(vertices, vertices, 2); + var width = ol.sphere.NORMAL.haversineDistance( + new ol.Coordinate(vertices[0], vertices[1]), + new ol.Coordinate(vertices[2], vertices[3])); + var height = ol.sphere.NORMAL.haversineDistance( + new ol.Coordinate(vertices[4], vertices[5]), + new ol.Coordinate(vertices[6], vertices[7])); + return (width + height) / 2; + } +}; + + /** * @return {Proj4js.Proj} Proj4js projection. */ diff --git a/test/spec/ol/projection.test.js b/test/spec/ol/projection.test.js index 5a217e0f40..c961d41819 100644 --- a/test/spec/ol/projection.test.js +++ b/test/spec/ol/projection.test.js @@ -144,6 +144,36 @@ describe('ol.projection', function() { expect(point.y).toRoughlyEqual(200146.976, 1); }); + it('numerically estimates point scale at the equator', function() { + var googleProjection = ol.projection.getFromCode('GOOGLE'); + expect(googleProjection.getPointResolution(1, new ol.Coordinate(0, 0))). + toRoughlyEqual(1, 1e-1); + }); + + it('numerically estimates point scale at various latitudes', function() { + var epsg3857Projection = ol.projection.getFromCode('EPSG:3857'); + var googleProjection = ol.projection.getFromCode('GOOGLE'); + var point, y; + for (y = -20; y <= 20; ++y) { + point = new ol.Coordinate(0, 1000000 * y); + expect(googleProjection.getPointResolution(1, point)).toRoughlyEqual( + epsg3857Projection.getPointResolution(1, point), 1e-1); + } + }); + + it('numerically estimates point scale at various points', function() { + var epsg3857Projection = ol.projection.getFromCode('EPSG:3857'); + var googleProjection = ol.projection.getFromCode('GOOGLE'); + var point, x, y; + for (x = -20; x <= 20; ++x) { + for (y = -20; y <= 20; ++y) { + point = new ol.Coordinate(1000000 * x, 1000000 * y); + expect(googleProjection.getPointResolution(1, point)).toRoughlyEqual( + epsg3857Projection.getPointResolution(1, point), 1e-1); + } + } + }); + }); describe('ol.projection.getTransform()', function() { From 5c6821ce71981b63ca6ff2448a873f564eb4cbe6 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Mon, 4 Mar 2013 00:31:36 +0100 Subject: [PATCH 27/41] Use more in-place transforms where possible --- src/ol/projection.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ol/projection.js b/src/ol/projection.js index 30cc5deb2c..3b87eecf49 100644 --- a/src/ol/projection.js +++ b/src/ol/projection.js @@ -501,8 +501,9 @@ ol.projection.cloneTransform = function(input, opt_output, opt_dimension) { */ ol.projection.transform = function(point, source, destination) { var transformFn = ol.projection.getTransform(source, destination); - var output = transformFn([point.x, point.y]); - return new ol.Coordinate(output[0], output[1]); + var vertex = [point.x, point.y]; + vertex = transformFn(vertex, vertex, 2); + return new ol.Coordinate(vertex[0], vertex[1]); }; @@ -516,6 +517,7 @@ ol.projection.transformWithCodes = function(point, sourceCode, destinationCode) { var transformFn = ol.projection.getTransformFromCodes( sourceCode, destinationCode); - var output = transformFn([point.x, point.y]); - return new ol.Coordinate(output[0], output[1]); + var vertex = [point.x, point.y]; + vertex = transformFn(vertex, vertex, 2); + return new ol.Coordinate(vertex[0], vertex[1]); }; From 8c2b01948bdbecb996ae8ec639b16c6010241eec Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Sun, 3 Mar 2013 20:50:13 +0100 Subject: [PATCH 28/41] Add ScaleLine control --- css/ol.css | 18 ++ src/objectliterals.exports | 6 + src/ol/control/scaleline.exports | 9 + src/ol/control/scalelinecontrol.js | 278 +++++++++++++++++++++++++++++ 4 files changed, 311 insertions(+) create mode 100644 src/ol/control/scaleline.exports create mode 100644 src/ol/control/scalelinecontrol.js diff --git a/css/ol.css b/css/ol.css index 197439505e..1a2ede8923 100644 --- a/css/ol.css +++ b/css/ol.css @@ -28,6 +28,24 @@ width: 100%; height: 100%; } +.ol-scale-line { + background: rgba(0,60,136,0.3); + border-radius: 4px; + bottom: 8px; + left: 8px; + padding: 2px; + position: absolute; +} +.ol-scale-line-inner { + border: 1px solid #eeeeee; + border-top: none; + color: #eeeeee; + font-size: 10px; + font-family: 'Lucida Grande',Verdana,Geneva,Lucida,Arial,Helvetica,sans-serif; + text-align: center; + margin: 1px; + padding: 0px 2px; +} .ol-viewport .ol-unselectable { -webkit-touch-callout: none; -webkit-user-select: none; diff --git a/src/objectliterals.exports b/src/objectliterals.exports index 3e0d0e4f1a..aa6bd4376e 100644 --- a/src/objectliterals.exports +++ b/src/objectliterals.exports @@ -57,6 +57,12 @@ @exportObjectLiteralProperty ol.control.AttributionOptions.map ol.Map|undefined @exportObjectLiteralProperty ol.control.AttributionOptions.target Element|undefined +@exportObjectLiteral ol.control.ScaleLineOptions +@exportObjectLiteralProperty ol.control.ScaleLineOptions.map ol.Map|undefined +@exportObjectLiteralProperty ol.control.ScaleLineOptions.minimumWidth number|undefined +@exportObjectLiteralProperty ol.control.ScaleLineOptions.target Element|undefined +@exportObjectLiteralProperty ol.control.ScaleLineOptions.units ol.control.ScaleLineUnits|undefined + @exportObjectLiteral ol.control.MousePositionOptions @exportObjectLiteralProperty ol.control.MousePositionOptions.coordinateFormat ol.CoordinateFormatType|undefined @exportObjectLiteralProperty ol.control.MousePositionOptions.map ol.Map|undefined diff --git a/src/ol/control/scaleline.exports b/src/ol/control/scaleline.exports new file mode 100644 index 0000000000..6d0cbe1cd1 --- /dev/null +++ b/src/ol/control/scaleline.exports @@ -0,0 +1,9 @@ +@exportClass ol.control.ScaleLine ol.control.ScaleLineOptions +@exportProperty ol.control.ScaleLine.prototype.setMap + +@exportSymbol ol.control.ScaleLineUnits +@exportProperty ol.control.ScaleLineUnits.DEGREES +@exportProperty ol.control.ScaleLineUnits.IMPERIAL +@exportProperty ol.control.ScaleLineUnits.NAUTICAL +@exportProperty ol.control.ScaleLineUnits.METRIC +@exportProperty ol.control.ScaleLineUnits.US diff --git a/src/ol/control/scalelinecontrol.js b/src/ol/control/scalelinecontrol.js new file mode 100644 index 0000000000..a9a0c707cf --- /dev/null +++ b/src/ol/control/scalelinecontrol.js @@ -0,0 +1,278 @@ +goog.provide('ol.control.ScaleLine'); +goog.provide('ol.control.ScaleLineUnits'); + +goog.require('goog.dom'); +goog.require('goog.style'); +goog.require('ol.FrameState'); +goog.require('ol.MapEvent'); +goog.require('ol.MapEventType'); +goog.require('ol.ProjectionUnits'); +goog.require('ol.TransformFunction'); +goog.require('ol.control.Control'); +goog.require('ol.projection'); +goog.require('ol.sphere.NORMAL'); + + +/** + * @enum {string} + */ +ol.control.ScaleLineUnits = { + DEGREES: 'degrees', + IMPERIAL: 'imperial', + NAUTICAL: 'nautical', + METRIC: 'metric', + US: 'us' +}; + + + +/** + * @constructor + * @extends {ol.control.Control} + * @param {ol.control.ScaleLineOptions=} opt_options Options. + */ +ol.control.ScaleLine = function(opt_options) { + + var options = opt_options || {}; + + /** + * @private + * @type {Element} + */ + this.innerElement_ = goog.dom.createDom(goog.dom.TagName.DIV, { + 'class': 'ol-scale-line-inner' + }); + + /** + * @private + * @type {Element} + */ + this.element_ = goog.dom.createDom(goog.dom.TagName.DIV, { + 'class': 'ol-scale-line ol-unselectable' + }, this.innerElement_); + + /** + * @private + * @type {number} + */ + this.minimumWidth_ = goog.isDef(options.minimumWidth) ? + options.minimumWidth : 64; + + /** + * @private + * @type {ol.control.ScaleLineUnits} + */ + this.units_ = goog.isDef(options.units) ? + options.units : ol.control.ScaleLineUnits.METRIC; + + /** + * @private + * @type {Array.} + */ + this.listenerKeys_ = null; + + /** + * @private + * @type {boolean} + */ + this.renderedVisible_ = false; + + /** + * @private + * @type {number|undefined} + */ + this.renderedWidth_; + + /** + * @private + * @type {string} + */ + this.renderedHTML_ = ''; + + /** + * @private + * @type {?ol.TransformFunction} + */ + this.toEPSG4326_ = null; + + goog.base(this, { + element: this.element_, + map: options.map, + target: options.target + }); + +}; +goog.inherits(ol.control.ScaleLine, ol.control.Control); + + +/** + * @const + * @type {Array.} + */ +ol.control.ScaleLine.LEADING_DIGITS = [1, 2, 5]; + + +/** + * @param {ol.MapEvent} mapEvent Map event. + */ +ol.control.ScaleLine.prototype.handleMapPostrender = function(mapEvent) { + var frameState = mapEvent.frameState; + this.updateElement_(mapEvent.frameState); +}; + + +/** + * @inheritDoc + */ +ol.control.ScaleLine.prototype.setMap = function(map) { + if (!goog.isNull(this.listenerKeys_)) { + goog.array.forEach(this.listenerKeys_, goog.events.unlistenByKey); + this.listenerKeys_ = null; + } + goog.base(this, 'setMap', map); + if (!goog.isNull(map)) { + this.listenerKeys_ = [ + goog.events.listen(map, ol.MapEventType.POSTRENDER, + this.handleMapPostrender, false, this) + ]; + } +}; + + +/** + * @param {?ol.FrameState} frameState Frame state. + * @private + */ +ol.control.ScaleLine.prototype.updateElement_ = function(frameState) { + + if (goog.isNull(frameState)) { + if (this.renderedVisible_) { + goog.style.showElement(this.element_, false); + this.renderedVisible_ = false; + } + return; + } + + var view2DState = frameState.view2DState; + var center = view2DState.center; + var projection = view2DState.projection; + var pointResolution = + projection.getPointResolution(view2DState.resolution, center); + var projectionUnits = projection.getUnits(); + + var cosLatitude; + if (projectionUnits == ol.ProjectionUnits.DEGREES && + (this.units_ == ol.control.ScaleLineUnits.METRIC || + this.units_ == ol.control.ScaleLineUnits.IMPERIAL)) { + + // Convert pointResolution from degrees to meters + this.toEPSG4326_ = null; + cosLatitude = Math.cos(goog.math.toRadians(center.y)); + pointResolution *= Math.PI * cosLatitude * ol.sphere.NORMAL.radius / 180; + + } else if (projectionUnits == ol.ProjectionUnits.METERS && + this.units_ == ol.control.ScaleLineUnits.DEGREES) { + + // Convert pointResolution from meters to degrees + if (goog.isNull(this.toEPSG4326_)) { + this.toEPSG4326_ = ol.projection.getTransform( + projection, ol.projection.getFromCode('EPSG:4326')); + } + var vertex = [center.x, center.y]; + vertex = this.toEPSG4326_(vertex, vertex, 2); + cosLatitude = Math.cos(goog.math.toRadians(vertex[1])); + pointResolution *= 180 / (Math.PI * cosLatitude * ol.sphere.NORMAL.radius); + + } else { + + this.toEPSG4326_ = null; + goog.asserts.assert( + ((this.units_ == ol.control.ScaleLineUnits.METRIC || + this.units_ == ol.control.ScaleLineUnits.IMPERIAL) && + projectionUnits == ol.ProjectionUnits.METERS) || + (this.units_ == ol.control.ScaleLineUnits.DEGREES && + projectionUnits == ol.ProjectionUnits.DEGREES)); + + } + + var nominalCount = this.minimumWidth_ * pointResolution; + var suffix = ''; + if (this.units_ == ol.control.ScaleLineUnits.DEGREES) { + if (nominalCount < 1 / 60) { + suffix = '\u2033'; // seconds + pointResolution *= 3600; + } else if (nominalCount < 1) { + suffix = '\u2032'; // minutes + pointResolution *= 60; + } else { + suffix = '\u00b0'; // degrees + } + } else if (this.units_ == ol.control.ScaleLineUnits.IMPERIAL) { + if (nominalCount < 0.9144) { + suffix = 'in'; + pointResolution /= 0.0254; + } else if (nominalCount < 1609.344) { + suffix = 'ft'; + pointResolution /= 0.3048; + } else { + suffix = 'mi'; + pointResolution /= 1609.344; + } + } else if (this.units_ == ol.control.ScaleLineUnits.NAUTICAL) { + pointResolution /= 1852; + suffix = 'nm'; + } else if (this.units_ == ol.control.ScaleLineUnits.METRIC) { + if (nominalCount < 1) { + suffix = 'mm'; + pointResolution *= 1000; + } else if (nominalCount < 1000) { + suffix = 'm'; + } else { + suffix = 'km'; + pointResolution /= 1000; + } + } else if (this.units_ == ol.control.ScaleLineUnits.US) { + if (nominalCount < 0.9144) { + suffix = 'in'; + pointResolution *= 39.37; + } else if (nominalCount < 1609.344) { + suffix = 'ft'; + pointResolution /= 0.30480061; + } else { + suffix = 'mi'; + pointResolution /= 1609.3472; + } + } else { + goog.asserts.assert(false); + } + + var i = 3 * Math.floor( + Math.log(this.minimumWidth_ * pointResolution) / Math.log(10)); + var count, width; + while (true) { + count = ol.control.ScaleLine.LEADING_DIGITS[i % 3] * + Math.pow(10, Math.floor(i / 3)); + width = Math.round(count / pointResolution); + if (width >= this.minimumWidth_) { + break; + } + ++i; + } + + var html = count + suffix; + if (this.renderedHTML_ != html) { + this.innerElement_.innerHTML = html; + this.renderedHTML_ = html; + } + + if (this.renderedWidth_ != width) { + this.innerElement_.style.width = width + 'px'; + this.renderedWidth_ = width; + } + + if (!this.renderedVisible_) { + goog.style.showElement(this.element_, true); + this.renderedVisible_ = true; + } + +}; From b663fd69f184146c761a1cefb0aee7d7fbbb3ec4 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Sun, 3 Mar 2013 20:51:52 +0100 Subject: [PATCH 29/41] Add scale line control options to map options --- src/objectliterals.exports | 2 ++ src/ol/map.js | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/objectliterals.exports b/src/objectliterals.exports index aa6bd4376e..abaa190619 100644 --- a/src/objectliterals.exports +++ b/src/objectliterals.exports @@ -10,6 +10,8 @@ @exportObjectLiteralProperty ol.MapOptions.mouseWheelZoomDelta number|undefined @exportObjectLiteralProperty ol.MapOptions.renderer ol.RendererHint|undefined @exportObjectLiteralProperty ol.MapOptions.renderers Array.|undefined +@exportObjectLiteralProperty ol.MapOptions.scaleLineControl boolean|undefined +@exportObjectLiteralProperty ol.MapOptions.scaleLineUnits ol.control.ScaleLineUnits|undefined @exportObjectLiteralProperty ol.MapOptions.shiftDragZoom boolean|undefined @exportObjectLiteralProperty ol.MapOptions.target Element|string @exportObjectLiteralProperty ol.MapOptions.touchPan boolean|undefined diff --git a/src/ol/map.js b/src/ol/map.js index 7978e829d4..b0600bcdeb 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -45,6 +45,7 @@ goog.require('ol.View'); goog.require('ol.View2D'); goog.require('ol.control.Attribution'); goog.require('ol.control.Control'); +goog.require('ol.control.ScaleLine'); goog.require('ol.control.Zoom'); goog.require('ol.interaction.DblClickZoom'); goog.require('ol.interaction.DragPan'); @@ -925,6 +926,16 @@ ol.Map.createControls_ = function(mapOptions) { controls.push(new ol.control.Attribution({})); } + var scaleLineControl = goog.isDef(mapOptions.scaleLineControl) ? + mapOptions.scaleLineControl : false; + if (scaleLineControl) { + var scaleLineUnits = goog.isDef(mapOptions.scaleLineUnits) ? + mapOptions.scaleLineUnits : undefined; + controls.push(new ol.control.ScaleLine({ + units: scaleLineUnits + })); + } + var zoomControl = goog.isDef(mapOptions.zoomControl) ? mapOptions.zoomControl : true; if (zoomControl) { From f3d01dcbd3b21b0ac0836d80ea3fc04b3eef4aed Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Sun, 3 Mar 2013 20:52:03 +0100 Subject: [PATCH 30/41] Add scale line to examples --- examples/epsg-4326.js | 3 +++ examples/full-screen.js | 1 + 2 files changed, 4 insertions(+) diff --git a/examples/epsg-4326.js b/examples/epsg-4326.js index 9acf4517f8..ba95c06146 100644 --- a/examples/epsg-4326.js +++ b/examples/epsg-4326.js @@ -3,6 +3,7 @@ goog.require('ol.Coordinate'); goog.require('ol.Map'); goog.require('ol.RendererHint'); goog.require('ol.View2D'); +goog.require('ol.control.ScaleLineUnits'); goog.require('ol.layer.TileLayer'); goog.require('ol.projection'); goog.require('ol.source.TiledWMS'); @@ -39,6 +40,8 @@ var map = new ol.Map({ layers: layers, // The OSgeo server does not set cross origin headers, so we cannot use WebGL renderers: [ol.RendererHint.CANVAS, ol.RendererHint.DOM], + scaleLineControl: true, + scaleLineUnits: ol.control.ScaleLineUnits.DEGREES, target: 'map', view: new ol.View2D({ projection: epsg4326, diff --git a/examples/full-screen.js b/examples/full-screen.js index e696c2fea1..8ab4ca96ea 100644 --- a/examples/full-screen.js +++ b/examples/full-screen.js @@ -15,6 +15,7 @@ var layer = new ol.layer.TileLayer({ var map = new ol.Map({ layers: new ol.Collection([layer]), renderers: ol.RendererHints.createFromQueryData(), + scaleLineControl: true, target: 'map', view: new ol.View2D({ center: new ol.Coordinate(0, 0), From 07e0fc3a2077c401548c072b8f17272634211cce Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Mon, 4 Mar 2013 07:30:33 +0100 Subject: [PATCH 31/41] Fix tileSize in the canvastilelayerrenderer. --- src/ol/renderer/canvas/canvastilelayerrenderer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index 617a1e2e65..9c338b7818 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -174,6 +174,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = var currentZ, i, scale, tileCoordKey, tileExtent, tilesToDraw; for (i = 0; i < zs.length; ++i) { currentZ = zs[i]; + tileSize = tileGrid.getTileSize(currentZ); tilesToDraw = tilesToDrawByZ[currentZ]; if (currentZ == z) { for (tileCoordKey in tilesToDraw) { From c35d07d481220b7acd00fa891c9f7cb60aec6472 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Mon, 4 Mar 2013 09:58:09 +0100 Subject: [PATCH 32/41] Rename minimumWidth to minWidth --- src/objectliterals.exports | 2 +- src/ol/control/scalelinecontrol.js | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/objectliterals.exports b/src/objectliterals.exports index abaa190619..fb5672147f 100644 --- a/src/objectliterals.exports +++ b/src/objectliterals.exports @@ -61,7 +61,7 @@ @exportObjectLiteral ol.control.ScaleLineOptions @exportObjectLiteralProperty ol.control.ScaleLineOptions.map ol.Map|undefined -@exportObjectLiteralProperty ol.control.ScaleLineOptions.minimumWidth number|undefined +@exportObjectLiteralProperty ol.control.ScaleLineOptions.minWidth number|undefined @exportObjectLiteralProperty ol.control.ScaleLineOptions.target Element|undefined @exportObjectLiteralProperty ol.control.ScaleLineOptions.units ol.control.ScaleLineUnits|undefined diff --git a/src/ol/control/scalelinecontrol.js b/src/ol/control/scalelinecontrol.js index a9a0c707cf..a2144e502c 100644 --- a/src/ol/control/scalelinecontrol.js +++ b/src/ol/control/scalelinecontrol.js @@ -55,8 +55,7 @@ ol.control.ScaleLine = function(opt_options) { * @private * @type {number} */ - this.minimumWidth_ = goog.isDef(options.minimumWidth) ? - options.minimumWidth : 64; + this.minWidth_ = goog.isDef(options.minWidth) ? options.minWidth : 64; /** * @private @@ -195,7 +194,7 @@ ol.control.ScaleLine.prototype.updateElement_ = function(frameState) { } - var nominalCount = this.minimumWidth_ * pointResolution; + var nominalCount = this.minWidth_ * pointResolution; var suffix = ''; if (this.units_ == ol.control.ScaleLineUnits.DEGREES) { if (nominalCount < 1 / 60) { @@ -247,13 +246,13 @@ ol.control.ScaleLine.prototype.updateElement_ = function(frameState) { } var i = 3 * Math.floor( - Math.log(this.minimumWidth_ * pointResolution) / Math.log(10)); + Math.log(this.minWidth_ * pointResolution) / Math.log(10)); var count, width; while (true) { count = ol.control.ScaleLine.LEADING_DIGITS[i % 3] * Math.pow(10, Math.floor(i / 3)); width = Math.round(count / pointResolution); - if (width >= this.minimumWidth_) { + if (width >= this.minWidth_) { break; } ++i; From b31d5cdb4a510324d0ef72351147a36e3393d3aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 4 Mar 2013 10:07:00 +0100 Subject: [PATCH 33/41] Update readme.md --- readme.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 85925eddb5..e969219100 100644 --- a/readme.md +++ b/readme.md @@ -5,7 +5,13 @@ ## Hosted Examples -The examples are hosted on GitHub (as GitHub pages). See http://openlayers.github.com/ol3/master/examples/. +The examples are hosted on GitHub (as GitHub pages): http://openlayers.github.com/ol3/master/examples/. + +By default the examples use the `ol.js` script, which is compiled using Closure Compiler's ADVANVCED mode. +By appending `?mode=simple` or `?mode=whitespace` to the URL you can make the example page load `ol-simple.js` +or `ol-whitespace.js` instead of `ol.js`. As their names suggest it, `ol-simple.js` and `ol-whitespace.js` +are compiled using the SIMPLE and WHITESPACE modes, respectively. For example: +http://openlayers.github.com/ol3/master/examples/full-screen.html?mode=simple. ## Build OpenLayers 3 From 2238c9bd6aaf2666a9fa22a429673a582308446e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 4 Mar 2013 10:15:31 +0100 Subject: [PATCH 34/41] Update readme.md --- readme.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/readme.md b/readme.md index e969219100..b94f437aa9 100644 --- a/readme.md +++ b/readme.md @@ -21,7 +21,7 @@ Run build.py: Windows users should run `build` instead. -## Run examples locally +## Run Examples locally Run the [Plovr](http://plovr.com/) web server with: @@ -39,18 +39,20 @@ and explore the `examples/` directory, for example by opening You can turn off compilation by appending `?mode=RAW` to the URL, for example . (By default mode is `ADVANCED`.) +Run examples without Plovr: + The examples can also be run against the `ol.js` standalone lib, without Plovr, just like the examples [hosted](http://openlayers.github.com/ol3/master/examples/) -on GitHub. You will want to run the examples against the standalone lib to verify -that will work correctly when copied on GitHub (as GitHub pages). Start by executing -the `hostexamples` build target: +on GitHub. Start by executing the `hostexamples` build target: $ ./build.py hostexamples -This will build `ol.js` and `ol.css`, creates the examples index page, and copy everything to -`build/gh-pages//`, where `` is the name of the local checked -out Git branch. You can now open the `build/gh-pages/examples` directory -in the browser, for example: . +This will build `ol.js`, `ol-simple.js`, `ol-whitespace.js`, and `ol.css`, create the examples index page, +and copy everything to `build/gh-pages//`, where `` is the name of the local +checked out Git branch. You can now open the examples index page in the browser, for example: +. To make an example use `ol-simple.js` or +`ol-whitespace.js` instead of `ol.js` append `?mode=simple` or `?mode=whitespace` to the example +URL. ## Run tests From eec1aec0e68e8c44eba59d33bcd18f03008a7e8a Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Sun, 3 Mar 2013 15:52:50 +0100 Subject: [PATCH 35/41] Remove ol.BingMapsStyle --- examples/two-layers.js | 3 +-- src/objectliterals.exports | 2 +- src/ol/source/bingmaps.exports | 6 ------ src/ol/source/bingmapssource.js | 13 ------------- 4 files changed, 2 insertions(+), 22 deletions(-) diff --git a/examples/two-layers.js b/examples/two-layers.js index 78451c0669..e325376b7f 100644 --- a/examples/two-layers.js +++ b/examples/two-layers.js @@ -1,4 +1,3 @@ -goog.require('ol.BingMapsStyle'); goog.require('ol.Collection'); goog.require('ol.Coordinate'); goog.require('ol.Map'); @@ -14,7 +13,7 @@ var layers = new ol.Collection([ new ol.layer.TileLayer({ source: new ol.source.BingMaps({ key: 'AgtFlPYDnymLEe9zJ5PCkghbNiFZE9aAtTy3mPaEnEBXqLHtFuTcKoZ-miMC3w7R', - style: ol.BingMapsStyle.AERIAL + style: 'Aerial' }) }), new ol.layer.TileLayer({ diff --git a/src/objectliterals.exports b/src/objectliterals.exports index 1abc752745..dd819ccd2d 100644 --- a/src/objectliterals.exports +++ b/src/objectliterals.exports @@ -96,7 +96,7 @@ @exportObjectLiteral ol.source.BingMapsOptions @exportObjectLiteralProperty ol.source.BingMapsOptions.culture string|undefined @exportObjectLiteralProperty ol.source.BingMapsOptions.key string -@exportObjectLiteralProperty ol.source.BingMapsOptions.style ol.BingMapsStyle +@exportObjectLiteralProperty ol.source.BingMapsOptions.style string @exportObjectLiteral ol.source.DebugTileSourceOptions @exportObjectLiteralProperty ol.source.DebugTileSourceOptions.extent ol.Extent|undefined diff --git a/src/ol/source/bingmaps.exports b/src/ol/source/bingmaps.exports index 516bf8777c..8f2a2384f2 100644 --- a/src/ol/source/bingmaps.exports +++ b/src/ol/source/bingmaps.exports @@ -1,7 +1 @@ @exportSymbol ol.source.BingMaps -@exportSymbol ol.BingMapsStyle -@exportProperty ol.BingMapsStyle.AERIAL -@exportProperty ol.BingMapsStyle.AERIAL_WITH_LABELS -@exportProperty ol.BingMapsStyle.ROAD -@exportProperty ol.BingMapsStyle.ORDNANCE_SURVEY -@exportProperty ol.BingMapsStyle.COLLINS_BART diff --git a/src/ol/source/bingmapssource.js b/src/ol/source/bingmapssource.js index 1e5355904c..7cd7a27155 100644 --- a/src/ol/source/bingmapssource.js +++ b/src/ol/source/bingmapssource.js @@ -1,4 +1,3 @@ -goog.provide('ol.BingMapsStyle'); goog.provide('ol.source.BingMaps'); goog.require('goog.Uri'); @@ -15,18 +14,6 @@ goog.require('ol.source.ImageTileSource'); goog.require('ol.tilegrid.XYZ'); -/** - * @enum {string} - */ -ol.BingMapsStyle = { - AERIAL: 'Aerial', - AERIAL_WITH_LABELS: 'AerialWithLabels', - ROAD: 'Road', - ORDNANCE_SURVEY: 'OrdnanceSurvey', - COLLINS_BART: 'CollinsBart' -}; - - /** * @constructor From 4baf397f7799baa75d4f0cfaa26bb3f004d26f81 Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Mon, 4 Mar 2013 17:14:07 +0100 Subject: [PATCH 36/41] Rework the structure of the resourceUrls object and remove duplicated resourceUrl object. --- src/ol/parser/ogc/wmtscapabilities_v1_0_0.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/ol/parser/ogc/wmtscapabilities_v1_0_0.js b/src/ol/parser/ogc/wmtscapabilities_v1_0_0.js index 1d1390248a..9260038a63 100644 --- a/src/ol/parser/ogc/wmtscapabilities_v1_0_0.js +++ b/src/ol/parser/ogc/wmtscapabilities_v1_0_0.js @@ -94,17 +94,19 @@ ol.parser.ogc.WMTSCapabilities_v1_0_0 = function() { obj['matrixHeight'] = parseInt(this.getChildValue(node), 10); }, 'ResourceURL': function(node, obj) { - obj['resourceUrl'] = obj['resourceUrl'] || {}; var resourceType = node.getAttribute('resourceType'); + var format = node.getAttribute('format'); + var template = node.getAttribute('template'); if (!obj['resourceUrls']) { - obj['resourceUrls'] = []; + obj['resourceUrls'] = {}; } - var resourceUrl = obj['resourceUrl'][resourceType] = { - 'format': node.getAttribute('format'), - 'template': node.getAttribute('template'), - 'resourceType': resourceType - }; - obj['resourceUrls'].push(resourceUrl); + if (!obj['resourceUrls'][resourceType]) { + obj['resourceUrls'][resourceType] = {}; + } + if (!obj['resourceUrls'][resourceType][format]) { + obj['resourceUrls'][resourceType][format] = []; + } + obj['resourceUrls'][resourceType][format].push(template); }, 'WSDL': function(node, obj) { obj['wsdl'] = {}; From 80509a6a623b0acf7a2e112ccaa5b7edc66ab8e9 Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Mon, 4 Mar 2013 17:15:26 +0100 Subject: [PATCH 37/41] Fix tests relative to the WMTS resourceUrl(s) object --- .../ogc/wmtscapabilities_v1_0_0.test.js | 30 +++++++++---------- .../xml/wmtscapabilities_v1_0_0/ogcsample.xml | 4 ++- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/test/spec/ol/parser/ogc/wmtscapabilities_v1_0_0.test.js b/test/spec/ol/parser/ogc/wmtscapabilities_v1_0_0.test.js index af7b43cd8d..a749a0eb5a 100644 --- a/test/spec/ol/parser/ogc/wmtscapabilities_v1_0_0.test.js +++ b/test/spec/ol/parser/ogc/wmtscapabilities_v1_0_0.test.js @@ -105,26 +105,24 @@ describe('ol.parser.ogc.wmtscapabilities_v1_0_0', function() { expect(wgs84Bbox.maxX).toEqual(180.0); expect(wgs84Bbox.minY).toEqual(-90.0); expect(wgs84Bbox.maxY).toEqual(90.0); - expect(layer.resourceUrl.tile.format).toEqual('image/png'); - var tpl = 'http://www.example.com/wmts/coastlines/{TileMatrix}/' + - '{TileRow}/{TileCol}.png'; - expect(layer.resourceUrl.tile.template).toEqual(tpl); - var format = 'application/gml+xml; version=3.1'; - expect(layer.resourceUrl.FeatureInfo.format).toEqual(format); - tpl = 'http://www.example.com/wmts/coastlines/{TileMatrixSet}/' + - '{TileMatrix}/{TileRow}/{TileCol}/{J}/{I}.xml'; - expect(layer.resourceUrl.FeatureInfo.template).toEqual(tpl); - expect(layer.resourceUrls[0].format).toEqual('image/png'); - expect(layer.resourceUrls[0].resourceType).toEqual('tile'); - tpl = 'http://www.example.com/wmts/coastlines/{TileMatrix}/' + + expect(layer.resourceUrls.hasOwnProperty('tile')).toBeTruthy(); + var format = 'image/png'; + expect(layer.resourceUrls.tile.hasOwnProperty(format)).toBeTruthy(); + expect(layer.resourceUrls.tile[format].length).toEqual(2); + var tpl = 'http://a.example.com/wmts/coastlines/{TileMatrix}/' + '{TileRow}/{TileCol}.png'; - expect(layer.resourceUrls[0].template).toEqual(tpl); + expect(layer.resourceUrls.tile[format][0]).toEqual(tpl); + tpl = 'http://b.example.com/wmts/coastlines/{TileMatrix}/' + + '{TileRow}/{TileCol}.png'; + expect(layer.resourceUrls.tile[format][1]).toEqual(tpl); + expect(layer.resourceUrls.hasOwnProperty('FeatureInfo')).toBeTruthy(); format = 'application/gml+xml; version=3.1'; - expect(layer.resourceUrls[1].format).toEqual(format); - expect(layer.resourceUrls[1].resourceType).toEqual('FeatureInfo'); + expect(layer.resourceUrls.FeatureInfo.hasOwnProperty(format)) + .toBeTruthy(); + expect(layer.resourceUrls.FeatureInfo[format].length).toEqual(1); tpl = 'http://www.example.com/wmts/coastlines/{TileMatrixSet}/' + '{TileMatrix}/{TileRow}/{TileCol}/{J}/{I}.xml'; - expect(layer.resourceUrls[1].template).toEqual(tpl); + expect(layer.resourceUrls.FeatureInfo[format][0]).toEqual(tpl); expect(dimensions.length).toEqual(1); expect(dimensions[0].title).toEqual('Time'); expect(dimensions[0]['abstract']).toEqual('Monthly datasets'); diff --git a/test/spec/ol/parser/ogc/xml/wmtscapabilities_v1_0_0/ogcsample.xml b/test/spec/ol/parser/ogc/xml/wmtscapabilities_v1_0_0/ogcsample.xml index 9f0f1bc690..0421214ffc 100644 --- a/test/spec/ol/parser/ogc/xml/wmtscapabilities_v1_0_0/ogcsample.xml +++ b/test/spec/ol/parser/ogc/xml/wmtscapabilities_v1_0_0/ogcsample.xml @@ -74,7 +74,9 @@ coastlines + template="http://a.example.com/wmts/coastlines/{TileMatrix}/{TileRow}/{TileCol}.png" /> +