-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13 from naviqore/feature/NAV-32-range-search-in-k…
…d-tree
- Loading branch information
Showing
18 changed files
with
1,154 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 0 additions & 31 deletions
31
src/main/java/ch/naviqore/gtfs/schedule/spatial/Coordinate.java
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
67 changes: 67 additions & 0 deletions
67
src/main/java/ch/naviqore/utils/spatial/CartesianCoordinate.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package ch.naviqore.utils.spatial; | ||
|
||
public class CartesianCoordinate implements Coordinate { | ||
private final double x; | ||
private final double y; | ||
|
||
public CartesianCoordinate(double x, double y) { | ||
validateCoordinate(x, y); | ||
this.x = x; | ||
this.y = y; | ||
} | ||
|
||
private static void validateCoordinate(double x, double y) { | ||
if (Double.isNaN(x) || Double.isNaN(y)) { | ||
throw new IllegalArgumentException("Coordinates cannot be NaN"); | ||
} | ||
} | ||
|
||
private void isOfSameType(Coordinate other) { | ||
if (other == null) { | ||
throw new IllegalArgumentException("Other coordinate must not be null"); | ||
} | ||
if (other.getClass() != this.getClass()) { | ||
throw new IllegalArgumentException("Other coordinate must be of type " + this.getClass().getSimpleName()); | ||
} | ||
} | ||
|
||
@Override | ||
public double getFirstComponent() { | ||
return x; | ||
} | ||
|
||
@Override | ||
public double getSecondComponent() { | ||
return y; | ||
} | ||
|
||
@Override | ||
public double distanceTo(Coordinate other) { | ||
isOfSameType(other); | ||
return distanceTo(other.getFirstComponent(), other.getSecondComponent()); | ||
} | ||
|
||
@Override | ||
public double distanceTo(double x, double y) { | ||
validateCoordinate(x, y); | ||
return Math.sqrt(Math.pow(this.x - x, 2) + Math.pow(this.y - y, 2)); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (obj == this) { | ||
return true; | ||
} | ||
if (obj == null || obj.getClass() != this.getClass()) { | ||
return false; | ||
} | ||
var that = (CartesianCoordinate) obj; | ||
return this.x == that.x && this.y == that.y; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "[" + this.getClass().getSimpleName() + ": " + x + ", " + y + "]"; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package ch.naviqore.utils.spatial; | ||
|
||
/** | ||
* This interface represents a generic 2D coordinate. Implementations of this interface should provide methods to get | ||
* the two components of the coordinate and calculate distances. | ||
*/ | ||
public interface Coordinate { | ||
|
||
/** | ||
* Examples for the first component are latitude or X coordinate. | ||
* | ||
* @return the first component of the 2D-coordinate | ||
*/ | ||
double getFirstComponent(); | ||
|
||
/** | ||
* Examples for the first component are longitude or Y coordinate. | ||
* | ||
* @return the second component of the 2D-coordinate | ||
*/ | ||
double getSecondComponent(); | ||
|
||
/** | ||
* Calculates the distance to another {@code Coordinate} object. | ||
* <p><i>Note: Implementations may raise an {@code IllegalArgumentException} if the other {@code Coordinate} object | ||
* is not of the same type.</i></p> | ||
*/ | ||
double distanceTo(Coordinate other); | ||
// TODO: Should we somehow enforce that distances between geo and cartesian coordinates cannot be calculated? | ||
|
||
/** | ||
* Calculates the distance to another point specified by its components. | ||
*/ | ||
double distanceTo(double firstComponent, double secondComponent); | ||
|
||
/** | ||
* Gets the coordinate component based on the specified {@code Axis}. | ||
*/ | ||
default double getComponent(Axis axis) { | ||
return axis == Axis.FIRST ? getFirstComponent() : getSecondComponent(); | ||
} | ||
|
||
/** | ||
* The axes of a 2D coordinate system. | ||
*/ | ||
enum Axis { | ||
FIRST, | ||
SECOND | ||
} | ||
} |
92 changes: 92 additions & 0 deletions
92
src/main/java/ch/naviqore/utils/spatial/GeoCoordinate.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package ch.naviqore.utils.spatial; | ||
|
||
public record GeoCoordinate(double latitude, double longitude) implements Coordinate, Comparable<GeoCoordinate> { | ||
|
||
private static final int EARTH_RADIUS = 6371000; | ||
|
||
public GeoCoordinate { | ||
validateCoordinate(latitude, longitude); | ||
} | ||
|
||
private static void validateCoordinate(double latitude, double longitude) { | ||
if (latitude < -90 || latitude > 90) { | ||
throw new IllegalArgumentException("Latitude must be between -90 and 90 degrees"); | ||
} | ||
if (longitude < -180 || longitude > 180) { | ||
throw new IllegalArgumentException("Longitude must be between -180 and 180 degrees"); | ||
} | ||
if (Double.isNaN(latitude) || Double.isNaN(longitude)) { | ||
throw new IllegalArgumentException("Coordinates cannot be NaN"); | ||
} | ||
} | ||
|
||
private void isOfSameType(Coordinate other) { | ||
if (other == null) { | ||
throw new IllegalArgumentException("Other coordinate must not be null"); | ||
} | ||
if (other.getClass() != this.getClass()) { | ||
throw new IllegalArgumentException("Other coordinate must be of type " + this.getClass().getSimpleName()); | ||
} | ||
} | ||
|
||
@Override | ||
public double getFirstComponent() { | ||
return latitude; | ||
} | ||
|
||
@Override | ||
public double getSecondComponent() { | ||
return longitude; | ||
} | ||
|
||
/** | ||
* Calculates the distance to another Coordinates object using the Haversine formula. | ||
* | ||
* @param other The other Coordinates object to calculate the distance to. | ||
* @return The distance in meters. | ||
*/ | ||
@Override | ||
public double distanceTo(Coordinate other) { | ||
isOfSameType(other); | ||
return distanceTo(other.getFirstComponent(), other.getSecondComponent()); | ||
} | ||
|
||
@Override | ||
public double distanceTo(double firstComponent, double secondComponent) { | ||
validateCoordinate(firstComponent, secondComponent); | ||
|
||
double lat1 = Math.toRadians(this.latitude); | ||
double lat2 = Math.toRadians(firstComponent); | ||
double lon1 = Math.toRadians(this.longitude); | ||
double lon2 = Math.toRadians(secondComponent); | ||
|
||
double dLat = lat2 - lat1; | ||
double dLon = lon2 - lon1; | ||
|
||
double a = Math.pow(Math.sin(dLat / 2), 2) + Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2); | ||
double c = 2 * Math.asin(Math.sqrt(a)); | ||
return EARTH_RADIUS * c; | ||
} | ||
|
||
@Override | ||
public int compareTo(GeoCoordinate other) { | ||
double epsilon = 1e-5; | ||
|
||
double diffLatitude = this.latitude - other.latitude(); | ||
if (Math.abs(diffLatitude) > epsilon) { | ||
return diffLatitude > 0 ? 1 : -1; | ||
} | ||
|
||
double diffLongitude = this.longitude - other.longitude(); | ||
if (Math.abs(diffLongitude) > epsilon) { | ||
return diffLongitude > 0 ? 1 : -1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "[" + this.getClass().getSimpleName() + ": " + latitude + "°, " + longitude + "°]"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package ch.naviqore.utils.spatial; | ||
|
||
/** | ||
* A location in a generic spatial coordinate system. | ||
* | ||
* @param <T> The type of the coordinates that defines this location, must extend {@code Coordinate}. | ||
*/ | ||
public interface Location<T extends Coordinate> { | ||
|
||
/** | ||
* Gets the coordinate that defines this location. | ||
*/ | ||
T getCoordinate(); | ||
|
||
} |
Oops, something went wrong.