From 7b3209b16115872c1232d218dbc661c7e1b590b7 Mon Sep 17 00:00:00 2001 From: Jan Meinl Date: Thu, 14 May 2026 16:20:41 +0200 Subject: [PATCH] Add map projection framework and integrate initial SwissGrid and UTM projections - Introduced `MapProjection` interface for handling coordinate projections and unprojections. - Added `SwissGridProjection` and `SwissGridVariant` for Swiss coordinate systems. - Implemented `UtmProjection` and `UtmResult` for UTM coordinate systems, including hemisphere and zone handling. - Created supporting classes such as `GeodeticDatum`, `MapDate`, and projection-specific result types for extensibility. - Extended `BalloonLiveParser` and added `TrackParser` interface to structure track parsing functionality. --- .../backend/map/GeodeticDatum.java | 7 +++ .../coph/flightscore/backend/map/MapDate.java | 6 +++ .../backend/map/projection/MapProjection.java | 10 ++++ .../projection/swiss/SwissGridProjection.java | 24 +++++++++ .../projection/swiss/SwissGridVariant.java | 8 +++ .../map/projection/swiss/SwissResult.java | 6 +++ .../map/projection/utm/UtmProjection.java | 52 +++++++++++++++++++ .../backend/map/projection/utm/UtmResult.java | 7 +++ .../track/parser/BalloonLiveParser.java | 9 +++- .../backend/track/parser/TrackParser.java | 12 +++++ 10 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 src/main/java/dev/coph/flightscore/backend/map/GeodeticDatum.java create mode 100644 src/main/java/dev/coph/flightscore/backend/map/MapDate.java create mode 100644 src/main/java/dev/coph/flightscore/backend/map/projection/MapProjection.java create mode 100644 src/main/java/dev/coph/flightscore/backend/map/projection/swiss/SwissGridProjection.java create mode 100644 src/main/java/dev/coph/flightscore/backend/map/projection/swiss/SwissGridVariant.java create mode 100644 src/main/java/dev/coph/flightscore/backend/map/projection/swiss/SwissResult.java create mode 100644 src/main/java/dev/coph/flightscore/backend/map/projection/utm/UtmProjection.java create mode 100644 src/main/java/dev/coph/flightscore/backend/map/projection/utm/UtmResult.java create mode 100644 src/main/java/dev/coph/flightscore/backend/track/parser/TrackParser.java diff --git a/src/main/java/dev/coph/flightscore/backend/map/GeodeticDatum.java b/src/main/java/dev/coph/flightscore/backend/map/GeodeticDatum.java new file mode 100644 index 0000000..9fbc1ba --- /dev/null +++ b/src/main/java/dev/coph/flightscore/backend/map/GeodeticDatum.java @@ -0,0 +1,7 @@ +package dev.coph.flightscore.backend.map; + +public record GeodeticDatum(double semiMajorAxis, double flattening, double dx, double dy, double dz) { + public static final GeodeticDatum WGS84 = new GeodeticDatum(6378137.0, 1 / 298.257223563, 0, 0, 0); + public static final GeodeticDatum ETRS89 = new GeodeticDatum(6378137.0, 1 / 298.257222101, 0, 0, 0); + public static final GeodeticDatum BESSEL_CH = new GeodeticDatum(6377397.155, 1 / 299.1528128, 674.374, 15.056, 405.346); +} \ No newline at end of file diff --git a/src/main/java/dev/coph/flightscore/backend/map/MapDate.java b/src/main/java/dev/coph/flightscore/backend/map/MapDate.java new file mode 100644 index 0000000..f906ca6 --- /dev/null +++ b/src/main/java/dev/coph/flightscore/backend/map/MapDate.java @@ -0,0 +1,6 @@ +package dev.coph.flightscore.backend.map; + +public class MapDate { + + +} diff --git a/src/main/java/dev/coph/flightscore/backend/map/projection/MapProjection.java b/src/main/java/dev/coph/flightscore/backend/map/projection/MapProjection.java new file mode 100644 index 0000000..8449a22 --- /dev/null +++ b/src/main/java/dev/coph/flightscore/backend/map/projection/MapProjection.java @@ -0,0 +1,10 @@ +package dev.coph.flightscore.backend.map.projection; + +import dev.coph.flightscore.backend.coordinate.Coordinate; +import dev.coph.flightscore.backend.map.GeodeticDatum; + +public interface MapProjection { + T project(double latitude, double longitude, GeodeticDatum sourceDatum); + + Coordinate unproject(T projectedCoordinate, GeodeticDatum sourceDatum); +} diff --git a/src/main/java/dev/coph/flightscore/backend/map/projection/swiss/SwissGridProjection.java b/src/main/java/dev/coph/flightscore/backend/map/projection/swiss/SwissGridProjection.java new file mode 100644 index 0000000..5c5a0e1 --- /dev/null +++ b/src/main/java/dev/coph/flightscore/backend/map/projection/swiss/SwissGridProjection.java @@ -0,0 +1,24 @@ +package dev.coph.flightscore.backend.map.projection.swiss; + +import dev.coph.flightscore.backend.coordinate.Coordinate; +import dev.coph.flightscore.backend.map.GeodeticDatum; +import dev.coph.flightscore.backend.map.projection.MapProjection; + +public class SwissGridProjection implements MapProjection { + private final GeodeticDatum targetDatum = GeodeticDatum.BESSEL_CH; + private final SwissGridVariant variant; + + public SwissGridProjection(SwissGridVariant variant) { + this.variant = variant; + } + + @Override + public SwissResult project(double latitude, double longitude, GeodeticDatum sourceDatum) { + return null; + } + + @Override + public Coordinate unproject(SwissResult projectedCoordinate, GeodeticDatum sourceDatum) { + return null; + } +} \ No newline at end of file diff --git a/src/main/java/dev/coph/flightscore/backend/map/projection/swiss/SwissGridVariant.java b/src/main/java/dev/coph/flightscore/backend/map/projection/swiss/SwissGridVariant.java new file mode 100644 index 0000000..aa469b8 --- /dev/null +++ b/src/main/java/dev/coph/flightscore/backend/map/projection/swiss/SwissGridVariant.java @@ -0,0 +1,8 @@ +package dev.coph.flightscore.backend.map.projection.swiss; + +public enum SwissGridVariant { + LV03, + LV95; + + +} diff --git a/src/main/java/dev/coph/flightscore/backend/map/projection/swiss/SwissResult.java b/src/main/java/dev/coph/flightscore/backend/map/projection/swiss/SwissResult.java new file mode 100644 index 0000000..67aa652 --- /dev/null +++ b/src/main/java/dev/coph/flightscore/backend/map/projection/swiss/SwissResult.java @@ -0,0 +1,6 @@ +package dev.coph.flightscore.backend.map.projection.swiss; + +public record SwissResult(double east, double north) { + + +} diff --git a/src/main/java/dev/coph/flightscore/backend/map/projection/utm/UtmProjection.java b/src/main/java/dev/coph/flightscore/backend/map/projection/utm/UtmProjection.java new file mode 100644 index 0000000..dd460dc --- /dev/null +++ b/src/main/java/dev/coph/flightscore/backend/map/projection/utm/UtmProjection.java @@ -0,0 +1,52 @@ +package dev.coph.flightscore.backend.map.projection.utm; + +import dev.coph.flightscore.backend.coordinate.Coordinate; +import dev.coph.flightscore.backend.map.GeodeticDatum; +import dev.coph.flightscore.backend.map.projection.MapProjection; + +public class UtmProjection implements MapProjection { + private final int zone; + private final boolean isNorthernHemisphere; + private final GeodeticDatum targetDatum; + + public UtmProjection(int zone, boolean isNorthernHemisphere, GeodeticDatum targetDatum) { + this.zone = zone; + this.isNorthernHemisphere = isNorthernHemisphere; + this.targetDatum = targetDatum; + } + + @Override + public UtmResult project(double latitude, double longitude, GeodeticDatum sourceDatum) { + return null; + } + + @Override + public Coordinate unproject(UtmResult projectedCoordinate, GeodeticDatum sourceDatum) { + return null; + } + + + private char getUtmLetterDesignator(double lat) { + if (lat <= 84 && lat >= 72) return 'X'; + else if (lat < 72 && lat >= 64) return 'W'; + else if (lat < 64 && lat >= 56) return 'V'; + else if (lat < 56 && lat >= 48) return 'U'; + else if (lat < 48 && lat >= 40) return 'T'; + else if (lat < 40 && lat >= 32) return 'S'; + else if (lat < 32 && lat >= 24) return 'R'; + else if (lat < 24 && lat >= 16) return 'Q'; + else if (lat < 16 && lat >= 8) return 'P'; + else if (lat < 8 && lat >= 0) return 'N'; + else if (lat < 0 && lat >= -8) return 'M'; + else if (lat < -8 && lat >= -16) return 'L'; + else if (lat < -16 && lat >= -24) return 'K'; + else if (lat < -24 && lat >= -32) return 'J'; + else if (lat < -32 && lat >= -40) return 'H'; + else if (lat < -40 && lat >= -48) return 'G'; + else if (lat < -48 && lat >= -56) return 'F'; + else if (lat < -56 && lat >= -64) return 'E'; + else if (lat < -64 && lat >= -72) return 'D'; + else if (lat < -72 && lat >= -80) return 'C'; + else return 'Z'; + } +} \ No newline at end of file diff --git a/src/main/java/dev/coph/flightscore/backend/map/projection/utm/UtmResult.java b/src/main/java/dev/coph/flightscore/backend/map/projection/utm/UtmResult.java new file mode 100644 index 0000000..52e27c6 --- /dev/null +++ b/src/main/java/dev/coph/flightscore/backend/map/projection/utm/UtmResult.java @@ -0,0 +1,7 @@ +package dev.coph.flightscore.backend.map.projection.utm; + +public record UtmResult(double easting, double northing, int zone, char band, String fullZone) { + public UtmResult(double easting, double northing, int zone, char band) { + this(easting, northing, zone, band, zone + String.valueOf(band)); + } +} diff --git a/src/main/java/dev/coph/flightscore/backend/track/parser/BalloonLiveParser.java b/src/main/java/dev/coph/flightscore/backend/track/parser/BalloonLiveParser.java index c4ffd5d..e92a09d 100644 --- a/src/main/java/dev/coph/flightscore/backend/track/parser/BalloonLiveParser.java +++ b/src/main/java/dev/coph/flightscore/backend/track/parser/BalloonLiveParser.java @@ -1,7 +1,12 @@ package dev.coph.flightscore.backend.track.parser; -public class BalloonLiveParser { +import dev.coph.flightscore.backend.track.Track; - +public class BalloonLiveParser implements TrackParser{ + + @Override + public Track parse(String[] lines) { + + } } diff --git a/src/main/java/dev/coph/flightscore/backend/track/parser/TrackParser.java b/src/main/java/dev/coph/flightscore/backend/track/parser/TrackParser.java new file mode 100644 index 0000000..876fd65 --- /dev/null +++ b/src/main/java/dev/coph/flightscore/backend/track/parser/TrackParser.java @@ -0,0 +1,12 @@ +package dev.coph.flightscore.backend.track.parser; + +import dev.coph.flightscore.backend.coordinate.Coordinate; +import dev.coph.flightscore.backend.track.Track; + +import java.io.File; + +public interface TrackParser { + + public Track parse(String[] lines, Coordinate referenceCoordinate ); + +}