mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-06-27 04:37:28 +10:00
Fix map centering weirdly
When nodes or markers are outside of the main area of interest.
This commit is contained in:
+52
-14
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_map/flutter_map.dart';
|
import 'package:flutter_map/flutter_map.dart';
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import '../connector/meshcore_connector.dart';
|
import '../connector/meshcore_connector.dart';
|
||||||
import '../l10n/l10n.dart';
|
import '../l10n/l10n.dart';
|
||||||
@@ -70,6 +71,25 @@ class _MapScreenState extends State<MapScreen> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double _standardDeviation(List<double> values) {
|
||||||
|
if (values.length <= 1) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final mean = values.reduce((a, b) => a + b) / values.length;
|
||||||
|
|
||||||
|
double sumSquaredDiff = 0.0;
|
||||||
|
for (final value in values) {
|
||||||
|
final diff = value - mean;
|
||||||
|
sumSquaredDiff += diff * diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sample standard deviation (n-1) — most appropriate here
|
||||||
|
final variance = sumSquaredDiff / (values.length - 1);
|
||||||
|
|
||||||
|
return sqrt(variance);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer2<MeshCoreConnector, AppSettingsService>(
|
return Consumer2<MeshCoreConnector, AppSettingsService>(
|
||||||
@@ -116,19 +136,37 @@ class _MapScreenState extends State<MapScreen> {
|
|||||||
_isSelectingPoi ||
|
_isSelectingPoi ||
|
||||||
highlightPosition != null;
|
highlightPosition != null;
|
||||||
if (contactsWithLocation.isNotEmpty || sharedMarkers.isNotEmpty) {
|
if (contactsWithLocation.isNotEmpty || sharedMarkers.isNotEmpty) {
|
||||||
double avgLat = contactsWithLocation
|
double avgLat = 0.0;
|
||||||
.map((c) => c.latitude!)
|
double avgLon = 0.0;
|
||||||
.fold<double>(0, (sum, lat) => sum + lat);
|
final allPoints = [
|
||||||
double avgLon = contactsWithLocation
|
...contactsWithLocation.map((c) => LatLng(c.latitude!, c.longitude!)),
|
||||||
.map((c) => c.longitude!)
|
...sharedMarkers.map((m) => m.position),
|
||||||
.fold<double>(0, (sum, lon) => sum + lon);
|
];
|
||||||
for (final marker in sharedMarkers) {
|
if (allPoints.length >= 3) {
|
||||||
avgLat += marker.position.latitude;
|
final latValues = allPoints.map((p) => p.latitude).toList();
|
||||||
avgLon += marker.position.longitude;
|
final lonValues = allPoints.map((p) => p.longitude).toList();
|
||||||
}
|
|
||||||
final total = contactsWithLocation.length + sharedMarkers.length;
|
final latStdDev = _standardDeviation(latValues);
|
||||||
if (total > 0) {
|
final lonStdDev = _standardDeviation(lonValues);
|
||||||
center = LatLng(avgLat / total, avgLon / total);
|
final filteredLatValues = latValues
|
||||||
|
.where((lat) => (lat - (latValues.reduce((a, b) => a + b) / latValues.length)).abs() <= latStdDev * 2)
|
||||||
|
.toList();
|
||||||
|
final filteredLonValues = lonValues
|
||||||
|
.where((lon) => (lon - (lonValues.reduce((a, b) => a + b) / lonValues.length)).abs() <= lonStdDev * 2)
|
||||||
|
.toList();
|
||||||
|
center = LatLng(
|
||||||
|
filteredLatValues.reduce((a, b) => a + b) / filteredLatValues.length,
|
||||||
|
filteredLonValues.reduce((a, b) => a + b) / filteredLonValues.length,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
for (final point in allPoints) {
|
||||||
|
avgLat += point.latitude;
|
||||||
|
avgLon += point.longitude;
|
||||||
|
}
|
||||||
|
center = LatLng(
|
||||||
|
avgLat / allPoints.length,
|
||||||
|
avgLon / allPoints.length,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (highlightPosition != null) {
|
if (highlightPosition != null) {
|
||||||
@@ -169,7 +207,7 @@ class _MapScreenState extends State<MapScreen> {
|
|||||||
mapController: _mapController,
|
mapController: _mapController,
|
||||||
options: MapOptions(
|
options: MapOptions(
|
||||||
initialCenter: center,
|
initialCenter: center,
|
||||||
initialZoom: 13.0,
|
initialZoom: 10.0,
|
||||||
minZoom: 2.0,
|
minZoom: 2.0,
|
||||||
maxZoom: 18.0,
|
maxZoom: 18.0,
|
||||||
onTap: (_, latLng) {
|
onTap: (_, latLng) {
|
||||||
|
|||||||
Reference in New Issue
Block a user