Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
/index.js
node_modules
+3
View File
@@ -0,0 +1,3 @@
language: node_js
sudo: false
node_js: 'node'
+29
View File
@@ -0,0 +1,29 @@
# Change log
## [1.1.1] - 2017-06-27
### Fixed
- Fix UTM zone number longitude boundaries (fixes [Turbo87/utm#19])
## [1.1.0] - 2016-11-07
### Added
- An option to disable range checking of easting and northing
### Fixed
- Fix case when `northern` is `false` (fixes [#3]; thanks go to **[@perhallstroem]**)
## [1.0.1] - 2016-07-01
### Fixed
- Fix `northern` never getting set (fixes [#1]; thanks go to **[@danielsiwiec]**)
## 1.0.0 - 2015-10-25
### Added
- Initial release
[1.1.1]: https://github.com/TimothyGu/utm/compare/v1.1.0...v1.1.1
[1.1.0]: https://github.com/TimothyGu/utm/compare/v1.0.1...v1.1.0
[1.0.1]: https://github.com/TimothyGu/utm/compare/v1.0.0...v1.0.1
[Turbo87/utm#19]: https://github.com/Turbo87/utm/issues/19
[#3]: https://github.com/TimothyGu/utm/issues/3
[#1]: https://github.com/TimothyGu/utm/issues/1
[@danielsiwiec]: https://github.com/danielsiwiec
[@perhallstroem]: https://github.com/perhallstroem
+8
View File
@@ -0,0 +1,8 @@
Copyright (C) 2012 Tobias Bieniek <Tobias.Bieniek@gmx.de>
Copyright (c) 2015 Tiancheng “Timothy” Gu
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+29
View File
@@ -0,0 +1,29 @@
# utm
Bidirectional UTM-WGS84 converter for JavaScript.
[![npm version](https://img.shields.io/npm/v/utm.svg)](https://www.npmjs.org/package/utm)
[![Travis](https://img.shields.io/travis/TimothyGu/utm.svg)](https://travis-ci.org/TimothyGu/utm)
Translated directly from [Tobias Bieniek's implementation in Python](https://github.com/Turbo87/utm).
## Usage
```js
var utm = require('utm')
```
### `utm.toLatLon(easting, northing, zoneNum, zoneLetter, northern, strict = true)`
Convert from UTM-WGS84 to latitude/longitude coordinates. One and only one of
`zoneLetter` and `northern` must be specified. `strict` option specifies
whether easting and northing are checked against their respective ranges.
Returns `{ latitude, longitude }`.
### `utm.fromLatLon(latitude, longitude[, zoneNum])`
Convert from latitude/longitude coordinates to UTM-WGS84. `zoneNum` can be set
to force a specific zone number.
Returns `{ easting, northing, zoneNum, zoneLetter }`.
+203
View File
@@ -0,0 +1,203 @@
'use strict'
var K0 = 0.9996;
var E = 0.00669438;
var E2 = Math.pow(E, 2);
var E3 = Math.pow(E, 3);
var E_P2 = E / (1 - E);
var SQRT_E = Math.sqrt(1 - E);
var _E = (1 - SQRT_E) / (1 + SQRT_E);
var _E2 = Math.pow(_E, 2);
var _E3 = Math.pow(_E, 3);
var _E4 = Math.pow(_E, 4);
var _E5 = Math.pow(_E, 5);
var M1 = 1 - E / 4 - 3 * E2 / 64 - 5 * E3 / 256;
var M2 = 3 * E / 8 + 3 * E2 / 32 + 45 * E3 / 1024;
var M3 = 15 * E2 / 256 + 45 * E3 / 1024;
var M4 = 35 * E3 / 3072;
var P2 = 3 / 2 * _E - 27 / 32 * _E3 + 269 / 512 * _E5;
var P3 = 21 / 16 * _E2 - 55 / 32 * _E4;
var P4 = 151 / 96 * _E3 - 417 / 128 * _E5;
var P5 = 1097 / 512 * _E4;
var R = 6378137;
var ZONE_LETTERS = 'CDEFGHJKLMNPQRSTUVWXX';
export function toLatLon(easting, northing, zoneNum, zoneLetter, northern, strict) {
strict = strict !== undefined ? strict : true;
if (!zoneLetter && northern === undefined) {
throw new Error('either zoneLetter or northern needs to be set');
} else if (zoneLetter && northern !== undefined) {
throw new Error('set either zoneLetter or northern, but not both');
}
if (strict) {
if (easting < 100000 || 1000000 <= easting) {
throw new RangeError('easting out of range (must be between 100 000 m and 999 999 m)');
}
if (northing < 0 || northing > 10000000) {
throw new RangeError('northing out of range (must be between 0 m and 10 000 000 m)');
}
}
if (zoneNum < 1 || zoneNum > 60) {
throw new RangeError('zone number out of range (must be between 1 and 60)');
}
if (zoneLetter) {
zoneLetter = zoneLetter.toUpperCase();
if (zoneLetter.length !== 1 || ZONE_LETTERS.indexOf(zoneLetter) === -1) {
throw new RangeError('zone letter out of range (must be between C and X)');
}
northern = zoneLetter >= 'N';
}
var x = easting - 500000;
var y = northing;
if (!northern) y -= 1e7;
var m = y / K0;
var mu = m / (R * M1);
var pRad = mu +
P2 * Math.sin(2 * mu) +
P3 * Math.sin(4 * mu) +
P4 * Math.sin(6 * mu) +
P5 * Math.sin(8 * mu);
var pSin = Math.sin(pRad);
var pSin2 = Math.pow(pSin, 2);
var pCos = Math.cos(pRad);
var pTan = Math.tan(pRad);
var pTan2 = Math.pow(pTan, 2);
var pTan4 = Math.pow(pTan, 4);
var epSin = 1 - E * pSin2;
var epSinSqrt = Math.sqrt(epSin);
var n = R / epSinSqrt;
var r = (1 - E) / epSin;
var c = _E * pCos * pCos;
var c2 = c * c;
var d = x / (n * K0);
var d2 = Math.pow(d, 2);
var d3 = Math.pow(d, 3);
var d4 = Math.pow(d, 4);
var d5 = Math.pow(d, 5);
var d6 = Math.pow(d, 6);
var latitude = pRad - (pTan / r) *
(d2 / 2 -
d4 / 24 * (5 + 3 * pTan2 + 10 * c - 4 * c2 - 9 * E_P2)) +
d6 / 720 * (61 + 90 * pTan2 + 298 * c + 45 * pTan4 - 252 * E_P2 - 3 * c2);
var longitude = (d -
d3 / 6 * (1 + 2 * pTan2 + c) +
d5 / 120 * (5 - 2 * c + 28 * pTan2 - 3 * c2 + 8 * E_P2 + 24 * pTan4)) / pCos;
return {
latitude: toDegrees(latitude),
longitude: toDegrees(longitude) + zoneNumberToCentralLongitude(zoneNum)
};
}
export function fromLatLon(latitude, longitude, forceZoneNum) {
if (latitude > 84 || latitude < -80) {
throw new RangeError('latitude out of range (must be between 80 deg S and 84 deg N)');
}
if (longitude > 180 || longitude < -180) {
throw new RangeError('longitude out of range (must be between 180 deg W and 180 deg E)');
}
var latRad = toRadians(latitude);
var latSin = Math.sin(latRad);
var latCos = Math.cos(latRad);
var latTan = Math.tan(latRad);
var latTan2 = Math.pow(latTan, 2);
var latTan4 = Math.pow(latTan, 4);
var zoneNum;
if (forceZoneNum === undefined) {
zoneNum = latLonToZoneNumber(latitude, longitude);
} else {
zoneNum = forceZoneNum;
}
var zoneLetter = latitudeToZoneLetter(latitude);
var lonRad = toRadians(longitude);
var centralLon = zoneNumberToCentralLongitude(zoneNum);
var centralLonRad = toRadians(centralLon);
var n = R / Math.sqrt(1 - E * latSin * latSin);
var c = E_P2 * latCos * latCos;
var a = latCos * (lonRad - centralLonRad);
var a2 = Math.pow(a, 2);
var a3 = Math.pow(a, 3);
var a4 = Math.pow(a, 4);
var a5 = Math.pow(a, 5);
var a6 = Math.pow(a, 6);
var m = R * (M1 * latRad -
M2 * Math.sin(2 * latRad) +
M3 * Math.sin(4 * latRad) -
M4 * Math.sin(6 * latRad));
var easting = K0 * n * (a +
a3 / 6 * (1 - latTan2 + c) +
a5 / 120 * (5 - 18 * latTan2 + latTan4 + 72 * c - 58 * E_P2)) + 500000;
var northing = K0 * (m + n * latTan * (a2 / 2 +
a4 / 24 * (5 - latTan2 + 9 * c + 4 * c * c) +
a6 / 720 * (61 - 58 * latTan2 + latTan4 + 600 * c - 330 * E_P2)));
if (latitude < 0) northing += 1e7;
return {
easting: easting,
northing: northing,
zoneNum: zoneNum,
zoneLetter: zoneLetter
};
}
function latitudeToZoneLetter(latitude) {
if (-80 <= latitude && latitude <= 84) {
return ZONE_LETTERS[Math.floor((latitude + 80) / 8)];
} else {
return null;
}
}
function latLonToZoneNumber(latitude, longitude) {
if (56 <= latitude && latitude < 64 && 3 <= longitude && longitude < 12) return 32;
if (72 <= latitude && latitude <= 84 && longitude >= 0) {
if (longitude < 9) return 31;
if (longitude < 21) return 33;
if (longitude < 33) return 35;
if (longitude < 42) return 37;
}
return Math.floor((longitude + 180) / 6) + 1;
}
function zoneNumberToCentralLongitude(zoneNum) {
return (zoneNum - 1) * 6 - 180 + 3;
}
function toDegrees(rad) {
return rad / Math.PI * 180;
}
function toRadians(deg) {
return deg * Math.PI / 180;
}
+208
View File
@@ -0,0 +1,208 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var K0 = 0.9996;
var E = 0.00669438;
var E2 = Math.pow(E, 2);
var E3 = Math.pow(E, 3);
var E_P2 = E / (1 - E);
var SQRT_E = Math.sqrt(1 - E);
var _E = (1 - SQRT_E) / (1 + SQRT_E);
var _E2 = Math.pow(_E, 2);
var _E3 = Math.pow(_E, 3);
var _E4 = Math.pow(_E, 4);
var _E5 = Math.pow(_E, 5);
var M1 = 1 - E / 4 - 3 * E2 / 64 - 5 * E3 / 256;
var M2 = 3 * E / 8 + 3 * E2 / 32 + 45 * E3 / 1024;
var M3 = 15 * E2 / 256 + 45 * E3 / 1024;
var M4 = 35 * E3 / 3072;
var P2 = 3 / 2 * _E - 27 / 32 * _E3 + 269 / 512 * _E5;
var P3 = 21 / 16 * _E2 - 55 / 32 * _E4;
var P4 = 151 / 96 * _E3 - 417 / 128 * _E5;
var P5 = 1097 / 512 * _E4;
var R = 6378137;
var ZONE_LETTERS = 'CDEFGHJKLMNPQRSTUVWXX';
function toLatLon(easting, northing, zoneNum, zoneLetter, northern, strict) {
strict = strict !== undefined ? strict : true;
if (!zoneLetter && northern === undefined) {
throw new Error('either zoneLetter or northern needs to be set');
} else if (zoneLetter && northern !== undefined) {
throw new Error('set either zoneLetter or northern, but not both');
}
if (strict) {
if (easting < 100000 || 1000000 <= easting) {
throw new RangeError('easting out of range (must be between 100 000 m and 999 999 m)');
}
if (northing < 0 || northing > 10000000) {
throw new RangeError('northing out of range (must be between 0 m and 10 000 000 m)');
}
}
if (zoneNum < 1 || zoneNum > 60) {
throw new RangeError('zone number out of range (must be between 1 and 60)');
}
if (zoneLetter) {
zoneLetter = zoneLetter.toUpperCase();
if (zoneLetter.length !== 1 || ZONE_LETTERS.indexOf(zoneLetter) === -1) {
throw new RangeError('zone letter out of range (must be between C and X)');
}
northern = zoneLetter >= 'N';
}
var x = easting - 500000;
var y = northing;
if (!northern) y -= 1e7;
var m = y / K0;
var mu = m / (R * M1);
var pRad = mu +
P2 * Math.sin(2 * mu) +
P3 * Math.sin(4 * mu) +
P4 * Math.sin(6 * mu) +
P5 * Math.sin(8 * mu);
var pSin = Math.sin(pRad);
var pSin2 = Math.pow(pSin, 2);
var pCos = Math.cos(pRad);
var pTan = Math.tan(pRad);
var pTan2 = Math.pow(pTan, 2);
var pTan4 = Math.pow(pTan, 4);
var epSin = 1 - E * pSin2;
var epSinSqrt = Math.sqrt(epSin);
var n = R / epSinSqrt;
var r = (1 - E) / epSin;
var c = _E * pCos * pCos;
var c2 = c * c;
var d = x / (n * K0);
var d2 = Math.pow(d, 2);
var d3 = Math.pow(d, 3);
var d4 = Math.pow(d, 4);
var d5 = Math.pow(d, 5);
var d6 = Math.pow(d, 6);
var latitude = pRad - (pTan / r) *
(d2 / 2 -
d4 / 24 * (5 + 3 * pTan2 + 10 * c - 4 * c2 - 9 * E_P2)) +
d6 / 720 * (61 + 90 * pTan2 + 298 * c + 45 * pTan4 - 252 * E_P2 - 3 * c2);
var longitude = (d -
d3 / 6 * (1 + 2 * pTan2 + c) +
d5 / 120 * (5 - 2 * c + 28 * pTan2 - 3 * c2 + 8 * E_P2 + 24 * pTan4)) / pCos;
return {
latitude: toDegrees(latitude),
longitude: toDegrees(longitude) + zoneNumberToCentralLongitude(zoneNum)
};
}
function fromLatLon(latitude, longitude, forceZoneNum) {
if (latitude > 84 || latitude < -80) {
throw new RangeError('latitude out of range (must be between 80 deg S and 84 deg N)');
}
if (longitude > 180 || longitude < -180) {
throw new RangeError('longitude out of range (must be between 180 deg W and 180 deg E)');
}
var latRad = toRadians(latitude);
var latSin = Math.sin(latRad);
var latCos = Math.cos(latRad);
var latTan = Math.tan(latRad);
var latTan2 = Math.pow(latTan, 2);
var latTan4 = Math.pow(latTan, 4);
var zoneNum;
if (forceZoneNum === undefined) {
zoneNum = latLonToZoneNumber(latitude, longitude);
} else {
zoneNum = forceZoneNum;
}
var zoneLetter = latitudeToZoneLetter(latitude);
var lonRad = toRadians(longitude);
var centralLon = zoneNumberToCentralLongitude(zoneNum);
var centralLonRad = toRadians(centralLon);
var n = R / Math.sqrt(1 - E * latSin * latSin);
var c = E_P2 * latCos * latCos;
var a = latCos * (lonRad - centralLonRad);
var a2 = Math.pow(a, 2);
var a3 = Math.pow(a, 3);
var a4 = Math.pow(a, 4);
var a5 = Math.pow(a, 5);
var a6 = Math.pow(a, 6);
var m = R * (M1 * latRad -
M2 * Math.sin(2 * latRad) +
M3 * Math.sin(4 * latRad) -
M4 * Math.sin(6 * latRad));
var easting = K0 * n * (a +
a3 / 6 * (1 - latTan2 + c) +
a5 / 120 * (5 - 18 * latTan2 + latTan4 + 72 * c - 58 * E_P2)) + 500000;
var northing = K0 * (m + n * latTan * (a2 / 2 +
a4 / 24 * (5 - latTan2 + 9 * c + 4 * c * c) +
a6 / 720 * (61 - 58 * latTan2 + latTan4 + 600 * c - 330 * E_P2)));
if (latitude < 0) northing += 1e7;
return {
easting: easting,
northing: northing,
zoneNum: zoneNum,
zoneLetter: zoneLetter
};
}
function latitudeToZoneLetter(latitude) {
if (-80 <= latitude && latitude <= 84) {
return ZONE_LETTERS[Math.floor((latitude + 80) / 8)];
} else {
return null;
}
}
function latLonToZoneNumber(latitude, longitude) {
if (56 <= latitude && latitude < 64 && 3 <= longitude && longitude < 12) return 32;
if (72 <= latitude && latitude <= 84 && longitude >= 0) {
if (longitude < 9) return 31;
if (longitude < 21) return 33;
if (longitude < 33) return 35;
if (longitude < 42) return 37;
}
return Math.floor((longitude + 180) / 6) + 1;
}
function zoneNumberToCentralLongitude(zoneNum) {
return (zoneNum - 1) * 6 - 180 + 3;
}
function toDegrees(rad) {
return rad / Math.PI * 180;
}
function toRadians(deg) {
return deg * Math.PI / 180;
}
exports.toLatLon = toLatLon;
exports.fromLatLon = fromLatLon;
+63
View File
@@ -0,0 +1,63 @@
{
"_args": [
[
"utm@1.1.1",
"/shd/CTC/TOOLS/TDS/TDS-source/Lts/Tools/ArAssetsV2"
]
],
"_development": true,
"_from": "utm@1.1.1",
"_id": "utm@1.1.1",
"_inBundle": false,
"_integrity": "sha512-rJIv6i1u86OVy91Burh/6oRFfE8zOCd6Unc8fvA0N7fjQT43ogqhVeUp5NByaZPe278QyiA5wMMEaAU9Jx6QRA==",
"_location": "/utm",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "utm@1.1.1",
"name": "utm",
"escapedName": "utm",
"rawSpec": "1.1.1",
"saveSpec": null,
"fetchSpec": "1.1.1"
},
"_requiredBy": [
"#DEV:/"
],
"_resolved": "https://registry.npmjs.org/utm/-/utm-1.1.1.tgz",
"_spec": "1.1.1",
"_where": "/shd/CTC/TOOLS/TDS/TDS-source/Lts/Tools/ArAssetsV2",
"author": {
"name": "Timothy Gu",
"email": "timothygu99@gmail.com"
},
"bugs": {
"url": "https://github.com/timothygu/utm/issues"
},
"description": "Bidirectional UTM-WGS84 converter",
"devDependencies": {
"chai": "^4.0.2",
"rollup": "^0.43.0",
"testit": "^2.1.2"
},
"homepage": "https://github.com/timothygu/utm#readme",
"jsnext:main": "index.es.js",
"keywords": [
"utm",
"latlon"
],
"license": "MIT",
"main": "index.js",
"module": "index.es.js",
"name": "utm",
"repository": {
"type": "git",
"url": "git+https://github.com/timothygu/utm.git"
},
"scripts": {
"build": "rollup -o index.js -f cjs index.es.js",
"test": "npm run build && node test.js"
},
"version": "1.1.1"
}
+244
View File
@@ -0,0 +1,244 @@
const testit = require('testit');
const { fromLatLon, toLatLon } = require('.');
const { expect } = require('chai');
// Arbitrary
const DELTA = 3e-5;
testit('normal conversions', () => {
for (const [
name,
[lat, lon],
[easting, northing, zoneNum, zoneLetter, northern]
] of [
[
'Aachen, Germany',
[50.77535, 6.08389],
[294409, 5628898, 32, 'U', true]
],
[
'New York, USA',
[40.71435, -74.00597],
[583960, 4507523, 18, 'T', true]
],
[
'Wellington, New Zealand',
[-41.28646, 174.77624],
[313784, 5427057, 60, 'G', false]
],
[
'Capetown, South Africa',
[-33.92487, 18.42406],
[261878, 6243186, 34, 'H', false]
],
[
'Mendoza, Argentina',
[-32.89018, -68.84405],
[514586, 6360877, 19, 'h', false]
],
[
'Fairbanks, Alaska, USA',
[64.83778, -147.71639],
[466013, 7190568, 6, 'W', true]
],
[
'Ben Nevis, Scotland, UK',
[56.79680, -5.00601],
[377486, 6296562, 30, 'V', true]
],
[
'Latitude 84',
[84, -5.00601],
[476594, 9328501, 30, 'X', true]
]
]) {
testit(`${name} fromLatLon`, () => {
check(fromLatLon(lat, lon));
check(fromLatLon(lat, lon, zoneNum));
function check(actual) {
expect(actual.easting).to.be.closeTo(easting, 0.5);
expect(actual.northing).to.be.closeTo(northing, 0.5);
expect(actual.zoneNum).to.equal(zoneNum);
expect(actual.zoneLetter).to.equal(zoneLetter.toUpperCase());
}
});
testit(`${name} toLatLon`, () => {
check(toLatLon(easting, northing, zoneNum, zoneLetter));
check(toLatLon(easting, northing, zoneNum, undefined, northern));
function check(actual) {
expect(actual.latitude).to.be.closeTo(lat, DELTA);
expect(actual.longitude).to.be.closeTo(lon, DELTA);
}
});
}
});
testit('range check', () => {
testit('fromLatLon bad range', () => {
for (const args of [
[-100, 0],
[-80.1, 0],
[84.1, 0],
[100, 0],
[0, -300],
[0, -180.1],
[0, 180.1],
[0, 300],
[-100, -300],
[100, -300],
[-100, 300],
[100, 300]
]) {
expect(() => fromLatLon(...args)).to.throw(RangeError);
}
});
testit('fromLatLon good range', () => {
for (const i of range(-80, 84, 0.01)) {
fromLatLon(i, 0);
}
for (const i of range(-180, 180, 0.01)) {
fromLatLon(0, i);
}
});
testit('toLatLon bad range', () => {
for (const args of [
// test easting range
[0, 5000000, 32, 'U'],
[99999, 5000000, 32, 'U'],
[1000000, 5000000, 32, 'U'],
[100000000000, 5000000, 32, 'U'],
// test northing range
[500000, -100000, 32, 'U'],
[500000, -1, 32, 'U'],
[500000, 10000001, 32, 'U'],
[500000, 50000000, 32, 'U'],
// test zone numbers
[500000, 5000000, 0, 'U'],
[500000, 5000000, 61, 'U'],
[500000, 5000000, 1000, 'U'],
// test zone letters
[500000, 5000000, 32, 'A'],
[500000, 5000000, 32, 'B'],
[500000, 5000000, 32, 'I'],
[500000, 5000000, 32, 'O'],
[500000, 5000000, 32, 'Y'],
[500000, 5000000, 32, 'Z']
]) {
expect(() => toLatLon(...args)).to.throw(RangeError);
}
});
testit('toLatLon good range', () => {
for (const i of range(100000, 999999, 1000)) {
toLatLon(i, 5000000, 32, 'U');
}
for (const i of range(10, 10000000, 1000)) {
toLatLon(500000, i, 32, 'U');
}
for (const i of range(1, 60)) {
toLatLon(500000, 5000000, i, 'U');
}
for (const i of range('C'.codePointAt(0), 'X'.codePointAt(0) + 1)) {
const ch = String.fromCodePoint(i);
if (ch !== 'I' && ch !== 'O') {
toLatLon(500000, 5000000, 32, ch);
}
}
});
});
testit('special cases', () => {
testit('zone 32', () => {
for (const [lat, lon, zoneNum, zoneLetter] of [
// inside
[56, 3, 32, 'V'],
[56, 6, 32, 'V'],
[56, 9, 32, 'V'],
[56, 11.999999, 32, 'V'],
[60, 3, 32, 'V'],
[60, 6, 32, 'V'],
[60, 9, 32, 'V'],
[60, 11.999999, 32, 'V'],
[63.999999, 3, 32, 'V'],
[63.999999, 6, 32, 'V'],
[63.999999, 9, 32, 'V'],
[63.999999, 11.999999, 32, 'V'],
// left of
[55.999999, 2.999999, 31, 'U'],
[56, 2.999999, 31, 'V'],
[60, 2.999999, 31, 'V'],
[63.999999, 2.999999, 31, 'V'],
[64, 2.999999, 31, 'W'],
// right of
[55.999999, 12, 33, 'U'],
[56, 12, 33, 'V'],
[60, 12, 33, 'V'],
[63.999999, 12, 33, 'V'],
[64, 12, 33, 'W'],
// below
[55.999999, 3, 31, 'U'],
[55.999999, 6, 32, 'U'],
[55.999999, 9, 32, 'U'],
[55.999999, 11.999999, 32, 'U'],
[55.999999, 12, 33, 'U'],
// above
[64, 3, 31, 'W'],
[64, 6, 32, 'W'],
[64, 9, 32, 'W'],
[64, 11.999999, 32, 'W'],
[64, 12, 33, 'W']
]) {
const results = fromLatLon(lat, lon);
expect(results.zoneNum).to.equal(zoneNum);
expect(results.zoneLetter).to.equal(zoneLetter.toUpperCase());
}
});
testit('right boundaries', () => {
for (const [lat, lon, zoneNum] of [
[40, 0, 31],
[40, 5.999999, 31],
[40, 6, 32],
[72, 0, 31],
[72, 5.999999, 31],
[72, 6, 31],
[72, 8.999999, 31],
[72, 9, 33]
]) {
const results = fromLatLon(lat, lon);
expect(results.zoneNum).to.equal(zoneNum);
}
});
});
function* range(start, stop, step = 1) {
if (arguments.length === 1) {
stop = start;
start = 0;
}
if (step === 0) {
throw new RangeError('step must not be zero');
}
let cur = start;
while (step > 0 ? cur < stop : cur > stop) {
yield cur;
cur += step;
}
}