fix: render isolated route acceleration and braking events
This commit is contained in:
parent
2f1b9ad024
commit
df83274bed
|
|
@ -309,32 +309,63 @@ class _MapScreenState extends ConsumerState<MapScreen> {
|
||||||
required String idPrefix,
|
required String idPrefix,
|
||||||
required Color color,
|
required Color color,
|
||||||
}) {
|
}) {
|
||||||
|
if (samples.isEmpty) return [];
|
||||||
|
|
||||||
|
// A threshold crossing is often only one telemetry sample wide. Requiring
|
||||||
|
// two consecutive qualifying samples made isolated acceleration/braking
|
||||||
|
// events disappear from the map. Build event runs, then include one GPS
|
||||||
|
// sample on each side so every event renders as a visible route segment.
|
||||||
final polylines = <AppPolyline>[];
|
final polylines = <AppPolyline>[];
|
||||||
List<AppLatLng> segment = [];
|
final eventIndices = <int>[];
|
||||||
|
|
||||||
|
for (var i = 0; i < samples.length; i++) {
|
||||||
|
final g = samples[i].longitudinalG ?? samples[i].accelX;
|
||||||
|
if (g != null && g.isFinite && predicate(g)) {
|
||||||
|
eventIndices.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (eventIndices.isEmpty) return polylines;
|
||||||
|
|
||||||
|
var runStart = eventIndices.first;
|
||||||
|
var runEnd = eventIndices.first;
|
||||||
var segmentIndex = 0;
|
var segmentIndex = 0;
|
||||||
|
|
||||||
void flush() {
|
void emitRun(int start, int end) {
|
||||||
if (segment.length >= 2) {
|
final expandedStart = start > 0 ? start - 1 : start;
|
||||||
|
final expandedEnd = end < samples.length - 1 ? end + 1 : end;
|
||||||
|
final points = <AppLatLng>[];
|
||||||
|
for (var i = expandedStart; i <= expandedEnd; i++) {
|
||||||
|
final sample = samples[i];
|
||||||
|
points.add(AppLatLng(sample.latitude!, sample.longitude!));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The surrounding point guarantees two points for an isolated event
|
||||||
|
// while preserving a single continuous segment for adjacent events.
|
||||||
|
if (points.length >= 2) {
|
||||||
polylines.add(AppPolyline(
|
polylines.add(AppPolyline(
|
||||||
id: '${idPrefix}_$segmentIndex',
|
id: '${idPrefix}_$segmentIndex',
|
||||||
points: List<AppLatLng>.from(segment),
|
points: points,
|
||||||
color: color,
|
color: color,
|
||||||
width: 7.0,
|
width: 7.0,
|
||||||
));
|
));
|
||||||
segmentIndex++;
|
segmentIndex++;
|
||||||
}
|
}
|
||||||
segment = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final sample in samples) {
|
for (var i = 1; i < eventIndices.length; i++) {
|
||||||
final g = sample.longitudinalG ?? sample.accelX;
|
final index = eventIndices[i];
|
||||||
if (g != null && g.isFinite && predicate(g)) {
|
// Keep nearby threshold samples in one event run. A gap of more than
|
||||||
segment.add(AppLatLng(sample.latitude!, sample.longitude!));
|
// two samples starts a new visual event while allowing brief sensor
|
||||||
|
// dropouts inside a hard maneuver.
|
||||||
|
if (index - runEnd <= 2) {
|
||||||
|
runEnd = index;
|
||||||
} else {
|
} else {
|
||||||
flush();
|
emitRun(runStart, runEnd);
|
||||||
|
runStart = runEnd = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flush();
|
emitRun(runStart, runEnd);
|
||||||
|
|
||||||
return polylines;
|
return polylines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue