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 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 update({ required mbx.MapboxMap mapboxMap, required Set>? 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(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'); } } }