Skip to content
Merged
Show file tree
Hide file tree
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 Oct 27, 2022
116d351
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Oct 27, 2022
acf9a5d
Improving code.
staudtMarius Oct 28, 2022
e424f0d
Merge remote-tracking branch 'origin/ms/#689-improving-implementation…
staudtMarius Oct 28, 2022
6e8025c
fmt
staudtMarius Oct 28, 2022
d879543
Adding some documentation.
staudtMarius Oct 28, 2022
a2d2faf
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Oct 31, 2022
d4d3156
Implementing some tests.
staudtMarius Oct 31, 2022
00c21f2
Adding missing file for SqlIdCoordinateSource test.
staudtMarius Oct 31, 2022
a19ff9f
fmt
staudtMarius Oct 31, 2022
354fc4a
fmt
staudtMarius Oct 31, 2022
9b59372
fmt
staudtMarius Oct 31, 2022
344d6fb
Some refactoring.
staudtMarius Nov 2, 2022
2644931
Implementing changes in CsvIdCoordinateSource.
staudtMarius Nov 3, 2022
c83873b
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Nov 7, 2022
f0ca780
Adding some tests.
staudtMarius Nov 7, 2022
529bee2
Adding requested changes.
staudtMarius Nov 8, 2022
9613ba9
Adding requested changes.
staudtMarius Nov 8, 2022
42ff465
``SqlIdCoordinateSource`` uses ``PostGis`` now.
staudtMarius Nov 15, 2022
975fa09
Fixing test problems.
staudtMarius Nov 15, 2022
d196187
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Nov 21, 2022
c98ed65
Implementing requested changes.
staudtMarius Nov 24, 2022
69b58f4
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Nov 24, 2022
44d1f70
Fixing ``Codacy`` error.
staudtMarius Nov 24, 2022
e3f5fee
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Nov 28, 2022
46476de
Updating code to use new method of ``PSU``.
staudtMarius Nov 28, 2022
ab993c2
Merge remote-tracking branch 'origin/ms/#689-improving-implementation…
staudtMarius Nov 28, 2022
d359718
Updating code to use new method of ``PSU``.
staudtMarius Nov 28, 2022
c7fa204
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
sebastian-peter Dec 9, 2022
ca6a2f7
Implementing requested changes.
staudtMarius Jan 9, 2023
c6768ec
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Jan 9, 2023
6c2c789
fmt
staudtMarius Jan 9, 2023
fbcfed4
Fixing failing test.
staudtMarius Jan 10, 2023
613ce64
Improving IdCoordinateSource documentation
staudtMarius Jan 12, 2023
f9b8c2f
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Jan 12, 2023
cd0993b
Fixing failing test.
staudtMarius Jan 12, 2023
4070b13
fmt
staudtMarius Jan 12, 2023
aac4301
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
sebastian-peter Jan 20, 2023
f956731
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
sebastian-peter Jan 25, 2023
b4bd815
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Feb 2, 2023
e5e5d15
Improving documentation.
staudtMarius Feb 2, 2023
e6860e4
Adding markdown support to docs.
staudtMarius Feb 7, 2023
7e0dc92
Fix conf.py
staudtMarius Feb 7, 2023
b46a15a
Fixing markdown table rendering.
staudtMarius Feb 8, 2023
9732383
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Feb 14, 2023
54d6e45
Merging `dev` changes.
staudtMarius Feb 14, 2023
f3ed621
Fixing ``readthedoc``.
staudtMarius Feb 14, 2023
2dbb6e2
Fixing ``readthedoc``.
staudtMarius Feb 15, 2023
34faee4
Fixing ``readthedoc``.
staudtMarius Feb 15, 2023
76d9f49
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Feb 17, 2023
b7cee23
Some documentation improvements.
staudtMarius Feb 17, 2023
b6c2029
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Feb 20, 2023
bf23b8c
Resolving sonatype issues.
staudtMarius Feb 20, 2023
b0a0ec2
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Feb 20, 2023
eaa51f0
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Mar 9, 2023
d873354
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Apr 11, 2023
b93afed
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Apr 14, 2023
45d10ab
Implementing requested changes.
staudtMarius Apr 14, 2023
71e02e3
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Apr 18, 2023
bc1c713
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Apr 24, 2023
5e19cd6
fmt
staudtMarius Apr 24, 2023
13bbc45
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Apr 24, 2023
a3455c0
Indentation
sebastian-peter Apr 24, 2023
377cc32
Updating readthedocs online build config
sebastian-peter Apr 24, 2023
cabc9f0
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius Apr 27, 2023
64f17b3
Implementing requested changes.
staudtMarius Apr 27, 2023
6885b36
Fixing documentation issues.
staudtMarius May 2, 2023
5f124b0
Fixing documentation issues.
staudtMarius May 2, 2023
78e3aa2
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius May 4, 2023
85ae7f0
Implementing requested documentation changes.
staudtMarius May 4, 2023
6841c3e
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius May 9, 2023
ee15cf3
Merge branch 'dev' into ms/#689-improving-implementation-of-ÍdCoordin…
staudtMarius May 15, 2023
3a1142c
Implementing requested changes.
staudtMarius May 16, 2023
7e9c6e6
fmt
staudtMarius May 16, 2023
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 @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `ThermalGrid` as a container for a completely connected thermal grid
- `EmResult` and `FlexOptionsResult` for Energy Management Systems [#651](https://github.com/ie3-institute/PowerSystemDataModel/issues/651)
- `EvcsInput` now has a parameter for enabling and disabling vehicle to grid support [#681](https://github.com/ie3-institute/PowerSystemDataModel/issues/681)
- Adding SQL id coordinate sources (``IdCoordinateSource``) [#689](https://github.com/ie3-institute/PowerSystemDataModel/issues/689)

### Fixed
- Reduced code smells [#492](https://github.com/ie3-institute/PowerSystemDataModel/issues/492)
Expand Down
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;

/**
* 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 + " ?;";
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);
}

@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;
}

@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, ";"));

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(
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(
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) {
// 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>=?;}
*
* @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 src/main/java/edu/ie3/datamodel/models/value/CoordinateValue.java
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;
}
}