From 92679aa6fd5bef4b68c3fe18eb34f3af3cd49cbb Mon Sep 17 00:00:00 2001 From: James Melville Date: Sun, 13 Feb 2022 09:01:21 +0000 Subject: [PATCH] Add bearingTo method for PointType (#2757) Signed-off-by: James Melville --- .../openhab/core/library/types/PointType.java | 18 ++++++++++ .../core/library/types/PointTypeTest.java | 33 +++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/library/types/PointType.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/library/types/PointType.java index ab39a42c6..5ec15c926 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/library/types/PointType.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/library/types/PointType.java @@ -128,6 +128,24 @@ public class PointType implements ComplexType, Command, State { return new DecimalType(result); } + /** + * Return the bearing in degrees from otherPoint following a great circle path. + * + * @param otherPoint + * @return bearing in degrees + * @see Calculate distance, bearing and more between + * Latitude/Longitude points + */ + public DecimalType bearingTo(PointType otherPoint) { + double y = Math.sin(otherPoint.longitude.doubleValue() - this.longitude.doubleValue()) + * Math.cos(otherPoint.latitude.doubleValue()); + double x = Math.cos(this.latitude.doubleValue()) * Math.sin(otherPoint.latitude.doubleValue()) + - Math.sin(this.latitude.doubleValue()) * Math.cos(otherPoint.latitude.doubleValue()) + * Math.cos(otherPoint.longitude.doubleValue() - this.longitude.doubleValue()); + double deg = (Math.atan2(y, x) * 180 / Math.PI + 360) % 360; + return new DecimalType(deg); + } + /** * Return the distance in meters from otherPoint, ignoring altitude. This algorithm also * ignores the oblate spheroid shape of Earth and assumes a perfect sphere, so results diff --git a/bundles/org.openhab.core/src/test/java/org/openhab/core/library/types/PointTypeTest.java b/bundles/org.openhab.core/src/test/java/org/openhab/core/library/types/PointTypeTest.java index 2f944a723..a1f3c4277 100644 --- a/bundles/org.openhab.core/src/test/java/org/openhab/core/library/types/PointTypeTest.java +++ b/bundles/org.openhab.core/src/test/java/org/openhab/core/library/types/PointTypeTest.java @@ -96,13 +96,16 @@ public class PointTypeTest { } @Test - public void testDistance() { + public void testDefaultConstructor() { // Ensure presence of default constructor PointType middleOfTheOcean = new PointType(); assertEquals(0, middleOfTheOcean.getLongitude().doubleValue(), 0.0000001); assertEquals(0, middleOfTheOcean.getLatitude().doubleValue(), 0.0000001); assertEquals(0, middleOfTheOcean.getAltitude().doubleValue(), 0.0000001); + } + @Test + public void testGravity() { PointType pointParis = PointType.valueOf("48.8566140,2.3522219"); assertEquals(2.3522219, pointParis.getLongitude().doubleValue(), 0.0000001); @@ -110,8 +113,10 @@ public class PointTypeTest { double gravParis = pointParis.getGravity().doubleValue(); assertEquals(gravParis, 9.809, 0.001); + } - // Check canonization of position + @Test + public void testCanonicalization() { PointType point3 = PointType.valueOf("-100,200"); double lat3 = point3.getLatitude().doubleValue(); double lon3 = point3.getLongitude().doubleValue(); @@ -119,7 +124,10 @@ public class PointTypeTest { assertTrue(lat3 < 90); assertTrue(lon3 < 180); assertTrue(lon3 > -180); + } + @Test + public void testConstructorToString() { PointType pointTest1 = new PointType("48.8566140,2.3522219,118"); PointType pointTest2 = new PointType(pointTest1.toString()); assertEquals(pointTest1.getAltitude().longValue(), pointTest2.getAltitude().longValue()); @@ -128,6 +136,27 @@ public class PointTypeTest { // Ensure that constructor and toString are consistent // https://bugs.eclipse.org/bugs/show_bug.cgi?id=467612#c17 + PointType point3 = PointType.valueOf("-100,200"); assertTrue(point3.equals(PointType.valueOf(point3.toString()))); } + + @Test + public void testDistance() { + PointType pointParis = PointType.valueOf("48.8566140,2.3522219"); + PointType greenwich = PointType.valueOf("51.477338,0.0"); + + assertEquals(336474.0, pointParis.distanceFrom(greenwich).doubleValue(), 1); + } + + @Test + public void testBearing() { + PointType middleOfTheOcean = PointType.valueOf("0.0,0.0"); + PointType greenwich = PointType.valueOf("51.477338,0.0"); + PointType mudchute = PointType.valueOf("51.492148,-0.012126"); + + assertEquals(0.0, middleOfTheOcean.bearingTo(greenwich).doubleValue()); + assertEquals(180, greenwich.bearingTo(middleOfTheOcean).doubleValue()); + assertEquals(344.0, greenwich.bearingTo(mudchute).doubleValue(), 1); + assertEquals(164.0, mudchute.bearingTo(greenwich).doubleValue(), 1); + } }