Rewrite MGRS to use new Geodesy module.

Added Ordnance Survey grid reference support
This commit is contained in:
j433866 2019-01-15 10:13:11 +00:00
parent ee360521bb
commit ad4451a757
3 changed files with 51 additions and 18 deletions

View file

@ -91,6 +91,7 @@
"esprima": "^4.0.1", "esprima": "^4.0.1",
"exif-parser": "^0.1.12", "exif-parser": "^0.1.12",
"file-saver": "^2.0.0-rc.4", "file-saver": "^2.0.0-rc.4",
"geodesy": "^1.1.3",
"highlight.js": "^9.13.1", "highlight.js": "^9.13.1",
"jquery": "^3.3.1", "jquery": "^3.3.1",
"js-crc": "^0.2.0", "js-crc": "^0.2.0",

View file

@ -7,7 +7,7 @@
*/ */
import geohash from "ngeohash"; import geohash from "ngeohash";
import mgrs from "mgrs"; import geodesy from "geodesy";
/** /**
* Co-ordinate formats * Co-ordinate formats
@ -17,7 +17,19 @@ export const FORMATS = [
"Degrees Decimal Minutes", "Degrees Decimal Minutes",
"Decimal Degrees", "Decimal Degrees",
"Geohash", "Geohash",
"Military Grid Reference System" "Military Grid Reference System",
"Ordnance Survey National Grid"
];
/**
* Formats that are made up of one string
* These formats skip bits like filtering delimiters and
* are outputted differently (only one output)
*/
export const STRING_FORMATS = [
"Geohash",
"Military Grid Reference System",
"Ordnance Survey National Grid"
]; ];
/** /**
@ -37,9 +49,22 @@ export function convertCoordinates (inLat, inLong, inFormat, outFormat, precisio
convLat = hash.latitude.toString(); convLat = hash.latitude.toString();
convLong = hash.longitude.toString(); convLong = hash.longitude.toString();
} else if (inFormat === "Military Grid Reference System") { } else if (inFormat === "Military Grid Reference System") {
const result = mgrs.toPoint(inLat.replace(" ", "")); const utm = geodesy.Mgrs.parse(inLat).toUtm();
convLat = result[1]; const result = utm.toLatLonE().toString("d", 4).replace(/[^0-9.,]/g, "");
convLong = result[0]; const splitResult = result.split(",");
if (splitResult.length === 2) {
convLat = splitResult[0];
convLong = splitResult[1];
}
} else if (inFormat === "Ordnance Survey National Grid") {
const osng = geodesy.OsGridRef.parse(inLat);
const latlon = geodesy.OsGridRef.osGridToLatLon(osng, geodesy.LatLonEllipsoidal.datum.WGS84);
const result = latlon.toString("d", 4).replace(/[^0-9.,]/g, "");
const splitResult = result.split(",");
if (splitResult.length === 2) {
convLat = splitResult[0];
convLong = splitResult[1];
}
} else { } else {
convLat = convertSingleCoordinate(inLat, inFormat, "Decimal Degrees", 15).split("°"); convLat = convertSingleCoordinate(inLat, inFormat, "Decimal Degrees", 15).split("°");
convLong = convertSingleCoordinate(inLong, inFormat, "Decimal Degrees", 15).split("°"); convLong = convertSingleCoordinate(inLong, inFormat, "Decimal Degrees", 15).split("°");
@ -49,7 +74,13 @@ export function convertCoordinates (inLat, inLong, inFormat, outFormat, precisio
if (outFormat === "Geohash") { if (outFormat === "Geohash") {
convLat = geohash.encode(parseFloat(convLat), parseFloat(convLong), precision); convLat = geohash.encode(parseFloat(convLat), parseFloat(convLong), precision);
} else if (outFormat === "Military Grid Reference System") { } else if (outFormat === "Military Grid Reference System") {
convLat = mgrs.forward([parseFloat(convLong), parseFloat(convLat)], precision); const utm = new geodesy.LatLonEllipsoidal(parseFloat(convLat), parseFloat(convLong)).toUtm();
const mgrs = utm.toMgrs();
convLat = mgrs.toString();
} else if (outFormat === "Ordnance Survey National Grid") {
const latlon = new geodesy.LatLonEllipsoidal(parseFloat(convLat), parseFloat(convLong));
const osng = geodesy.OsGridRef.latLonToOsGrid(latlon);
convLat = osng.toString();
} else { } else {
convLat = convertSingleCoordinate(convLat.toString(), "Decimal Degrees", outFormat, precision); convLat = convertSingleCoordinate(convLat.toString(), "Decimal Degrees", outFormat, precision);
convLong = convertSingleCoordinate(convLong.toString(), "Decimal Degrees", outFormat, precision); convLong = convertSingleCoordinate(convLong.toString(), "Decimal Degrees", outFormat, precision);

View file

@ -6,7 +6,7 @@
import Operation from "../Operation"; import Operation from "../Operation";
import OperationError from "../errors/OperationError"; import OperationError from "../errors/OperationError";
import {FORMATS, convertCoordinates, convertSingleCoordinate, findDelim, findFormat} from "../lib/ConvertCoordinates"; import {FORMATS, STRING_FORMATS, convertCoordinates, convertSingleCoordinate, findDelim, findFormat} from "../lib/ConvertCoordinates";
import Utils from "../Utils"; import Utils from "../Utils";
/** /**
@ -22,7 +22,7 @@ class ConvertCoordinateFormat extends Operation {
this.name = "Convert co-ordinate format"; this.name = "Convert co-ordinate format";
this.module = "Hashing"; this.module = "Hashing";
this.description = "Convert geographical coordinates between different formats.<br><br>Supported formats:<ul><li>Degrees Minutes Seconds (DMS)</li><li>Degrees Decimal Minutes (DDM)</li><li>Decimal Degrees (DD)</li><li>Geohash</li><li>Military Grid Reference System (MGRS)</li></ul>"; this.description = "Convert geographical coordinates between different formats.<br><br>Supported formats:<ul><li>Degrees Minutes Seconds (DMS)</li><li>Degrees Decimal Minutes (DDM)</li><li>Decimal Degrees (DD)</li><li>Geohash</li><li>Military Grid Reference System (MGRS)</li><li>Ordnance Survey National Grid (OSNG)</li></ul>";
this.infoURL = "https://wikipedia.org/wiki/Geographic_coordinate_conversion"; this.infoURL = "https://wikipedia.org/wiki/Geographic_coordinate_conversion";
this.inputType = "string"; this.inputType = "string";
this.outputType = "string"; this.outputType = "string";
@ -107,14 +107,14 @@ class ConvertCoordinateFormat extends Operation {
} }
} }
if (inDelim === "" && (inFormat !== "Geohash" && inFormat !== "Military Grid Reference System")) { if (inDelim === "" && (!STRING_FORMATS.includes(inFormat))) {
throw new OperationError("Could not automatically detect the input delimiter."); throw new OperationError("Could not automatically detect the input delimiter.");
} }
// Prepare input data // Prepare input data
if (inFormat === "Geohash" || inFormat === "Military Grid Reference System") { if (STRING_FORMATS.includes(inFormat)) {
// Geohash only has one value, so just use the input // Geohash only has one value, so just use the input
// Replace anything that isn't a valid character in Geohash / MGRS // Replace anything that isn't a valid character in Geohash / MGRS / OSNG
inLat = input.replace(/[^A-Za-z0-9]/, ""); inLat = input.replace(/[^A-Za-z0-9]/, "");
} else if (inDelim === "Direction Preceding") { } else if (inDelim === "Direction Preceding") {
// Split on the compass directions // Split on the compass directions
@ -152,7 +152,7 @@ class ConvertCoordinateFormat extends Operation {
} }
} }
if (inFormat !== "Geohash" && inFormat !== "Military Grid Reference System" && outDelim.includes("Direction")) { if (!STRING_FORMATS.includes(inFormat) && outDelim.includes("Direction")) {
// Match on compass directions, and store the first 2 matches for the output // Match on compass directions, and store the first 2 matches for the output
const dir = input.match(/[NnEeSsWw]/g); const dir = input.match(/[NnEeSsWw]/g);
if (dir !== null) { if (dir !== null) {
@ -173,14 +173,15 @@ class ConvertCoordinateFormat extends Operation {
// Convert the co-ordinates // Convert the co-ordinates
if (inLat !== undefined) { if (inLat !== undefined) {
if (inLong === undefined) { if (inLong === undefined) {
if (inFormat !== "Geohash" && inFormat !== "Military Grid Reference System") { if (!STRING_FORMATS.includes(inFormat)) {
if (outFormat === "Geohash" || outFormat === "Military Grid Reference System"){ if (STRING_FORMATS.includes(outFormat)){
throw new OperationError(`${outFormat} needs both a latitude and a longitude to be calculated`); throw new OperationError(`${outFormat} needs both a latitude and a longitude to be calculated`);
} }
} }
if (inFormat === "Geohash" || inFormat === "Military Grid Reference System") { if (STRING_FORMATS.includes(inFormat)) {
// Geohash conversion is in convertCoordinates despite needing // Geohash conversion is in convertCoordinates despite needing
// only one input as it needs to output two values // only one input as it needs to output two values
inLat = inLat.replace(/[^A-Za-z0-9]/g, "");
[outLat, outLong] = convertCoordinates(inLat, inLat, inFormat, outFormat, precision); [outLat, outLong] = convertCoordinates(inLat, inLat, inFormat, outFormat, precision);
} else { } else {
outLat = convertSingleCoordinate(inLat, inFormat, outFormat, precision); outLat = convertSingleCoordinate(inLat, inFormat, outFormat, precision);
@ -195,16 +196,16 @@ class ConvertCoordinateFormat extends Operation {
// Output conversion results if successful // Output conversion results if successful
if (outLat !== undefined) { if (outLat !== undefined) {
let output = ""; let output = "";
if (outDelim === "Direction Preceding" && outFormat !== "Geohash" && outFormat !== "Military Grid Reference System") { if (outDelim === "Direction Preceding" && !STRING_FORMATS.includes(outFormat)) {
output += latDir += " "; output += latDir += " ";
} }
output += outLat; output += outLat;
if (outDelim === "Direction Following" && outFormat !== "Geohash" && outFormat !== "Military Grid Reference System") { if (outDelim === "Direction Following" && !STRING_FORMATS.includes(outFormat)) {
output += " " + latDir; output += " " + latDir;
} }
output += outSeparator; output += outSeparator;
if (outLong !== undefined && outFormat !== "Geohash" && outFormat !== "Military Grid Reference System") { if (outLong !== undefined && !STRING_FORMATS.includes(outFormat)) {
if (outDelim === "Direction Preceding") { if (outDelim === "Direction Preceding") {
output += longDir + " "; output += longDir + " ";
} }