mirror of
https://github.com/NASAWorldWind/WebWorldWind.git
synced 2025-12-08 19:46:18 +00:00
501 lines
20 KiB
JavaScript
501 lines
20 KiB
JavaScript
/*
|
||
* Copyright 2003-2006, 2009, 2017, 2020 United States Government, as represented
|
||
* by the Administrator of the National Aeronautics and Space Administration.
|
||
* All rights reserved.
|
||
*
|
||
* The NASAWorldWind/WebWorldWind platform is licensed under the Apache License,
|
||
* Version 2.0 (the "License"); you may not use this file except in compliance
|
||
* with the License. You may obtain a copy of the License
|
||
* at http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software distributed
|
||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||
* specific language governing permissions and limitations under the License.
|
||
*
|
||
* NASAWorldWind/WebWorldWind also contains the following 3rd party Open Source
|
||
* software:
|
||
*
|
||
* ES6-Promise – under MIT License
|
||
* libtess.js – SGI Free Software License B
|
||
* Proj4 – under MIT License
|
||
* JSZip – under MIT License
|
||
*
|
||
* A complete listing of 3rd Party software notices and licenses included in
|
||
* WebWorldWind can be found in the WebWorldWind 3rd-party notices and licenses
|
||
* PDF found in code directory.
|
||
*/
|
||
define([
|
||
'src/globe/ElevationModel',
|
||
'src/geom/Angle',
|
||
'src/geom/Location',
|
||
'src/geom/Sector',
|
||
'src/globe/EarthElevationModel',
|
||
'src/globe/Tessellator',
|
||
'src/globe/GebcoElevationCoverage',
|
||
'src/globe/AsterV2ElevationCoverage',
|
||
'src/globe/UsgsNedElevationCoverage',
|
||
'src/globe/UsgsNedHiElevationCoverage',
|
||
'src/globe/TiledElevationCoverage'
|
||
], function (ElevationModel, Angle, Location, Sector, EarthElevationModel, Tessellator, GebcoElevationCoverage,
|
||
AsterV2ElevationCoverage, UsgsNedElevationCoverage, UsgsNedHiElevationCoverage, TiledElevationCoverage) {
|
||
"use strict";
|
||
describe("ElevationModel tests", function () {
|
||
|
||
var MockCoverage = function (resolution, minElevation, maxElevation) {
|
||
TiledElevationCoverage.call(this, {
|
||
coverageSector: Sector.FULL_SPHERE,
|
||
resolution: resolution,
|
||
retrievalImageFormat: "application/bil16",
|
||
levelZeroDelta: new Location(45, 45),
|
||
numLevels: 1,
|
||
tileWidth: 256,
|
||
tileHeight: 256,
|
||
minElevation: minElevation ? minElevation : -11000,
|
||
maxElevation: maxElevation ? maxElevation : 8850
|
||
});
|
||
|
||
this.displayName = "Mock Elevation Coverage";
|
||
};
|
||
|
||
MockCoverage.prototype = Object.create(TiledElevationCoverage.prototype);
|
||
|
||
MockCoverage.prototype.minAndMaxElevationsForSector = function (sector, result) {
|
||
if (result[0] > this.minElevation) {
|
||
result[0] = this.minElevation;
|
||
}
|
||
if (result[1] < this.maxElevation) {
|
||
result[1] = this.maxElevation;
|
||
}
|
||
|
||
return true;
|
||
};
|
||
|
||
MockCoverage.prototype.elevationAtLocation = function (latitude, longitude) {
|
||
return this.maxElevation;
|
||
};
|
||
|
||
MockCoverage.prototype.elevationsForGrid = function (sector, numLat, numLon, result) {
|
||
for (var i = 0, n = result.length; i < n; i++) {
|
||
result[i] = this.maxElevation;
|
||
}
|
||
|
||
return 1;
|
||
};
|
||
|
||
// TODO: It would appear that Array.fill is not supported by the unit test engine. (PhantomJS 2.1.1 at the time of this writing)
|
||
// TODO: Revisit the need for this hack with future versions of PhantomJS.
|
||
Array.prototype.fill = function (n) {
|
||
for (var i = 0; i < this.length; i++) {
|
||
this[i] = n;
|
||
}
|
||
};
|
||
|
||
describe("Missing parameter tests", function () {
|
||
it("Correctly rejects calls with missing or invalid parameters", function () {
|
||
var elevationModel = new ElevationModel();
|
||
expect(function () {
|
||
elevationModel.addCoverage();
|
||
}).toThrow();
|
||
expect(function () {
|
||
elevationModel.containsCoverage();
|
||
}).toThrow();
|
||
expect(function () {
|
||
elevationModel.removeCoverage();
|
||
}).toThrow();
|
||
expect(function () {
|
||
elevationModel.elevationsForGrid();
|
||
}).toThrow();
|
||
expect(function () {
|
||
elevationModel.elevationsForGrid("dummySector");
|
||
}).toThrow();
|
||
expect(function () {
|
||
elevationModel.elevationsForGrid("dummySector", 10);
|
||
}).toThrow();
|
||
expect(function () {
|
||
elevationModel.elevationsForGrid("dummySector", 10, 10);
|
||
}).toThrow();
|
||
expect(function () {
|
||
elevationModel.elevationsForGrid("dummySector", 10, 10, 10);
|
||
}).toThrow();
|
||
expect(function () {
|
||
elevationModel.minAndMaxElevationsForSector();
|
||
}).toThrow();
|
||
expect(function () {
|
||
elevationModel.bestCoverageAtLocation(0, 0);
|
||
}).toThrow();
|
||
expect(function () {
|
||
elevationModel.bestCoverageAtLocation(0, 0, -1);
|
||
}).toThrow();
|
||
});
|
||
});
|
||
|
||
describe("Elevation result tests", function () {
|
||
it("Returns correct min and max elevations for a sector", function () {
|
||
var n = 12;
|
||
var em = new ElevationModel();
|
||
for (var i = 0; i < n; i++) {
|
||
var c = new MockCoverage(i + 1, -i - 1, i + 1);
|
||
em.addCoverage(c);
|
||
}
|
||
|
||
var minMax = em.minAndMaxElevationsForSector(new Sector(-1, 1, -1, 1));
|
||
expect(minMax[0]).toEqual(-1);
|
||
expect(minMax[1]).toEqual(1);
|
||
});
|
||
|
||
it("Returns correct min and max elevations for a sector when some coverages are disabled", function () {
|
||
var em = new ElevationModel();
|
||
var n = 12;
|
||
for (var i = 0; i < n; i++) {
|
||
var c = new MockCoverage(i + 1, -i - 1, i + 1);
|
||
em.addCoverage(c);
|
||
if (i < 2) {
|
||
c.enabled = false;
|
||
}
|
||
}
|
||
|
||
var minMax = em.minAndMaxElevationsForSector(new Sector(-1, 1, -1, 1));
|
||
expect(minMax[0]).toEqual(-3);
|
||
expect(minMax[1]).toEqual(3);
|
||
});
|
||
|
||
it("Returns correct elevation for a location", function () {
|
||
var em = new ElevationModel();
|
||
var n = 12;
|
||
for (var i = n; i >= 1; i--) {
|
||
var c = new MockCoverage(i, -i, i);
|
||
em.addCoverage(c);
|
||
}
|
||
|
||
var e = em.elevationAtLocation(0, 0);
|
||
expect(e).toEqual(1);
|
||
});
|
||
|
||
it("Returns correct best coverage for a location", function () {
|
||
var em = new ElevationModel();
|
||
var n = 12;
|
||
for (var i = n; i >= 1; i--) {
|
||
var c = new MockCoverage(i, -i, i);
|
||
em.addCoverage(c);
|
||
}
|
||
|
||
c = em.bestCoverageAtLocation(0, 0, 6.7);
|
||
expect(c.resolution).toEqual(7);
|
||
c = em.bestCoverageAtLocation(0, 0, 6.2);
|
||
expect(c.resolution).toEqual(6);
|
||
});
|
||
|
||
it("Returns correct best coverage for a location with some coverages disabled", function () {
|
||
var em = new ElevationModel();
|
||
var n = 12;
|
||
for (var i = n; i >= 1; i--) {
|
||
var c = new MockCoverage(i, -i, i);
|
||
em.addCoverage(c);
|
||
if (i === 6 || i === 7) {
|
||
c.enabled = false;
|
||
}
|
||
}
|
||
|
||
c = em.bestCoverageAtLocation(0, 0, 6.7);
|
||
expect(c.resolution).toEqual(8);
|
||
c = em.bestCoverageAtLocation(0, 0, 6.2);
|
||
expect(c.resolution).toEqual(5);
|
||
});
|
||
|
||
it("Returns null best coverage for a location with no available coverages", function () {
|
||
var em = new ElevationModel();
|
||
var n = 12;
|
||
for (var i = n; i >= 1; i--) {
|
||
var c = new MockCoverage(i, -i, i);
|
||
em.addCoverage(c);
|
||
c.enabled = false;
|
||
}
|
||
|
||
c = em.bestCoverageAtLocation(0, 0, 6.7);
|
||
expect(c).toEqual(null);
|
||
});
|
||
|
||
it("Returns correct elevation for a location when some coverages are disabled", function () {
|
||
|
||
var em = new ElevationModel();
|
||
var n = 12;
|
||
for (var i = 0; i < n; i++) {
|
||
var c = new MockCoverage(n - i, -i - 1, i + 1);
|
||
em.addCoverage(c);
|
||
}
|
||
em.coverages[n - 1].enabled = false;
|
||
em.coverages[n - 2].enabled = false;
|
||
var e = em.elevationAtLocation(0, 0);
|
||
expect(e).toEqual(n - 2);
|
||
});
|
||
|
||
it("Returns correct elevations for a grid", function () {
|
||
var em = new ElevationModel();
|
||
var n = 12;
|
||
for (var i = 0; i < n; i++) {
|
||
var c = new MockCoverage(n - i, -i - 1, i + 1);
|
||
em.addCoverage(c);
|
||
}
|
||
|
||
var result = [0];
|
||
em.elevationsForGrid(new Sector(-1, 1, -1, 1), 1, 1, 1, result);
|
||
expect(result[0]).toEqual(n);
|
||
});
|
||
|
||
it("Returns correct elevations for a grid when some coverages are disabled", function () {
|
||
var em = new ElevationModel();
|
||
var n = 12;
|
||
for (var i = 0; i < n; i++) {
|
||
var c = new MockCoverage(n - i, -i - 1, i + 1);
|
||
em.addCoverage(c);
|
||
}
|
||
|
||
em.coverages[n - 1].enabled = false;
|
||
em.coverages[n - 2].enabled = false;
|
||
var result = [0];
|
||
em.elevationsForGrid(new Sector(-1, 1, -1, 1), 1, 1, 1, result);
|
||
expect(result[0]).toEqual(n - 2);
|
||
});
|
||
|
||
it("Prioritizes coverages correctly according to resolution", function () {
|
||
var em = new EarthElevationModel();
|
||
var ts = new Tessellator();
|
||
|
||
for (var i = 0; i < ts.maximumSubdivisionDepth; i++) {
|
||
var l = ts.levels.levels[i];
|
||
var targetResolution = ts.coverageTargetResolution(l.texelSize);
|
||
var preferredIndex = em.preferredCoverageIndex(Sector.FULL_SPHERE, null, targetResolution);
|
||
var preferredCoverage = em.coverages[preferredIndex];
|
||
if (l.levelNumber < 6) {
|
||
expect(preferredCoverage instanceof GebcoElevationCoverage).toBe(true);
|
||
}
|
||
else if (l.levelNumber < 10) {
|
||
expect(preferredCoverage instanceof AsterV2ElevationCoverage).toBe(true);
|
||
}
|
||
else {
|
||
expect((preferredCoverage instanceof UsgsNedElevationCoverage) ||
|
||
(preferredCoverage instanceof UsgsNedHiElevationCoverage)).toBe(true);
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
describe("Coverage list manipulation tests", function () {
|
||
it("Maintains coverages in the correct order, respecting the sortCoverages flag", function () {
|
||
var n = 12;
|
||
var em = new ElevationModel();
|
||
var coverages = [];
|
||
for (var i = n; i > 0; i--) {
|
||
var c = new MockCoverage(n - i + 1);
|
||
em.addCoverage(c);
|
||
coverages.push(c);
|
||
}
|
||
|
||
for (i = 0; i < n; i++) {
|
||
expect(coverages[n - (i + 1)] === em.coverages[i]).toBe(true);
|
||
}
|
||
});
|
||
|
||
it("Rejects duplicate coverages", function () {
|
||
var em = new ElevationModel();
|
||
var coverages = [];
|
||
var n = 12, c;
|
||
for (var t = 0; t < 2; t++) {
|
||
var expectedResult = (t === 0);
|
||
for (var i = 0; i < n; i++) {
|
||
if (expectedResult) {
|
||
c = new MockCoverage(i + 1);
|
||
coverages.push(c);
|
||
} else {
|
||
c = coverages[i];
|
||
}
|
||
expect(em.addCoverage(c)).toBe(expectedResult);
|
||
}
|
||
}
|
||
});
|
||
|
||
it("Clears coverage list", function () {
|
||
var em = new ElevationModel();
|
||
for (var i = 1; i < 12; i++) {
|
||
var c = new MockCoverage(i);
|
||
em.addCoverage(c);
|
||
}
|
||
em.removeAllCoverages();
|
||
expect(em.coverages.length).toEqual(0);
|
||
});
|
||
|
||
it("Detects coverage containment", function () {
|
||
var em = new ElevationModel();
|
||
var i, n = 12;
|
||
var coverages = [];
|
||
for (i = 0; i < n; i++) {
|
||
var c = new MockCoverage(i + 1);
|
||
em.addCoverage(c);
|
||
coverages.push(c);
|
||
}
|
||
|
||
for (i = 0; i < n; i++) {
|
||
expect(em.containsCoverage(coverages[i])).toBe(true);
|
||
}
|
||
});
|
||
|
||
it("Removes coverages", function () {
|
||
var em = new ElevationModel();
|
||
var i, n = 12;
|
||
var coverages = [];
|
||
for (i = 0; i < n; i++) {
|
||
var c = new MockCoverage(n - i);
|
||
em.addCoverage(c);
|
||
coverages.push(c);
|
||
}
|
||
|
||
var removedCoverage = coverages.splice(3, 1);
|
||
em.removeCoverage(removedCoverage[0]);
|
||
n = coverages.length;
|
||
expect(em.coverages.length).toEqual(n);
|
||
for (i = 0; i < n; i++) {
|
||
expect(coverages[i] === em.coverages[i]).toBe(true);
|
||
}
|
||
});
|
||
|
||
it("Clears coverage list", function () {
|
||
var em = new ElevationModel();
|
||
for (var i = 1; i < 12; i++) {
|
||
var c = new MockCoverage(i);
|
||
em.addCoverage(c);
|
||
}
|
||
em.removeAllCoverages();
|
||
expect(em.coverages.length).toEqual(0);
|
||
});
|
||
});
|
||
|
||
describe("StateKey tests", function () {
|
||
it("StateKey changes due to list manipulation", function () {
|
||
var em = new ElevationModel();
|
||
var prevStateKey = em.stateKey;
|
||
em.addCoverage(new MockCoverage(1));
|
||
expect(em.stateKey).not.toEqual(prevStateKey);
|
||
|
||
prevStateKey = em.stateKey;
|
||
em.removeAllCoverages();
|
||
expect(em.stateKey).not.toEqual(prevStateKey);
|
||
|
||
prevStateKey = em.stateKey;
|
||
em.addCoverage(new MockCoverage(1));
|
||
em.addCoverage(new MockCoverage(1));
|
||
expect(em.stateKey).not.toEqual(prevStateKey);
|
||
|
||
prevStateKey = em.stateKey;
|
||
em.removeCoverage(em.coverages[0]);
|
||
expect(em.stateKey).not.toEqual(prevStateKey);
|
||
});
|
||
});
|
||
|
||
describe("Timestamp calculation tests", function () {
|
||
it("Calculates timestamp correctly", function () {
|
||
var em = new ElevationModel();
|
||
var newestCoverage;
|
||
for (var i = 0; i < 10; i++) {
|
||
var c = new MockCoverage(i + 1);
|
||
em.addCoverage(c);
|
||
c.timestamp += Math.round(Math.random() * 1000);
|
||
if (!newestCoverage || newestCoverage.timestamp < c.timestamp) {
|
||
newestCoverage = c;
|
||
}
|
||
}
|
||
|
||
expect(newestCoverage.timestamp).toEqual(em.timestamp);
|
||
});
|
||
|
||
it("Returns correct timestamp after coverage removal", function () {
|
||
var em = new ElevationModel();
|
||
var n = 10;
|
||
for (var i = 0; i < n; i++) {
|
||
var c = new MockCoverage(i + 1);
|
||
em.addCoverage(c);
|
||
c.timestamp += Math.round(Math.random() * 1000);
|
||
}
|
||
var sortedCoverages = em.coverages.slice();
|
||
sortedCoverages.sort(function (c1, c2) {
|
||
return c2.timestamp - c1.timestamp;
|
||
});
|
||
expect(sortedCoverages[0].timestamp).toEqual(em.timestamp);
|
||
em.removeCoverage(sortedCoverages[0]);
|
||
expect(sortedCoverages[1].timestamp).toEqual(em.timestamp);
|
||
});
|
||
|
||
});
|
||
|
||
describe("Min and max elevation calculation tests", function () {
|
||
it("Calculates elevations correctly", function () {
|
||
var em = new ElevationModel();
|
||
var n = 10;
|
||
for (var i = 0; i < n; i++) {
|
||
var c = new MockCoverage(i + 1, (Math.random() + 1) * -1000, (Math.random() + 1) * 1000);
|
||
em.addCoverage(c);
|
||
}
|
||
var sortedCoverages = em.coverages.slice();
|
||
sortedCoverages.sort(function (c1, c2) {
|
||
return c1.minElevation - c2.minElevation;
|
||
});
|
||
expect(sortedCoverages[0].minElevation).toEqual(em.minElevation);
|
||
|
||
sortedCoverages.sort(function (c1, c2) {
|
||
return c1.maxElevation - c2.maxElevation;
|
||
});
|
||
expect(sortedCoverages[n - 1].maxElevation).toEqual(em.maxElevation);
|
||
});
|
||
it("Disregards elevations for disabled coverages", function () {
|
||
var em = new ElevationModel();
|
||
var enabledCoverages = [];
|
||
for (var i = 0; i < 10; i++) {
|
||
var c = new MockCoverage(i + 1, (Math.random() + 1) * -1000, (Math.random() + 1) * 1000);
|
||
em.addCoverage(c);
|
||
c.enabled = (i % 2) > 0;
|
||
if (c.enabled) {
|
||
enabledCoverages.push(c);
|
||
}
|
||
}
|
||
enabledCoverages.sort(function (c1, c2) {
|
||
return c1.minElevation - c2.minElevation;
|
||
});
|
||
expect(enabledCoverages[0].minElevation).toEqual(em.minElevation);
|
||
|
||
enabledCoverages.sort(function (c1, c2) {
|
||
return c1.maxElevation - c2.maxElevation;
|
||
});
|
||
expect(enabledCoverages[enabledCoverages.length - 1].maxElevation).toEqual(em.maxElevation);
|
||
});
|
||
|
||
it("Returns correct elevations after coverage removal", function () {
|
||
var em = new ElevationModel();
|
||
var n = 10;
|
||
for (var i = 0; i < n; i++) {
|
||
var c = new MockCoverage(i + 1, (Math.random() + 1) * -1000, (Math.random() + 1) * 1000);
|
||
em.addCoverage(c);
|
||
}
|
||
var sortedCoverages = em.coverages.slice();
|
||
sortedCoverages.sort(function (c1, c2) {
|
||
return c1.minElevation - c2.minElevation;
|
||
});
|
||
expect(sortedCoverages[0].minElevation).toEqual(em.minElevation);
|
||
em.removeCoverage(sortedCoverages[0]);
|
||
expect(sortedCoverages[1].minElevation).toEqual(em.minElevation);
|
||
|
||
sortedCoverages = em.coverages.slice();
|
||
n = sortedCoverages.length;
|
||
sortedCoverages.sort(function (c1, c2) {
|
||
return c1.maxElevation - c2.maxElevation;
|
||
});
|
||
expect(sortedCoverages[n - 1].maxElevation).toEqual(em.maxElevation);
|
||
em.removeCoverage(sortedCoverages[n - 1]);
|
||
expect(sortedCoverages[n - 2].maxElevation).toEqual(em.maxElevation);
|
||
});
|
||
});
|
||
});
|
||
})
|
||
;
|
||
|
||
|