mirror of
https://github.com/NASAWorldWind/WebWorldWind.git
synced 2025-12-08 19:46:18 +00:00
702 lines
26 KiB
JavaScript
702 lines
26 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/geom/Location',
|
||
'src/geom/Angle',
|
||
'src/globe/EarthElevationModel',
|
||
'src/globe/ElevationModel',
|
||
'src/globe/Globe'
|
||
], function (Location, Angle, EarthElevationModel, ElevationModel, Globe) {
|
||
"use strict";
|
||
|
||
describe("Location Tests", function () {
|
||
|
||
it("Should construct a location", function () {
|
||
var location = new Location(37.52, 15.08);
|
||
expect(location.latitude).toEqual(37.52);
|
||
expect(location.longitude).toEqual(15.08);
|
||
});
|
||
|
||
it("Should create a location initialized at (0,0)", function () {
|
||
var locationZero = Location.ZERO;
|
||
expect(locationZero.latitude).toEqual(0);
|
||
expect(locationZero.longitude).toEqual(0);
|
||
});
|
||
|
||
it("Should create a location from radians coordinates", function () {
|
||
var radiansLatitude = 37.52 / Angle.RADIANS_TO_DEGREES;
|
||
var radiansLongitude = 15.08 / Angle.RADIANS_TO_DEGREES;
|
||
|
||
var location = Location.fromRadians(radiansLatitude, radiansLongitude);
|
||
expect(location.latitude).toBeCloseTo(37.52);
|
||
expect(location.longitude).toBeCloseTo(15.08);
|
||
});
|
||
|
||
describe("Copies this location to the latitude and longitude of a specified location", function () {
|
||
|
||
it("Copies the location successfully", function () {
|
||
var location = new Location(0, 0);
|
||
var locationTarget = new Location(37.52, 15.08);
|
||
|
||
location.copy(locationTarget);
|
||
expect(location.latitude).toEqual(37.52);
|
||
expect(location.longitude).toEqual(15.08);
|
||
});
|
||
|
||
it("Should throw an exception on missing location input", function () {
|
||
expect(function () {
|
||
var location = new Location(0, 0);
|
||
location.copy(null);
|
||
}).toThrow();
|
||
});
|
||
});
|
||
|
||
it('Sets latitude and longitude of a location', function () {
|
||
var location = new Location(0, 0);
|
||
location.set(37.52, 15.08);
|
||
expect(location.latitude).toEqual(37.52);
|
||
expect(location.longitude).toEqual(15.08);
|
||
});
|
||
|
||
describe('Checks if two locations are equal', function () {
|
||
|
||
it('Equal locations', function () {
|
||
var locationA = new Location(37.52, 15.08);
|
||
var locationB = new Location(37.52, 15.08);
|
||
expect(locationA.equals(locationB)).toBe(true);
|
||
});
|
||
|
||
it('Different locations', function () {
|
||
var locationA = new Location(37.52, 15.08);
|
||
var locationB = new Location(37, 18);
|
||
expect(locationA.equals(locationB)).toBe(false);
|
||
});
|
||
});
|
||
|
||
describe('Computes a location along a path', function () {
|
||
|
||
var locationA = new Location(37.52, 15.00);
|
||
var locationB = new Location(45.48, 9.09);
|
||
|
||
it('Compute with Great Circle', function () {
|
||
var resultLocation = Location.interpolateAlongPath(
|
||
WorldWind.GREAT_CIRCLE,
|
||
0.5,
|
||
locationA,
|
||
locationB,
|
||
new Location());
|
||
expect(resultLocation.latitude).toBeCloseTo(41.537, 2);
|
||
expect(resultLocation.longitude).toBeCloseTo(12.227, 2);
|
||
});
|
||
|
||
it('Compute with Rhumb Line', function () {
|
||
var resultLocation = Location.interpolateAlongPath(
|
||
WorldWind.RHUMB_LINE,
|
||
0.5,
|
||
locationA,
|
||
locationB,
|
||
new Location());
|
||
expect(resultLocation.latitude).toBeCloseTo(41.5, 2);
|
||
expect(resultLocation.longitude).toBeCloseTo(12.135, 2);
|
||
});
|
||
|
||
it('Compute with Linear', function () {
|
||
var resultLocation = Location.interpolateAlongPath(
|
||
WorldWind.LINEAR,
|
||
0.5,
|
||
locationA,
|
||
locationB,
|
||
new Location());
|
||
expect(resultLocation.latitude).toBeCloseTo(41.5, 2);
|
||
expect(resultLocation.longitude).toBeCloseTo(12.044, 2);
|
||
});
|
||
|
||
it('Compute with Linear with fraction greater than 1', function () {
|
||
var resultLocation = Location.interpolateAlongPath(
|
||
WorldWind.LINEAR,
|
||
4.5,
|
||
locationA,
|
||
locationB,
|
||
new Location());
|
||
expect(resultLocation.latitude).toBeCloseTo(45.48, 2);
|
||
expect(resultLocation.longitude).toBeCloseTo(9.089, 2);
|
||
});
|
||
|
||
it('Compute with Linear with not recognized path', function () {
|
||
var resultLocation = Location.interpolateAlongPath(
|
||
null,
|
||
0.5,
|
||
locationA,
|
||
locationB,
|
||
new Location());
|
||
expect(resultLocation.latitude).toBeCloseTo(41.5, 2);
|
||
expect(resultLocation.longitude).toBeCloseTo(12.044, 2);
|
||
});
|
||
|
||
it('Store result in the provided variable', function () {
|
||
var resultLocation = new Location(0, 0);
|
||
Location.interpolateAlongPath(
|
||
WorldWind.LINEAR,
|
||
0.5,
|
||
locationA,
|
||
locationB,
|
||
resultLocation);
|
||
expect(resultLocation.latitude).toBeCloseTo(41.5, 2);
|
||
expect(resultLocation.longitude).toBeCloseTo(12.044, 2);
|
||
});
|
||
|
||
describe('Exceptions', function () {
|
||
|
||
it('Location A not provided', function () {
|
||
expect(function () {
|
||
Location.interpolateAlongPath(
|
||
WorldWind.LINEAR,
|
||
0.5,
|
||
null,
|
||
locationB,
|
||
new Location());
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Location B not provided', function () {
|
||
expect(function () {
|
||
Location.interpolateAlongPath(
|
||
WorldWind.LINEAR,
|
||
0.5,
|
||
locationA,
|
||
null,
|
||
new Location());
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Result storage not provided', function () {
|
||
expect(function () {
|
||
Location.interpolateAlongPath(
|
||
WorldWind.LINEAR,
|
||
0.5,
|
||
locationA,
|
||
locationB,
|
||
null);
|
||
}).toThrow();
|
||
});
|
||
});
|
||
});
|
||
|
||
describe('Computes a location along a great circle path', function () {
|
||
|
||
var locationA = new Location(37.52, 15.00);
|
||
var locationB = new Location(45.48, 9.09);
|
||
|
||
it('Compute with Great Circle', function () {
|
||
var resultLocation = Location.interpolateGreatCircle(
|
||
0.5,
|
||
locationA,
|
||
locationB,
|
||
new Location());
|
||
expect(resultLocation.latitude).toBeCloseTo(41.537, 2);
|
||
expect(resultLocation.longitude).toBeCloseTo(12.227, 2);
|
||
});
|
||
|
||
it('Equal locations', function () {
|
||
var resultLocation = Location.interpolateGreatCircle(
|
||
0.5,
|
||
locationA,
|
||
locationA,
|
||
new Location());
|
||
expect(resultLocation).toEqual(locationA);
|
||
});
|
||
|
||
describe('Exceptions', function () {
|
||
|
||
it('Location A not provided', function () {
|
||
expect(function () {
|
||
Location.interpolateGreatCircle(
|
||
0.5,
|
||
null,
|
||
locationB,
|
||
new Location());
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Location B not provided', function () {
|
||
expect(function () {
|
||
Location.interpolateGreatCircle(
|
||
0.5,
|
||
locationA,
|
||
null,
|
||
new Location());
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Result storage not provided', function () {
|
||
expect(function () {
|
||
Location.interpolateGreatCircle(
|
||
0.5,
|
||
locationA,
|
||
locationB,
|
||
null);
|
||
}).toThrow();
|
||
});
|
||
});
|
||
});
|
||
|
||
describe('Computes a location along a rhumb path', function () {
|
||
|
||
var locationA = new Location(37.52, 15.00);
|
||
var locationB = new Location(45.48, 9.09);
|
||
|
||
it('Compute with rhumb path', function () {
|
||
var resultLocation = Location.interpolateRhumb(
|
||
0.5,
|
||
locationA,
|
||
locationB,
|
||
new Location());
|
||
expect(resultLocation.latitude).toBeCloseTo(41.5, 2);
|
||
expect(resultLocation.longitude).toBeCloseTo(12.135, 2);
|
||
});
|
||
|
||
it('Equal locations', function () {
|
||
var resultLocation = Location.interpolateRhumb(
|
||
0.5,
|
||
locationA,
|
||
locationA,
|
||
new Location());
|
||
expect(resultLocation).toEqual(locationA);
|
||
});
|
||
|
||
describe('Exceptions', function () {
|
||
|
||
it('Location A not provided', function () {
|
||
expect(function () {
|
||
Location.interpolateRhumb(
|
||
0.5,
|
||
null,
|
||
locationB,
|
||
new Location());
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Location B not provided', function () {
|
||
expect(function () {
|
||
Location.interpolateRhumb(
|
||
0.5,
|
||
locationA,
|
||
null,
|
||
new Location());
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Result storage not provided', function () {
|
||
expect(function () {
|
||
Location.interpolateRhumb(
|
||
0.5,
|
||
locationA,
|
||
locationB,
|
||
null);
|
||
}).toThrow();
|
||
});
|
||
});
|
||
});
|
||
|
||
describe('Computes a location along a linear path', function () {
|
||
|
||
var locationA = new Location(37.52, 15.00);
|
||
var locationB = new Location(45.48, 9.09);
|
||
|
||
it('Compute with linear path', function () {
|
||
var resultLocation = Location.interpolateLinear(
|
||
0.5,
|
||
locationA,
|
||
locationB,
|
||
new Location());
|
||
expect(resultLocation.latitude).toBeCloseTo(41.5, 2);
|
||
expect(resultLocation.longitude).toBeCloseTo(12.044, 2);
|
||
});
|
||
|
||
it('Equal locations', function () {
|
||
var resultLocation = Location.interpolateLinear(
|
||
0.5,
|
||
locationA,
|
||
locationA,
|
||
new Location());
|
||
expect(resultLocation).toEqual(locationA);
|
||
});
|
||
|
||
describe('Exceptions', function () {
|
||
|
||
it('Location A not provided', function () {
|
||
expect(function () {
|
||
Location.interpolateLinear(
|
||
0.5,
|
||
null,
|
||
locationB,
|
||
new Location());
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Location B not provided', function () {
|
||
expect(function () {
|
||
Location.interpolateLinear(
|
||
0.5,
|
||
locationA,
|
||
null,
|
||
new Location());
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Result storage not provided', function () {
|
||
expect(function () {
|
||
Location.interpolateLinear(
|
||
0.5,
|
||
locationA,
|
||
locationB,
|
||
null);
|
||
}).toThrow();
|
||
});
|
||
});
|
||
});
|
||
|
||
describe('Computes the great circle angle pointing from the first to the second location', function () {
|
||
|
||
var locationA = new Location(37.52, 15.00);
|
||
var locationB = new Location(45.48, 9.09);
|
||
|
||
it('Compute the angle', function () {
|
||
var resultAngle = Location.greatCircleAzimuth(
|
||
locationA,
|
||
locationB);
|
||
expect(resultAngle).toBeCloseTo(-27.154, 2);
|
||
});
|
||
|
||
it('Compute the angle with equal locations', function () {
|
||
var resultAngle = Location.greatCircleAzimuth(
|
||
locationA,
|
||
locationA);
|
||
expect(resultAngle).toEqual(0);
|
||
});
|
||
|
||
describe('Exceptions', function () {
|
||
|
||
it('Location A not provided', function () {
|
||
expect(function () {
|
||
Location.greatCircleAzimuth(
|
||
locationA,
|
||
null);
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Location B not provided', function () {
|
||
expect(function () {
|
||
Location.greatCircleAzimuth(
|
||
null,
|
||
locationB);
|
||
}).toThrow();
|
||
});
|
||
|
||
});
|
||
});
|
||
|
||
describe('Computes the rhumb angle pointing from the first to the second location', function () {
|
||
|
||
var locationA = new Location(37.52, 15.00);
|
||
var locationB = new Location(45.48, 9.09);
|
||
|
||
it('Compute the angle', function () {
|
||
var resultAngle = Location.rhumbAzimuth(
|
||
locationA,
|
||
locationB);
|
||
expect(resultAngle).toBeCloseTo(-29.026, 2);
|
||
});
|
||
|
||
it('Compute the angle with equal locations', function () {
|
||
var resultAngle = Location.rhumbAzimuth(
|
||
locationA,
|
||
locationA);
|
||
expect(resultAngle).toEqual(0);
|
||
});
|
||
|
||
describe('Exceptions', function () {
|
||
|
||
it('Location A not provided', function () {
|
||
expect(function () {
|
||
Location.rhumbAzimuth(
|
||
locationA,
|
||
null);
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Location B not provided', function () {
|
||
expect(function () {
|
||
Location.rhumbAzimuth(
|
||
null,
|
||
locationB);
|
||
}).toThrow();
|
||
});
|
||
|
||
});
|
||
});
|
||
|
||
describe('Computes the linear angle pointing from the first to the second location', function () {
|
||
|
||
var locationA = new Location(37.52, 15.00);
|
||
var locationB = new Location(45.48, 9.09);
|
||
|
||
it('Compute the angle', function () {
|
||
var resultAngle = Location.linearAzimuth(
|
||
locationA,
|
||
locationB);
|
||
expect(resultAngle).toBeCloseTo(-36.592, 2);
|
||
});
|
||
|
||
it('Compute the angle with equal locations', function () {
|
||
var resultAngle = Location.linearAzimuth(
|
||
locationA,
|
||
locationA);
|
||
expect(resultAngle).toEqual(0);
|
||
});
|
||
|
||
describe('Exceptions', function () {
|
||
|
||
it('Location A not provided', function () {
|
||
expect(function () {
|
||
Location.linearAzimuth(
|
||
locationA,
|
||
null);
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Location B not provided', function () {
|
||
expect(function () {
|
||
Location.linearAzimuth(
|
||
null,
|
||
locationB);
|
||
}).toThrow();
|
||
});
|
||
|
||
});
|
||
});
|
||
|
||
describe('Computes the rhumb angular distance between two locations', function () {
|
||
|
||
var locationA = new Location(37.52, 15.00);
|
||
var locationB = new Location(45.48, 9.09);
|
||
|
||
it('Compute the distance', function () {
|
||
var resultDistance = Location.rhumbDistance(
|
||
locationA,
|
||
locationB);
|
||
expect(resultDistance).toBeCloseTo(0.158, 2);
|
||
});
|
||
|
||
it('Compute the distance with equal locations', function () {
|
||
var resultDistance = Location.rhumbDistance(
|
||
locationA,
|
||
locationA);
|
||
expect(resultDistance).toEqual(0);
|
||
});
|
||
|
||
describe('Exceptions', function () {
|
||
|
||
it('Location A not provided', function () {
|
||
expect(function () {
|
||
Location.rhumbDistance(
|
||
locationA,
|
||
null);
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Location B not provided', function () {
|
||
expect(function () {
|
||
Location.rhumbDistance(
|
||
null,
|
||
locationB);
|
||
}).toThrow();
|
||
});
|
||
|
||
});
|
||
});
|
||
|
||
describe('Computes the linear angular distance between two locations', function () {
|
||
|
||
var locationA = new Location(37.52, 15.00);
|
||
var locationB = new Location(45.48, 9.09);
|
||
|
||
it('Compute the distance', function () {
|
||
var resultDistance = Location.linearDistance(
|
||
locationA,
|
||
locationB);
|
||
expect(resultDistance).toBeCloseTo(0.173, 2);
|
||
});
|
||
|
||
it('Compute the distance with equal locations', function () {
|
||
var resultDistance = Location.linearDistance(
|
||
locationA,
|
||
locationA);
|
||
expect(resultDistance).toEqual(0);
|
||
});
|
||
|
||
describe('Exceptions', function () {
|
||
|
||
it('Location A not provided', function () {
|
||
expect(function () {
|
||
Location.linearDistance(
|
||
locationA,
|
||
null);
|
||
}).toThrow();
|
||
});
|
||
|
||
it('Location B not provided', function () {
|
||
expect(function () {
|
||
Location.linearDistance(
|
||
null,
|
||
locationB);
|
||
}).toThrow();
|
||
});
|
||
|
||
});
|
||
});
|
||
|
||
describe('Determines whether a list of locations crosses the dateline', function () {
|
||
|
||
it('Locations cross the dateline', function () {
|
||
var locations = [new Location(29.94, 160.57), new Location(29.96, -151.66)];
|
||
var cross = Location.locationsCrossDateLine(locations);
|
||
expect(cross).toBe(true);
|
||
});
|
||
|
||
it('Locations do not cross the dateline', function () {
|
||
var locations = [new Location(37.52, 15.00), new Location(40, 18.00)];
|
||
var cross = Location.locationsCrossDateLine(locations);
|
||
expect(cross).toBe(false);
|
||
});
|
||
|
||
it('Locations not provided', function () {
|
||
expect(function () {
|
||
Location.locationsCrossDateLine(null);
|
||
}).toThrow();
|
||
});
|
||
});
|
||
|
||
describe('Great-Circle-Arc-Extreme-Latitude Locations', function () {
|
||
|
||
it('Returns extreme locations', function () {
|
||
var locations = [
|
||
new Location(37.00, 15.00),
|
||
new Location(47.00, 15.00),
|
||
new Location(47.00, 17.00),
|
||
new Location(55.00, 12.00),
|
||
new Location(55.00, 18.00),
|
||
];
|
||
var result = Location.greatCircleArcExtremeLocations(locations);
|
||
expect(result[0]).toEqual(new Location(37.00, 15.00));
|
||
expect(result[1]).toEqual(new Location(55.00, 12.00));
|
||
});
|
||
|
||
it('Locations not provided', function () {
|
||
expect(function () {
|
||
Location.greatCircleArcExtremeLocations(null);
|
||
}).toThrow();
|
||
});
|
||
});
|
||
|
||
describe('Great-Circle-Arc-Extreme-Latitude between two Locations', function () {
|
||
|
||
it('Returns extreme locations', function () {
|
||
var locationA = new Location(187.00, 65.00);
|
||
var locationB = new Location(145.00, 88.00);
|
||
|
||
var result = Location.greatCircleArcExtremeForTwoLocations(locationA, locationB);
|
||
expect(result[0].latitude).toBeCloseTo(-3.503, 2);
|
||
expect(result[0].longitude).toBeCloseTo(-113.306, 2);
|
||
expect(result[1]).toEqual(new Location(187.00, 65.00));
|
||
});
|
||
|
||
it('Locations not provided', function () {
|
||
expect(function () {
|
||
Location.greatCircleArcExtremeForTwoLocations(null);
|
||
}).toThrow();
|
||
});
|
||
});
|
||
|
||
describe('Great-Circle-Extreme-Locations Using Azimuth', function () {
|
||
|
||
it('Returns extreme locations', function () {
|
||
var location = new Location(37.52, 15.08);
|
||
|
||
var expectedLocations = [
|
||
new Location(-9.527, 70.736),
|
||
new Location(9.527, -109.263)
|
||
];
|
||
|
||
var result = Location.greatCircleExtremeLocationsUsingAzimuth(location, 120);
|
||
expect(result[0].latitude).toBeCloseTo(expectedLocations[0].latitude);
|
||
expect(result[0].longitude).toBeCloseTo(expectedLocations[0].longitude);
|
||
expect(result[1].latitude).toBeCloseTo(expectedLocations[1].latitude);
|
||
expect(result[1].longitude).toBeCloseTo(expectedLocations[1].longitude);
|
||
});
|
||
|
||
it('Locations not provided', function () {
|
||
expect(function () {
|
||
Location.greatCircleExtremeLocationsUsingAzimuth(null, 120);
|
||
}).toThrow();
|
||
});
|
||
});
|
||
|
||
describe('Determines where a line between two positions crosses a given meridian', function () {
|
||
|
||
it('Meridian intersected', function () {
|
||
var locationA = new Location(-120, 15.08);
|
||
var locationB = new Location(87.00, 25.12);
|
||
var globe = new Globe(new EarthElevationModel());
|
||
|
||
var intersection = Location.intersectionWithMeridian(locationA, locationB, 180, globe);
|
||
expect(intersection).toBeCloseTo(-54.824);
|
||
|
||
});
|
||
|
||
it('Meridian not intersected', function () {
|
||
var locationA = new Location(37.52, 15.08);
|
||
var locationB = new Location(87.00, 25.12);
|
||
var globe = new Globe(new EarthElevationModel());
|
||
|
||
var intersection = Location.intersectionWithMeridian(locationA, locationB, 180, globe);
|
||
expect(intersection).toEqual(null);
|
||
|
||
});
|
||
});
|
||
|
||
it("Checks location Poles", function () {
|
||
expect(Location.poles).toEqual({
|
||
'NONE': 0,
|
||
'NORTH': 1,
|
||
'SOUTH': 2
|
||
});
|
||
});
|
||
|
||
});
|
||
}); |