WebWorldWind/test/geom/Sector.test.js
2022-04-14 14:10:27 -05:00

575 lines
25 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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/geom/Sector',
'src/geom/Location',
'src/globe/EarthElevationModel',
'src/globe/ElevationModel',
'src/geom/BoundingBox',
'src/geom/Vec3',
'src/render/DrawContext',
'src/globe/Globe'
], function (Sector, Location, EarthElevationModel, ElevationModel, BoundingBox, Vec3, DrawContext, Globe) {
"use strict";
describe("Sector Tests", function () {
it("Should construct a Sector", function () {
var sector = new Sector(37, 39, 13, 18);
expect(sector.minLatitude).toEqual(37);
expect(sector.maxLatitude).toEqual(39);
expect(sector.minLongitude).toEqual(13);
expect(sector.maxLongitude).toEqual(18);
});
it("Should create a sector initialized with all 0", function () {
var sectorZero = Sector.ZERO;
expect(sectorZero.minLatitude).toEqual(0);
expect(sectorZero.maxLatitude).toEqual(0);
expect(sectorZero.minLongitude).toEqual(0);
expect(sectorZero.maxLongitude).toEqual(0);
});
it("Should create a sector that encompasses the full range of latitude and longitude", function () {
var sectorFull = Sector.FULL_SPHERE;
expect(sectorFull.minLatitude).toEqual(-90);
expect(sectorFull.maxLatitude).toEqual(90);
expect(sectorFull.minLongitude).toEqual(-180);
expect(sectorFull.maxLongitude).toEqual(180);
});
describe("Copies this sector to the latitude and longitude of a specified sector", function () {
it("Copies the sector successfully", function () {
var sector = new Sector(0, 0, 0, 0);
var sectorTarget = new Sector(37, 39, 13, 18);
sector.copy(sectorTarget);
expect(sector.minLatitude).toEqual(37);
expect(sector.maxLatitude).toEqual(39);
expect(sector.minLongitude).toEqual(13);
expect(sector.maxLongitude).toEqual(18);
});
it("Should throw an exception on missing sector input", function () {
expect(function () {
var sector = new Sector(0, 0, 0, 0);
sector.copy(null);
}).toThrow();
});
});
describe("Indicates whether this sector has width or height", function () {
it("Sector is not empty", function () {
var sector = new Sector(37, 39, 13, 18);
expect(sector.isEmpty()).toBe(false);
});
it("Sector is empty", function () {
var sector = new Sector(37, 37, 13, 13);
expect(sector.isEmpty()).toBe(true);
});
});
it("Returns the angle between this sector's minimum and maximum latitudes, in degrees", function () {
var sector = new Sector(37, 39, 13, 18);
expect(sector.deltaLatitude()).toEqual(2);
});
it("Returns the angle between this sector's minimum and maximum longitude, in degrees", function () {
var sector = new Sector(37, 39, 13, 18);
expect(sector.deltaLongitude()).toEqual(5);
});
it("Returns the angle midway between this sector's minimum and maximum latitudes", function () {
var sector = new Sector(37, 39, 13, 18);
expect(sector.centroidLatitude()).toEqual(38);
});
it("Returns the angle midway between this sector's minimum and maximum longitude", function () {
var sector = new Sector(37, 39, 13, 18);
expect(sector.centroidLongitude()).toEqual(15.5);
});
describe("Computes the location of the angular center of this sector", function () {
it("Computes the location correctly", function () {
var sector = new Sector(37, 39, 13, 18);
var result = new Location(0, 0);
sector.centroid(result);
expect(result.latitude).toEqual(38);
expect(result.longitude).toEqual(15.5);
});
it("Should throw an exception on missing result", function () {
expect(function () {
var sector = new Sector(37, 39, 13, 18);
sector.centroid(null);
}).toThrow();
});
});
it("Returns this sector's minimum latitude in radians", function () {
var sector = new Sector(37, 39, 13, 18);
var minLatitudeRadians = sector.minLatitudeRadians();
expect(minLatitudeRadians).toBeCloseTo(0.645);
});
it("Returns this sector's maximum latitude in radians", function () {
var sector = new Sector(37, 39, 13, 18);
var maxLatitudeRadians = sector.maxLatitudeRadians();
expect(maxLatitudeRadians).toBeCloseTo(0.680);
});
it("Returns this sector's minimum longitude in radians", function () {
var sector = new Sector(37, 39, 13, 18);
var minLongitudeRadians = sector.minLongitudeRadians();
expect(minLongitudeRadians).toBeCloseTo(0.226);
});
it("Returns this sector's minimum longitude in radians", function () {
var sector = new Sector(37, 39, 13, 18);
var maxLongitudeRadians = sector.maxLongitudeRadians();
expect(maxLongitudeRadians).toBeCloseTo(0.314);
});
describe("Modifies this sector to encompass an array of specified locations", function () {
it("Set the bounding correctly", function () {
var sector = new Sector(37, 39, 13, 18);
var locations = [
new Location(37.52, 15.08),
new Location(38.63, 15.32),
new Location(38.72, 16.03),
new Location(38.88, 12.34)
];
sector.setToBoundingSector(locations);
expect(sector.minLatitude).toEqual(37.52);
expect(sector.maxLatitude).toEqual(38.88);
expect(sector.minLongitude).toEqual(12.34);
expect(sector.maxLongitude).toEqual(16.03);
});
it("Should throw an exception on missing locations array", function () {
expect(function () {
var sector = new Sector(37, 39, 13, 18);
sector.setToBoundingSector(null);
}).toThrow();
});
});
describe("Computes bounding sectors from a list of locations that span the dateline", function () {
it("Computes the sectors correctly", function () {
var locations = [
new Location(37.52, 15.08),
new Location(38.63, 15.32),
new Location(38.72, 16.03),
new Location(38.88, 12.34)
];
var resultSector = Sector.splitBoundingSectors(locations);
expect(resultSector.length).toBe(2);
expect(resultSector[0].minLatitude).toEqual(37.52);
expect(resultSector[0].maxLatitude).toEqual(38.88);
expect(resultSector[0].minLongitude).toEqual(12.34);
expect(resultSector[0].maxLongitude).toEqual(180);
expect(resultSector[1].minLatitude).toEqual(37.52);
expect(resultSector[1].maxLatitude).toEqual(38.88);
expect(resultSector[1].minLongitude).toEqual(-180);
expect(resultSector[1].maxLongitude).toEqual(-180);
});
it("Should throw an exception on missing locations array", function () {
expect(function () {
Sector.splitBoundingSectors(null);
}).toThrow();
});
});
describe("Indicates whether this sector intersects a specified sector", function () {
it("The first sector intersects the second one", function () {
var sectorA = new Sector(37, 39, 13, 18);
var sectorB = new Sector(39, 40, 18, 19);
var intersection = sectorA.intersects(sectorB);
expect(intersection).toBe(true);
});
it("The first sector does not intersect the second one", function () {
var sectorA = new Sector(37, 39, 13, 18);
var sectorB = new Sector(42, 44, 15, 19);
var intersection = sectorA.intersects(sectorB);
expect(intersection).toBe(false);
});
});
describe("Indicates whether this sector intersects strictly a specified sector", function () {
it("The first sector intersects the second one", function () {
var sectorA = new Sector(37, 39, 13, 18);
var sectorB = new Sector(38, 40, 17, 19);
var intersection = sectorA.overlaps(sectorB);
expect(intersection).toBe(true);
});
it("The first sector does not intersects the second one", function () {
var sectorA = new Sector(37, 39, 13, 18);
var sectorB = new Sector(39, 40, 18, 19);
var intersection = sectorA.overlaps(sectorB);
expect(intersection).toBe(false);
});
});
describe("Indicates whether this sector fully contains a specified sector", function () {
it("The first sector contains the second one", function () {
var sectorA = new Sector(36, 39, 13, 18);
var sectorB = new Sector(38, 38, 15, 17);
var contains = sectorA.contains(sectorB);
expect(contains).toBe(true);
});
it("The first sector does not contains the second one", function () {
var sectorA = new Sector(37, 39, 13, 18);
var sectorB = new Sector(39, 40, 18, 19);
var contains = sectorA.contains(sectorB);
expect(contains).toBe(false);
});
});
describe("Indicates whether this sector contains a specified geographic location", function () {
it("The sector contains the location", function () {
var sector = new Sector(36, 39, 13, 18);
var contains = sector.containsLocation(37, 15);
expect(contains).toBe(true);
});
it("The sector does not contains the location", function () {
var sector = new Sector(36, 39, 13, 18);
var contains = sector.containsLocation(37, 22);
expect(contains).toBe(false);
});
});
describe("Sets this sector to the intersection of itself and a specified sector", function () {
it("Returns the intersection", function () {
var sectorA = new Sector(36, 39, 13, 18);
var sectorB = new Sector(38, 40, 15, 17);
sectorA.intersection(sectorB);
expect(sectorA.minLatitude).toEqual(38);
expect(sectorA.maxLatitude).toEqual(39);
expect(sectorA.minLongitude).toEqual(15);
expect(sectorA.maxLongitude).toEqual(17);
});
it("Should throw an exception on missing sector input", function () {
expect(function () {
var sector = new Sector(0, 0, 0, 0);
sector.intersection(null);
}).toThrow();
});
});
describe("Get corners method", function () {
it("Returns corner points in the correct order", function () {
var sector = new Sector(44, 45, -95, -94);
var corners = sector.getCorners();
expect(corners[0].latitude).toEqual(44);
expect(corners[0].longitude).toEqual(-95);
expect(corners[1].latitude).toEqual(44);
expect(corners[1].longitude).toEqual(-94);
expect(corners[2].latitude).toEqual(45);
expect(corners[2].longitude).toEqual(-94);
expect(corners[3].latitude).toEqual(45);
expect(corners[3].longitude).toEqual(-95);
});
});
describe("Compute bounding points method", function () {
it("Should throw an exception because no globe is provided", function () {
var sector = new Sector(44, 45, -95, -94);
expect(function () {
sector.computeBoundingPoints(null /* globe */, 1 /* verticalExaggeration */)
}).toThrow();
});
it("Computes the correct bounding points for a given sector", function () {
// create a globe that returns mock elevations for a given sector so we don't have to rely on
// asynchronous tile calls to finish.
Globe.prototype.minAndMaxElevationsForSector = function (sector) {
return [125.0, 350.0];
};
var mockGlobe = new Globe(new EarthElevationModel());
var sector = new Sector(44.0, 45.0, -95.0, -94.0);
var boundingPoints = sector.computeBoundingPoints(mockGlobe, 1 /* verticalExaggeration */);
var results = [-4578078.7560, 4408178.4447, -400529.9919, -4578239.9915, 4408334.7429, -400544.0982,
-4584371.7046, 4408178.4447, -320570.4981, -4584533.1618, 4408334.7429, -320581.7883,
-4506674.4276, 4487436.7972, -315137.3752, -4506833.1390, 4487595.8962, -315148.4734,
-4500488.1337, 4487436.7972, -393741.6920, -4500646.6273, 4487595.8962, -393755.5584,
-4542910.2988, 4448133.5080, -357534.7945, -4581561.0285, 4408334.7429, -360576.6729];
var resultCount = 0;
for (var i = 0; i < boundingPoints.length; i++) {
var vec = boundingPoints[i];
for (var j = 0; j < 3; j++) {
expect(vec[j]).toBeCloseTo(results[resultCount], 3);
resultCount++;
}
}
});
it("Computes the correct bounding points for a sector crossing the anti-Meridian", function () {
// create a globe that returns mock elevations for a given sector so we don't have to rely on
// asynchronous tile calls to finish.
Globe.prototype.minAndMaxElevationsForSector = function (sector) {
return [125.0, 350.0];
};
var mockGlobe = new Globe(new EarthElevationModel());
var sector = new Sector(44.0, 45.0, -179, 179.0);
var boundingPoints = sector.computeBoundingPoints(mockGlobe, 1 /* verticalExaggeration */);
var results = [-80203.6904, 4408178.4447, -4594866.3461, -80206.5151, 4408334.7429, -4595028.1729,
80203.6904, 4408178.4447, -4594866.3461, 80206.5151, 4408334.7429, -4595028.1729,
78844.3747, 4487436.7972, -4516991.2028, 78847.1514, 4487595.8962, -4517150.2776,
-78844.3747, 4487436.7972, -4516991.2028, -78847.1514, 4487595.8962, -4517150.2776,
0.0000, 4448133.5080, 4556957.8791, 0.0000, 4408334.7429, 4595728.1245,
-4556784.3641, 4448133.5080, 39766.4547, 4556784.3641, 4448133.5080, 39766.4547,
-79529.8810, 4448133.5080, -4556263.8324, 79529.8810, 4448133.5080, -4556263.8324];
var resultCount = 0;
for (var i = 0; i < boundingPoints.length; i++) {
var vec = boundingPoints[i];
for (var j = 0; j < 3; j++) {
expect(vec[j]).toBeCloseTo(results[resultCount], 3);
resultCount++;
}
}
});
it("Computes the correct bounding points for a sector spanning the globe horizontally", function () {
// create a globe that returns mock elevations for a given sector so we don't have to rely on
// asynchronous tile calls to finish.
Globe.prototype.minAndMaxElevationsForSector = function (sector) {
return [125.0, 350.0];
};
var mockGlobe = new Globe(new EarthElevationModel());
var sector = new Sector(44.0, 45.0, -180, 180.0);
var boundingPoints = sector.computeBoundingPoints(mockGlobe, 1 /* verticalExaggeration */);
var results = [-0.0000, 4408178.4447, -4595566.2731, -0.0000, 4408334.7429, -4595728.1245,
0.0000, 4408178.4447, -4595566.2731, 0.0000, 4408334.7429, -4595728.1245,
0.0000, 4487436.7972, -4517679.2672, 0.0000, 4487595.8962, -4517838.3662,
0.0000, 4487436.7972, -4517679.2672, -0.0000, 4487595.8962, -4517838.3662,
0.0000, 4448133.5080, 4556957.8791, 0.0000, 4408334.7429, 4595728.1245,
0.0000, 4408334.7429, 4595728.1245, 4595728.1245, 4408334.7429, 0.0000,
-4595728.1245, 4408334.7429, 0.0000, 0.0000, 4408334.7429, -4595728.1245,
0.0000, 4487595.8962, 4517838.3662, 4517838.3662, 4487595.8962,
0.0000, -4517838.3662, 4487595.8962, 0.0000, 0.0000, 4487595.8962, -4517838.3662];
var resultCount = 0;
for (var i = 0; i < boundingPoints.length; i++) {
var vec = boundingPoints[i];
for (var j = 0; j < 3; j++) {
expect(vec[j]).toBeCloseTo(results[resultCount], 3);
resultCount++;
}
}
});
it("Computes the correct bounding points for a sector in the southern hemisphere", function () {
// create a globe that returns mock elevations for a given sector so we don't have to rely on
// asynchronous tile calls to finish.
Globe.prototype.minAndMaxElevationsForSector = function (sector) {
return [125.0, 350.0];
};
var mockGlobe = new Globe(new EarthElevationModel());
var sector = new Sector(-45.0, -44.0, -95.0, -94.0);
var boundingPoints = sector.computeBoundingPoints(mockGlobe, 1 /* verticalExaggeration */);
var results = [-4500488.1337, -4487436.7972, -393741.6920, -4500646.6273, -4487595.8962, -393755.5584,
-4506674.4276, -4487436.7972, -315137.3752, -4506833.1390, -4487595.8962, -315148.4734,
-4584371.7046, -4408178.4447, -320570.4981, -4584533.1618, -4408334.7429, -320581.7883,
-4578078.7560, -4408178.4447, -400529.9919, -4578239.9915, -4408334.7429, -400544.0982,
-4542910.2988, -4448133.5080, -357534.7945, -4581561.0285, -4408334.7429, -360576.6729];
var resultCount = 0;
for (var i = 0; i < boundingPoints.length; i++) {
var vec = boundingPoints[i];
for (var j = 0; j < 3; j++) {
expect(vec[j]).toBeCloseTo(results[resultCount], 3);
resultCount++;
}
}
});
it("Computes the correct bounding points for a sector crossing the equator", function () {
// create a globe that returns mock elevations for a given sector so we don't have to rely on
// asynchronous tile calls to finish.
Globe.prototype.minAndMaxElevationsForSector = function (sector) {
return [125.0, 350.0];
};
var mockGlobe = new Globe(new EarthElevationModel());
var sector = new Sector(-10.0, 10.0, -95.0, -94.0);
var boundingPoints = sector.computeBoundingPoints(mockGlobe, 1 /* verticalExaggeration */);
var results = [-6258091.0395, -1100270.2538, -547512.0213, -6258311.7780, -1100309.3246, -547531.3334,
-6266693.3042, -1100270.2538, -438209.8842, -6266914.3462, -1100309.3246, -438225.3410,
-6266693.3042, 1100270.2538, -438209.8842, -6266914.3462, 1100309.3246, -438225.3410,
-6258091.0395, 1100270.2538, -547512.0213, -6258311.7780, 1100309.3246, -547531.3334,
-6358824.2533, 0.0000, -500450.3221, -6262851.5323, -1100309.3246, -492897.1052,
-6262851.5323, 1100309.3246, -492897.1052, -6354214.9312, 0.0000, -555921.7721,
-6362949.3262, 0.0000, -444940.7609];
var resultCount = 0;
for (var i = 0; i < boundingPoints.length; i++) {
var vec = boundingPoints[i];
for (var j = 0; j < 3; j++) {
expect(vec[j]).toBeCloseTo(results[resultCount], 3);
resultCount++;
}
}
});
});
describe("Sets this sector to the union of itself and a specified sector", function () {
it("Returns the intersection", function () {
var sectorA = new Sector(36, 39, 13, 18);
var sectorB = new Sector(38, 40, 15, 17);
sectorA.union(sectorB);
expect(sectorA.minLatitude).toEqual(36);
expect(sectorA.maxLatitude).toEqual(40);
expect(sectorA.minLongitude).toEqual(13);
expect(sectorA.maxLongitude).toEqual(18);
});
it("Should throw an exception on missing sector input", function () {
expect(function () {
var sector = new Sector(0, 0, 0, 0);
sector.union(null);
}).toThrow();
});
});
describe("Computes points and distances", function () {
it("Computes a center point", function () {
const sector = new Sector(-90, -45, -180, -135);
expect(function () {
sector.computeCenterPoint(null, 1);
}).toThrow();
var mockGlobe = new Globe(new EarthElevationModel());
const center = sector.computeCenterPoint(mockGlobe, 1);
const result = new Vec3(-936736.6335818054, -5869977.306109176, -2261482.2851649104);
expect(center).toEqual(result);
});
it("Computes corner points", function () {
const sector = new Sector(-90, -45, -180, -135);
expect(function () {
sector.computeCornerPoints(null, 1);
}).toThrow();
const corners = [new Vec3(-4.798926572645884e-26, -6356752.314245179, -3.9186209248144716e-10),
new Vec3(-2.770883428835813e-10, -6356752.314245179, -2.7708834288358126e-10),
new Vec3(-3194419.1450605746, -4487348.408865919, -3194419.145060574),
new Vec3(-5.532453209639622e-10, -4487348.408865919, -4517590.878848932)];
var mockGlobe = new Globe(new EarthElevationModel());
const result = sector.computeCornerPoints(mockGlobe, 1);
for (let i = 0, len = result.length; i < len; i++) {
for (let j=0; j<3; j++) {
expect(corners[i][j]).toBeCloseTo(result[i][j],6);
}
}
});
it("Computes distance from a point.", function () {
var MockGlContext = function () { };
var dc = new DrawContext(new MockGlContext());
dc.globe = new Globe(new EarthElevationModel());
const sector = new Sector(-90, -45, -180, -135);
const point = new Vec3(-13332838.783247922, 8170373.735383635, -4852756.455372253);
expect(function () {
sector.distanceTo(null, point);
}).toThrow();
expect(function () {
sector.distanceTo(dc, null);
}).toThrow();
const distance = sector.distanceTo(dc, point);
expect(distance).toBeCloseTo(16302011.080715783, 7);
});
});
});
});