distance);
+
+ /**
+ * Method for finding the corner points of a given coordinate. If a point matches the given
+ * coordinate, only this point is returned.
+ *
+ * The max. number of returned corner points is set by the implementation (default: 4).
*
*
To work properly, the given collection of {@link CoordinateDistance}'s should already be
* sorted by distance.
*
- * @param coordinate at the center of the bounding box
- * @param distances list of found points with their distances
- * @param numberOfPoints that should be returned
- * @return list of distances
+ * @param coordinate at the center
+ * @param coordinateDistances list of fount points with their distances
+ * @return either a list with one exact match or a list of corner points (default implementation:
+ * max. 4 points)
*/
- default List restrictToBoundingBox(
- Point coordinate, Collection distances, int numberOfPoints) {
+ default List findCornerPoints(
+ Point coordinate, Collection coordinateDistances) {
boolean topLeft = false;
boolean topRight = false;
boolean bottomLeft = false;
boolean bottomRight = false;
List resultingDistances = new ArrayList<>();
- List other = new ArrayList<>();
// search for smallest bounding box
- for (CoordinateDistance distance : distances) {
+ for (CoordinateDistance distance : coordinateDistances) {
Point point = distance.getCoordinateB();
// check for bounding box
if (coordinate.equalsExact(point, 1e-6)) {
// if current point is matching the given coordinate, we need to return only the current
// point
- resultingDistances.clear();
- resultingDistances.add(distance);
- return resultingDistances;
+ return List.of(distance);
} else if (!topLeft
- && (point.getX() < coordinate.getX() && point.getY() > coordinate.getY())) {
+ && (point.getX() <= coordinate.getX() && point.getY() >= coordinate.getY())) {
resultingDistances.add(distance);
topLeft = true;
} else if (!topRight
- && (point.getX() > coordinate.getX() && point.getY() > coordinate.getY())) {
+ && (point.getX() >= coordinate.getX() && point.getY() >= coordinate.getY())) {
resultingDistances.add(distance);
topRight = true;
} else if (!bottomLeft
- && (point.getX() < coordinate.getX() && point.getY() < coordinate.getY())) {
+ && (point.getX() <= coordinate.getX() && point.getY() <= coordinate.getY())) {
resultingDistances.add(distance);
bottomLeft = true;
} else if (!bottomRight
- && (point.getX() > coordinate.getX() && point.getY() < coordinate.getY())) {
+ && (point.getX() >= coordinate.getX() && point.getY() <= coordinate.getY())) {
resultingDistances.add(distance);
bottomRight = true;
- } else {
- other.add(distance);
}
}
- // check if n distances are found
- int diff = numberOfPoints - resultingDistances.size();
-
- if (diff > 0) {
- resultingDistances.addAll(other.stream().limit(diff).toList());
- } else if (diff < 0) {
- return resultingDistances.stream().limit(numberOfPoints).toList();
- }
-
return resultingDistances;
}
}
diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSource.java
index 7868c809e..04a1b08d9 100644
--- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSource.java
+++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSource.java
@@ -161,20 +161,31 @@ public List getNearestCoordinates(Point coordinate, int n) {
@Override
public List getClosestCoordinates(
Point coordinate, int n, ComparableQuantity distance) {
- Set points = coordinateToId.keySet();
-
- Envelope envelope = GeoUtils.calculateBoundingBox(coordinate, distance);
- Set reducedPoints =
- points.stream()
- .filter(point -> envelope.contains(point.getCoordinate()))
- .collect(Collectors.toSet());
+ Collection reducedPoints = getCoordinatesInBoundingBox(coordinate, distance);
return calculateCoordinateDistances(coordinate, n, reducedPoints);
}
+ @Override
+ public List findCornerPoints(
+ Point coordinate, ComparableQuantity distance) {
+ Collection points = getCoordinatesInBoundingBox(coordinate, distance);
+ return findCornerPoints(
+ coordinate, GeoUtils.calcOrderedCoordinateDistances(coordinate, points));
+ }
+
public int getCoordinateCount() {
return idToCoordinate.keySet().size();
}
+ private Collection getCoordinatesInBoundingBox(
+ Point coordinate, ComparableQuantity distance) {
+ Set points = coordinateToId.keySet();
+ Envelope envelope = GeoUtils.calculateBoundingBox(coordinate, distance);
+ return points.stream()
+ .filter(point -> envelope.contains(point.getCoordinate()))
+ .collect(Collectors.toSet());
+ }
+
/**
* Build a stream with mappings from field identifiers to attributes
*
diff --git a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSource.java b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSource.java
index 387039266..4424d3adf 100644
--- a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSource.java
+++ b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSource.java
@@ -178,25 +178,37 @@ public List getNearestCoordinates(Point coordinate, int n) {
@Override
public List getClosestCoordinates(
Point coordinate, int n, ComparableQuantity distance) {
+ List points = getCoordinatesInBoundingBox(coordinate, distance);
+ return calculateCoordinateDistances(coordinate, n, points);
+ }
+
+ @Override
+ public List findCornerPoints(
+ Point coordinate, ComparableQuantity distance) {
+ List points = getCoordinatesInBoundingBox(coordinate, distance);
+ return findCornerPoints(
+ coordinate, GeoUtils.calcOrderedCoordinateDistances(coordinate, points));
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+ private List getCoordinatesInBoundingBox(
+ Point coordinate, ComparableQuantity distance) {
Envelope envelope = GeoUtils.calculateBoundingBox(coordinate, distance);
- List values =
- executeQueryToList(
+ return executeQueryToList(
queryForBoundingBox,
ps -> {
ps.setDouble(1, envelope.getMinX());
ps.setDouble(2, envelope.getMinY());
ps.setDouble(3, envelope.getMaxX());
ps.setDouble(4, envelope.getMaxY());
- });
-
- List points = values.stream().map(value -> value.coordinate).toList();
-
- return calculateCoordinateDistances(coordinate, n, points);
+ })
+ .stream()
+ .map(value -> value.coordinate)
+ .toList();
}
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
private CoordinateValue createCoordinateValue(Map fieldToValues) {
fieldToValues.remove("distance");
diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/IdCoordinateSourceMock.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/IdCoordinateSourceMock.groovy
index bdbe1fea6..b6e2a909a 100644
--- a/src/test/groovy/edu/ie3/datamodel/io/source/IdCoordinateSourceMock.groovy
+++ b/src/test/groovy/edu/ie3/datamodel/io/source/IdCoordinateSourceMock.groovy
@@ -48,4 +48,9 @@ class IdCoordinateSourceMock implements IdCoordinateSource {
List getClosestCoordinates(Point coordinate, int n, ComparableQuantity distance) {
return Collections.emptyList()
}
+
+ @Override
+ List findCornerPoints(Point coordinate, ComparableQuantity distance) {
+ return Collections.emptyList()
+ }
}
diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/IdCoordinateSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/IdCoordinateSourceTest.groovy
index 833a47c48..ce336adf2 100644
--- a/src/test/groovy/edu/ie3/datamodel/io/source/IdCoordinateSourceTest.groovy
+++ b/src/test/groovy/edu/ie3/datamodel/io/source/IdCoordinateSourceTest.groovy
@@ -14,15 +14,15 @@ class IdCoordinateSourceTest extends Specification {
private final IdCoordinateSourceMock coordinateSourceMock = new IdCoordinateSourceMock()
private final Point point0 = GeoUtils.buildPoint(52.5, 7.5)
- private final Point point1 = GeoUtils.buildPoint(53, 8)
+ private final Point point1 = GeoUtils.buildPoint(53, 7.9)
private final Point point2 = GeoUtils.buildPoint(53, 7)
- private final Point point3 = GeoUtils.buildPoint(53, 6)
- private final Point point4 = GeoUtils.buildPoint(52, 8)
+ private final Point point3 = GeoUtils.buildPoint(53, 6.2)
+ private final Point point4 = GeoUtils.buildPoint(52, 7.9)
private final Point point5 = GeoUtils.buildPoint(52, 7)
- private final Point point6 = GeoUtils.buildPoint(52, 6)
- private final Point point7 = GeoUtils.buildPoint(51, 8)
+ private final Point point6 = GeoUtils.buildPoint(52, 6.2)
+ private final Point point7 = GeoUtils.buildPoint(51, 7.9)
private final Point point8 = GeoUtils.buildPoint(51, 7)
- private final Point point9 = GeoUtils.buildPoint(51, 6)
+ private final Point point9 = GeoUtils.buildPoint(51, 6.2)
private final List points = [
point1,
@@ -36,27 +36,25 @@ class IdCoordinateSourceTest extends Specification {
point9
]
- def "IdCoordinateSource should return correct number of corner points restricted to the bounding box"() {
+ def "IdCoordinateSource should return only the corner points of a collection of coordinate distances"() {
given:
List expectedPoints = [
+ point1,
point2,
point4,
- point5,
- point6,
- point8
+ point5
]
when:
- List distances = coordinateSourceMock.calculateCoordinateDistances(point0, 9, points)
- List result = coordinateSourceMock.restrictToBoundingBox(point0, distances, 4)
+ List distances = GeoUtils.calcOrderedCoordinateDistances(point0, points)
+ List result = coordinateSourceMock.findCornerPoints(point0, distances)
then:
- for (CoordinateDistance value: result) {
- expectedPoints.contains(value.coordinateB)
- }
+ result.size() == expectedPoints.size()
+ result*.coordinateB.containsAll(expectedPoints)
}
- def "IdCoordinateSource should return only one point of the bounding box if the starting coordinate exactly matched the found coordinate"() {
+ def "IdCoordinateSource should return only one point if the starting coordinate exactly matched the found coordinate"() {
given:
Point matchingPoint = GeoUtils.buildPoint(52.5, 7.5)
@@ -64,8 +62,8 @@ class IdCoordinateSourceTest extends Specification {
List withExactMatch = new ArrayList<>(points)
withExactMatch.addAll(matchingPoint)
- List distances = coordinateSourceMock.calculateCoordinateDistances(point0, 9, withExactMatch)
- List result = coordinateSourceMock.restrictToBoundingBox(point0, distances, 4)
+ List distances = GeoUtils.calcOrderedCoordinateDistances(point0, withExactMatch)
+ List result = coordinateSourceMock.findCornerPoints(point0, distances)
then:
result.size() == 1
diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSourceCosmoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSourceCosmoIT.groovy
index b878d2b28..d45e457e6 100644
--- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSourceCosmoIT.groovy
+++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSourceCosmoIT.groovy
@@ -206,4 +206,28 @@ class CsvIdCoordinateSourceCosmoIT extends Specification implements CsvTestDataM
then:
actualDistances.size() == 1
}
+
+ def "The CsvCoordinateSource will return less than four corner points if not enough points are within the given distance"() {
+ given:
+ def basePoint = GeoUtils.buildPoint(39.61, 1.38)
+ def distance = Quantities.getQuantity(10000, Units.METRE)
+
+ when:
+ def actualDistances = source.findCornerPoints(basePoint, distance)
+
+ then:
+ actualDistances.size() == 3
+ }
+
+ def "The CsvCoordinateSource will return one point if there is an exact match"() {
+ given:
+ def basePoint = GeoUtils.buildPoint(39.617162, 1.438029)
+ def distance = Quantities.getQuantity(100, Units.METRE)
+
+ when:
+ def actualDistances = source.findCornerPoints(basePoint, distance)
+
+ then:
+ actualDistances.size() == 1
+ }
}
diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSourceIconIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSourceIconIT.groovy
index 869c9d882..8a9105b00 100644
--- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSourceIconIT.groovy
+++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSourceIconIT.groovy
@@ -191,4 +191,40 @@ class CsvIdCoordinateSourceIconIT extends Specification implements CsvTestDataMe
then:
actualDistances.size() == 1
}
+
+ def "The CsvCoordinateSource will return the four corner points if enough points are within the given distance"() {
+ given:
+ def basePoint = GeoUtils.buildPoint(51.45, 7.4)
+ def distance = Quantities.getQuantity(10000, Units.METRE)
+
+ when:
+ def actualDistances = source.findCornerPoints(basePoint, distance)
+
+ then:
+ actualDistances.size() == 4
+ }
+
+ def "The CsvCoordinateSource will return less than four corner points if not enough points are within the given distance"() {
+ given:
+ def basePoint = GeoUtils.buildPoint(51.45, 7.38)
+ def distance = Quantities.getQuantity(5000, Units.METRE)
+
+ when:
+ def actualDistances = source.findCornerPoints(basePoint, distance)
+
+ then:
+ actualDistances.size() == 2
+ }
+
+ def "The CsvCoordinateSource will return one point if there is an exact match"() {
+ given:
+ def basePoint = GeoUtils.buildPoint(51.5, 7.438)
+ def distance = Quantities.getQuantity(100, Units.METRE)
+
+ when:
+ def actualDistances = source.findCornerPoints(basePoint, distance)
+
+ then:
+ actualDistances.size() == 1
+ }
}
diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSourceIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSourceIT.groovy
index 39be186ff..9678012b8 100644
--- a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSourceIT.groovy
+++ b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSourceIT.groovy
@@ -187,4 +187,40 @@ class SqlIdCoordinateSourceIT extends Specification implements TestContainerHelp
expectedValues.contains(coordinateDistance.coordinateB)
}
}
+
+ def "The CsvCoordinateSource will return the four corner points if enough points are within the given distance"() {
+ given:
+ def basePoint = GeoUtils.buildPoint(51.45, 7.4)
+ def distance = Quantities.getQuantity(10000, Units.METRE)
+
+ when:
+ def actualDistances = source.findCornerPoints(basePoint, distance)
+
+ then:
+ actualDistances.size() == 4
+ }
+
+ def "The CsvCoordinateSource will return less than four corner points if not enough points are within the given distance"() {
+ given:
+ def basePoint = GeoUtils.buildPoint(51.45, 7.38)
+ def distance = Quantities.getQuantity(5000, Units.METRE)
+
+ when:
+ def actualDistances = source.findCornerPoints(basePoint, distance)
+
+ then:
+ actualDistances.size() == 2
+ }
+
+ def "The CsvCoordinateSource will return one point if there is an exact match"() {
+ given:
+ def basePoint = GeoUtils.buildPoint(51.5, 7.438)
+ def distance = Quantities.getQuantity(100, Units.METRE)
+
+ when:
+ def actualDistances = source.findCornerPoints(basePoint, distance)
+
+ then:
+ actualDistances.size() == 1
+ }
}
diff --git a/src/test/groovy/edu/ie3/test/common/WeatherTestData.groovy b/src/test/groovy/edu/ie3/test/common/WeatherTestData.groovy
index 343af527a..2eed3c090 100644
--- a/src/test/groovy/edu/ie3/test/common/WeatherTestData.groovy
+++ b/src/test/groovy/edu/ie3/test/common/WeatherTestData.groovy
@@ -80,6 +80,11 @@ abstract class WeatherTestData {
List getClosestCoordinates(Point coordinate, int n, ComparableQuantity distance) {
throw new UnsupportedOperationException("This method is not supported!")
}
+
+ @Override
+ List findCornerPoints(Point coordinate, ComparableQuantity distance) {
+ throw new UnsupportedOperationException("This method is not supported!")
+ }
}
public static final IdCoordinateSource coordinateSource = new DummyIdCoordinateSource()