From d68c3df1d0829142405ac38c06f230f5264c0624 Mon Sep 17 00:00:00 2001 From: John Cocula Date: Mon, 31 Aug 2015 23:17:15 +0100 Subject: [PATCH] Fixes for issue #3104 --- .../core/library/items/LocationItem.java | 147 ++++---- .../openhab/core/library/types/PointType.java | 343 +++++++++--------- 2 files changed, 250 insertions(+), 240 deletions(-) diff --git a/bundles/core/org.openhab.core.library/src/main/java/org/openhab/core/library/items/LocationItem.java b/bundles/core/org.openhab.core.library/src/main/java/org/openhab/core/library/items/LocationItem.java index 6f2cbb9c905..4e996045647 100644 --- a/bundles/core/org.openhab.core.library/src/main/java/org/openhab/core/library/items/LocationItem.java +++ b/bundles/core/org.openhab.core.library/src/main/java/org/openhab/core/library/items/LocationItem.java @@ -1,73 +1,74 @@ -/** - * Copyright (c) 2010-2015, openHAB.org and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.core.library.items; - -import java.util.ArrayList; -import java.util.List; - -import org.openhab.core.items.GenericItem; -import org.openhab.core.library.types.DecimalType; -import org.openhab.core.library.types.PointType; -import org.openhab.core.types.Command; -import org.openhab.core.types.State; -import org.openhab.core.types.UnDefType; - -/** - * A LocationItem can be used to store GPS related informations, addresses... - * This is useful for location awareness related functions - * - * @author Gaël L'hopital - * @since 1.7.0 - */ -public class LocationItem extends GenericItem { - private static List> acceptedDataTypes = new ArrayList>(); - private static List> acceptedCommandTypes = new ArrayList>(); - - static { - acceptedDataTypes.add(PointType.class); - acceptedDataTypes.add(UnDefType.class); - } - - public LocationItem(String name) { - super(name); - } - - public List> getAcceptedDataTypes() { - return acceptedDataTypes; - } - - public List> getAcceptedCommandTypes() { - return acceptedCommandTypes; - } - - /** - * Compute the distance with another Point type, - * http://stackoverflow.com/questions/837872/calculate-distance-in-meters-when-you-know-longitude-and-latitude-in-java - * @return distance between the two points in meters - */ - public DecimalType distanceFrom(PointType away){ - - double dist = -1; - - if ((away != null) && (this.state instanceof PointType)) { - - PointType me = (PointType) this.state; - - double dLat = Math.pow(Math.sin(Math.toRadians(away.getLatitude().doubleValue() - me.getLatitude().doubleValue()) / 2),2); - double dLng = Math.pow(Math.sin(Math.toRadians(away.getLongitude().doubleValue() - me.getLongitude().doubleValue()) / 2),2); - double a = dLat + Math.cos(Math.toRadians(me.getLatitude().doubleValue())) - * Math.cos(Math.toRadians(away.getLatitude().doubleValue())) * dLng; - - dist = PointType.WGS84_a * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); - } - - return new DecimalType(dist); - } - -} +/** + * Copyright (c) 2010-2015, openHAB.org and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.core.library.items; + +import java.util.ArrayList; +import java.util.List; + +import org.openhab.core.items.GenericItem; +import org.openhab.core.library.types.DecimalType; +import org.openhab.core.library.types.PointType; +import org.openhab.core.types.Command; +import org.openhab.core.types.State; +import org.openhab.core.types.UnDefType; + +/** + * A LocationItem can be used to store GPS related informations, addresses... + * This is useful for location awareness related functions + * + * @author Gaël L'hopital + * @since 1.7.0 + */ +public class LocationItem extends GenericItem { + private static List> acceptedDataTypes = new ArrayList>(); + private static List> acceptedCommandTypes = new ArrayList>(); + + static { + acceptedDataTypes.add(PointType.class); + acceptedDataTypes.add(UnDefType.class); + acceptedCommandTypes.add(PointType.class); + } + + public LocationItem(String name) { + super(name); + } + + public List> getAcceptedDataTypes() { + return acceptedDataTypes; + } + + public List> getAcceptedCommandTypes() { + return acceptedCommandTypes; + } + + /** + * Compute the distance with another Point type, + * http://stackoverflow.com/questions/837872/calculate-distance-in-meters-when-you-know-longitude-and-latitude-in-java + * @return distance between the two points in meters + */ + public DecimalType distanceFrom(PointType away){ + + double dist = -1; + + if ((away != null) && (this.state instanceof PointType)) { + + PointType me = (PointType) this.state; + + double dLat = Math.pow(Math.sin(Math.toRadians(away.getLatitude().doubleValue() - me.getLatitude().doubleValue()) / 2),2); + double dLng = Math.pow(Math.sin(Math.toRadians(away.getLongitude().doubleValue() - me.getLongitude().doubleValue()) / 2),2); + double a = dLat + Math.cos(Math.toRadians(me.getLatitude().doubleValue())) + * Math.cos(Math.toRadians(away.getLatitude().doubleValue())) * dLng; + + dist = PointType.WGS84_a * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); + } + + return new DecimalType(dist); + } + +} diff --git a/bundles/core/org.openhab.core.library/src/main/java/org/openhab/core/library/types/PointType.java b/bundles/core/org.openhab.core.library/src/main/java/org/openhab/core/library/types/PointType.java index b2c85c0581c..dd825a19e49 100644 --- a/bundles/core/org.openhab.core.library/src/main/java/org/openhab/core/library/types/PointType.java +++ b/bundles/core/org.openhab.core.library/src/main/java/org/openhab/core/library/types/PointType.java @@ -1,167 +1,176 @@ -/** - * Copyright (c) 2010-2015, openHAB.org and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.openhab.core.library.types; - -import java.math.BigDecimal; -import java.util.Formatter; -import java.util.SortedMap; -import java.util.TreeMap; - -import org.openhab.core.types.Command; -import org.openhab.core.types.ComplexType; -import org.openhab.core.types.PrimitiveType; -import org.openhab.core.types.State; - -/** - * This type can be used for items that are dealing with GPS functionality. - * - * @author Gaël L'hopital - * @since 1.7.0 - */ -public class PointType implements ComplexType, Command, State { - - public static final double EARTH_GRAVITATIONAL_CONSTANT = 3.986004418e14; - public static final double WGS84_a = 6378137; // The equatorial radius of - // WGS84 ellipsoid (6378137 - // m). - private BigDecimal latitude; // in decimal degrees - private BigDecimal longitude; // in decimal degrees - private BigDecimal altitude = BigDecimal.ZERO; // in decimal meters - // constants for the constituents - static final public String KEY_LATITUDE = "lat"; - static final public String KEY_LONGITUDE = "long"; - static final public String KEY_ALTITUDE = "alt"; - private static final BigDecimal circle = new BigDecimal(360); - private static final BigDecimal flat = new BigDecimal(180); - private static final BigDecimal right = new BigDecimal(90); - public static final PointType EMPTY = new PointType(new DecimalType(0), - new DecimalType(0)); - - public PointType(DecimalType latitude, DecimalType longitude) { - canonicalize(latitude, longitude); - } - - public PointType(DecimalType latitude, DecimalType longitude, - DecimalType altitude) { - this(latitude, longitude); - setAltitude(altitude); - } - - public PointType(StringType latitude, StringType longitude) { - this(new DecimalType(latitude.toString()), new DecimalType( - longitude.toString())); - } - - public PointType(StringType latitude, StringType longitude, - StringType altitude) { - this(new DecimalType(latitude.toString()), new DecimalType( - longitude.toString()), new DecimalType(altitude.toString())); - } - - public PointType(String value) { - if (!value.isEmpty()) { - String[] elements = value.split(","); - if (elements.length >= 2) { - canonicalize(new DecimalType(elements[0]), new DecimalType( - elements[1])); - if (elements.length == 3) { - setAltitude(new DecimalType(elements[2])); - } - } - } - } - - public DecimalType getLatitude() { - return new DecimalType(latitude); - } - - public DecimalType getLongitude() { - return new DecimalType(longitude); - } - - public DecimalType getAltitude() { - return new DecimalType(altitude); - } - - public void setAltitude(DecimalType altitude) { - this.altitude = altitude.toBigDecimal(); - } - - public DecimalType getGravity() { - double latRad = Math.toRadians(latitude.doubleValue()); - double deltaG = -2000.0 * (altitude.doubleValue() / 1000) - * EARTH_GRAVITATIONAL_CONSTANT / (Math.pow(WGS84_a, 3.0)); - double sin2lat = Math.sin(latRad) * Math.sin(latRad); - double sin22lat = Math.sin(2.0 * latRad) * Math.sin(2.0 * latRad); - double result = (9.780327 * (1.0 + 5.3024e-3 * sin2lat - 5.8e-6 * sin22lat) + deltaG); - return new DecimalType(result); - } - - /** - *

