Browse Source

Merge branch 'Dachande663-operation-haversine' into esm

n1474335 7 năm trước cách đây
mục cha
commit
bd34f6bb6d

+ 1 - 0
src/core/config/Categories.json

@@ -328,6 +328,7 @@
             "Generate UUID",
             "Generate TOTP",
             "Generate HOTP",
+            "Haversine distance",
             "Render Image",
             "Remove EXIF",
             "Extract EXIF",

+ 58 - 0
src/core/operations/HaversineDistance.mjs

@@ -0,0 +1,58 @@
+/**
+ * @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.<br><br>e.g. <code>51.487263,-0.124323, 38.9517,-77.1467</code>";
+        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;

+ 1 - 0
test/index.mjs

@@ -44,6 +44,7 @@ import "./tests/operations/ConditionalJump";
 import "./tests/operations/Register";
 import "./tests/operations/Comment";
 import "./tests/operations/Hash";
+import "./tests/operations/HaversineDistance";
 import "./tests/operations/Hexdump";
 import "./tests/operations/Image";
 import "./tests/operations/MorseCode";

+ 22 - 0
test/tests/operations/HaversineDistance.mjs

@@ -0,0 +1,22 @@
+/**
+ * Haversine distance tests.
+ *
+ * @author Dachande663 [dachande663@gmail.com]
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+import TestRegister from "../../TestRegister";
+
+TestRegister.addTests([
+    {
+        name: "Haversine distance",
+        input: "51.487263,-0.124323, 38.9517,-77.1467",
+        expectedOutput: "5619355.701829259",
+        recipeConfig: [
+            {
+                "op": "Haversine distance",
+                "args": []
+            }
+        ],
+    }
+]);