/** * @author Dachande663 [dachande663@gmail.com] * @copyright Crown Copyright 2018 * @license Apache-2.0 */ import Operation from "../Operation"; import OperationError from "../errors/OperationError"; /** * HaversineDistance operation */ class HaversineDistance extends Operation { /** * HaversineDistance constructor */ constructor() { super(); this.name = "Haversine distance"; this.module = "Default"; this.description = "Returns the distance between two pairs of GPS latitude and longitude co-ordinates in metres.

e.g. 51.487263,-0.124323, 38.9517,-77.1467"; this.infoURL = "https://wikipedia.org/wiki/Haversine_formula"; this.inputType = "string"; this.outputType = "number"; this.args = []; } /** * @param {string} input * @param {Object[]} args * @returns {number} */ run(input, args) { const values = input.match(/^(-?\d+(\.\d+)?), ?(-?\d+(\.\d+)?), ?(-?\d+(\.\d+)?), ?(-?\d+(\.\d+)?)$/); if (!values) { throw new OperationError("Input must in the format lat1, lng1, lat2, lng2"); } const lat1 = parseFloat(values[1]); const lng1 = parseFloat(values[3]); const lat2 = parseFloat(values[6]); const lng2 = parseFloat(values[8]); const TO_RAD = Math.PI / 180; const dLat = (lat2-lat1) * TO_RAD; const dLng = (lng2-lng1) * TO_RAD; const a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1 * TO_RAD) * Math.cos(lat2 * TO_RAD) * Math.sin(dLng/2) * Math.sin(dLng/2); const metres = 6371000 * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); return metres; } } export default HaversineDistance;