- * Formats the value of this type according to a pattern (@see - * {@link Formatter}). One single value of this type can be referenced by - * the pattern using an index. The item order is defined by the natural - * (alphabetical) order of their keys. - *

- * - * @param pattern - * the pattern to use containing indexes to reference the single - * elements of this type. - */ - @Override - public String format(String pattern) { - return String.format(pattern, getConstituents().values().toArray()); - } - - public PointType valueOf(String value) { - return new PointType(value); - } - - @Override - public String toString() { - return String.format("%1$.2f°N, %2$.2f°W, %3$.2f m", latitude, longitude, altitude); - } - - @Override - public SortedMap getConstituents() { - SortedMap result = new TreeMap(); - result.put(KEY_LATITUDE, getLatitude()); - result.put(KEY_LONGITUDE, getLongitude()); - result.put(KEY_ALTITUDE, getAltitude()); - return result; - } - - /** - * Canonicalize the current latitude and longitude values such that: - * - *
-	 * -90 <= latitude <= +90 - 180 < longitude <= +180
-	 * 
- */ - private void canonicalize(DecimalType aLat, DecimalType aLon) { - latitude = flat.add(aLat.toBigDecimal()).remainder(circle); - longitude = aLon.toBigDecimal(); - if (latitude.compareTo(BigDecimal.ZERO) == -1) - latitude.add(circle); - latitude = latitude.subtract(flat); - if (latitude.compareTo(right) == 1) { - latitude = flat.subtract(latitude); - longitude = longitude.add(flat); - } else if (latitude.compareTo(right.negate()) == -1) { - latitude = flat.negate().subtract(latitude); - longitude = longitude.add(flat); - } - longitude = flat.add(longitude).remainder(circle); - if (longitude.compareTo(BigDecimal.ZERO) <= 0) - longitude = longitude.add(circle); - longitude = longitude.subtract(flat); - } - -} +/** + * Copyright (c) 2010-2015, openHAB.org and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.openhab.core.library.types; + +import java.math.BigDecimal; +import java.util.Formatter; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.openhab.core.types.Command; +import org.openhab.core.types.ComplexType; +import org.openhab.core.types.PrimitiveType; +import org.openhab.core.types.State; + +/** + * This type can be used for items that are dealing with GPS functionality. + * + * @author Gaël L'hopital + * @since 1.7.0 + */ +public class PointType implements ComplexType, Command, State { + + public static final double EARTH_GRAVITATIONAL_CONSTANT = 3.986004418e14; + public static final double WGS84_a = 6378137; // The equatorial radius of + // WGS84 ellipsoid (6378137 + // m). + private BigDecimal latitude = BigDecimal.ZERO; // in decimal degrees + private BigDecimal longitude = BigDecimal.ZERO; // in decimal degrees + private BigDecimal altitude = BigDecimal.ZERO; // in decimal meters + // constants for the constituents + static final public String KEY_LATITUDE = "lat"; + static final public String KEY_LONGITUDE = "long"; + static final public String KEY_ALTITUDE = "alt"; + private static final BigDecimal circle = new BigDecimal(360); + private static final BigDecimal flat = new BigDecimal(180); + private static final BigDecimal right = new BigDecimal(90); + public static final PointType EMPTY = new PointType(new DecimalType(0), + new DecimalType(0)); + + /** + * Default constructor creates a point at sea level where the equator + * (0° latitude) and the prime meridian (0° longitude) intersect. (A + * nullary constructor is needed by + * {@link org.openhab.core.internal.items.ItemUpdater#receiveUpdate}) + */ + @SuppressWarnings("restriction") + public PointType() {} + + public PointType(DecimalType latitude, DecimalType longitude) { + canonicalize(latitude, longitude); + } + + public PointType(DecimalType latitude, DecimalType longitude, + DecimalType altitude) { + this(latitude, longitude); + setAltitude(altitude); + } + + public PointType(StringType latitude, StringType longitude) { + this(new DecimalType(latitude.toString()), new DecimalType( + longitude.toString())); + } + + public PointType(StringType latitude, StringType longitude, + StringType altitude) { + this(new DecimalType(latitude.toString()), new DecimalType( + longitude.toString()), new DecimalType(altitude.toString())); + } + + public PointType(String value) { + if (!value.isEmpty()) { + String[] elements = value.split(","); + if (elements.length >= 2) { + canonicalize(new DecimalType(elements[0]), new DecimalType( + elements[1])); + if (elements.length == 3) { + setAltitude(new DecimalType(elements[2])); + } + } + } + } + + public DecimalType getLatitude() { + return new DecimalType(latitude); + } + + public DecimalType getLongitude() { + return new DecimalType(longitude); + } + + public DecimalType getAltitude() { + return new DecimalType(altitude); + } + + public void setAltitude(DecimalType altitude) { + this.altitude = altitude.toBigDecimal(); + } + + public DecimalType getGravity() { + double latRad = Math.toRadians(latitude.doubleValue()); + double deltaG = -2000.0 * (altitude.doubleValue() / 1000) + * EARTH_GRAVITATIONAL_CONSTANT / (Math.pow(WGS84_a, 3.0)); + double sin2lat = Math.sin(latRad) * Math.sin(latRad); + double sin22lat = Math.sin(2.0 * latRad) * Math.sin(2.0 * latRad); + double result = (9.780327 * (1.0 + 5.3024e-3 * sin2lat - 5.8e-6 * sin22lat) + deltaG); + return new DecimalType(result); + } + + /** + *

+ * Formats the value of this type according to a pattern (@see + * {@link Formatter}). One single value of this type can be referenced by + * the pattern using an index. The item order is defined by the natural + * (alphabetical) order of their keys. + *

+ * + * @param pattern + * the pattern to use containing indexes to reference the single + * elements of this type. + */ + @Override + public String format(String pattern) { + return String.format(pattern, getConstituents().values().toArray()); + } + + public PointType valueOf(String value) { + return new PointType(value); + } + + @Override + public String toString() { + return String.format("%1$.2f°N, %2$.2f°W, %3$.2f m", latitude, longitude, altitude); + } + + @Override + public SortedMap getConstituents() { + SortedMap result = new TreeMap(); + result.put(KEY_LATITUDE, getLatitude()); + result.put(KEY_LONGITUDE, getLongitude()); + result.put(KEY_ALTITUDE, getAltitude()); + return result; + } + + /** + * Canonicalize the current latitude and longitude values such that: + * + *
+	 * -90 <= latitude <= +90 - 180 < longitude <= +180
+	 * 
+ */ + private void canonicalize(DecimalType aLat, DecimalType aLon) { + latitude = flat.add(aLat.toBigDecimal()).remainder(circle); + longitude = aLon.toBigDecimal(); + if (latitude.compareTo(BigDecimal.ZERO) == -1) + latitude.add(circle); + latitude = latitude.subtract(flat); + if (latitude.compareTo(right) == 1) { + latitude = flat.subtract(latitude); + longitude = longitude.add(flat); + } else if (latitude.compareTo(right.negate()) == -1) { + latitude = flat.negate().subtract(latitude); + longitude = longitude.add(flat); + } + longitude = flat.add(longitude).remainder(circle); + if (longitude.compareTo(BigDecimal.ZERO) <= 0) + longitude = longitude.add(circle); + longitude = longitude.subtract(flat); + } + +}