From e7deed1af5bfdacf6e64c09ef4493da305670dc8 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Dec 2014 13:52:55 -0500 Subject: [PATCH 01/11] Modify Rectangle.intersectWith to work with extents across the IDL. --- Source/Core/Rectangle.js | 23 +++++++++++++++++++++-- Specs/Core/RectangleSpec.js | 24 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Source/Core/Rectangle.js b/Source/Core/Rectangle.js index 7d7384532c1c..7e9f0f321d67 100644 --- a/Source/Core/Rectangle.js +++ b/Source/Core/Rectangle.js @@ -472,9 +472,28 @@ define([ } //>>includeEnd('debug'); - var west = Math.max(rectangle.west, otherRectangle.west); + var rectangleEast = rectangle.east; + var rectangleWest = rectangle.west; + + var otherRectangleEast = otherRectangle.east; + var otherRectangleWest = otherRectangle.west; + + if (rectangleEast < rectangleWest && otherRectangleEast > 0.0) { + rectangleEast += CesiumMath.TWO_PI; + } else if (otherRectangleEast < otherRectangleWest && rectangleEast > 0.0) { + otherRectangleEast += CesiumMath.TWO_PI; + } + + if (rectangleEast < rectangleWest && otherRectangleWest < 0.0) { + otherRectangleWest += CesiumMath.TWO_PI; + } else if (otherRectangleEast < otherRectangleWest && rectangleWest < 0.0) { + rectangleWest += CesiumMath.TWO_PI; + } + + var west = CesiumMath.negativePiToPi(Math.max(rectangleWest, otherRectangleWest)); + var east = CesiumMath.negativePiToPi(Math.min(rectangleEast, otherRectangleEast)); + var south = Math.max(rectangle.south, otherRectangle.south); - var east = Math.min(rectangle.east, otherRectangle.east); var north = Math.min(rectangle.north, otherRectangle.north); if (!defined(result)) { return new Rectangle(west, south, east, north); diff --git a/Specs/Core/RectangleSpec.js b/Specs/Core/RectangleSpec.js index 7ee99de2a40b..7f0561f48340 100644 --- a/Specs/Core/RectangleSpec.js +++ b/Specs/Core/RectangleSpec.js @@ -373,6 +373,30 @@ defineSuite([ expect(result).toBe(returnedResult); }); + it('intersectWith works across the IDL (1)', function() { + var rectangle1 = Rectangle.fromDegrees(170.0, -10.0, -170.0, 10.0); + var rectangle2 = Rectangle.fromDegrees(-175.0, 5.0, -160.0, 15.0); + var expected = Rectangle.fromDegrees(-175.0, 5.0, -170.0, 10.0); + expect(Rectangle.intersectWith(rectangle1, rectangle2)).toEqual(expected); + expect(Rectangle.intersectWith(rectangle2, rectangle1)).toEqual(expected); + }); + + it('intersectWith works across the IDL (2)', function() { + var rectangle1 = Rectangle.fromDegrees(170.0, -10.0, -170.0, 10.0); + var rectangle2 = Rectangle.fromDegrees(160.0, 5.0, 175.0, 15.0); + var expected = Rectangle.fromDegrees(170.0, 5.0, 175.0, 10.0); + expect(Rectangle.intersectWith(rectangle1, rectangle2)).toEqual(expected); + expect(Rectangle.intersectWith(rectangle2, rectangle1)).toEqual(expected); + }); + + it('intersectWith works across the IDL (3)', function() { + var rectangle1 = Rectangle.fromDegrees(170.0, -10.0, -170.0, 10.0); + var rectangle2 = Rectangle.fromDegrees(175.0, 5.0, -175.0, 15.0); + var expected = Rectangle.fromDegrees(175.0, 5.0, -175.0, 10.0); + expect(Rectangle.intersectWith(rectangle1, rectangle2)).toEqual(expected); + expect(Rectangle.intersectWith(rectangle2, rectangle1)).toEqual(expected); + }); + it('contains works', function() { var rectangle = new Rectangle(west, south, east, north); expect(Rectangle.contains(rectangle, new Cartographic(west, south))).toEqual(true); From b5441764d2875f7795c9d78d6a3ee20b377a5a01 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Dec 2014 15:04:13 -0500 Subject: [PATCH 02/11] Modify Rectangle.intersectWith to return undefined if there is no intersection and Rectangle.contains to work across the IDL. --- Source/Core/Math.js | 6 +- Source/Core/Rectangle.js | 54 +++++----- Source/Core/VRTheWorldTerrainProvider.js | 4 +- Source/Scene/BingMapsImageryProvider.js | 2 +- Specs/Core/RectangleSpec.js | 127 ++++++++++++++++------- 5 files changed, 129 insertions(+), 64 deletions(-) diff --git a/Source/Core/Math.js b/Source/Core/Math.js index 6dd2230457f9..97993e2fdff2 100644 --- a/Source/Core/Math.js +++ b/Source/Core/Math.js @@ -493,7 +493,11 @@ define([ throw new DeveloperError('x is required.'); } //>>includeEnd('debug'); - return CesiumMath.mod(x, CesiumMath.TWO_PI); + var mod = CesiumMath.mod(x, CesiumMath.TWO_PI); + if (mod === 0.0 && x !== 0.0) { + return CesiumMath.sign(x) * CesiumMath.TWO_PI; + } + return mod; }; /** diff --git a/Source/Core/Rectangle.js b/Source/Core/Rectangle.js index 7e9f0f321d67..5bc600a0c62b 100644 --- a/Source/Core/Rectangle.js +++ b/Source/Core/Rectangle.js @@ -439,17 +439,19 @@ define([ var east = rectangle.east; var west = rectangle.west; - var longitude = (west + east) * 0.5; if (east < west) { - longitude = CesiumMath.negativePiToPi(longitude + CesiumMath.PI); + east += CesiumMath.TWO_PI; } + var longitude = CesiumMath.negativePiToPi((west + east) * 0.5); + var latitude = (rectangle.south + rectangle.north) * 0.5; + if (!defined(result)) { - return new Cartographic(longitude, (rectangle.south + rectangle.north) * 0.5); + return new Cartographic(longitude, latitude); } result.longitude = longitude; - result.latitude = (rectangle.south + rectangle.north) * 0.5; + result.latitude = latitude; result.height = 0.0; return result; }; @@ -460,7 +462,7 @@ define([ * @param {Rectangle} rectangle On rectangle to find an intersection * @param {Rectangle} otherRectangle Another rectangle to find an intersection * @param {Rectangle} [result] The object onto which to store the result. - * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided. + * @returns {Rectangle|undefined} The modified result parameter, a new Rectangle instance if none was provided or undefined if there is no intersection. */ Rectangle.intersectWith = function(rectangle, otherRectangle, result) { //>>includeStart('debug', pragmas.debug); @@ -493,8 +495,17 @@ define([ var west = CesiumMath.negativePiToPi(Math.max(rectangleWest, otherRectangleWest)); var east = CesiumMath.negativePiToPi(Math.min(rectangleEast, otherRectangleEast)); + if ((rectangle.west < rectangle.east || otherRectangle.west < otherRectangle.east) && east <= west) { + return undefined; + } + var south = Math.max(rectangle.south, otherRectangle.south); var north = Math.min(rectangle.north, otherRectangle.north); + + if (south >= north) { + return undefined; + } + if (!defined(result)) { return new Rectangle(west, south, east, north); } @@ -522,27 +533,22 @@ define([ } //>>includeEnd('debug'); - return cartographic.longitude >= rectangle.west && - cartographic.longitude <= rectangle.east && - cartographic.latitude >= rectangle.south && - cartographic.latitude <= rectangle.north; - }; + var longitude = cartographic.longitude; + var latitude = cartographic.latitude; - /** - * Determines if the rectangle is empty, i.e., if west >= east - * or south >= north. - * - * @param {Rectangle} rectangle The rectangle - * @returns {Boolean} True if the rectangle is empty; otherwise, false. - */ - Rectangle.isEmpty = function(rectangle) { - //>>includeStart('debug', pragmas.debug); - if (!defined(rectangle)) { - throw new DeveloperError('rectangle is required'); - } - //>>includeEnd('debug'); + var west = rectangle.west; + var east = rectangle.east; - return rectangle.west >= rectangle.east || rectangle.south >= rectangle.north; + if (east < west) { + east += CesiumMath.TWO_PI; + if (longitude < 0.0) { + longitude += CesiumMath.TWO_PI; + } + } + return longitude >= west && + longitude <= east && + latitude >= rectangle.south && + latitude <= rectangle.north; }; var subsampleLlaScratch = new Cartographic(); diff --git a/Source/Core/VRTheWorldTerrainProvider.js b/Source/Core/VRTheWorldTerrainProvider.js index e27b416bd03d..cccc11de7b60 100644 --- a/Source/Core/VRTheWorldTerrainProvider.js +++ b/Source/Core/VRTheWorldTerrainProvider.js @@ -310,7 +310,7 @@ define([ var testRectangle = rectangle.rectangle; var intersection = Rectangle.intersectWith(testRectangle, parentRectangle, rectangleScratch); - if (!Rectangle.isEmpty(intersection)) { + if (defined(intersection)) { // Parent tile is inside this rectangle, so at least one child is, too. if (isTileInRectangle(tilingScheme, testRectangle, x * 2, y * 2, level + 1)) { childMask |= 4; // northwest @@ -332,7 +332,7 @@ define([ function isTileInRectangle(tilingScheme, rectangle, x, y, level) { var tileRectangle = tilingScheme.tileXYToRectangle(x, y, level); - return !Rectangle.isEmpty(Rectangle.intersectWith(tileRectangle, rectangle, rectangleScratch)); + return defined(Rectangle.intersectWith(tileRectangle, rectangle, rectangleScratch)); } /** diff --git a/Source/Scene/BingMapsImageryProvider.js b/Source/Scene/BingMapsImageryProvider.js index 11e5a66021d9..2584a6e333dd 100644 --- a/Source/Scene/BingMapsImageryProvider.js +++ b/Source/Scene/BingMapsImageryProvider.js @@ -631,7 +631,7 @@ define([ var area = coverageAreas[areaIndex]; if (level >= area.zoomMin && level <= area.zoomMax) { var intersection = Rectangle.intersectWith(rectangle, area.bbox, intersectionScratch); - if (!Rectangle.isEmpty(intersection)) { + if (defined(intersection)) { included = true; } } diff --git a/Specs/Core/RectangleSpec.js b/Specs/Core/RectangleSpec.js index 7f0561f48340..a608db7f953a 100644 --- a/Specs/Core/RectangleSpec.js +++ b/Specs/Core/RectangleSpec.js @@ -320,7 +320,7 @@ defineSuite([ it('center works without a result parameter', function() { var rectangle = new Rectangle(west, south, east, north); var returnedResult = Rectangle.center(rectangle); - expect(returnedResult).toEqual(center); + expect(returnedResult).toEqualEpsilon(center, CesiumMath.EPSILON11); }); it('center works with a result parameter', function() { @@ -328,13 +328,13 @@ defineSuite([ var result = new Cartographic(); var returnedResult = Rectangle.center(rectangle, result); expect(result).toBe(returnedResult); - expect(returnedResult).toEqual(center); + expect(returnedResult).toEqualEpsilon(center, CesiumMath.EPSILON11); }); it('center works across IDL', function() { var rectangle = Rectangle.fromDegrees(170, 0, -170, 0); var returnedResult = Rectangle.center(rectangle); - expect(returnedResult).toEqualEpsilon(Cartographic.fromDegrees(-180, 0), CesiumMath.EPSILON11); + expect(returnedResult).toEqualEpsilon(Cartographic.fromDegrees(180, 0), CesiumMath.EPSILON11); rectangle = Rectangle.fromDegrees(160, 0, -170, 0); returnedResult = Rectangle.center(rectangle); @@ -397,53 +397,108 @@ defineSuite([ expect(Rectangle.intersectWith(rectangle2, rectangle1)).toEqual(expected); }); - it('contains works', function() { - var rectangle = new Rectangle(west, south, east, north); - expect(Rectangle.contains(rectangle, new Cartographic(west, south))).toEqual(true); - expect(Rectangle.contains(rectangle, new Cartographic(west, north))).toEqual(true); - expect(Rectangle.contains(rectangle, new Cartographic(east, south))).toEqual(true); - expect(Rectangle.contains(rectangle, new Cartographic(east, north))).toEqual(true); - expect(Rectangle.contains(rectangle, Rectangle.center(rectangle))).toEqual(true); - expect(Rectangle.contains(rectangle, new Cartographic(west - 0.1, south))).toEqual(false); - expect(Rectangle.contains(rectangle, new Cartographic(west, north + 0.1))).toEqual(false); - expect(Rectangle.contains(rectangle, new Cartographic(east, south - 0.1))).toEqual(false); - expect(Rectangle.contains(rectangle, new Cartographic(east + 0.1, north))).toEqual(false); + it('intersectWith returns undefined for a point', function() { + var rectangle1 = new Rectangle(west, south, east, north); + var rectangle2 = new Rectangle(east, north, east + 0.1, north + 0.1); + expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); }); - it('isEmpty reports a non-empty rectangle', function() { - var rectangle = new Rectangle(1.0, 1.0, 2.0, 2.0); - expect(Rectangle.isEmpty(rectangle)).toEqual(false); + it('intersectWith returns undefined for a east-west line (1)', function() { + var rectangle1 = new Rectangle(west, south, east, north); + var rectangle2 = new Rectangle(west, north, east, north + 0.1); + expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); }); - it('isEmpty reports true for a point', function() { - var rectangle = new Rectangle(2.0, 2.0, 2.0, 2.0); - expect(Rectangle.isEmpty(rectangle)).toEqual(true); + it('intersectWith returns undefined for a east-west line (2)', function() { + var rectangle1 = new Rectangle(west, south, east, north); + var rectangle2 = new Rectangle(west, south + 0.1, east, south); + expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); }); - it('isEmpty reports true for a north-south line', function() { - var rectangle = new Rectangle(2.0, 2.0, 2.0, 2.1); - expect(Rectangle.isEmpty(rectangle)).toEqual(true); + it('intersectWith returns undefined for a north-south line (1)', function() { + var rectangle1 = new Rectangle(west, south, east, north); + var rectangle2 = new Rectangle(east, south, east + 0.1, north); + expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); }); - it('isEmpty reports true for an east-west line', function() { - var rectangle = new Rectangle(2.0, 2.0, 2.1, 2.0); - expect(Rectangle.isEmpty(rectangle)).toEqual(true); + it('intersectWith returns undefined for a north-south line (2)', function() { + var rectangle1 = new Rectangle(west, south, east, north); + var rectangle2 = new Rectangle(west - 0.1, south, west, north); + expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); }); - it('isEmpty reports true if north-south direction is degenerate', function() { - var rectangle = new Rectangle(1.0, 1.1, 2.0, 1.0); - expect(Rectangle.isEmpty(rectangle)).toEqual(true); + it('intersectWith returns undefined for a north-south line (3)', function() { + var west = CesiumMath.toRadians(170.0); + var south = CesiumMath.toRadians(-10.0); + var east = CesiumMath.toRadians(-170.0); + var north = CesiumMath.toRadians(10.0); + + var rectangle1 = new Rectangle(west, south, east, north); + var rectangle2 = new Rectangle(east, south, east + 0.1, north); + expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); }); - it('isEmpty reports true if east-west direction is degenerate', function() { - var rectangle = new Rectangle(1.1, 1.0, 1.0, 2.0); - expect(Rectangle.isEmpty(rectangle)).toEqual(true); + it('intersectWith returns undefined for a north-south line (4)', function() { + var west = CesiumMath.toRadians(170.0); + var south = CesiumMath.toRadians(-10.0); + var east = CesiumMath.toRadians(-170.0); + var north = CesiumMath.toRadians(10.0); + + var rectangle1 = new Rectangle(west, south, east, north); + var rectangle2 = new Rectangle(west - 0.1, south, west, north); + expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); }); - it('isEmpty throws with no rectangle', function() { - expect(function() { - Rectangle.isEmpty(); - }).toThrowDeveloperError(); + it('intersectWith returns undefined if north-south direction is degenerate', function() { + var rectangle1 = new Rectangle(west, south, east, north); + var rectangle2 = new Rectangle(west, north + 0.1, east, north + 0.2); + expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); + }); + + it('intersectWith returns undefined if east-west direction is degenerate', function() { + var rectangle1 = new Rectangle(west, south, east, north); + var rectangle2 = new Rectangle(east + 0.1, south, east + 0.2, north); + expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); + }); + + it('contains works', function() { + var rectangle = new Rectangle(west, south, east, north); + expect(Rectangle.contains(rectangle, new Cartographic(west, south))).toEqual(true); + expect(Rectangle.contains(rectangle, new Cartographic(west, north))).toEqual(true); + expect(Rectangle.contains(rectangle, new Cartographic(east, south))).toEqual(true); + expect(Rectangle.contains(rectangle, new Cartographic(east, north))).toEqual(true); + expect(Rectangle.contains(rectangle, Rectangle.center(rectangle))).toEqual(true); + expect(Rectangle.contains(rectangle, new Cartographic(west - 0.1, south))).toEqual(false); + expect(Rectangle.contains(rectangle, new Cartographic(west, north + 0.1))).toEqual(false); + expect(Rectangle.contains(rectangle, new Cartographic(east, south - 0.1))).toEqual(false); + expect(Rectangle.contains(rectangle, new Cartographic(east + 0.1, north))).toEqual(false); + }); + + it('contains works with rectangle across the IDL', function() { + var west = CesiumMath.toRadians(170.0); + var south = CesiumMath.toRadians(-10.0); + var east = CesiumMath.toRadians(-170.0); + var north = CesiumMath.toRadians(10.0); + + var rectangle = new Rectangle(west, south, east, north); + expect(Rectangle.contains(rectangle, new Cartographic(west, south))).toEqual(true); + expect(Rectangle.contains(rectangle, new Cartographic(west, north))).toEqual(true); + expect(Rectangle.contains(rectangle, new Cartographic(east, south))).toEqual(true); + expect(Rectangle.contains(rectangle, new Cartographic(east, north))).toEqual(true); + expect(Rectangle.contains(rectangle, Rectangle.center(rectangle))).toEqual(true); + expect(Rectangle.contains(rectangle, new Cartographic(west - 0.1, south))).toEqual(false); + expect(Rectangle.contains(rectangle, new Cartographic(west, north + 0.1))).toEqual(false); + expect(Rectangle.contains(rectangle, new Cartographic(east, south - 0.1))).toEqual(false); + expect(Rectangle.contains(rectangle, new Cartographic(east + 0.1, north))).toEqual(false); }); it('subsample works south of the equator', function() { From 929883077d760e3534028f35ae4b03a6f0ffd494 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Dec 2014 15:35:19 -0500 Subject: [PATCH 03/11] Modify Rectangle.subsample to work across the IDL. --- Source/Core/Rectangle.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/Core/Rectangle.js b/Source/Core/Rectangle.js index 5bc600a0c62b..74b6b7e3c33b 100644 --- a/Source/Core/Rectangle.js +++ b/Source/Core/Rectangle.js @@ -612,9 +612,8 @@ define([ } for ( var i = 1; i < 8; ++i) { - var temp = -Math.PI + i * CesiumMath.PI_OVER_TWO; - if (west < temp && temp < east) { - lla.longitude = temp; + lla.longitude = -Math.PI + i * CesiumMath.PI_OVER_TWO; + if (Rectangle.contains(rectangle, lla)) { result[length] = ellipsoid.cartographicToCartesian(lla, result[length]); length++; } From 9c221026547e5cadcac06b6c5f2a89cf691a00f1 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Dec 2014 16:57:56 -0500 Subject: [PATCH 04/11] Add Rectangle width and height properties to compute the width correctly for rectangles crossing the IDL. Replace all instances of east - west because it assumes east > west. --- Source/Core/GeographicTilingScheme.js | 20 ++++---- Source/Core/HeightmapTessellator.js | 10 ++-- Source/Core/QuantizedMeshTerrainData.js | 4 +- Source/Core/Rectangle.js | 49 +++++++++++++++++++ Source/Core/RectangleGeometry.js | 5 +- Source/Core/RectangleOutlineGeometry.js | 1 - Source/Core/WebMercatorTilingScheme.js | 5 +- Source/Scene/GlobeSurfaceTile.js | 8 +-- Source/Scene/ImageryLayer.js | 26 +++++----- Source/Scene/WebMapServiceImageryProvider.js | 4 +- .../createVerticesFromQuantizedTerrainMesh.js | 13 ++++- .../Workers/upsampleQuantizedTerrainMesh.js | 13 ++++- .../Scene/WebMapServiceImageryProviderSpec.js | 4 +- 13 files changed, 115 insertions(+), 47 deletions(-) diff --git a/Source/Core/GeographicTilingScheme.js b/Source/Core/GeographicTilingScheme.js index cb41f1f97504..6e0537d2260d 100644 --- a/Source/Core/GeographicTilingScheme.js +++ b/Source/Core/GeographicTilingScheme.js @@ -175,11 +175,11 @@ define([ var xTiles = this.getNumberOfXTilesAtLevel(level); var yTiles = this.getNumberOfYTilesAtLevel(level); - var xTileWidth = (rectangle.east - rectangle.west) / xTiles; + var xTileWidth = rectangle.width / xTiles; var west = x * xTileWidth + rectangle.west; var east = (x + 1) * xTileWidth + rectangle.west; - var yTileHeight = (rectangle.north - rectangle.south) / yTiles; + var yTileHeight = rectangle.height / yTiles; var north = rectangle.north - y * yTileHeight; var south = rectangle.north - (y + 1) * yTileHeight; @@ -207,10 +207,7 @@ define([ */ GeographicTilingScheme.prototype.positionToTileXY = function(position, level, result) { var rectangle = this._rectangle; - if (position.latitude > rectangle.north || - position.latitude < rectangle.south || - position.longitude < rectangle.west || - position.longitude > rectangle.east) { + if (!Rectangle.contains(rectangle, position)) { // outside the bounds of the tiling scheme return undefined; } @@ -218,10 +215,15 @@ define([ var xTiles = this.getNumberOfXTilesAtLevel(level); var yTiles = this.getNumberOfYTilesAtLevel(level); - var xTileWidth = (rectangle.east - rectangle.west) / xTiles; - var yTileHeight = (rectangle.north - rectangle.south) / yTiles; + var xTileWidth = rectangle.width / xTiles; + var yTileHeight = rectangle.height / yTiles; - var xTileCoordinate = (position.longitude - rectangle.west) / xTileWidth | 0; + var longitude = position.longitude; + if (rectangle.east < rectangle.west) { + longitude += CesiumMath.TWO_PI; + } + + var xTileCoordinate = (longitude - rectangle.west) / xTileWidth | 0; if (xTileCoordinate >= xTiles) { xTileCoordinate = xTiles - 1; } diff --git a/Source/Core/HeightmapTessellator.js b/Source/Core/HeightmapTessellator.js index a29283892132..db1c326719e7 100644 --- a/Source/Core/HeightmapTessellator.js +++ b/Source/Core/HeightmapTessellator.js @@ -6,7 +6,8 @@ define([ './DeveloperError', './Ellipsoid', './freezeObject', - './Math' + './Math', + './Rectangle' ], function( Cartesian3, defaultValue, @@ -14,7 +15,8 @@ define([ DeveloperError, Ellipsoid, freezeObject, - CesiumMath) { + CesiumMath, + Rectangle) { "use strict"; /** @@ -186,8 +188,8 @@ define([ var elementMultiplier = defaultValue(structure.elementMultiplier, HeightmapTessellator.DEFAULT_STRUCTURE.elementMultiplier); var isBigEndian = defaultValue(structure.isBigEndian, HeightmapTessellator.DEFAULT_STRUCTURE.isBigEndian); - var granularityX = (nativeRectangle.east - nativeRectangle.west) / (width - 1); - var granularityY = (nativeRectangle.north - nativeRectangle.south) / (height - 1); + var granularityX = Rectangle.computeWidth(nativeRectangle) / (width - 1); + var granularityY = Rectangle.computeHeight(nativeRectangle) / (height - 1); var radiiSquared = ellipsoid.radiiSquared; var radiiSquaredX = radiiSquared.x; diff --git a/Source/Core/QuantizedMeshTerrainData.js b/Source/Core/QuantizedMeshTerrainData.js index 7cd473d99d77..a3ee8c967aaa 100644 --- a/Source/Core/QuantizedMeshTerrainData.js +++ b/Source/Core/QuantizedMeshTerrainData.js @@ -414,9 +414,9 @@ define([ * the rectangle, so expect incorrect results for positions far outside the rectangle. */ QuantizedMeshTerrainData.prototype.interpolateHeight = function(rectangle, longitude, latitude) { - var u = CesiumMath.clamp((longitude - rectangle.west) / (rectangle.east - rectangle.west), 0.0, 1.0); + var u = CesiumMath.clamp((longitude - rectangle.west) / rectangle.width, 0.0, 1.0); u *= maxShort; - var v = CesiumMath.clamp((latitude - rectangle.south) / (rectangle.north - rectangle.south), 0.0, 1.0); + var v = CesiumMath.clamp((latitude - rectangle.south) / rectangle.height, 0.0, 1.0); v *= maxShort; var uBuffer = this._uValues; diff --git a/Source/Core/Rectangle.js b/Source/Core/Rectangle.js index 74b6b7e3c33b..61acdb85bab1 100644 --- a/Source/Core/Rectangle.js +++ b/Source/Core/Rectangle.js @@ -3,6 +3,7 @@ define([ './Cartographic', './defaultValue', './defined', + './defineProperties', './DeveloperError', './Ellipsoid', './freezeObject', @@ -11,6 +12,7 @@ define([ Cartographic, defaultValue, defined, + defineProperties, DeveloperError, Ellipsoid, freezeObject, @@ -64,6 +66,53 @@ define([ this.north = defaultValue(north, 0.0); }; + defineProperties(Rectangle.prototype, { + /** + * Gets the width of the rectangle in radians. + * @memberof Rectangle.prototype + * @type {Number} + */ + width : { + get : function() { + return Rectangle.computeWidth(this); + } + }, + + /** + * Gets the height of the rectangle in radians. + * @memberof Rectangle.prototype + * @type {Number} + */ + height : { + get : function() { + return Rectangle.computeHeight(this); + } + } + }); + + Rectangle.computeWidth = function(rectangle) { + //>>includeStart('debug', pragmas.debug); + if (!defined(rectangle)) { + throw new DeveloperError('rectangle is required.'); + } + //>>includeEnd('debug'); + var east = rectangle.east; + var west = rectangle.west; + if (east < west) { + east += CesiumMath.TWO_PI; + } + return east - west; + }; + + Rectangle.computeHeight = function(rectangle) { + //>>includeStart('debug', pragmas.debug); + if (!defined(rectangle)) { + throw new DeveloperError('rectangle is required.'); + } + //>>includeEnd('debug'); + return rectangle.north - rectangle.south; + }; + /** * Creates an rectangle given the boundary longitude and latitude in degrees. * diff --git a/Source/Core/RectangleGeometry.js b/Source/Core/RectangleGeometry.js index e593de391f46..3170206c47bb 100644 --- a/Source/Core/RectangleGeometry.js +++ b/Source/Core/RectangleGeometry.js @@ -519,7 +519,6 @@ define([ * @exception {DeveloperError} options.rectangle.east must be in the interval [-Pi, Pi]. * @exception {DeveloperError} options.rectangle.west must be in the interval [-Pi, Pi]. * @exception {DeveloperError} options.rectangle.north must be greater than options.rectangle.south. - * @exception {DeveloperError} options.rectangle.east must be greater than options.rectangle.west. * * @see RectangleGeometry#createGeometry * @@ -616,8 +615,8 @@ define([ Matrix3.clone(Matrix3.IDENTITY, tangentRotationMatrix); } - options.lonScalar = 1.0 / (rectangle.east - rectangle.west); - options.latScalar = 1.0 / (rectangle.north - rectangle.south); + options.lonScalar = 1.0 / rectangle.width; + options.latScalar = 1.0 / rectangle.height; options.vertexFormat = vertexFormat; options.textureMatrix = textureMatrix; options.tangentRotationMatrix = tangentRotationMatrix; diff --git a/Source/Core/RectangleOutlineGeometry.js b/Source/Core/RectangleOutlineGeometry.js index b7236922b2e4..bf2b4eb8e279 100644 --- a/Source/Core/RectangleOutlineGeometry.js +++ b/Source/Core/RectangleOutlineGeometry.js @@ -180,7 +180,6 @@ define([ * @exception {DeveloperError} options.rectangle.east must be in the interval [-Pi, Pi]. * @exception {DeveloperError} options.rectangle.west must be in the interval [-Pi, Pi]. * @exception {DeveloperError} options.rectangle.north must be greater than rectangle.south. - * @exception {DeveloperError} options.rectangle.east must be greater than rectangle.west. * * @see RectangleOutlineGeometry#createGeometry * diff --git a/Source/Core/WebMercatorTilingScheme.js b/Source/Core/WebMercatorTilingScheme.js index e77377f4b540..51402c103bc1 100644 --- a/Source/Core/WebMercatorTilingScheme.js +++ b/Source/Core/WebMercatorTilingScheme.js @@ -219,10 +219,7 @@ define([ */ WebMercatorTilingScheme.prototype.positionToTileXY = function(position, level, result) { var rectangle = this._rectangle; - if (position.latitude > rectangle.north || - position.latitude < rectangle.south || - position.longitude < rectangle.west || - position.longitude > rectangle.east) { + if (!Rectangle.contains(rectangle, position)) { // outside the bounds of the tiling scheme return undefined; } diff --git a/Source/Scene/GlobeSurfaceTile.js b/Source/Scene/GlobeSurfaceTile.js index 7220a940e668..8c423ee9ad2f 100644 --- a/Source/Scene/GlobeSurfaceTile.js +++ b/Source/Scene/GlobeSurfaceTile.js @@ -733,11 +733,11 @@ define([ // Compute the water mask translation and scale var sourceTileRectangle = sourceTile.rectangle; var tileRectangle = tile.rectangle; - var tileWidth = tileRectangle.east - tileRectangle.west; - var tileHeight = tileRectangle.north - tileRectangle.south; + var tileWidth = tileRectangle.width; + var tileHeight = tileRectangle.height; - var scaleX = tileWidth / (sourceTileRectangle.east - sourceTileRectangle.west); - var scaleY = tileHeight / (sourceTileRectangle.north - sourceTileRectangle.south); + var scaleX = tileWidth / sourceTileRectangle.width; + var scaleY = tileHeight / sourceTileRectangle.height; surfaceTile.waterMaskTranslationAndScale.x = scaleX * (tileRectangle.west - sourceTileRectangle.west) / tileWidth; surfaceTile.waterMaskTranslationAndScale.y = scaleY * (tileRectangle.south - sourceTileRectangle.south) / tileHeight; surfaceTile.waterMaskTranslationAndScale.z = scaleX; diff --git a/Source/Scene/ImageryLayer.js b/Source/Scene/ImageryLayer.js index 222ec6ec504f..a492dea8fbcf 100644 --- a/Source/Scene/ImageryLayer.js +++ b/Source/Scene/ImageryLayer.js @@ -379,7 +379,7 @@ define([ var imageryBounds = Rectangle.intersectWith(imageryProvider.rectangle, this._rectangle, imageryBoundsScratch); var rectangle = Rectangle.intersectWith(tile.rectangle, imageryBounds, tileImageryBoundsScratch); - if (rectangle.east <= rectangle.west || rectangle.north <= rectangle.south) { + if (!defined(rectangle)) { // There is no overlap between this terrain tile and this imagery // provider. Unless this is the base layer, no skeletons need to be created. // We stretch texels at the edge of the base layer over the entire globe. @@ -441,8 +441,8 @@ define([ // of the northwest tile, we don't actually need the northernmost or westernmost tiles. // We define "very close" as being within 1/512 of the width of the tile. - var veryCloseX = (tile.rectangle.north - tile.rectangle.south) / 512.0; - var veryCloseY = (tile.rectangle.east - tile.rectangle.west) / 512.0; + var veryCloseX = tile.rectangle.height / 512.0; + var veryCloseY = tile.rectangle.width / 512.0; var northwestTileRectangle = imageryTilingScheme.tileXYToRectangle(northwestTileCoordinates.x, northwestTileCoordinates.y, imageryLevel); if (Math.abs(northwestTileRectangle.south - tile.rectangle.north) < veryCloseY && northwestTileCoordinates.y < southeastTileCoordinates.y) { @@ -477,11 +477,11 @@ define([ // it may not start at the northern or western edge of the terrain tile. // Calculate where it does start. if (!this.isBaseLayer() && Math.abs(clippedImageryRectangle.west - tile.rectangle.west) >= veryCloseX) { - maxU = Math.min(1.0, (clippedImageryRectangle.west - terrainRectangle.west) / (terrainRectangle.east - terrainRectangle.west)); + maxU = Math.min(1.0, (clippedImageryRectangle.west - terrainRectangle.west) / terrainRectangle.width); } if (!this.isBaseLayer() && Math.abs(clippedImageryRectangle.north - tile.rectangle.north) >= veryCloseY) { - minV = Math.max(0.0, (clippedImageryRectangle.north - terrainRectangle.south) / (terrainRectangle.north - terrainRectangle.south)); + minV = Math.max(0.0, (clippedImageryRectangle.north - terrainRectangle.south) / terrainRectangle.height); } var initialMinV = minV; @@ -492,7 +492,7 @@ define([ imageryRectangle = imageryTilingScheme.tileXYToRectangle(i, northwestTileCoordinates.y, imageryLevel); clippedImageryRectangle = Rectangle.intersectWith(imageryRectangle, imageryBounds, clippedRectangleScratch); - maxU = Math.min(1.0, (clippedImageryRectangle.east - terrainRectangle.west) / (terrainRectangle.east - terrainRectangle.west)); + maxU = Math.min(1.0, (clippedImageryRectangle.east - terrainRectangle.west) / terrainRectangle.width); // If this is the eastern-most imagery tile mapped to this terrain tile, // and there are more imagery tiles to the east of this one, the maxU @@ -509,7 +509,7 @@ define([ imageryRectangle = imageryTilingScheme.tileXYToRectangle(i, j, imageryLevel); clippedImageryRectangle = Rectangle.intersectWith(imageryRectangle, imageryBounds, clippedRectangleScratch); - minV = Math.max(0.0, (clippedImageryRectangle.south - terrainRectangle.south) / (terrainRectangle.north - terrainRectangle.south)); + minV = Math.max(0.0, (clippedImageryRectangle.south - terrainRectangle.south) / terrainRectangle.height); // If this is the southern-most imagery tile mapped to this terrain tile, // and there are more imagery tiles to the south of this one, the minV @@ -543,11 +543,11 @@ define([ ImageryLayer.prototype._calculateTextureTranslationAndScale = function(tile, tileImagery) { var imageryRectangle = tileImagery.readyImagery.rectangle; var terrainRectangle = tile.rectangle; - var terrainWidth = terrainRectangle.east - terrainRectangle.west; - var terrainHeight = terrainRectangle.north - terrainRectangle.south; + var terrainWidth = terrainRectangle.width; + var terrainHeight = terrainRectangle.height; - var scaleX = terrainWidth / (imageryRectangle.east - imageryRectangle.west); - var scaleY = terrainHeight / (imageryRectangle.north - imageryRectangle.south); + var scaleX = terrainWidth / imageryRectangle.width; + var scaleY = terrainHeight / imageryRectangle.height; return new Cartesian4( scaleX * (terrainRectangle.west - imageryRectangle.west) / terrainWidth, scaleY * (terrainRectangle.south - imageryRectangle.south) / terrainHeight, @@ -674,7 +674,7 @@ define([ // avoids precision problems in the reprojection transformation while making // no noticeable difference in the georeferencing of the image. if (!(this._imageryProvider.tilingScheme instanceof GeographicTilingScheme) && - (rectangle.east - rectangle.west) / texture.width > 1e-5) { + rectangle.width / texture.width > 1e-5) { var reprojectedTexture = reprojectToGeographic(this, context, texture, imagery.rectangle); texture.destroy(); imagery.texture = texture = reprojectedTexture; @@ -949,7 +949,7 @@ define([ var ellipsoid = tilingScheme.ellipsoid; var latitudeFactor = !(layer._imageryProvider.tilingScheme instanceof GeographicTilingScheme) ? Math.cos(latitudeClosestToEquator) : 1.0; var tilingSchemeRectangle = tilingScheme.rectangle; - var levelZeroMaximumTexelSpacing = ellipsoid.maximumRadius * (tilingSchemeRectangle.east - tilingSchemeRectangle.west) * latitudeFactor / (imageryProvider.tileWidth * tilingScheme.getNumberOfXTilesAtLevel(0)); + var levelZeroMaximumTexelSpacing = ellipsoid.maximumRadius * tilingSchemeRectangle.width * latitudeFactor / (imageryProvider.tileWidth * tilingScheme.getNumberOfXTilesAtLevel(0)); var twoToTheLevelPower = levelZeroMaximumTexelSpacing / texelSpacing; var level = Math.log(twoToTheLevelPower) / Math.log(2); diff --git a/Source/Scene/WebMapServiceImageryProvider.js b/Source/Scene/WebMapServiceImageryProvider.js index 10234cab5e53..972f5a3aa2fc 100644 --- a/Source/Scene/WebMapServiceImageryProvider.js +++ b/Source/Scene/WebMapServiceImageryProvider.js @@ -475,8 +475,8 @@ define([ projected = this._tilingScheme.projection.project(cartographic, cartesian3Scratch); } - var i = (this._tileWidth * (projected.x - rectangle.west) / (rectangle.east - rectangle.west)) | 0; - var j = (this._tileHeight * (rectangle.north - projected.y) / (rectangle.north - rectangle.south)) | 0; + var i = (this._tileWidth * (projected.x - rectangle.west) / rectangle.width) | 0; + var j = (this._tileHeight * (rectangle.north - projected.y) / rectangle.height) | 0; var url; diff --git a/Source/Workers/createVerticesFromQuantizedTerrainMesh.js b/Source/Workers/createVerticesFromQuantizedTerrainMesh.js index 3df7d1a245bb..2a5f354e1daf 100644 --- a/Source/Workers/createVerticesFromQuantizedTerrainMesh.js +++ b/Source/Workers/createVerticesFromQuantizedTerrainMesh.js @@ -134,6 +134,15 @@ define([ var vertexIndex = vertexBufferIndex / vertexStride; + var north = rectangle.north; + var south = rectangle.south; + var east = rectangle.east; + var west = rectangle.west; + + if (east < west) { + east += CesiumMath.TWO_PI; + } + for (var i = start; i !== end; i += increment) { var index = edgeVertices[i]; var offset = index * vertexStride; @@ -141,8 +150,8 @@ define([ var v = vertexBuffer[offset + vIndex]; var h = vertexBuffer[offset + hIndex]; - cartographicScratch.longitude = CesiumMath.lerp(rectangle.west, rectangle.east, u); - cartographicScratch.latitude = CesiumMath.lerp(rectangle.south, rectangle.north, v); + cartographicScratch.longitude = CesiumMath.lerp(west, east, u); + cartographicScratch.latitude = CesiumMath.lerp(south, north, v); cartographicScratch.height = h - skirtLength; var position = ellipsoid.cartographicToCartesian(cartographicScratch, cartesian3Scratch); diff --git a/Source/Workers/upsampleQuantizedTerrainMesh.js b/Source/Workers/upsampleQuantizedTerrainMesh.js index dbae013f9ea9..a7fccc685cf9 100644 --- a/Source/Workers/upsampleQuantizedTerrainMesh.js +++ b/Source/Workers/upsampleQuantizedTerrainMesh.js @@ -180,6 +180,15 @@ define([ var ellipsoid = Ellipsoid.clone(parameters.ellipsoid); var rectangle = parameters.childRectangle; + var north = rectangle.north; + var south = rectangle.south; + var east = rectangle.east; + var west = rectangle.west; + + if (east < west) { + east += CesiumMath.TWO_PI; + } + for (i = 0; i < uBuffer.length; ++i) { u = uBuffer[i]; if (u <= minU) { @@ -217,8 +226,8 @@ define([ heightBuffer[i] = height; - cartographicScratch.longitude = CesiumMath.lerp(rectangle.west, rectangle.east, u); - cartographicScratch.latitude = CesiumMath.lerp(rectangle.south, rectangle.north, v); + cartographicScratch.longitude = CesiumMath.lerp(west, east, u); + cartographicScratch.latitude = CesiumMath.lerp(south, north, v); cartographicScratch.height = height; ellipsoid.cartographicToCartesian(cartographicScratch, cartesian3Scratch); diff --git a/Specs/Scene/WebMapServiceImageryProviderSpec.js b/Specs/Scene/WebMapServiceImageryProviderSpec.js index 9f385b91c44c..fbdc62e31515 100644 --- a/Specs/Scene/WebMapServiceImageryProviderSpec.js +++ b/Specs/Scene/WebMapServiceImageryProviderSpec.js @@ -7,6 +7,7 @@ defineSuite([ 'Core/GeographicTilingScheme', 'Core/loadImage', 'Core/loadWithXhr', + 'Core/Math', 'Core/queryToObject', 'Core/Rectangle', 'Core/WebMercatorTilingScheme', @@ -26,6 +27,7 @@ defineSuite([ GeographicTilingScheme, loadImage, loadWithXhr, + CesiumMath, queryToObject, Rectangle, WebMercatorTilingScheme, @@ -344,7 +346,7 @@ defineSuite([ expect(provider.tileHeight).toEqual(256); expect(provider.maximumLevel).toBeUndefined(); expect(provider.tilingScheme).toBeInstanceOf(GeographicTilingScheme); - expect(provider.rectangle).toEqual(rectangle); + expect(provider.rectangle).toEqualEpsilon(rectangle, CesiumMath.EPSILON14); expect(provider.tileDiscardPolicy).toBeUndefined(); }); }); From 37853155b1b4533b84a526d0f98774852c8253a3 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Dec 2014 17:24:41 -0500 Subject: [PATCH 05/11] Fix Rectangle contains function. Math.negativePiToPi can introduce some error. --- Source/Core/Rectangle.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Rectangle.js b/Source/Core/Rectangle.js index 61acdb85bab1..50251de3c125 100644 --- a/Source/Core/Rectangle.js +++ b/Source/Core/Rectangle.js @@ -594,8 +594,8 @@ define([ longitude += CesiumMath.TWO_PI; } } - return longitude >= west && - longitude <= east && + return (longitude > west || CesiumMath.equalsEpsilon(longitude, west, CesiumMath.EPSILON14)) && + (longitude < east || CesiumMath.equalsEpsilon(longitude, east, CesiumMath.EPSILON14)) && latitude >= rectangle.south && latitude <= rectangle.north; }; From 3f8b0a6fdfb3833603b2599e3ba85d6ac34caee9 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Dec 2014 17:41:40 -0500 Subject: [PATCH 06/11] Add doc and tests to compute width and height functions. --- Source/Core/Rectangle.js | 10 ++++++++++ Specs/Core/RectangleSpec.js | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/Source/Core/Rectangle.js b/Source/Core/Rectangle.js index 50251de3c125..93c486562dfc 100644 --- a/Source/Core/Rectangle.js +++ b/Source/Core/Rectangle.js @@ -90,6 +90,11 @@ define([ } }); + /** + * Computes the width of a rectangle in radians. + * @param {Rectangle} rectangle The rectangle to compute the width of. + * @returns {Number} The width. + */ Rectangle.computeWidth = function(rectangle) { //>>includeStart('debug', pragmas.debug); if (!defined(rectangle)) { @@ -104,6 +109,11 @@ define([ return east - west; }; + /** + * Computes the height of a rectangle in radians. + * @param {Rectangle} rectangle The rectangle to compute the height of. + * @returns {Number} The height. + */ Rectangle.computeHeight = function(rectangle) { //>>includeStart('debug', pragmas.debug); if (!defined(rectangle)) { diff --git a/Specs/Core/RectangleSpec.js b/Specs/Core/RectangleSpec.js index a608db7f953a..5e7eb3ab3099 100644 --- a/Specs/Core/RectangleSpec.js +++ b/Specs/Core/RectangleSpec.js @@ -36,6 +36,24 @@ defineSuite([ expect(rectangle.north).toEqual(north); }); + it('computeWidth', function() { + var rectangle = new Rectangle(west, south, east, north); + var expected = east - west; + expect(Rectangle.computeWidth(rectangle)).toEqual(expected); + expect(rectangle.width).toEqual(expected); + + rectangle = new Rectangle(2.0, -1.0, -2.0, 1.0); + expected = rectangle.east - rectangle.west + CesiumMath.TWO_PI; + expect(rectangle.width).toEqual(expected); + }); + + it('computeHeight', function() { + var rectangle = new Rectangle(west, south, east, north); + var expected = north - south; + expect(Rectangle.computeHeight(rectangle)).toEqual(expected); + expect(rectangle.height).toEqual(expected); + }); + it('fromDegrees produces expected values.', function() { var west = -10.0; var south = -20.0; From eb475e42db0d28b39c2c3d80a4106579db5e3dc5 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 8 Dec 2014 19:04:17 -0500 Subject: [PATCH 07/11] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index ffd8e9fd0d9b..d1b4b975bff0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ Change Log * Improved polygon loading performance. * Added `Math.mod` which computes `m % n` but also works when `m` is negative. +* Fixed imagery providers whose rectangle crosses the IDL. [#2195](https://github.com/AnalyticalGraphicsInc/cesium/issues/2195) ### 1.4 - 2014-12-01 From 7fa88d767a8531fdc00bad6a5cee24d5cb2d6256 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 9 Dec 2014 10:39:28 -0500 Subject: [PATCH 08/11] Tweak CHANGES.md --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index d1b4b975bff0..34114bb506b4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,7 +5,7 @@ Change Log * Improved polygon loading performance. * Added `Math.mod` which computes `m % n` but also works when `m` is negative. -* Fixed imagery providers whose rectangle crosses the IDL. [#2195](https://github.com/AnalyticalGraphicsInc/cesium/issues/2195) +* Fixed imagery providers whose rectangle crosses the IDL. Added `Rectangle.computeWidth`, `Rectangle.computeHeight`, `Rectangle.width`, and `Rectangle.height`. [#2195](https://github.com/AnalyticalGraphicsInc/cesium/issues/2195) ### 1.4 - 2014-12-01 From 63a027b4be8cddf6bfd425dc0c6c7335b4963b01 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 9 Dec 2014 12:05:10 -0500 Subject: [PATCH 09/11] Fix ImageryLayer test. --- Source/Scene/ImageryLayer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Scene/ImageryLayer.js b/Source/Scene/ImageryLayer.js index a492dea8fbcf..d0a06a972b36 100644 --- a/Source/Scene/ImageryLayer.js +++ b/Source/Scene/ImageryLayer.js @@ -389,6 +389,7 @@ define([ var baseImageryRectangle = imageryBounds; var baseTerrainRectangle = tile.rectangle; + rectangle = tileImageryBoundsScratch; if (baseTerrainRectangle.south >= baseImageryRectangle.north) { rectangle.north = rectangle.south = baseImageryRectangle.north; From ed78a10bc696b7556987bd44d5529b9b24128c11 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 9 Dec 2014 12:50:43 -0500 Subject: [PATCH 10/11] Deprecate Rectangle.intersectWith and Rectangle.isEmpty. --- CHANGES.md | 3 + Source/Core/Rectangle.js | 61 ++++++++++++- Source/Core/VRTheWorldTerrainProvider.js | 4 +- Source/Scene/BingMapsImageryProvider.js | 2 +- Source/Scene/ImageryLayer.js | 10 +-- Source/Scene/WebMapServiceImageryProvider.js | 2 +- Specs/Core/RectangleSpec.js | 90 +++++++++++--------- 7 files changed, 120 insertions(+), 52 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 34114bb506b4..50364353cc5b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,9 @@ Change Log ### 1.5 - 2015-01-05 +* Deprecated + * `Rectangle.intersectWith` was deprecated in Cesium 1.5. It will be removed in Cesium 1.6. Use `Rectangle.intersection`. + * `Rectangle.isEmpty` was deprecated in Cesium 1.5. It will be removed in Cesium 1.6. * Improved polygon loading performance. * Added `Math.mod` which computes `m % n` but also works when `m` is negative. * Fixed imagery providers whose rectangle crosses the IDL. Added `Rectangle.computeWidth`, `Rectangle.computeHeight`, `Rectangle.width`, and `Rectangle.height`. [#2195](https://github.com/AnalyticalGraphicsInc/cesium/issues/2195) diff --git a/Source/Core/Rectangle.js b/Source/Core/Rectangle.js index 93c486562dfc..215c9f1efa66 100644 --- a/Source/Core/Rectangle.js +++ b/Source/Core/Rectangle.js @@ -4,6 +4,7 @@ define([ './defaultValue', './defined', './defineProperties', + './deprecationWarning', './DeveloperError', './Ellipsoid', './freezeObject', @@ -13,6 +14,7 @@ define([ defaultValue, defined, defineProperties, + deprecationWarning, DeveloperError, Ellipsoid, freezeObject, @@ -523,7 +525,7 @@ define([ * @param {Rectangle} [result] The object onto which to store the result. * @returns {Rectangle|undefined} The modified result parameter, a new Rectangle instance if none was provided or undefined if there is no intersection. */ - Rectangle.intersectWith = function(rectangle, otherRectangle, result) { + Rectangle.intersection = function(rectangle, otherRectangle, result) { //>>includeStart('debug', pragmas.debug); if (!defined(rectangle)) { throw new DeveloperError('rectangle is required'); @@ -575,6 +577,63 @@ define([ return result; }; + /** + * Computes the intersection of two rectangles + * + * @deprecated + * + * @param {Rectangle} rectangle On rectangle to find an intersection + * @param {Rectangle} otherRectangle Another rectangle to find an intersection + * @param {Rectangle} [result] The object onto which to store the result. + * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided. + */ + Rectangle.intersectWith = function(rectangle, otherRectangle, result) { + deprecationWarning('Rectangle.intersectWith', 'Rectangle.intersectWith was deprecated in Cesium 1.5. It will be removed in Cesium 1.6. Use Rectangle.intersection.'); + + //>>includeStart('debug', pragmas.debug); + if (!defined(rectangle)) { + throw new DeveloperError('rectangle is required'); + } + if (!defined(otherRectangle)) { + throw new DeveloperError('otherRectangle is required.'); + } + //>>includeEnd('debug'); + + var west = Math.max(rectangle.west, otherRectangle.west); + var south = Math.max(rectangle.south, otherRectangle.south); + var east = Math.min(rectangle.east, otherRectangle.east); + var north = Math.min(rectangle.north, otherRectangle.north); + if (!defined(result)) { + return new Rectangle(west, south, east, north); + } + result.west = west; + result.south = south; + result.east = east; + result.north = north; + return result; + }; + + /** + * Determines if the rectangle is empty, i.e., if west >= east + * or south >= north. + * + * @deprecated + * + * @param {Rectangle} rectangle The rectangle + * @returns {Boolean} True if the rectangle is empty; otherwise, false. + */ + Rectangle.isEmpty = function(rectangle) { + deprecationWarning('Rectangle.isEmpty', 'Rectangle.isEmpty was deprecated in Cesium 1.5. It will be removed in Cesium 1.6.'); + + //>>includeStart('debug', pragmas.debug); + if (!defined(rectangle)) { + throw new DeveloperError('rectangle is required'); + } + //>>includeEnd('debug'); + + return rectangle.west >= rectangle.east || rectangle.south >= rectangle.north; + }; + /** * Returns true if the cartographic is on or inside the rectangle, false otherwise. * diff --git a/Source/Core/VRTheWorldTerrainProvider.js b/Source/Core/VRTheWorldTerrainProvider.js index cccc11de7b60..ee6a9338d9cf 100644 --- a/Source/Core/VRTheWorldTerrainProvider.js +++ b/Source/Core/VRTheWorldTerrainProvider.js @@ -309,7 +309,7 @@ define([ var testRectangle = rectangle.rectangle; - var intersection = Rectangle.intersectWith(testRectangle, parentRectangle, rectangleScratch); + var intersection = Rectangle.intersection(testRectangle, parentRectangle, rectangleScratch); if (defined(intersection)) { // Parent tile is inside this rectangle, so at least one child is, too. if (isTileInRectangle(tilingScheme, testRectangle, x * 2, y * 2, level + 1)) { @@ -332,7 +332,7 @@ define([ function isTileInRectangle(tilingScheme, rectangle, x, y, level) { var tileRectangle = tilingScheme.tileXYToRectangle(x, y, level); - return defined(Rectangle.intersectWith(tileRectangle, rectangle, rectangleScratch)); + return defined(Rectangle.intersection(tileRectangle, rectangle, rectangleScratch)); } /** diff --git a/Source/Scene/BingMapsImageryProvider.js b/Source/Scene/BingMapsImageryProvider.js index 2584a6e333dd..a300a400f644 100644 --- a/Source/Scene/BingMapsImageryProvider.js +++ b/Source/Scene/BingMapsImageryProvider.js @@ -630,7 +630,7 @@ define([ for (var areaIndex = 0, areaLength = attribution.coverageAreas.length; !included && areaIndex < areaLength; ++areaIndex) { var area = coverageAreas[areaIndex]; if (level >= area.zoomMin && level <= area.zoomMax) { - var intersection = Rectangle.intersectWith(rectangle, area.bbox, intersectionScratch); + var intersection = Rectangle.intersection(rectangle, area.bbox, intersectionScratch); if (defined(intersection)) { included = true; } diff --git a/Source/Scene/ImageryLayer.js b/Source/Scene/ImageryLayer.js index d0a06a972b36..11836ab4f04c 100644 --- a/Source/Scene/ImageryLayer.js +++ b/Source/Scene/ImageryLayer.js @@ -376,8 +376,8 @@ define([ // the geometry tile. The ImageryProvider and ImageryLayer both have the // opportunity to constrain the rectangle. The imagery TilingScheme's rectangle // always fully contains the ImageryProvider's rectangle. - var imageryBounds = Rectangle.intersectWith(imageryProvider.rectangle, this._rectangle, imageryBoundsScratch); - var rectangle = Rectangle.intersectWith(tile.rectangle, imageryBounds, tileImageryBoundsScratch); + var imageryBounds = Rectangle.intersection(imageryProvider.rectangle, this._rectangle, imageryBoundsScratch); + var rectangle = Rectangle.intersection(tile.rectangle, imageryBounds, tileImageryBoundsScratch); if (!defined(rectangle)) { // There is no overlap between this terrain tile and this imagery @@ -466,7 +466,7 @@ define([ var terrainRectangle = tile.rectangle; var imageryRectangle = imageryTilingScheme.tileXYToRectangle(northwestTileCoordinates.x, northwestTileCoordinates.y, imageryLevel); - var clippedImageryRectangle = Rectangle.intersectWith(imageryRectangle, imageryBounds, clippedRectangleScratch); + var clippedImageryRectangle = Rectangle.intersection(imageryRectangle, imageryBounds, clippedRectangleScratch); var minU; var maxU = 0.0; @@ -491,7 +491,7 @@ define([ minU = maxU; imageryRectangle = imageryTilingScheme.tileXYToRectangle(i, northwestTileCoordinates.y, imageryLevel); - clippedImageryRectangle = Rectangle.intersectWith(imageryRectangle, imageryBounds, clippedRectangleScratch); + clippedImageryRectangle = Rectangle.intersection(imageryRectangle, imageryBounds, clippedRectangleScratch); maxU = Math.min(1.0, (clippedImageryRectangle.east - terrainRectangle.west) / terrainRectangle.width); @@ -509,7 +509,7 @@ define([ maxV = minV; imageryRectangle = imageryTilingScheme.tileXYToRectangle(i, j, imageryLevel); - clippedImageryRectangle = Rectangle.intersectWith(imageryRectangle, imageryBounds, clippedRectangleScratch); + clippedImageryRectangle = Rectangle.intersection(imageryRectangle, imageryBounds, clippedRectangleScratch); minV = Math.max(0.0, (clippedImageryRectangle.south - terrainRectangle.south) / terrainRectangle.height); // If this is the southern-most imagery tile mapped to this terrain tile, diff --git a/Source/Scene/WebMapServiceImageryProvider.js b/Source/Scene/WebMapServiceImageryProvider.js index 972f5a3aa2fc..0915f19a5d5f 100644 --- a/Source/Scene/WebMapServiceImageryProvider.js +++ b/Source/Scene/WebMapServiceImageryProvider.js @@ -151,7 +151,7 @@ define([ this._rectangle = defaultValue(options.rectangle, Rectangle.MAX_VALUE); this._tilingScheme = defined(options.tilingScheme) ? options.tilingScheme : new GeographicTilingScheme(); - this._rectangle = Rectangle.intersectWith(this._rectangle, this._tilingScheme.rectangle); + this._rectangle = Rectangle.intersection(this._rectangle, this._tilingScheme.rectangle); var credit = options.credit; if (typeof credit === 'string') { diff --git a/Specs/Core/RectangleSpec.js b/Specs/Core/RectangleSpec.js index 5e7eb3ab3099..6a5fbf0010af 100644 --- a/Specs/Core/RectangleSpec.js +++ b/Specs/Core/RectangleSpec.js @@ -373,84 +373,84 @@ defineSuite([ }).toThrowDeveloperError(); }); - it('intersectWith works without a result parameter', function() { + it('intersection works without a result parameter', function() { var rectangle = new Rectangle(0.5, 0.1, 0.75, 0.9); var rectangle2 = new Rectangle(0.0, 0.25, 1.0, 0.8); var expected = new Rectangle(0.5, 0.25, 0.75, 0.8); - var returnedResult = Rectangle.intersectWith(rectangle, rectangle2); + var returnedResult = Rectangle.intersection(rectangle, rectangle2); expect(returnedResult).toEqual(expected); }); - it('intersectWith works with a result parameter', function() { + it('intersection works with a result parameter', function() { var rectangle = new Rectangle(0.5, 0.1, 0.75, 0.9); var rectangle2 = new Rectangle(0.0, 0.25, 1.0, 0.8); var expected = new Rectangle(0.5, 0.25, 0.75, 0.8); var result = new Rectangle(); - var returnedResult = Rectangle.intersectWith(rectangle, rectangle2, result); + var returnedResult = Rectangle.intersection(rectangle, rectangle2, result); expect(returnedResult).toEqual(expected); expect(result).toBe(returnedResult); }); - it('intersectWith works across the IDL (1)', function() { + it('intersection works across the IDL (1)', function() { var rectangle1 = Rectangle.fromDegrees(170.0, -10.0, -170.0, 10.0); var rectangle2 = Rectangle.fromDegrees(-175.0, 5.0, -160.0, 15.0); var expected = Rectangle.fromDegrees(-175.0, 5.0, -170.0, 10.0); - expect(Rectangle.intersectWith(rectangle1, rectangle2)).toEqual(expected); - expect(Rectangle.intersectWith(rectangle2, rectangle1)).toEqual(expected); + expect(Rectangle.intersection(rectangle1, rectangle2)).toEqual(expected); + expect(Rectangle.intersection(rectangle2, rectangle1)).toEqual(expected); }); - it('intersectWith works across the IDL (2)', function() { + it('intersection works across the IDL (2)', function() { var rectangle1 = Rectangle.fromDegrees(170.0, -10.0, -170.0, 10.0); var rectangle2 = Rectangle.fromDegrees(160.0, 5.0, 175.0, 15.0); var expected = Rectangle.fromDegrees(170.0, 5.0, 175.0, 10.0); - expect(Rectangle.intersectWith(rectangle1, rectangle2)).toEqual(expected); - expect(Rectangle.intersectWith(rectangle2, rectangle1)).toEqual(expected); + expect(Rectangle.intersection(rectangle1, rectangle2)).toEqual(expected); + expect(Rectangle.intersection(rectangle2, rectangle1)).toEqual(expected); }); - it('intersectWith works across the IDL (3)', function() { + it('intersection works across the IDL (3)', function() { var rectangle1 = Rectangle.fromDegrees(170.0, -10.0, -170.0, 10.0); var rectangle2 = Rectangle.fromDegrees(175.0, 5.0, -175.0, 15.0); var expected = Rectangle.fromDegrees(175.0, 5.0, -175.0, 10.0); - expect(Rectangle.intersectWith(rectangle1, rectangle2)).toEqual(expected); - expect(Rectangle.intersectWith(rectangle2, rectangle1)).toEqual(expected); + expect(Rectangle.intersection(rectangle1, rectangle2)).toEqual(expected); + expect(Rectangle.intersection(rectangle2, rectangle1)).toEqual(expected); }); - it('intersectWith returns undefined for a point', function() { + it('intersection returns undefined for a point', function() { var rectangle1 = new Rectangle(west, south, east, north); var rectangle2 = new Rectangle(east, north, east + 0.1, north + 0.1); - expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); - expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle2, rectangle1)).not.toBeDefined(); }); - it('intersectWith returns undefined for a east-west line (1)', function() { + it('intersection returns undefined for a east-west line (1)', function() { var rectangle1 = new Rectangle(west, south, east, north); var rectangle2 = new Rectangle(west, north, east, north + 0.1); - expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); - expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle2, rectangle1)).not.toBeDefined(); }); - it('intersectWith returns undefined for a east-west line (2)', function() { + it('intersection returns undefined for a east-west line (2)', function() { var rectangle1 = new Rectangle(west, south, east, north); var rectangle2 = new Rectangle(west, south + 0.1, east, south); - expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); - expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle2, rectangle1)).not.toBeDefined(); }); - it('intersectWith returns undefined for a north-south line (1)', function() { + it('intersection returns undefined for a north-south line (1)', function() { var rectangle1 = new Rectangle(west, south, east, north); var rectangle2 = new Rectangle(east, south, east + 0.1, north); - expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); - expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle2, rectangle1)).not.toBeDefined(); }); - it('intersectWith returns undefined for a north-south line (2)', function() { + it('intersection returns undefined for a north-south line (2)', function() { var rectangle1 = new Rectangle(west, south, east, north); var rectangle2 = new Rectangle(west - 0.1, south, west, north); - expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); - expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle2, rectangle1)).not.toBeDefined(); }); - it('intersectWith returns undefined for a north-south line (3)', function() { + it('intersection returns undefined for a north-south line (3)', function() { var west = CesiumMath.toRadians(170.0); var south = CesiumMath.toRadians(-10.0); var east = CesiumMath.toRadians(-170.0); @@ -458,11 +458,11 @@ defineSuite([ var rectangle1 = new Rectangle(west, south, east, north); var rectangle2 = new Rectangle(east, south, east + 0.1, north); - expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); - expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle2, rectangle1)).not.toBeDefined(); }); - it('intersectWith returns undefined for a north-south line (4)', function() { + it('intersection returns undefined for a north-south line (4)', function() { var west = CesiumMath.toRadians(170.0); var south = CesiumMath.toRadians(-10.0); var east = CesiumMath.toRadians(-170.0); @@ -470,22 +470,22 @@ defineSuite([ var rectangle1 = new Rectangle(west, south, east, north); var rectangle2 = new Rectangle(west - 0.1, south, west, north); - expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); - expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle2, rectangle1)).not.toBeDefined(); }); - it('intersectWith returns undefined if north-south direction is degenerate', function() { + it('intersection returns undefined if north-south direction is degenerate', function() { var rectangle1 = new Rectangle(west, south, east, north); var rectangle2 = new Rectangle(west, north + 0.1, east, north + 0.2); - expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); - expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle2, rectangle1)).not.toBeDefined(); }); - it('intersectWith returns undefined if east-west direction is degenerate', function() { + it('intersection returns undefined if east-west direction is degenerate', function() { var rectangle1 = new Rectangle(west, south, east, north); var rectangle2 = new Rectangle(east + 0.1, south, east + 0.2, north); - expect(Rectangle.intersectWith(rectangle1, rectangle2)).not.toBeDefined(); - expect(Rectangle.intersectWith(rectangle2, rectangle1)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle1, rectangle2)).not.toBeDefined(); + expect(Rectangle.intersection(rectangle2, rectangle1)).not.toBeDefined(); }); it('contains works', function() { @@ -622,10 +622,16 @@ defineSuite([ }).toThrowDeveloperError(); }); - it('intersectWith throws with no rectangle', function() { + it('intersection throws with no rectangle', function() { + expect(function() { + Rectangle.intersection(undefined); + }).toThrowDeveloperError(); + }); + + it('intersection throws with no otherRectangle', function() { var rectangle = new Rectangle(west, south, east, north); expect(function() { - Rectangle.intersectWith(undefined); + Rectangle.intersection(rectangle, undefined); }).toThrowDeveloperError(); }); From 3aceb0ac622afb6d6b3296020cf4564f22f71904 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 9 Dec 2014 12:58:39 -0500 Subject: [PATCH 11/11] Tweak CHANGES.md --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 50364353cc5b..8bb681ca3965 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,7 @@ Change Log ### 1.5 - 2015-01-05 * Deprecated - * `Rectangle.intersectWith` was deprecated in Cesium 1.5. It will be removed in Cesium 1.6. Use `Rectangle.intersection`. + * `Rectangle.intersectWith` was deprecated in Cesium 1.5. It will be removed in Cesium 1.6. Use `Rectangle.intersection`, which is the same but returns `undefined` when two rectangles do not intersect. * `Rectangle.isEmpty` was deprecated in Cesium 1.5. It will be removed in Cesium 1.6. * Improved polygon loading performance. * Added `Math.mod` which computes `m % n` but also works when `m` is negative.