aves_mio0.31/lib/widgets/common/map/mapbox/tracks_layer.dart
2026-07-18 13:39:22 +02:00

119 lines
2.8 KiB
Dart

import 'dart:convert';
import 'package:aves_map/aves_map.dart';
import 'package:flutter/material.dart';
import 'package:latlong2/latlong.dart';
import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart' as mbx;
class MapboxTracksLayer {
static const sourceId = 'aves-mapbox-tracks-source';
static const layerId = 'aves-mapbox-tracks-layer';
static Future<void> remove({
required mbx.MapboxMap mapboxMap,
required void Function(String message) log,
required String reason,
}) async {
final style = mapboxMap.style as dynamic;
log('remove tracks layer reason=$reason');
try {
await style.removeStyleLayer(layerId);
} catch (_) {
// Layer may not exist.
}
try {
await style.removeStyleSource(sourceId);
} catch (_) {
// Source may not exist.
}
}
static Future<void> update({
required mbx.MapboxMap mapboxMap,
required Set<List<LatLng>>? tracks,
required Color color,
required double width,
required void Function(String message) log,
required String reason,
}) async {
await remove(
mapboxMap: mapboxMap,
log: log,
reason: reason,
);
if (tracks == null || tracks.isEmpty) {
log('tracks skipped empty reason=$reason');
return;
}
final lineStrings = tracks
.map(
(track) => track
.where(
(point) =>
point.latitude.isFinite && point.longitude.isFinite,
)
.map(
(point) => [
point.longitude,
point.latitude,
],
)
.toList(),
)
.where((coordinates) => coordinates.length >= 2)
.toList();
if (lineStrings.isEmpty) {
log('tracks skipped no valid line strings reason=$reason');
return;
}
final geoJson = jsonEncode({
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'MultiLineString',
'coordinates': lineStrings,
},
},
],
});
log(
'add tracks layer '
'reason=$reason '
'tracks=${tracks.length} '
'segments=${lineStrings.length} '
'points=${lineStrings.fold<int>(0, (sum, line) => sum + line.length)}',
);
try {
await mapboxMap.style.addSource(
mbx.GeoJsonSource(
id: sourceId,
data: geoJson,
),
);
await mapboxMap.style.addLayer(
mbx.LineLayer(
id: layerId,
sourceId: sourceId,
lineColor: color.value,
lineWidth: width,
lineOpacity: 1.0,
),
);
} catch (e) {
log('tracks layer add failed reason=$reason error=$e');
}
}
}