Skip to content
This repository has been archived by the owner on May 17, 2021. It is now read-only.

Fixes for PointType; added distanceFrom(otherPoint) #3410

Merged
merged 1 commit into from
Nov 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ public void testDistance() {
LocationItem locationBerlin = new LocationItem("berlin");
locationBerlin.setState(pointBerlin);

DecimalType distance = locationParis.distanceFrom(pointParis);
DecimalType distance = locationParis.distanceFrom(locationParis);
assertEquals(distance.intValue(),0);

double parisBerlin = locationParis.distanceFrom(pointBerlin).doubleValue();
double parisBerlin = locationParis.distanceFrom(locationBerlin).doubleValue();
assertEquals(parisBerlin,878400,50);

double gravParis = pointParis.getGravity().doubleValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,27 +48,16 @@ public List<Class<? extends Command>> getAcceptedCommandTypes() {
}

/**
* 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 the distance from another LocationItem.
* @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));
public DecimalType distanceFrom(LocationItem awayItem) {
if (awayItem != null && awayItem.state instanceof PointType && this.state instanceof PointType) {
PointType thisPoint = (PointType)this.state;
PointType awayPoint = (PointType)awayItem.state;
return thisPoint.distanceFrom(awayPoint);
}

return new DecimalType(dist);
return new DecimalType(-1);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.lang.StringUtils;
import org.openhab.core.types.Command;
import org.openhab.core.types.ComplexType;
import org.openhab.core.types.PrimitiveType;
Expand Down Expand Up @@ -74,15 +75,18 @@ public PointType(StringType latitude, StringType longitude,
}

public PointType(String value) {
if (!value.isEmpty()) {
if (StringUtils.isNotBlank(value)) {
String[] elements = value.split(",");
if (elements.length >= 2) {
canonicalize(new DecimalType(elements[0]), new DecimalType(
elements[1]));
canonicalize(new DecimalType(elements[0]), new DecimalType(elements[1]));
if (elements.length == 3) {
setAltitude(new DecimalType(elements[2]));
}
} else {
throw new IllegalArgumentException(value + " is not a valid PointType syntax");
}
} else {
throw new IllegalArgumentException("Constructor argument must not be blank");
}
}

Expand Down Expand Up @@ -112,6 +116,25 @@ public DecimalType getGravity() {
return new DecimalType(result);
}

/**
* Return the distance in meters from otherPoint, ignoring altitude. This algorithm also
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you specify which algorithm that is being used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's based on the Haversine formula.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool, I haven't used that one before. Might be useful to update the javadoc with this info.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your question prompted me to do so. Thanks for suggesting!

* ignores the oblate spheroid shape of Earth and assumes a perfect sphere, so results
* are inexact.
*
* @param otherPoint
* @return distance in meters
* @see <a href="https://en.wikipedia.org/wiki/Haversine_formula">Haversine formula</a>
*/
public DecimalType distanceFrom(PointType otherPoint) {
double dLat = Math.toRadians(otherPoint.latitude.doubleValue() - this.latitude.doubleValue());
double dLong = Math.toRadians(otherPoint.longitude.doubleValue() - this.longitude.doubleValue());
double a = Math.pow(Math.sin(dLat / 2D), 2D) + Math.cos(Math.toRadians(this.latitude.doubleValue()))
* Math.cos(Math.toRadians(otherPoint.latitude.doubleValue()))
* Math.pow(Math.sin(dLong / 2D), 2D);
double c = 2D * Math.atan2(Math.sqrt(a), Math.sqrt(1D - a));
return new DecimalType(WGS84_a * c);
}

/**
* <p>
* Formats the value of this type according to a pattern (@see
Expand All @@ -129,13 +152,20 @@ public String format(String pattern) {
return String.format(pattern, getConstituents().values().toArray());
}

public PointType valueOf(String value) {
public static 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);
StringBuilder sb = new StringBuilder(latitude.toPlainString());
sb.append(',');
sb.append(longitude.toPlainString());
if (!altitude.equals(BigDecimal.ZERO)) {
sb.append(',');
sb.append(altitude.toPlainString());
}
return sb.toString();
}

@Override
Expand Down