Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7cea9d6
Improvements to finding corner points in `IdCoordinateSource`.
staudtMarius Feb 21, 2024
1bbf944
Updating docs.
staudtMarius Feb 21, 2024
d218cb5
Updating docs.
staudtMarius Feb 21, 2024
a8c5c26
Merge branch 'dev' into ms/#1016-improvements-to-finding-corner-point…
staudtMarius Feb 21, 2024
6222b43
Merge branch 'dev' into ms/#1016-improvements-to-finding-corner-point…
staudtMarius Feb 23, 2024
4f2cef7
Enhancing `IdCoordinateSource` with new method.
staudtMarius Feb 23, 2024
bf29239
Merge remote-tracking branch 'origin/ms/#1016-improvements-to-finding…
staudtMarius Feb 23, 2024
9ad22b9
Merge branch 'dev' into ms/#1016-improvements-to-finding-corner-point…
staudtMarius Feb 28, 2024
0da041b
Enhancing docs.
staudtMarius Feb 28, 2024
a140934
Merge branch 'dev' into ms/#1016-improvements-to-finding-corner-point…
staudtMarius Mar 1, 2024
289aab8
Enhancing docs.
staudtMarius Mar 1, 2024
83232d1
Fix table error in docs.
staudtMarius Mar 1, 2024
d8074ba
Merge branch 'dev' into ms/#1016-improvements-to-finding-corner-point…
staudtMarius Apr 3, 2024
47bff19
Adapting to changes.
staudtMarius Apr 3, 2024
61d7fb9
Fixing `Codacy` issue.
staudtMarius Apr 4, 2024
cba1f07
Merge branch 'dev' into ms/#1016-improvements-to-finding-corner-point…
staudtMarius Apr 9, 2024
a3afad2
Merge branch 'dev' into ms/#1016-improvements-to-finding-corner-point…
staudtMarius Apr 15, 2024
dbd3575
Fixing `CHANGELOG`.
staudtMarius Apr 15, 2024
e3055e7
Merge branch 'dev' into ms/#1016-improvements-to-finding-corner-point…
staudtMarius Apr 23, 2024
f05b897
Merge branch 'dev' into ms/#1016-improvements-to-finding-corner-point…
staudtMarius Apr 25, 2024
2e69461
Merge branch 'dev' into ms/#1016-improvements-to-finding-corner-point…
danielfeismann Apr 30, 2024
41b8a79
Adapting docs.
staudtMarius May 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Removing `uuid` as required column from input and result time series [#826](https://github.com/ie3-institute/PowerSystemDataModel/issues/826)
- Removing the support for the old csv format that was marked `deprecated` back in version `1.1.0` [#795](https://github.com/ie3-institute/PowerSystemDataModel/issues/795)
- BREAKING: Updating PowerSystemUtils dependency to 2.2 [#1006](https://github.com/ie3-institute/PowerSystemDataModel/issues/1006)
- Improvements to the search for corner points in `IdCoordinateSource` [#1016](https://github.com/ie3-institute/PowerSystemDataModel/issues/1016)

## [4.1.0] - 2023-11-02

Expand Down
22 changes: 10 additions & 12 deletions docs/readthedocs/models/input/additionaldata/idcoordinatesource.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,17 @@ return less than n coordinates.


## Finding and returning the closest corner coordinates:
In most cases we need four corner coordinates for our given coordinate. Therefor the
IdCoordinateSource contains a method that will use the calculated distances to find the closest
corner coordinates for the given coordinate.
In most cases we need four corner coordinates for our given coordinate. Therefor the IdCoordinateSource contains methods
that tries to return the corner points for a given coordinate. The max. number of corner points is specified by the
implementation of the second method.

``` java
List<CoordinateDistance> restrictToBoundingBox(
Point coordinate,
Collection<CoordinateDistance> distances,
int numberOfPoints
)
List<CoordinateDistance> findCornerPoints(Point coordinate, ComparableQuantity<Length> distance)
List<CoordinateDistance> findCornerPoints(Point coordinate, Collection<CoordinateDistance> distances)
```

For a given set of coordinates, the closest four corner coordinates plus more close points if n > 4
are returned. If n < 4 the method will return the closest n corner coordinates. If the set of
coordinates contains a coordinate that matches the given coordinate, only this one coordinate is
returned. If n > number of coordinates in the set, all coordinates are returned.
1. This method can be used to return the corner points by specifying a maximum search distance.

2. If a coordinate matches the given coordinate, only this coordinate is returned. If no coordinate matches the given
coordinate, this method tries to return four corner points.

36 changes: 36 additions & 0 deletions docs/readthedocs/models/input/idcoordinate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
(idCoordinate-model)=

# IdCoordinate

Representation of an id-coordinate-pair used primarily for weather sources.

## Attributes, Units and Remarks

```{eval-rst}
.. list-table::
:widths: 33 33 33
:header-rows: 0
* - Attribute
- Unit
- Remarks
* - id
- --
- Human readable identifier
* - latitide
- --
- Latitude of the coordinate
* - longitude
- --
- Longitude of the coordinate
```

## Caveats

Nothing - at least not known.
If you found something, please contact us!
1 change: 1 addition & 0 deletions docs/readthedocs/models/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ Model classes you can use to describe a data set as input to power system simula
maxdepth: 1
---
input/operator
input/idcoordinate
```

### Grid Related Models
Expand Down
69 changes: 32 additions & 37 deletions src/main/java/edu/ie3/datamodel/io/source/IdCoordinateSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,7 @@ List<CoordinateDistance> getClosestCoordinates(

/**
* Calculates and returns the nearest n coordinate distances to the given coordinate from a given
* collection of points. If the set is empty or null an empty list is returned. If n is greater
* than four, this method will try to return the corner points of the bounding box.
* collection of points. If the set is empty or null an empty list is returned.
*
* @param coordinate the coordinate to look up the nearest neighbours for
* @param n how many neighbours to look up
Expand All @@ -95,81 +94,77 @@ List<CoordinateDistance> getClosestCoordinates(
default List<CoordinateDistance> calculateCoordinateDistances(
Point coordinate, int n, Collection<Point> coordinates) {
if (coordinates != null && !coordinates.isEmpty()) {
SortedSet<CoordinateDistance> sortedDistances =
GeoUtils.calcOrderedCoordinateDistances(coordinate, coordinates);
return restrictToBoundingBox(coordinate, sortedDistances, n);
return GeoUtils.calcOrderedCoordinateDistances(coordinate, coordinates).stream()
.limit(n)
.toList();
} else {
return Collections.emptyList();
}
}

/**
* Method for evaluating the found points. This method tries to return the four corner points of
* the bounding box of the given coordinate. If one of the found points matches the given
* coordinate, only this point is returned. If the given number of searched points is less than
* four, this method will only return the nearest n corner points. If the given number of searched
* points is greater than four, this method will return the four corner points plus the nearest n
* points to match the number of searched points.
* Method for finding the corner points of a given coordinate within a given distance.
*
* <p>The max. number of returned corner points is set by the implementation (default: 4).
*
* @param coordinate at the center
* @param distance 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)
*/
List<CoordinateDistance> findCornerPoints(Point coordinate, ComparableQuantity<Length> distance);

/**
* Method for finding the corner points of a given coordinate. If a point matches the given
* coordinate, only this point is returned.
*
* <p>The max. number of returned corner points is set by the implementation (default: 4).
*
* <p>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<CoordinateDistance> restrictToBoundingBox(
Point coordinate, Collection<CoordinateDistance> distances, int numberOfPoints) {
default List<CoordinateDistance> findCornerPoints(
Point coordinate, Collection<CoordinateDistance> coordinateDistances) {
boolean topLeft = false;
boolean topRight = false;
boolean bottomLeft = false;
boolean bottomRight = false;

List<CoordinateDistance> resultingDistances = new ArrayList<>();
List<CoordinateDistance> 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,20 +161,31 @@ public List<CoordinateDistance> getNearestCoordinates(Point coordinate, int n) {
@Override
public List<CoordinateDistance> getClosestCoordinates(
Point coordinate, int n, ComparableQuantity<Length> distance) {
Set<Point> points = coordinateToId.keySet();

Envelope envelope = GeoUtils.calculateBoundingBox(coordinate, distance);
Set<Point> reducedPoints =
points.stream()
.filter(point -> envelope.contains(point.getCoordinate()))
.collect(Collectors.toSet());
Collection<Point> reducedPoints = getCoordinatesInBoundingBox(coordinate, distance);
return calculateCoordinateDistances(coordinate, n, reducedPoints);
}

@Override
public List<CoordinateDistance> findCornerPoints(
Point coordinate, ComparableQuantity<Length> distance) {
Collection<Point> points = getCoordinatesInBoundingBox(coordinate, distance);
return findCornerPoints(
coordinate, GeoUtils.calcOrderedCoordinateDistances(coordinate, points));
}

public int getCoordinateCount() {
return idToCoordinate.keySet().size();
}

private Collection<Point> getCoordinatesInBoundingBox(
Point coordinate, ComparableQuantity<Length> distance) {
Set<Point> 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
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,25 +178,37 @@ public List<CoordinateDistance> getNearestCoordinates(Point coordinate, int n) {
@Override
public List<CoordinateDistance> getClosestCoordinates(
Point coordinate, int n, ComparableQuantity<Length> distance) {
List<Point> points = getCoordinatesInBoundingBox(coordinate, distance);
return calculateCoordinateDistances(coordinate, n, points);
}

@Override
public List<CoordinateDistance> findCornerPoints(
Point coordinate, ComparableQuantity<Length> distance) {
List<Point> points = getCoordinatesInBoundingBox(coordinate, distance);
return findCornerPoints(
coordinate, GeoUtils.calcOrderedCoordinateDistances(coordinate, points));
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

private List<Point> getCoordinatesInBoundingBox(
Point coordinate, ComparableQuantity<Length> distance) {
Envelope envelope = GeoUtils.calculateBoundingBox(coordinate, distance);

List<CoordinateValue> 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<Point> points = values.stream().map(value -> value.coordinate).toList();

return calculateCoordinateDistances(coordinate, n, points);
})
.stream()
.map(value -> value.coordinate)
.toList();
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

private CoordinateValue createCoordinateValue(Map<String, String> fieldToValues) {
fieldToValues.remove("distance");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,9 @@ class IdCoordinateSourceMock implements IdCoordinateSource {
List<CoordinateDistance> getClosestCoordinates(Point coordinate, int n, ComparableQuantity<Length> distance) {
return Collections.emptyList()
}

@Override
List<CoordinateDistance> findCornerPoints(Point coordinate, ComparableQuantity<Length> distance) {
return Collections.emptyList()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Point> points = [
point1,
Expand All @@ -36,36 +36,34 @@ 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<Point> expectedPoints = [
point1,
point2,
point4,
point5,
point6,
point8
point5
]

when:
List<CoordinateDistance> distances = coordinateSourceMock.calculateCoordinateDistances(point0, 9, points)
List<CoordinateDistance> result = coordinateSourceMock.restrictToBoundingBox(point0, distances, 4)
SortedSet<CoordinateDistance> distances = GeoUtils.calcOrderedCoordinateDistances(point0, points)
List<CoordinateDistance> result = coordinateSourceMock.findCornerPoints(point0, distances)

then:
for (CoordinateDistance value: result) {
expectedPoints.contains(value.coordinateB)
}
result.size() == expectedPoints.size()
result.collect { it.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)

when:
List<Point> withExactMatch = new ArrayList<>(points)
withExactMatch.addAll(matchingPoint)

List<CoordinateDistance> distances = coordinateSourceMock.calculateCoordinateDistances(point0, 9, withExactMatch)
List<CoordinateDistance> result = coordinateSourceMock.restrictToBoundingBox(point0, distances, 4)
SortedSet<CoordinateDistance> distances = GeoUtils.calcOrderedCoordinateDistances(point0, withExactMatch)
List<CoordinateDistance> result = coordinateSourceMock.findCornerPoints(point0, distances)

then:
result.size() == 1
Expand Down
Loading