From 516914c935981e5bdfdb098e00b7aad2a7e91a61 Mon Sep 17 00:00:00 2001 From: tschaub Date: Thu, 29 Sep 2011 12:21:05 -0600 Subject: [PATCH] Push dateline wrapping to intersectsBounds method. It should simplify things by pushing the dateline wrapping stuff into the intersectsBounds method. --- lib/OpenLayers/BaseTypes/Bounds.js | 78 +++++++++++++++++++------- lib/OpenLayers/Tile.js | 27 ++------- tests/manual/dateline-smallextent.html | 18 ++++-- 3 files changed, 76 insertions(+), 47 deletions(-) diff --git a/lib/OpenLayers/BaseTypes/Bounds.js b/lib/OpenLayers/BaseTypes/Bounds.js index e33c49667f..06dc5e1d2f 100644 --- a/lib/OpenLayers/BaseTypes/Bounds.js +++ b/lib/OpenLayers/BaseTypes/Bounds.js @@ -428,48 +428,79 @@ OpenLayers.Bounds = OpenLayers.Class({ * * Parameters: * bounds - {} The target bounds. + * options - {Object} Optional parameters. + * + * Acceptable options: * inclusive - {Boolean} Treat coincident borders as intersecting. Default * is true. If false, bounds that do not overlap but only touch at the * border will not be considered as intersecting. + * worldBounds - {} If a worldBounds is provided, two + * bounds will be considered as intersecting if they intersect when + * shifted to within the world bounds. This applies only to bounds that + * cross or are completely outside the world bounds. * * Returns: * {Boolean} The passed-in bounds object intersects this bounds. */ - intersectsBounds:function(bounds, inclusive) { - if (inclusive == null) { - inclusive = true; + intersectsBounds:function(bounds, options) { + options = options || {}; + if (typeof options === "boolean") { + options = {inclusive: true}; + } + if (options.worldBounds) { + var self = this.wrapDateLine(options.worldBounds) + bounds = bounds.wrapDateLine(options.worldBounds); + } else { + self = this; + } + if (options.inclusive == null) { + options.inclusive = true; } var intersects = false; var mightTouch = ( - this.left == bounds.right || - this.right == bounds.left || - this.top == bounds.bottom || - this.bottom == bounds.top + self.left == bounds.right || + self.right == bounds.left || + self.top == bounds.bottom || + self.bottom == bounds.top ); // if the two bounds only touch at an edge, and inclusive is false, // then the bounds don't *really* intersect. - if (inclusive || !mightTouch) { + if (options.inclusive || !mightTouch) { // otherwise, if one of the boundaries even partially contains another, // inclusive of the edges, then they do intersect. var inBottom = ( - ((bounds.bottom >= this.bottom) && (bounds.bottom <= this.top)) || - ((this.bottom >= bounds.bottom) && (this.bottom <= bounds.top)) + ((bounds.bottom >= self.bottom) && (bounds.bottom <= self.top)) || + ((self.bottom >= bounds.bottom) && (self.bottom <= bounds.top)) ); var inTop = ( - ((bounds.top >= this.bottom) && (bounds.top <= this.top)) || - ((this.top > bounds.bottom) && (this.top < bounds.top)) + ((bounds.top >= self.bottom) && (bounds.top <= self.top)) || + ((self.top > bounds.bottom) && (self.top < bounds.top)) ); var inLeft = ( - ((bounds.left >= this.left) && (bounds.left <= this.right)) || - ((this.left >= bounds.left) && (this.left <= bounds.right)) + ((bounds.left >= self.left) && (bounds.left <= self.right)) || + ((self.left >= bounds.left) && (self.left <= bounds.right)) ); var inRight = ( - ((bounds.right >= this.left) && (bounds.right <= this.right)) || - ((this.right >= bounds.left) && (this.right <= bounds.right)) + ((bounds.right >= self.left) && (bounds.right <= self.right)) || + ((self.right >= bounds.left) && (self.right <= bounds.right)) ); intersects = ((inBottom || inTop) && (inLeft || inRight)); } + // document me + if (options.worldBounds && !intersects) { + var world = options.worldBounds; + var width = world.getWidth(); + var selfCrosses = !world.containsBounds(self); + var boundsCrosses = !world.containsBounds(bounds); + if (selfCrosses && !boundsCrosses) { + bounds = bounds.add(-width, 0); + intersects = self.intersectsBounds(bounds, {inclusive: options.inclusive}); + } else if (boundsCrosses && !selfCrosses) { + self = self.add(-width, 0); + intersects = bounds.intersectsBounds(self, {inclusive: options.inclusive}); + } + } return intersects; }, @@ -577,8 +608,9 @@ OpenLayers.Bounds = OpenLayers.Class({ * a different bounds value if this bounds is * *entirely* outside of the maxExtent. If this * bounds straddles the dateline (is part in/part - * out of maxExtent), the returned bounds will be - * merely a copy of this one. + * out of maxExtent), the returned bounds will always + * cross the left edge of the given maxExtent. + *. */ wrapDateLine: function(maxExtent, options) { options = options || {}; @@ -589,18 +621,24 @@ OpenLayers.Bounds = OpenLayers.Class({ var newBounds = this.clone(); if (maxExtent) { + var width = maxExtent.getWidth(); //shift right? while ( newBounds.left < maxExtent.left && (newBounds.right - rightTolerance) <= maxExtent.left ) { - newBounds = newBounds.add(maxExtent.getWidth(), 0); + newBounds = newBounds.add(width, 0); } //shift left? while ( (newBounds.left + leftTolerance) >= maxExtent.right && newBounds.right > maxExtent.right ) { - newBounds = newBounds.add(-maxExtent.getWidth(), 0); + newBounds = newBounds.add(-width, 0); } + + // crosses right? force left + if (newBounds.left < maxExtent.right && newBounds.right > maxExtent.right) { + newBounds = newBounds.add(-width, 0); + } } return newBounds; diff --git a/lib/OpenLayers/Tile.js b/lib/OpenLayers/Tile.js index bc7c1baf6f..aa3b89b1ee 100644 --- a/lib/OpenLayers/Tile.js +++ b/lib/OpenLayers/Tile.js @@ -175,29 +175,10 @@ OpenLayers.Tile = OpenLayers.Class({ var withinMaxExtent = false, maxExtent = this.layer.maxExtent; if (maxExtent) { - // prepare up to 3 versions of the layer's maxExtent, to make sure - // that the intersectsBounds check below catches all cases of - // extents that cross the dateline: - // (1) left bound positive, right bound negative (wrapped) - // (2) left bound positive, right bound positive (exceeding world) - // (3) left bound negative (exceeding world), right bound positive - var maxExtents = [maxExtent]; - if (this.layer.map.baseLayer.wrapDateLine) { - if (maxExtent.left > maxExtent.right) { - var worldWidth = this.layer.map.getMaxExtent().getWidth(); - maxExtent = this.layer.maxExtent.clone(); - maxExtent.left -= worldWidth; - maxExtents.push(maxExtent); - maxExtent = this.layer.maxExtent.clone(); - maxExtent.right += worldWidth; - maxExtents.push(maxExtent); - } - } - for (var i=maxExtents.length-1; i>=0; --i) { - if (this.bounds.intersectsBounds(maxExtents[i], false)) { - withinMaxExtent = true; - break; - } + var map = this.layer.map; + var worldBounds = map.baseLayer.wrapDateLine && map.getMaxExtent(); + if (this.bounds.intersectsBounds(maxExtent, {inclusive: false, worldBounds: worldBounds})) { + withinMaxExtent = true; } } diff --git a/tests/manual/dateline-smallextent.html b/tests/manual/dateline-smallextent.html index ed80a8a9e7..3dc9025f18 100644 --- a/tests/manual/dateline-smallextent.html +++ b/tests/manual/dateline-smallextent.html @@ -22,19 +22,29 @@ var map; function init(){ map = new OpenLayers.Map('map'); - var osm = new OpenLayers.Layer.OSM( - "OSM", null, + var base = new OpenLayers.Layer.WMS("marble", + "http://demo.opengeo.org/geoserver/wms", + {layers: "topp:naturalearth"}, {wrapDateLine: true} ); - var extent = new OpenLayers.Bounds(15849982.183008, -11368938.517442, -14206280.326992, -1350184.3474419); + var extent = new OpenLayers.Bounds(142.3828125,-70.902270266175,233.6171875,-12.039326531729); var wms = new OpenLayers.Layer.WMS( "world", "http://demo.opengeo.org/geoserver/wms", {layers: 'world', transparent: true}, {maxExtent: extent} ); + + var poly = extent.toGeometry(); + var vector = new OpenLayers.Layer.Vector(); + poly.components[0].components.forEach(function(point) { + vector.addFeatures([ + new OpenLayers.Feature.Vector(point) + ]); + }) - map.addLayers([osm, wms]); + map.addLayers([base, wms, vector]); + map.addControl(new OpenLayers.Control.LayerSwitcher()); map.zoomToExtent(extent); }