From 7397d1aea122a4beead0ac8a2e86850551521d8d Mon Sep 17 00:00:00 2001 From: Kamiya Date: Sun, 10 Aug 2025 09:11:08 +0800 Subject: [PATCH 1/2] fix: map value placements --- lib/app/map/_lib/managers/monitor.dart | 13 ++++++++++++- lib/widgets/map/map.dart | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/app/map/_lib/managers/monitor.dart b/lib/app/map/_lib/managers/monitor.dart index c9d29d2c1..12735e68d 100644 --- a/lib/app/map/_lib/managers/monitor.dart +++ b/lib/app/map/_lib/managers/monitor.dart @@ -289,8 +289,19 @@ class MonitorMapLayerManager extends MapLayerManager { textHaloColor: colors.outlineVariant.toHexStringRGB(), textHaloWidth: 1, textFont: ['Noto Sans TC Regular'], - textOffset: [0, 1], + textRadialOffset: 1.5, textAnchor: 'top', + textJustify: 'auto', + textVariableAnchor: [ + 'top', + 'bottom', + 'left', + 'right', + 'top-left', + 'bottom-left', + 'top-right', + 'bottom-right', + ], visibility: visible ? 'visible' : 'none', ); diff --git a/lib/widgets/map/map.dart b/lib/widgets/map/map.dart index 2690b8dae..3ac70774f 100644 --- a/lib/widgets/map/map.dart +++ b/lib/widgets/map/map.dart @@ -328,7 +328,7 @@ class DpipMapState extends State { final double adjustedZoomValue = adjustedZoom(widget.initialCameraPosition.zoom); return MapLibreMap( - minMaxZoomPreference: widget.minMaxZoomPreference ?? const MinMaxZoomPreference(4, 15), + minMaxZoomPreference: widget.minMaxZoomPreference ?? const MinMaxZoomPreference(4, 12.5), trackCameraPosition: true, initialCameraPosition: CameraPosition(target: widget.initialCameraPosition.target, zoom: adjustedZoomValue), styleString: styleAbsoluteFilePath!, From 2b2012ab9aca43501a07cfbe6a9fa3b08b9b9479 Mon Sep 17 00:00:00 2001 From: Kamiya Date: Sun, 10 Aug 2025 09:12:33 +0800 Subject: [PATCH 2/2] fix: typing --- lib/api/model/report/earthquake_report.dart | 10 ++++--- .../report/partial_earthquake_report.dart | 9 ++++-- lib/api/model/rts/rts.dart | 6 ++-- lib/api/model/station_intensity.dart | 10 ++++--- lib/api/model/weather/rain.dart | 8 ++++-- lib/api/model/weather/weather.dart | 6 ++-- lib/core/rts.dart | 28 ++----------------- lib/models/data.dart | 17 +++++++++-- lib/route/report/report.dart | 3 +- lib/utils/extensions/latlng.dart | 4 ++- lib/utils/map_utils.dart | 8 +++--- 11 files changed, 56 insertions(+), 53 deletions(-) diff --git a/lib/api/model/report/earthquake_report.dart b/lib/api/model/report/earthquake_report.dart index 3c295ee36..b30e93a08 100644 --- a/lib/api/model/report/earthquake_report.dart +++ b/lib/api/model/report/earthquake_report.dart @@ -1,11 +1,13 @@ import 'package:collection/collection.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:timezone/timezone.dart'; + import 'package:dpip/api/model/report/area_intensity.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/geojson.dart'; import 'package:dpip/utils/map_utils.dart'; import 'package:dpip/utils/parser.dart'; -import 'package:json_annotation/json_annotation.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; -import 'package:timezone/timezone.dart'; part 'earthquake_report.g.dart'; @@ -203,7 +205,7 @@ class EarthquakeReport { .toList(); final cross = GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - ..setGeometry(latlng.toGeoJsonCoordinates()) + ..setGeometry(latlng.asGeoJsonCooridnate) ..setProperty('icon', 'cross-7') ..setProperty('magnitude', magnitude); diff --git a/lib/api/model/report/partial_earthquake_report.dart b/lib/api/model/report/partial_earthquake_report.dart index 3a1f7ae15..fcd469f94 100644 --- a/lib/api/model/report/partial_earthquake_report.dart +++ b/lib/api/model/report/partial_earthquake_report.dart @@ -1,10 +1,13 @@ -import 'package:dpip/utils/geojson.dart'; -import 'package:dpip/utils/parser.dart'; import 'package:flutter/material.dart'; + import 'package:json_annotation/json_annotation.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; import 'package:timezone/timezone.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; +import 'package:dpip/utils/geojson.dart'; +import 'package:dpip/utils/parser.dart'; + part 'partial_earthquake_report.g.dart'; @JsonSerializable() @@ -163,7 +166,7 @@ class PartialEarthquakeReport { GeoJsonFeatureBuilder toGeoJsonFeature() { return GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) .setId(time.millisecondsSinceEpoch) - .setGeometry(latlng.toGeoJsonCoordinates()) + .setGeometry(latlng.asGeoJsonCooridnate) .setProperty('icon', 'cross-$intensity') .setProperty('magnitude', magnitude) .setProperty('intensity', intensity) diff --git a/lib/api/model/rts/rts.dart b/lib/api/model/rts/rts.dart index 04433c24b..112977a51 100644 --- a/lib/api/model/rts/rts.dart +++ b/lib/api/model/rts/rts.dart @@ -1,8 +1,10 @@ +import 'package:json_annotation/json_annotation.dart'; + import 'package:dpip/api/model/rts/rts_intensity.dart'; import 'package:dpip/api/model/rts/rts_station.dart'; import 'package:dpip/core/providers.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/geojson.dart'; -import 'package:json_annotation/json_annotation.dart'; part 'rts.g.dart'; @@ -38,7 +40,7 @@ class Rts { } return GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - ..setGeometry(latlng.toGeoJsonCoordinates()) + ..setGeometry(latlng.asGeoJsonCooridnate) ..setProperty('id', id) ..setProperty('I', s.I) ..setProperty('i', s.i) diff --git a/lib/api/model/station_intensity.dart b/lib/api/model/station_intensity.dart index d46c0435a..918c96544 100644 --- a/lib/api/model/station_intensity.dart +++ b/lib/api/model/station_intensity.dart @@ -1,7 +1,9 @@ -import 'package:dpip/utils/geojson.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; +import 'package:dpip/utils/geojson.dart'; + part 'station_intensity.g.dart'; @JsonSerializable() @@ -25,8 +27,8 @@ class StationIntensity { Map toJson() => _$StationIntensityToJson(this); GeoJsonFeatureBuilder toGeoJsonFeature() { - return GeoJsonFeatureBuilder( - GeoJsonFeatureType.Point, - ).setGeometry(latlng.toGeoJsonCoordinates()).setProperty('icon', 'intensity-$intensity'); + return GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) + ..setGeometry(latlng.asGeoJsonCooridnate) + ..setProperty('icon', 'intensity-$intensity'); } } diff --git a/lib/api/model/weather/rain.dart b/lib/api/model/weather/rain.dart index d4af0e2f9..c17cd37a2 100644 --- a/lib/api/model/weather/rain.dart +++ b/lib/api/model/weather/rain.dart @@ -1,8 +1,10 @@ -import 'package:dpip/utils/geojson.dart'; -import 'package:dpip/widgets/map/latlng_altitude.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; +import 'package:dpip/utils/geojson.dart'; +import 'package:dpip/widgets/map/latlng_altitude.dart'; + part 'rain.g.dart'; @JsonSerializable() @@ -21,7 +23,7 @@ class RainStation { GeoJsonFeatureBuilder toFeatureBuilder() => GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - ..setGeometry(station.latlng.toGeoJsonCoordinates()) + ..setGeometry(station.latlng.asGeoJsonCooridnate) ..setProperty('id', id) ..setProperty('name', station.name) ..setProperty('county', station.county) diff --git a/lib/api/model/weather/weather.dart b/lib/api/model/weather/weather.dart index bb1bfcec1..49e745784 100644 --- a/lib/api/model/weather/weather.dart +++ b/lib/api/model/weather/weather.dart @@ -1,7 +1,9 @@ -import 'package:dpip/utils/geojson.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; +import 'package:dpip/utils/geojson.dart'; + part 'weather.g.dart'; @JsonSerializable() @@ -25,7 +27,7 @@ class WeatherStation { GeoJsonFeatureBuilder toFeatureBuilder() { final direction = (data.wind.direction + 180) % 360; return GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - .setGeometry(station.latlng.toGeoJsonCoordinates()) + .setGeometry(station.latlng.asGeoJsonCooridnate) .setProperty('id', id) .setProperty('name', station.name) .setProperty('county', station.county) diff --git a/lib/core/rts.dart b/lib/core/rts.dart index ee4920035..dc51161d9 100644 --- a/lib/core/rts.dart +++ b/lib/core/rts.dart @@ -1,8 +1,6 @@ -import 'package:dpip/api/model/eew.dart'; -import 'package:dpip/api/model/station_info.dart'; -import 'package:dpip/utils/extensions/latlng.dart'; import 'package:intl/intl.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; + +import 'package:dpip/api/model/station_info.dart'; StationInfo findAppropriateItem(List infos, int date) { final DateTime targetDate = (date == 0) ? DateTime.now() : DateTime.fromMillisecondsSinceEpoch(date); @@ -16,25 +14,3 @@ StationInfo findAppropriateItem(List infos, int date) { return sortedItems.last; } - -bool checkBoxSkip(Map eewLastInfo, Map eewDist, List box) { - bool passed = false; - - for (final eew in eewLastInfo.keys) { - int skip = 0; - for (int i = 0; i < 4; i++) { - final dist = LatLng( - eewLastInfo[eew]!.info.latitude, - eewLastInfo[eew]!.info.longitude, - ).to(LatLng(box[i][1], box[i][0])); - - if (eewDist[eew]! > dist) skip++; - } - if (skip >= 4) { - passed = true; - break; - } - } - - return passed; -} diff --git a/lib/models/data.dart b/lib/models/data.dart index 9d0c792e4..add02d777 100644 --- a/lib/models/data.dart +++ b/lib/models/data.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:collection'; +import 'dart:math'; import 'package:flutter/material.dart'; @@ -16,6 +17,7 @@ import 'package:dpip/api/model/weather/rain.dart'; import 'package:dpip/api/model/weather/weather.dart'; import 'package:dpip/core/eew.dart'; import 'package:dpip/global.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/geojson.dart'; import 'package:dpip/utils/log.dart'; import 'package:dpip/utils/map_utils.dart'; @@ -286,9 +288,18 @@ class DpipDataModel extends _DpipDataModel { for (final MapEntry(key: id, value: s) in station.entries) { if (s.work == false) continue; + + final coordinates = s.info.last.latlng.asGeoJsonCooridnate; + + // Create displaced coordinates with ~5 meter random offset + final random = Random(); + final offsetLng = (random.nextDouble() - 0.5) * 0.00009; // ~5m longitude offset + final offsetLat = (random.nextDouble() - 0.5) * 0.00009; // ~5m latitude offset + final displacedCoordinates = [coordinates[0] + offsetLng, coordinates[1] + offsetLat]; + final feature = GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - ..setGeometry(s.info.last.latlng.toGeoJsonCoordinates() as List) + ..setGeometry(displacedCoordinates) ..setId(int.parse(id)) ..setProperty('id', id) ..setProperty('net', s.net) @@ -338,7 +349,7 @@ class DpipDataModel extends _DpipDataModel { final epicenter = GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - ..setGeometry(e.info.latlng.toGeoJsonCoordinates() as List) + ..setGeometry(e.info.latlng.asGeoJsonCooridnate) ..setProperty('type', 'x'); builder.addFeature(epicenter); @@ -355,7 +366,7 @@ class DpipDataModel extends _DpipDataModel { if (s.work == false) continue; final feature = GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - ..setGeometry(s.info.last.latlng.toGeoJsonCoordinates() as List) + ..setGeometry(s.info.last.latlng.asGeoJsonCooridnate) ..setId(int.parse(id)) ..setProperty('net', s.net) ..setProperty('code', s.info.last.code); diff --git a/lib/route/report/report.dart b/lib/route/report/report.dart index 496ff04ed..0e7f9334e 100644 --- a/lib/route/report/report.dart +++ b/lib/route/report/report.dart @@ -11,6 +11,7 @@ import 'package:dpip/core/eew.dart'; import 'package:dpip/route/report/report_sheet_content.dart'; import 'package:dpip/utils/extensions/build_context.dart'; import 'package:dpip/utils/extensions/color_scheme.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/geojson.dart'; import 'package:dpip/utils/intensity_color.dart'; import 'package:dpip/utils/log.dart'; @@ -96,7 +97,7 @@ class _ReportRouteState extends State with TickerProviderStateMixin 'properties': { 'intensity': 10, // 10 is for classifying epicenter cross }, - 'geometry': {'coordinates': data.latlng.toGeoJsonCoordinates(), 'type': 'Point'}, + 'geometry': {'coordinates': data.latlng.asGeoJsonCooridnate, 'type': 'Point'}, }); expandBounds(bounds, data.latlng); diff --git a/lib/utils/extensions/latlng.dart b/lib/utils/extensions/latlng.dart index 5f4b61a31..d6565e383 100644 --- a/lib/utils/extensions/latlng.dart +++ b/lib/utils/extensions/latlng.dart @@ -6,8 +6,10 @@ import 'package:dpip/utils/geojson.dart'; extension GeoJsonLatLng on LatLng { bool get isValid => latitude != 0 && longitude != 0; + List get asGeoJsonCooridnate => [longitude, latitude]; + GeoJsonFeatureBuilder toFeatureBuilder() { - return GeoJsonFeatureBuilder(GeoJsonFeatureType.Point)..setGeometry(toGeoJsonCoordinates() as List); + return GeoJsonFeatureBuilder(GeoJsonFeatureType.Point)..setGeometry(asGeoJsonCooridnate); } /// Calculates the distance between the supplied coordinates in meters. The distance between the coordinates is diff --git a/lib/utils/map_utils.dart b/lib/utils/map_utils.dart index da3b93636..0df0da4dd 100644 --- a/lib/utils/map_utils.dart +++ b/lib/utils/map_utils.dart @@ -129,7 +129,7 @@ Map circle(LatLng center, double radius, {int steps = 64, Units for (var i = 0; i < steps; i++) { final point = destination(center, radius, (i * -360) / steps, units: units); - coordinates.add(point.toGeoJsonCoordinates()); + coordinates.add(point.asGeoJsonCooridnate); } coordinates.add(coordinates[0]); @@ -154,11 +154,11 @@ GeoJsonFeatureBuilder circleFeature({ }) { // main final polygon = GeoJsonFeatureBuilder(GeoJsonFeatureType.Polygon); - final List coordinates = []; + final List> coordinates = []; for (var i = 0; i < steps; i++) { final point = destination(center, radius, (i * -360) / steps, units: units); - coordinates.add(point.toGeoJsonCoordinates()); + coordinates.add(point.asGeoJsonCooridnate); } coordinates.add(coordinates[0]); @@ -166,7 +166,7 @@ GeoJsonFeatureBuilder circleFeature({ return polygon.setGeometry(coordinates); } -bool checkBoxSkip(Map eewLastInfo, Map eewDist, List box) { +bool checkBoxSkip(Map eewLastInfo, Map eewDist, List> box) { bool passed = false; for (final eew in eewLastInfo.keys) {