Skip to content

Commit

Permalink
Merge pull request #18 from grumlimited/0.5.3
Browse files Browse the repository at this point in the history
0.5.3
  • Loading branch information
gr211 authored Feb 24, 2018
2 parents 8b31e9b + c556627 commit ec9719b
Show file tree
Hide file tree
Showing 13 changed files with 300 additions and 509 deletions.
140 changes: 76 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ This library is being used on [www.rentbarometer.com](http://www.rentbarometer.c

This library implements in Java lots of ideas from [Movable-Type](http://www.movable-type.co.uk/scripts/latlong.html). Many thanks.

## Versions

### 0.5.3
* Changed constructors to default and private visibility
* Removed `get...()` keyword out of `EarthCalc` methods
* `EarthCalc.getDistance()` is now `EarthCalc.gcdDistance()`
* Renamed `BoundingArea.isContainedWithin(...)` to `BoundingArea.contains(...)`

## Installing

### Download
Expand Down Expand Up @@ -43,88 +51,92 @@ You will need a JDK 1.8 and maven.
<version>v0.5.2</version>
</dependency>

Please refer to [jitpack.io/#grumlimited/geocalc/0.5.2](https://jitpack.io/#grumlimited/geocalc/0.5.2) for more information
Please refer to [jitpack.io/#grumlimited/geocalc/0.5.3](https://jitpack.io/#grumlimited/geocalc/0.5.3) for more information

## Usage

### Creating a Point

//Kew, London
Coordinate lat = new DegreeCoordinate(51.4843774);
Coordinate lng = new DegreeCoordinate(-0.2912044);
Point kew = new Point(lat, lng);
Coordinate lat = Coordinate.fromDegrees(51.4843774);
Coordinate lng = Coordinate.fromDegrees(-0.2912044);
Point kew = Point.at(lat, lng);

### Converting between systems

Allows conversion of a coordinate between degrees, radians, D-M-s and GPS systems,

double radians = degreeCoordinate.getRadianCoordinate().getRadians();
double radians = degreeCoordinate.toRadianCoordinate().radians;

double minutes = degreeCoordinate.getDMSCoordinate().getMinutes();
double seconds = degreeCoordinate.getDMSCoordinate().getSeconds();
double wholeDegrees = degreeCoordinate.getDMSCoordinate().getWholeDegrees();
double minutes = degreeCoordinate.toDMSCoordinate().minutes;
double seconds = degreeCoordinate.toDMSCoordinate().seconds;
double wholeDegrees = degreeCoordinate.toDMSCoordinate().wholeDegrees;

minutes = degreeCoordinate.getGPSCoordinate().getMinutes();
seconds = degreeCoordinate.getGPSCoordinate().getSeconds(); // always 0
wholeDegrees = degreeCoordinate.getGPSCoordinate().getWholeDegrees();
minutes = degreeCoordinate.toGPSCoordinate().minutes;
seconds = degreeCoordinate.toGPSCoordinate().seconds; // always 0
wholeDegrees = degreeCoordinate.toGPSCoordinate().wholeDegrees;

back and forth

new DegreeCoordinate(-46.5456).getDMSCoordinate().getGPSCoordinate().getRadianCoordinate().decimalDegrees // getGPSCoordinate() implies loss of precision
Coordinate.fromDegrees(-46.5456)
.toDMSCoordinate()
.toGPSCoordinate()
.toRadianCoordinate()
.decimalDegrees // toGPSCoordinate() implied loss of precision

### Distance between 2 points

#### Spherical law of cosines

//Kew, London
Coordinate lat = new DegreeCoordinate(51.4843774);
Coordinate lng = new DegreeCoordinate(-0.2912044);
Point kew = new Point(lat, lng);
Coordinate lat = Coordinate.fromDegrees(51.4843774);
Coordinate lng = Coordinate.fromDegrees(-0.2912044);
Point kew = Point.at(lat, lng);

//Richmond, London
lat = new DegreeCoordinate(51.4613418);
lng = new DegreeCoordinate(-0.3035466);
Point richmond = new Point(lat, lng);
lat = Coordinate.fromDegrees(51.4613418);
lng = Coordinate.fromDegrees(-0.3035466);
Point richmond = Point.at(lat, lng);

double distance = EarthCalc.getDistance(richmond, kew); //in meters
double distance = EarthCalc.gcdDistance(richmond, kew); //in meters

#### Harvesine formula

//Kew, London
Coordinate lat = new DegreeCoordinate(51.4843774);
Coordinate lng = new DegreeCoordinate(-0.2912044);
Point kew = new Point(lat, lng);
Coordinate lat = Coordinate.fromDegrees(51.4843774);
Coordinate lng = Coordinate.fromDegrees(-0.2912044);
Point kew = Point.at(lat, lng);

//Richmond, London
lat = new DegreeCoordinate(51.4613418);
lng = new DegreeCoordinate(-0.3035466);
Point richmond = new Point(lat, lng);
lat = Coordinate.fromDegrees(51.4613418);
lng = Coordinate.fromDegrees(-0.3035466);
Point richmond = Point.at(lat, lng);

double distance = EarthCalc.getHarvesineDistance(richmond, kew); //in meters
double distance = EarthCalc.harvesineDistance(richmond, kew); //in meters

#### Vincenty formula

//Kew, London
Coordinate lat = new DegreeCoordinate(51.4843774);
Coordinate lng = new DegreeCoordinate(-0.2912044);
Point kew = new Point(lat, lng);
Coordinate lat = Coordinate.fromDegrees(51.4843774);
Coordinate lng = Coordinate.fromDegrees(-0.2912044);
Point kew = Point.at(lat, lng);

//Richmond, London
lat = new DegreeCoordinate(51.4613418);
lng = new DegreeCoordinate(-0.3035466);
Point richmond = new Point(lat, lng);
lat = Coordinate.fromDegrees(51.4613418);
lng = Coordinate.fromDegrees(-0.3035466);
Point richmond = Point.at(lat, lng);

double distance = EarthCalc.getVincentyDistance(richmond, kew); //in meters
double distance = EarthCalc.vincentyDistance(richmond, kew); //in meters


### Finding a point at 'distance in meters away' from a standpoint, given a bearing

`otherPoint` will be 1000m away from Kew

//Kew
Coordinate lat = new DegreeCoordinate(51.4843774);
Coordinate lng = new DegreeCoordinate(-0.2912044);
Point kew = new Point(lat, lng);
Coordinate lat = Coordinate.fromDegrees(51.4843774);
Coordinate lng = Coordinate.fromDegrees(-0.2912044);
Point kew = Point.at(lat, lng);

//Distance away point, bearing is 45deg
Point otherPoint = EarthCalc.pointRadialDistance(kew, 45, 1000);
Expand All @@ -139,7 +151,7 @@ other points, you need to figure out which ones are at most, say, 3000 meters aw
While this only gives an approximation, it is several order of magnitude faster
than calculating the distances from each point in the set to the reference point.

BoundingArea area = EarthCalc.getBoundingArea(kew, 3000);
BoundingArea area = EarthCalc.boundingArea(kew, 3000);
Point nw = area.getNorthWest();
Point se = area.getSouthEast();
Expand All @@ -150,58 +162,58 @@ Now, given that rectangle delimited by 'nw' and 'se', you can determine which po
Now say you have a BoundingArea,

//somewhere in Europe, not sure where ;-)
Point northEast = new Point(new DegreeCoordinate(70), new DegreeCoordinate(145));
Point southWest = new Point(new DegreeCoordinate(50), new DegreeCoordinate(110));
Point northEast = Point.at(Coordinate.fromDegrees(70), Coordinate.fromDegrees(145));
Point southWest = Point.at(Coordinate.fromDegrees(50), Coordinate.fromDegrees(110));
BoundingArea boundingArea = new BoundingArea(northEast, southWest);
you can determine whether a point is contained within that area using:

Point point1 = new Point(new DegreeCoordinate(60), new DegreeCoordinate(120));
assertTrue(boundingArea.isContainedWithin(point1)); //true
Point point1 = Point.at(Coordinate.fromDegrees(60), Coordinate.fromDegrees(120));
assertTrue(boundingArea.contains(point1)); //true

Point point2 = new Point(new DegreeCoordinate(45), new DegreeCoordinate(120));
assertFalse(boundingArea.isContainedWithin(point2)); //false
Point point2 = Point.at(Coordinate.fromDegrees(45), Coordinate.fromDegrees(120));
assertFalse(boundingArea.contains(point2)); //false

### Bearing between two points

#### Azimuth bearing - great circle path

//Kew
Coordinate lat = new DegreeCoordinate(51.4843774);
Coordinate lng = new DegreeCoordinate(-0.2912044);
Point kew = new Point(lat, lng);
Coordinate lat = Coordinate.fromDegrees(51.4843774);
Coordinate lng = Coordinate.fromDegrees(-0.2912044);
Point kew = Point.at(lat, lng);

//Richmond, London
lat = new DegreeCoordinate(51.4613418);
lng = new DegreeCoordinate(-0.3035466);
Point richmond = new Point(lat, lng);
lat = Coordinate.fromDegrees(51.4613418);
lng = Coordinate.fromDegrees(-0.3035466);
Point richmond = Point.at(lat, lng);

double bearing = EarthCalc.getBearing(kew, richmond); //in decimal degrees
double bearing = EarthCalc.bearing(kew, richmond); //in decimal degrees

#### Azimuth bearing - Vincenty formula

//Kew
Coordinate lat = new DegreeCoordinate(51.4843774);
Coordinate lng = new DegreeCoordinate(-0.2912044);
Point kew = new Point(lat, lng);
Coordinate lat = Coordinate.fromDegrees(51.4843774);
Coordinate lng = Coordinate.fromDegrees(-0.2912044);
Point kew = Point.at(lat, lng);

//Richmond, London
lat = new DegreeCoordinate(51.4613418);
lng = new DegreeCoordinate(-0.3035466);
Point richmond = new Point(lat, lng);
lat = Coordinate.fromDegrees(51.4613418);
lng = Coordinate.fromDegrees(-0.3035466);
Point richmond = Point.at(lat, lng);

double bearing = EarthCalc.getVincentyBearing(kew, richmond); //in decimal degrees
double bearing = EarthCalc.vincentyBearing(kew, richmond); //in decimal degrees

#### Final bearing - Vincenty formula

//Kew
Coordinate lat = new DegreeCoordinate(51.4843774);
Coordinate lng = new DegreeCoordinate(-0.2912044);
Point kew = new Point(lat, lng);
Coordinate lat = Coordinate.fromDegrees(51.4843774);
Coordinate lng = Coordinate.fromDegrees(-0.2912044);
Point kew = Point.at(lat, lng);

//Richmond, London
lat = new DegreeCoordinate(51.4613418);
lng = new DegreeCoordinate(-0.3035466);
Point richmond = new Point(lat, lng);
lat = Coordinate.fromDegrees(51.4613418);
lng = Coordinate.fromDegrees(-0.3035466);
Point richmond = Point.at(lat, lng);

double bearing = EarthCalc.getVincentyFinalBearing(kew, richmond); //in decimal degrees
double bearing = EarthCalc.vincentyFinalBearing(kew, richmond); //in decimal degrees
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<groupId>com.grum</groupId>
<artifactId>geocalc</artifactId>
<packaging>jar</packaging>
<version>0.5.2</version>
<version>0.5.3-SNAPSHOT</version>
<name>Geocalc</name>
<url>http://www.grumlimited.co.uk</url>

Expand Down
33 changes: 14 additions & 19 deletions src/main/java/com/grum/geocalc/BoundingArea.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,38 +32,22 @@

package com.grum.geocalc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Represents an area, defined by its top left and bottom right
* coordinates
*
* @author rgallet
*/
public class BoundingArea {
private Logger logger = LoggerFactory.getLogger(getClass());
private Point northEast, southWest;
private Point southEast, northWest;

public BoundingArea(Point northEast, Point southWest) {
this.northEast = northEast;
this.southWest = southWest;

southEast = new Point(new DegreeCoordinate(southWest.getLatitude()), new DegreeCoordinate(northEast.getLongitude()));
northWest = new Point(new DegreeCoordinate(northEast.getLatitude()), new DegreeCoordinate(southWest.getLongitude()));
}

@Deprecated
public Point getBottomRight() {
logger.debug("getBottomRight() is deprecated. Use getSouthWest() instead.");
return southWest;
}

@Deprecated
public Point getTopLeft() {
logger.debug("getTopLeft() is deprecated. Use getNorthEast() instead.");
return northEast;
southEast = Point.at(Coordinate.fromDegrees(southWest.getLatitude()), Coordinate.fromDegrees(northEast.getLongitude()));
northWest = Point.at(Coordinate.fromDegrees(northEast.getLatitude()), Coordinate.fromDegrees(southWest.getLongitude()));
}

public Point getNorthEast() {
Expand All @@ -87,7 +71,15 @@ public String toString() {
return "BoundingArea{" + "northEast=" + northEast + ", southWest=" + southWest + '}';
}

/**
* @Deprecated use contains(Point point)
*/
@Deprecated
public boolean isContainedWithin(Point point) {
return contains(point);
}

public boolean contains(Point point) {
boolean predicate1 = point.latitude >= this.southWest.latitude && point.latitude <= this.northEast.latitude;

if (!predicate1) {
Expand All @@ -114,13 +106,16 @@ public boolean equals(Object obj) {
if (obj == null) {
return false;
}

if (getClass() != obj.getClass()) {
return false;
}
final BoundingArea other = (BoundingArea) obj;

BoundingArea other = (BoundingArea) obj;
if (this.northEast != other.northEast && (this.northEast == null || !this.northEast.equals(other.northEast))) {
return false;
}

return !(this.southWest != other.southWest && (this.southWest == null || !this.southWest.equals(other.southWest)));
}

Expand Down
24 changes: 20 additions & 4 deletions src/main/java/com/grum/geocalc/Coordinate.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,23 @@ public double getValue() {
return getDecimalDegrees();
}

DMSCoordinate getDMSCoordinate() {
public static DegreeCoordinate fromDegrees(double decimalDegrees) {
return new DegreeCoordinate(decimalDegrees);
}

public static DMSCoordinate fromDMS(double wholeDegrees, double minutes, double seconds) {
return new DMSCoordinate(wholeDegrees, minutes, seconds);
}

public static GPSCoordinate fromGPS(double wholeDegrees, double minutes) {
return new GPSCoordinate(wholeDegrees, minutes);
}

public static RadianCoordinate fromRadians(double radians) {
return new RadianCoordinate(radians);
}

DMSCoordinate toDMSCoordinate() {
double _wholeDegrees = (int) getDecimalDegrees();
double remaining = abs(getDecimalDegrees() - _wholeDegrees);
double _minutes = (int) (remaining * 60);
Expand All @@ -65,19 +81,19 @@ DMSCoordinate getDMSCoordinate() {
return new DMSCoordinate(_wholeDegrees, _minutes, _seconds);
}

DegreeCoordinate getDegreeCoordinate() {
DegreeCoordinate toDegreeCoordinate() {
return new DegreeCoordinate(getDecimalDegrees());
}

GPSCoordinate getGPSCoordinate() {
GPSCoordinate toGPSCoordinate() {
double _wholeDegrees = floor(getDecimalDegrees());
double remaining = getDecimalDegrees() - _wholeDegrees;
double _minutes = floor(remaining * 60);

return new GPSCoordinate(_wholeDegrees, _minutes);
}

RadianCoordinate getRadianCoordinate() {
RadianCoordinate toRadianCoordinate() {
return new RadianCoordinate(toRadians(getDecimalDegrees()));
}
}
3 changes: 1 addition & 2 deletions src/main/java/com/grum/geocalc/DMSCoordinate.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,10 @@ public class DMSCoordinate extends Coordinate {

public final double wholeDegrees, minutes, seconds;

public DMSCoordinate(double wholeDegrees, double minutes, double seconds) {
DMSCoordinate(double wholeDegrees, double minutes, double seconds) {
this.wholeDegrees = wholeDegrees;
this.minutes = minutes;
this.seconds = seconds;

}

@Override
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/com/grum/geocalc/DegreeCoordinate.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,9 @@
*/
public class DegreeCoordinate extends Coordinate {

//degrees
final double decimalDegrees;

public DegreeCoordinate(double decimalDegrees) {
DegreeCoordinate(double decimalDegrees) {
this.decimalDegrees = decimalDegrees;
}

Expand Down
Loading

0 comments on commit ec9719b

Please sign in to comment.