You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by mi...@apache.org on 2020/05/16 10:46:53 UTC

[incubator-streampipes-extensions] 02/04: creating utility for distance calculation

This is an automated email from the ASF dual-hosted git repository.

micklich pushed a commit to branch feature/geodesicCalc
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes-extensions.git

commit 0754ef5ab96ae94c5fc11e2bd9ac57739a4c4271
Author: micklich <fl...@disy.net>
AuthorDate: Sat May 16 12:40:49 2020 +0200

    creating utility for distance calculation
---
 .../geo/jvm/processor/util/SpLengthCalculator.java | 198 +++++++++++++++++++++
 1 file changed, 198 insertions(+)

diff --git a/streampipes-processors-geo-jvm/src/main/java/org/apache/streampipes/processors/geo/jvm/processor/util/SpLengthCalculator.java b/streampipes-processors-geo-jvm/src/main/java/org/apache/streampipes/processors/geo/jvm/processor/util/SpLengthCalculator.java
new file mode 100644
index 0000000..61552d1
--- /dev/null
+++ b/streampipes-processors-geo-jvm/src/main/java/org/apache/streampipes/processors/geo/jvm/processor/util/SpLengthCalculator.java
@@ -0,0 +1,198 @@
+package org.apache.streampipes.processors.geo.jvm.processor.util;
+
+import si.uom.SI;
+import tec.units.ri.quantity.Quantities;
+import tec.units.ri.unit.MetricPrefix;
+
+
+//import com.github.jqudt.Quantity;
+//import com.github.jqudt.Unit;
+
+import javax.measure.Quantity;
+import javax.measure.Unit;
+import javax.measure.quantity.Length;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+
+public class SpLengthCalculator {
+
+  private final double EARTHRADIUS = 6378137; //meters
+
+  private final Unit<Length> M = SI.METRE;
+  private final Unit<Length> KM = MetricPrefix.KILO(SI.METRE);
+  private final Unit<Length> MILE = SI.METRE.multiply(1609344).divide(1000);
+  private final Unit<Length> FOOT = SI.METRE.multiply(3048).divide(10000);
+
+  public enum ValidLengthUnits {
+    METER(1), KM(2), MILE(3), FOOT(4);
+
+    private final int number;
+
+    ValidLengthUnits(int number) {
+      this.number = number;
+    }
+
+    public int getNumber() {
+      return number;
+    }
+  }
+
+
+  private Integer decimalPosition;
+  private Quantity<Length> length;
+
+  // ========================= constructor
+  public SpLengthCalculator(int decimalPosition) {
+    this.length = Quantities.getQuantity(-9999, M);
+    this.decimalPosition = decimalPosition;
+  }
+
+
+  // ========================== getter
+
+  public int getDecimalPosition() {
+    return decimalPosition;
+  }
+
+  public Double getLengthValue() {
+    return (length.getValue()).doubleValue();
+  }
+
+  public String getLengthUnit() {
+    return length.getUnit().toString();
+  }
+
+  public Unit<Length> getUnit() {
+    return length.getUnit();
+  }
+
+  public String getLengthAsString() {
+    String result = doubleToString(getLengthValue(), getDecimalPosition());
+    return result;
+  }
+
+
+  // ========================== setter
+
+  private void setLength(Quantity<Length> length) {
+    this.length = length;
+  }
+
+  private void setLength(double value, Unit<Length> unit) {
+    this.length = Quantities.getQuantity(value, unit);
+  }
+
+
+  // unit Transformation
+  /**
+   * convert  Quantity<Length>  value to Unit<Length>
+   *
+   * @param value choose target Unit<Length> from enum @see ValidLengthUnits
+   */
+  public void convertUnit(ValidLengthUnits value) {
+    switch (value.getNumber()) {
+      case 1:
+        setLength(this.length.to(M));
+        break;
+      case 2:
+        setLength(this.length.to(KM));
+        break;
+      case 3:
+        setLength(this.length.to(MILE));
+        break;
+      case 4:
+        setLength(this.length.to(FOOT));
+        break;
+    }
+  }
+
+  /**
+   * convert  Quantity<Length>  value to Unit<Length>
+   *
+   * @param value choose int value corresponding to ValidLengthUnits
+   */
+  public void convertUnit(int value) {
+    switch (value) {
+      case 1:
+        setLength(this.length.to(M));
+        break;
+      case 2:
+        setLength(this.length.to(KM));
+        break;
+      case 3:
+        setLength(this.length.to(MILE));
+        break;
+      case 4:
+        setLength(this.length.to(FOOT));
+        break;
+    }
+  }
+
+
+  /**
+   * transform the double value to a String depending on the {@link DecimalFormat} pattern.
+   * Max 10 decimal positions are defined. negative values are interpreted as 4 digits.
+   *
+   * @param value
+   * @param decimalPositions
+   * @return
+   */
+  public static String doubleToString(Double value, int decimalPositions) {
+
+    //handle negative values but should not be possible but if 3 decimal Position will be used
+    if (decimalPositions < 0) {
+      decimalPositions = 3;
+    }
+    // setup the decimal format to prevent scientific format style
+    DecimalFormat df = new DecimalFormat();
+
+    // transform the decimal
+    DecimalFormatSymbols dfs = new DecimalFormatSymbols();
+    // uses always the . instead of , for decimal separator
+    dfs.setDecimalSeparator('.');
+    df.setDecimalFormatSymbols(dfs);
+    df.setGroupingUsed(false);
+
+    // if decimal position higher than 0 is chosen, decimal Pos will be set. if negative value all
+    // calc decimal position will be used
+    if (decimalPositions >= 0) {
+      df.setMaximumFractionDigits(decimalPositions);
+    }
+
+    //writes the result into a String to parse this into the stream. Cannot be parsed as a Double Otherwise scientific style comes back
+    String result = df.format(value);
+
+    return result;
+  }
+
+
+  public void calcGeodesicDistance(double lat1, double lng1, double lat2, double lng2) {
+     // using haversine formula
+    double dLat = Math.toRadians(lat2-lat1);
+    double dLng = Math.toRadians(lng2-lng1);
+    double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
+        Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
+            Math.sin(dLng/2) * Math.sin(dLng/2);
+    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
+    float dist = (float) (EARTHRADIUS * c);
+
+    setLength(dist, M);
+  }
+
+
+
+  public void calcGeodesicDistanceNew(double lat1, double lng1, double lat2, double lng2) {
+    // using haversine formula
+    double dLat = Math.toRadians(lat2-lat1);
+    double dLng = Math.toRadians(lng2-lng1);
+    double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
+        Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
+            Math.sin(dLng/2) * Math.sin(dLng/2);
+    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
+    float dist = (float) (EARTHRADIUS * c);
+
+    setLength(dist, M);
+  }
+
+
+}