#1382 DDM coordinate format
This commit is contained in:
parent
f108103a4b
commit
6a5b0770e0
8 changed files with 68 additions and 10 deletions
|
@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## <a id="unreleased"></a>[Unreleased]
|
## <a id="unreleased"></a>[Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- DDM coordinate format option
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Video: use `media-kit` instead of `ffmpeg-kit` for metadata fetch
|
- Video: use `media-kit` instead of `ffmpeg-kit` for metadata fetch
|
||||||
|
|
|
@ -210,6 +210,7 @@
|
||||||
"albumTierRegular": "Others",
|
"albumTierRegular": "Others",
|
||||||
|
|
||||||
"coordinateFormatDms": "DMS",
|
"coordinateFormatDms": "DMS",
|
||||||
|
"coordinateFormatDdm": "DDM",
|
||||||
"coordinateFormatDecimal": "Decimal degrees",
|
"coordinateFormatDecimal": "Decimal degrees",
|
||||||
"coordinateDms": "{coordinate} {direction}",
|
"coordinateDms": "{coordinate} {direction}",
|
||||||
"@coordinateDms": {
|
"@coordinateDms": {
|
||||||
|
|
|
@ -60,12 +60,15 @@ class CoordinateFilter extends CollectionFilter {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String getLabel(BuildContext context) {
|
String getLabel(BuildContext context) {
|
||||||
return _formatBounds((latLng) => settings.coordinateFormat.format(
|
return _formatBounds((latLng) {
|
||||||
context,
|
final format = settings.coordinateFormat;
|
||||||
latLng,
|
return format.format(
|
||||||
minuteSecondPadding: minuteSecondPadding,
|
context,
|
||||||
dmsSecondDecimals: 0,
|
latLng,
|
||||||
));
|
minuteSecondPadding: minuteSecondPadding,
|
||||||
|
dmsSecondDecimals: format == CoordinateFormat.ddm ? 2 : 0,
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -8,15 +8,17 @@ import 'package:latlong2/latlong.dart';
|
||||||
extension ExtraCoordinateFormat on CoordinateFormat {
|
extension ExtraCoordinateFormat on CoordinateFormat {
|
||||||
static const _separator = ', ';
|
static const _separator = ', ';
|
||||||
|
|
||||||
String format(BuildContext context, LatLng latLng, {bool minuteSecondPadding = false, int dmsSecondDecimals = 2}) {
|
String format(BuildContext context, LatLng latLng, {bool minuteSecondPadding = false, int? dmsSecondDecimals}) {
|
||||||
final text = formatWithoutDirectionality(context.l10n, latLng, minuteSecondPadding: minuteSecondPadding, dmsSecondDecimals: dmsSecondDecimals);
|
final text = formatWithoutDirectionality(context.l10n, latLng, minuteSecondPadding: minuteSecondPadding, dmsSecondDecimals: dmsSecondDecimals);
|
||||||
return context.applyDirectionality(text);
|
return context.applyDirectionality(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
String formatWithoutDirectionality(AppLocalizations l10n, LatLng latLng, {bool minuteSecondPadding = false, int dmsSecondDecimals = 2}) {
|
String formatWithoutDirectionality(AppLocalizations l10n, LatLng latLng, {bool minuteSecondPadding = false, int? dmsSecondDecimals}) {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case CoordinateFormat.dms:
|
case CoordinateFormat.dms:
|
||||||
return toDMS(l10n, latLng, minuteSecondPadding: minuteSecondPadding, secondDecimals: dmsSecondDecimals).join(_separator);
|
return toDMS(l10n, latLng, minuteSecondPadding: minuteSecondPadding, secondDecimals: dmsSecondDecimals ?? 2).join(_separator);
|
||||||
|
case CoordinateFormat.ddm:
|
||||||
|
return toDDM(l10n, latLng, minutePadding: minuteSecondPadding, minuteDecimals: dmsSecondDecimals ?? 4).join(_separator);
|
||||||
case CoordinateFormat.decimal:
|
case CoordinateFormat.decimal:
|
||||||
return _toDecimal(l10n, latLng).join(_separator);
|
return _toDecimal(l10n, latLng).join(_separator);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +37,19 @@ extension ExtraCoordinateFormat on CoordinateFormat {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns coordinates formatted as DDM, e.g. ['41° 24.2028′ N', '2° 10.4418′ E']
|
||||||
|
static List<String> toDDM(AppLocalizations l10n, LatLng latLng, {bool minutePadding = false, int minuteDecimals = 4}) {
|
||||||
|
final locale = l10n.localeName;
|
||||||
|
final lat = latLng.latitude;
|
||||||
|
final lng = latLng.longitude;
|
||||||
|
final latSexa = _decimal2ddm(lat, minutePadding, minuteDecimals, locale);
|
||||||
|
final lngSexa = _decimal2ddm(lng, minutePadding, minuteDecimals, locale);
|
||||||
|
return [
|
||||||
|
l10n.coordinateDms(latSexa, lat < 0 ? l10n.coordinateDmsSouth : l10n.coordinateDmsNorth),
|
||||||
|
l10n.coordinateDms(lngSexa, lng < 0 ? l10n.coordinateDmsWest : l10n.coordinateDmsEast),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
static String _decimal2sexagesimal(
|
static String _decimal2sexagesimal(
|
||||||
double degDecimal,
|
double degDecimal,
|
||||||
bool minuteSecondPadding,
|
bool minuteSecondPadding,
|
||||||
|
@ -54,6 +69,22 @@ extension ExtraCoordinateFormat on CoordinateFormat {
|
||||||
return '$degText° $minText′ $secText″';
|
return '$degText° $minText′ $secText″';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String _decimal2ddm(
|
||||||
|
double degDecimal,
|
||||||
|
bool minutePadding,
|
||||||
|
int minuteDecimals,
|
||||||
|
String locale,
|
||||||
|
) {
|
||||||
|
final degAbs = degDecimal.abs();
|
||||||
|
final deg = degAbs.toInt();
|
||||||
|
final min = (degAbs - deg) * 60;
|
||||||
|
|
||||||
|
final degText = NumberFormat('0', locale).format(deg);
|
||||||
|
final minText = NumberFormat('${'0' * (minutePadding ? 2 : 1)}${minuteDecimals > 0 ? '.${'0' * minuteDecimals}' : ''}', locale).format(min);
|
||||||
|
|
||||||
|
return '$degText° $minText′';
|
||||||
|
}
|
||||||
|
|
||||||
static List<String> _toDecimal(AppLocalizations l10n, LatLng latLng) {
|
static List<String> _toDecimal(AppLocalizations l10n, LatLng latLng) {
|
||||||
final coordinateFormatter = NumberFormat('0.000000°', l10n.localeName);
|
final coordinateFormatter = NumberFormat('0.000000°', l10n.localeName);
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -45,6 +45,7 @@ extension ExtraCoordinateFormatView on CoordinateFormat {
|
||||||
final l10n = context.l10n;
|
final l10n = context.l10n;
|
||||||
return switch (this) {
|
return switch (this) {
|
||||||
CoordinateFormat.dms => l10n.coordinateFormatDms,
|
CoordinateFormat.dms => l10n.coordinateFormatDms,
|
||||||
|
CoordinateFormat.ddm => l10n.coordinateFormatDdm,
|
||||||
CoordinateFormat.decimal => l10n.coordinateFormatDecimal,
|
CoordinateFormat.decimal => l10n.coordinateFormatDecimal,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ enum AvesThemeColorMode { monochrome, polychrome }
|
||||||
|
|
||||||
enum ConfirmationDialog { createVault, deleteForever, moveToBin, moveUndatedItems }
|
enum ConfirmationDialog { createVault, deleteForever, moveToBin, moveUndatedItems }
|
||||||
|
|
||||||
enum CoordinateFormat { dms, decimal }
|
enum CoordinateFormat { dms, ddm, decimal }
|
||||||
|
|
||||||
enum DisplayRefreshRateMode { auto, highest, lowest }
|
enum DisplayRefreshRateMode { auto, highest, lowest }
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,12 @@ class MpvVideoController extends AvesVideoController {
|
||||||
Future<void> _init({int startMillis = 0}) async {
|
Future<void> _init({int startMillis = 0}) async {
|
||||||
final playing = _instance.state.playing;
|
final playing = _instance.state.playing;
|
||||||
|
|
||||||
|
// Audio quality is better with `audiotrack` than `opensles` (the default).
|
||||||
|
// Calling `setAudioDevice` does not seem to work.
|
||||||
|
// As of 2025/01/13, directly setting audio output via property works for some files but not all,
|
||||||
|
// and switching from a supported file to an unsupported file crashes:
|
||||||
|
// cf https://github.com/media-kit/media-kit/issues/1061
|
||||||
|
|
||||||
await _applyLoop();
|
await _applyLoop();
|
||||||
await _instance.open(Media(entry.uri), play: playing);
|
await _instance.open(Media(entry.uri), play: playing);
|
||||||
await _instance.setSubtitleTrack(SubtitleTrack.no());
|
await _instance.setSubtitleTrack(SubtitleTrack.no());
|
||||||
|
|
|
@ -18,6 +18,18 @@ void main() {
|
||||||
expect(ExtraCoordinateFormat.toDMS(l10n, const LatLng(0, 0), secondDecimals: 4), ['0° 0′ 0.0000″ N', '0° 0′ 0.0000″ E']);
|
expect(ExtraCoordinateFormat.toDMS(l10n, const LatLng(0, 0), secondDecimals: 4), ['0° 0′ 0.0000″ N', '0° 0′ 0.0000″ E']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Decimal degrees to DDM', () {
|
||||||
|
final l10n = lookupAppLocalizations(AvesApp.supportedLocales.first);
|
||||||
|
expect(ExtraCoordinateFormat.toDDM(l10n, const LatLng(37.496667, 127.0275)), ['37° 29.8000′ N', '127° 1.6500′ E']); // Gangnam
|
||||||
|
expect(ExtraCoordinateFormat.toDDM(l10n, const LatLng(78.9243503, 11.9230465)), ['78° 55.4610′ N', '11° 55.3828′ E']); // Ny-Ålesund
|
||||||
|
expect(ExtraCoordinateFormat.toDDM(l10n, const LatLng(-38.6965891, 175.9830047)), ['38° 41.7953′ S', '175° 58.9803′ E']); // Taupo
|
||||||
|
expect(ExtraCoordinateFormat.toDDM(l10n, const LatLng(-64.249391, -56.6556145)), ['64° 14.9635′ S', '56° 39.3369′ W']); // Marambio
|
||||||
|
expect(ExtraCoordinateFormat.toDDM(l10n, const LatLng(0, 0)), ['0° 0.0000′ N', '0° 0.0000′ E']);
|
||||||
|
expect(ExtraCoordinateFormat.toDDM(l10n, const LatLng(0, 0), minutePadding: true), ['0° 00.0000′ N', '0° 00.0000′ E']);
|
||||||
|
expect(ExtraCoordinateFormat.toDDM(l10n, const LatLng(0, 0), minuteDecimals: 0), ['0° 0′ N', '0° 0′ E']);
|
||||||
|
expect(ExtraCoordinateFormat.toDDM(l10n, const LatLng(0, 0), minuteDecimals: 6), ['0° 0.000000′ N', '0° 0.000000′ E']);
|
||||||
|
});
|
||||||
|
|
||||||
test('bounds center', () {
|
test('bounds center', () {
|
||||||
expect(GeoUtils.getLatLngCenter(const [LatLng(10, 30), LatLng(30, 50)]), const LatLng(20.28236664671092, 39.351653000319956));
|
expect(GeoUtils.getLatLngCenter(const [LatLng(10, 30), LatLng(30, 50)]), const LatLng(20.28236664671092, 39.351653000319956));
|
||||||
expect(GeoUtils.getLatLngCenter(const [LatLng(10, -179), LatLng(30, 179)]), const LatLng(20.00279344048298, -179.9358157370226));
|
expect(GeoUtils.getLatLngCenter(const [LatLng(10, -179), LatLng(30, 179)]), const LatLng(20.00279344048298, -179.9358157370226));
|
||||||
|
|
Loading…
Reference in a new issue