-
Notifications
You must be signed in to change notification settings - Fork 7
SQL source for weather coordinates using PostGIS #694
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
sebastian-peter
merged 74 commits into
dev
from
ms/#689-improving-implementation-of-ÍdCoordinateSource
May 16, 2023
The head ref may contain hidden characters: "ms/#689-improving-implementation-of-\u00CDdCoordinateSource"
Merged
Changes from 6 commits
Commits
Show all changes
74 commits
Select commit
Hold shift + click to select a range
22a6fee
Improving implementation of idCoordinateSource.
staudtMarius 116d351
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius acf9a5d
Improving code.
staudtMarius e424f0d
Merge remote-tracking branch 'origin/ms/#689-improving-implementation…
staudtMarius 6e8025c
fmt
staudtMarius d879543
Adding some documentation.
staudtMarius a2d2faf
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius d4d3156
Implementing some tests.
staudtMarius 00c21f2
Adding missing file for SqlIdCoordinateSource test.
staudtMarius a19ff9f
fmt
staudtMarius 354fc4a
fmt
staudtMarius 9b59372
fmt
staudtMarius 344d6fb
Some refactoring.
staudtMarius 2644931
Implementing changes in CsvIdCoordinateSource.
staudtMarius c83873b
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius f0ca780
Adding some tests.
staudtMarius 529bee2
Adding requested changes.
staudtMarius 9613ba9
Adding requested changes.
staudtMarius 42ff465
``SqlIdCoordinateSource`` uses ``PostGis`` now.
staudtMarius 975fa09
Fixing test problems.
staudtMarius d196187
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius c98ed65
Implementing requested changes.
staudtMarius 69b58f4
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius 44d1f70
Fixing ``Codacy`` error.
staudtMarius e3f5fee
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius 46476de
Updating code to use new method of ``PSU``.
staudtMarius ab993c2
Merge remote-tracking branch 'origin/ms/#689-improving-implementation…
staudtMarius d359718
Updating code to use new method of ``PSU``.
staudtMarius c7fa204
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
sebastian-peter ca6a2f7
Implementing requested changes.
staudtMarius c6768ec
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius 6c2c789
fmt
staudtMarius fbcfed4
Fixing failing test.
staudtMarius 613ce64
Improving IdCoordinateSource documentation
staudtMarius f9b8c2f
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius cd0993b
Fixing failing test.
staudtMarius 4070b13
fmt
staudtMarius aac4301
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
sebastian-peter f956731
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
sebastian-peter b4bd815
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius e5e5d15
Improving documentation.
staudtMarius e6860e4
Adding markdown support to docs.
staudtMarius 7e0dc92
Fix conf.py
staudtMarius b46a15a
Fixing markdown table rendering.
staudtMarius 9732383
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius 54d6e45
Merging `dev` changes.
staudtMarius f3ed621
Fixing ``readthedoc``.
staudtMarius 2dbb6e2
Fixing ``readthedoc``.
staudtMarius 34faee4
Fixing ``readthedoc``.
staudtMarius 76d9f49
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius b7cee23
Some documentation improvements.
staudtMarius b6c2029
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius bf23b8c
Resolving sonatype issues.
staudtMarius b0a0ec2
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius eaa51f0
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius d873354
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius b93afed
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius 45d10ab
Implementing requested changes.
staudtMarius 71e02e3
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius bc1c713
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius 5e19cd6
fmt
staudtMarius 13bbc45
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius a3455c0
Indentation
sebastian-peter 377cc32
Updating readthedocs online build config
sebastian-peter cabc9f0
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius 64f17b3
Implementing requested changes.
staudtMarius 6885b36
Fixing documentation issues.
staudtMarius 5f124b0
Fixing documentation issues.
staudtMarius 78e3aa2
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius 85ae7f0
Implementing requested documentation changes.
staudtMarius 6841c3e
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius ee15cf3
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius 3a1142c
Implementing requested changes.
staudtMarius 7e9c6e6
fmt
staudtMarius File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
315 changes: 315 additions & 0 deletions
315
src/main/java/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSource.java
This file contains hidden or 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,315 @@ | ||
| /* | ||
| * © 2022. TU Dortmund University, | ||
| * Institute of Energy Systems, Energy Efficiency and Energy Economics, | ||
| * Research group Distribution grid planning and operation | ||
| */ | ||
| package edu.ie3.datamodel.io.source.sql; | ||
|
|
||
| import edu.ie3.datamodel.io.connectors.SqlConnector; | ||
| import edu.ie3.datamodel.io.factory.SimpleFactoryData; | ||
| import edu.ie3.datamodel.io.factory.timeseries.IdCoordinateFactory; | ||
| import edu.ie3.datamodel.io.source.IdCoordinateSource; | ||
| import edu.ie3.datamodel.models.value.CoordinateValue; | ||
| import edu.ie3.util.geo.CoordinateDistance; | ||
| import java.sql.Array; | ||
| import java.util.*; | ||
| import org.apache.commons.lang3.tuple.Pair; | ||
| import org.locationtech.jts.geom.Point; | ||
|
|
||
| /** SQL source for coordinate data */ | ||
| public class SqlIdCoordinateSource extends SqlDataSource<CoordinateValue> | ||
| implements IdCoordinateSource { | ||
| private static final String WHERE = " WHERE "; | ||
| private final IdCoordinateFactory factory; | ||
| private final double maxDistance; | ||
| private static final double earthRadius = 6378137.0; | ||
staudtMarius marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| /** | ||
| * Queries that are available within this source. Motivation to have them as field value is to | ||
| * avoid creating a new string each time, bc they're always the same. | ||
| */ | ||
| private final String basicQuery; | ||
|
|
||
| private final String queryForPoint; | ||
| private final String queryForId; | ||
| private final String queryForBoundingBox; | ||
|
|
||
| /** | ||
| * Initializes a new SqlIdCoordinateSource | ||
| * | ||
| * @param connector the connector needed for the database connection | ||
| * @param schemaName the database schema to use | ||
| * @param coordinateTableName the name of the table containing coordinate data | ||
| * @param factory instance of a coordinate factory | ||
| * @param maxDistance maximal search distance for points | ||
| */ | ||
| public SqlIdCoordinateSource( | ||
| SqlConnector connector, | ||
| String schemaName, | ||
| String coordinateTableName, | ||
| IdCoordinateFactory factory, | ||
| double maxDistance) { | ||
| super(connector); | ||
|
|
||
| this.factory = factory; | ||
| this.maxDistance = maxDistance; | ||
|
|
||
| String dbIdColumnName = getDbColumnName(factory.getIdField(), coordinateTableName); | ||
| String dbLatitudeColumnName = getDbColumnName(factory.getLatField(), coordinateTableName); | ||
| String dbLongitudeColumnName = getDbColumnName(factory.getLonField(), coordinateTableName); | ||
|
|
||
| // setup queries | ||
| this.basicQuery = "SELECT * FROM " + schemaName + ".\"" + coordinateTableName + " ?;"; | ||
staudtMarius marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| this.queryForPoint = createQueryForPoint(schemaName, coordinateTableName, dbIdColumnName); | ||
| this.queryForId = | ||
| createQueryForId( | ||
| schemaName, coordinateTableName, dbLatitudeColumnName, dbLongitudeColumnName); | ||
| this.queryForBoundingBox = | ||
| createQueryForBoundingBox( | ||
| schemaName, coordinateTableName, dbLatitudeColumnName, dbLongitudeColumnName); | ||
| } | ||
|
|
||
| @Override | ||
| protected Optional<CoordinateValue> createEntity(Map<String, String> fieldToValues) { | ||
| SimpleFactoryData factoryData = new SimpleFactoryData(fieldToValues, Pair.class); | ||
| Optional<Pair<Integer, Point>> option = factory.get(factoryData); | ||
|
|
||
| if (option.isEmpty()) return Optional.empty(); | ||
|
|
||
| Pair<Integer, Point> data = option.get(); | ||
|
|
||
| return Optional.of(new CoordinateValue(data.getKey(), data.getValue())); | ||
| } | ||
|
|
||
| @Override | ||
| public Optional<Point> getCoordinate(int id) { | ||
| List<CoordinateValue> values = executeQuery(queryForPoint, ps -> ps.setInt(1, id)); | ||
|
|
||
| return Optional.of(values.get(0).coordinate); | ||
staudtMarius marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| @Override | ||
| public Collection<Point> getCoordinates(int... ids) { | ||
| Object[] idSet = Arrays.asList(ids, ids.length).toArray(); | ||
|
|
||
| List<CoordinateValue> values = | ||
| executeQuery( | ||
| queryForPoint, | ||
| ps -> { | ||
| Array sqlArray = ps.getConnection().createArrayOf("integer", idSet); | ||
| ps.setArray(1, sqlArray); | ||
| }); | ||
|
|
||
| List<Point> points = new ArrayList<>(); | ||
|
|
||
| for (CoordinateValue value : values) { | ||
| points.add(value.coordinate); | ||
| } | ||
|
|
||
| return points; | ||
staudtMarius marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| @Override | ||
| public Optional<Integer> getId(Point coordinate) { | ||
| double latitude = coordinate.getY(); | ||
| double longitude = coordinate.getX(); | ||
|
|
||
| List<CoordinateValue> values = | ||
| executeQuery( | ||
| queryForId, | ||
| ps -> { | ||
| ps.setDouble(1, latitude); | ||
| ps.setDouble(2, longitude); | ||
| }); | ||
|
|
||
| return Optional.of(values.get(0).id); | ||
| } | ||
|
|
||
| @Override | ||
| public Collection<Point> getAllCoordinates() { | ||
| List<CoordinateValue> values = executeQuery(basicQuery, ps -> ps.setString(1, ";")); | ||
staudtMarius marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ArrayList<Point> points = new ArrayList<>(); | ||
|
|
||
| for (CoordinateValue value : values) { | ||
| points.add(value.coordinate); | ||
| } | ||
|
|
||
| return points; | ||
| } | ||
|
|
||
| @Override | ||
| public List<CoordinateDistance> getNearestCoordinates(Point coordinate, int n) { | ||
| double[] xyDeltas = calculateXYDelta(coordinate); | ||
|
|
||
| double longitude = coordinate.getX(); | ||
| double latitude = coordinate.getY(); | ||
|
|
||
| List<CoordinateValue> values = | ||
| executeQuery( | ||
| queryForBoundingBox, | ||
| ps -> { | ||
| ps.setDouble(1, longitude - xyDeltas[0]); | ||
| ps.setDouble(2, longitude + xyDeltas[0]); | ||
| ps.setDouble(3, latitude - xyDeltas[1]); | ||
| ps.setDouble(4, latitude + xyDeltas[1]); | ||
| }); | ||
|
|
||
| ArrayList<Point> points = new ArrayList<>(); | ||
|
|
||
| for (CoordinateValue value : values) { | ||
| points.add(value.coordinate); | ||
| } | ||
|
|
||
| List<CoordinateDistance> distances = getNearestCoordinates(coordinate, 2 * n, points); | ||
|
|
||
| return checkForBoundingBox(coordinate, distances, n); | ||
| } | ||
|
|
||
| @Override | ||
| public List<CoordinateDistance> getNearestCoordinates( | ||
staudtMarius marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Point coordinate, int n, Collection<Point> coordinates) { | ||
| return IdCoordinateSource.super.getNearestCoordinates(coordinate, n, coordinates); | ||
| } | ||
|
|
||
| /** | ||
| * Method for evaluating the found points and returning the n corner points of the bounding box. | ||
| * | ||
| * @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 | ||
| */ | ||
| private List<CoordinateDistance> checkForBoundingBox( | ||
staudtMarius marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Point coordinate, List<CoordinateDistance> distances, int numberOfPoints) { | ||
| 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) { | ||
| Point point = distance.getCoordinateB(); | ||
|
|
||
| // check for bounding box | ||
| if (!topLeft && (point.getX() < coordinate.getX() && point.getY() > coordinate.getY())) { | ||
| resultingDistances.add(distance); | ||
| topLeft = true; | ||
| } else if (!topRight | ||
| && (point.getX() > coordinate.getX() && point.getY() > coordinate.getY())) { | ||
| resultingDistances.add(distance); | ||
| topRight = true; | ||
| } else if (!bottomLeft | ||
| && (point.getX() < coordinate.getX() && point.getY() < coordinate.getY())) { | ||
| resultingDistances.add(distance); | ||
| bottomLeft = true; | ||
| } else if (!bottomRight | ||
| && (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; | ||
| } | ||
|
|
||
| /** | ||
| * Method to calculate a bounding box around a point with a defined radius. | ||
| * | ||
| * @param coordinate the coordinate at the center of the bounding box. | ||
| * @return x- and y-delta | ||
| */ | ||
| private double[] calculateXYDelta(Point coordinate) { | ||
staudtMarius marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // calculate y-delta | ||
| double deltaY = maxDistance / earthRadius; | ||
|
|
||
| // calculate some functions | ||
| double sinus = Math.sin(deltaY / 2); | ||
| double squaredSinus = sinus * sinus; | ||
|
|
||
| double cosine = Math.cos(Math.toRadians(coordinate.getY())); | ||
| double squaredCosine = cosine * cosine; | ||
|
|
||
| // calculate x-delta | ||
| double deltaX = 2 * Math.asin(Math.sqrt(squaredSinus / squaredCosine)); | ||
|
|
||
| return new double[] {deltaX, deltaY}; | ||
| } | ||
|
|
||
| /** | ||
| * Creates a basic query to retrieve an entry for a given id with the following pattern: <br> | ||
| * {@code <base query> WHERE <id column>=?;} | ||
| * | ||
| * @param schemaName the name of the database schema | ||
| * @param coordinateTableName the name of the database table | ||
| * @param idColumn the name of the column holding the id info | ||
| * @return the query string | ||
| */ | ||
| private String createQueryForPoint( | ||
| String schemaName, String coordinateTableName, String idColumn) { | ||
| return createBaseQueryString(schemaName, coordinateTableName) + WHERE + idColumn + " =?; "; | ||
| } | ||
|
|
||
| /** | ||
| * Creates a basic query to retrieve an id for a given point with the following pattern: <br> | ||
| * {@code <base query> WHERE <latitude column>=? AND <longitude column>=?;} | ||
staudtMarius marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| * | ||
| * @param schemaName the name of the database schema | ||
| * @param coordinateTableName the name of the database table | ||
| * @param latitudeColumnName the name of the latitude column | ||
| * @param longitudeColumnName the name of the longitude column | ||
| * @return the query string | ||
| */ | ||
| private String createQueryForId( | ||
| String schemaName, | ||
| String coordinateTableName, | ||
| String latitudeColumnName, | ||
| String longitudeColumnName) { | ||
| return createBaseQueryString(schemaName, coordinateTableName) | ||
| + WHERE | ||
| + latitudeColumnName | ||
| + " =? AND " | ||
| + longitudeColumnName | ||
| + " =?; "; | ||
| } | ||
|
|
||
| /** | ||
| * Creates a basic query to retrieve all entries in a given box. The box is defines by a latitude | ||
| * interval and a longitude interval. The pattern looks like this: <br> | ||
| * {@code <base query> WHERE <latitude column> BETWEEN ? AND ? AND <longitude column> BETWEEN ? | ||
| * AND ?;} | ||
| * | ||
| * @param schemaName the name of the database | ||
| * @param coordinateTableName the name of the database table | ||
| * @param longitudeColumnName the name of the second column | ||
| * @param latitudeColumnName the name of the first column | ||
| * @return the query string | ||
| */ | ||
| private String createQueryForBoundingBox( | ||
| String schemaName, | ||
| String coordinateTableName, | ||
| String longitudeColumnName, | ||
| String latitudeColumnName) { | ||
| return createBaseQueryString(schemaName, coordinateTableName) | ||
| + WHERE | ||
| + longitudeColumnName | ||
| + " BETWEEN ? AND ? " | ||
| + " AND " | ||
| + latitudeColumnName | ||
| + " BETWEEN ? AND ?; "; | ||
| } | ||
| } | ||
18 changes: 18 additions & 0 deletions
18
src/main/java/edu/ie3/datamodel/models/value/CoordinateValue.java
This file contains hidden or 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,18 @@ | ||
| /* | ||
| * © 2022. TU Dortmund University, | ||
| * Institute of Energy Systems, Energy Efficiency and Energy Economics, | ||
| * Research group Distribution grid planning and operation | ||
| */ | ||
| package edu.ie3.datamodel.models.value; | ||
|
|
||
| import org.locationtech.jts.geom.Point; | ||
|
|
||
| public class CoordinateValue implements Value { | ||
| public final Integer id; | ||
| public final Point coordinate; | ||
|
|
||
| public CoordinateValue(int id, Point coordinate) { | ||
| this.id = id; | ||
| this.coordinate = coordinate; | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.