Compare commits
2 Commits
239ca7c5b4
...
9180ad93cf
| Author | SHA1 | Date | |
|---|---|---|---|
| 9180ad93cf | |||
| 404b532d38 |
@@ -3,13 +3,21 @@ import 'dart:collection';
|
||||
import '../proto/messages.pb.dart';
|
||||
import 'packet_buffer.dart';
|
||||
|
||||
/// One column of decimated data. `hasData=false` means no packet contributed
|
||||
/// a value for this channel in the column's time slice.
|
||||
/// One column of decimated data.
|
||||
///
|
||||
/// Tri-state: a column is either
|
||||
/// - `hasData` — at least one packet in the slice carried this channel
|
||||
/// (renders as a line/min-max span),
|
||||
/// - `isGap` — a packet landed in the slice but had no value for this
|
||||
/// channel (renders as hatched missing-data),
|
||||
/// - neither — no packet at all fell in the slice (empty, skipped; the
|
||||
/// polyline interpolates across).
|
||||
class DecimatedColumn {
|
||||
const DecimatedColumn(this.min, this.max, this.hasData);
|
||||
const DecimatedColumn(this.min, this.max, this.hasData, this.isGap);
|
||||
final double min;
|
||||
final double max;
|
||||
final bool hasData;
|
||||
final bool isGap;
|
||||
}
|
||||
|
||||
/// Classification of a missing-data segment.
|
||||
@@ -82,14 +90,18 @@ class Decimator {
|
||||
final mins = List<double>.filled(pixelWidth, double.infinity);
|
||||
final maxs = List<double>.filled(pixelWidth, double.negativeInfinity);
|
||||
final has = List<bool>.filled(pixelWidth, false);
|
||||
final gap = List<bool>.filled(pixelWidth, false);
|
||||
|
||||
for (final p in buffer.iterateRange(startUs, endUs)) {
|
||||
final v = _channelValue(p, channel);
|
||||
if (v == null) continue;
|
||||
final tsUs = p.timestampUs.toInt();
|
||||
var col = ((tsUs - startUs) / pixUs).floor();
|
||||
if (col < 0) col = 0;
|
||||
if (col >= pixelWidth) col = pixelWidth - 1;
|
||||
final v = _channelValue(p, channel);
|
||||
if (v == null) {
|
||||
gap[col] = true;
|
||||
continue;
|
||||
}
|
||||
if (!has[col]) {
|
||||
mins[col] = v;
|
||||
maxs[col] = v;
|
||||
@@ -101,7 +113,9 @@ class Decimator {
|
||||
}
|
||||
return List.generate(
|
||||
pixelWidth,
|
||||
(i) => DecimatedColumn(mins[i], maxs[i], has[i]),
|
||||
// A column with at least one value renders as data even if some other
|
||||
// packet in the same slice was missing the field.
|
||||
(i) => DecimatedColumn(mins[i], maxs[i], has[i], gap[i] && !has[i]),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -136,7 +150,7 @@ class Decimator {
|
||||
final hatched = <({int startPx, int endPx})>[];
|
||||
int? gapStart;
|
||||
for (var i = 0; i < cols.length; i++) {
|
||||
if (!cols[i].hasData) {
|
||||
if (cols[i].isGap) {
|
||||
gapStart ??= i;
|
||||
} else if (gapStart != null) {
|
||||
hatched.add((startPx: gapStart, endPx: i - 1));
|
||||
|
||||
@@ -106,10 +106,14 @@ class ChartPainter extends CustomPainter {
|
||||
bool started = false;
|
||||
for (var i = 0; i < cols.length; i++) {
|
||||
final c = cols[i];
|
||||
if (!c.hasData) {
|
||||
// Real missing-data gap: break the polyline.
|
||||
if (c.isGap) {
|
||||
started = false;
|
||||
continue;
|
||||
}
|
||||
// Empty column (no packet fell here — sub-packet-period zoom). Let the
|
||||
// path interpolate across.
|
||||
if (!c.hasData) continue;
|
||||
final x = xForCol(i);
|
||||
final yMinPx = yForVal(c.max); // Higher value = smaller y.
|
||||
final yMaxPx = yForVal(c.min);
|
||||
|
||||
@@ -85,11 +85,17 @@ class _PpsPill extends StatelessWidget {
|
||||
return Row(mainAxisSize: MainAxisSize.min, children: [
|
||||
const Text('PPS ',
|
||||
style: TextStyle(fontSize: 11, color: Colors.grey)),
|
||||
Text(pps.round().toString(),
|
||||
SizedBox(
|
||||
width: 32,
|
||||
child: Text(
|
||||
pps.round().toString(),
|
||||
textAlign: TextAlign.right,
|
||||
style: const TextStyle(
|
||||
fontFamily: 'monospace',
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w500)),
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -147,7 +153,14 @@ class _StatusPill extends StatelessWidget {
|
||||
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||
_Dot(dot, size: 7),
|
||||
const SizedBox(width: 5),
|
||||
Text(text, style: TextStyle(fontSize: 10, color: fg)),
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontFamily: 'monospace',
|
||||
fontSize: 10,
|
||||
color: fg,
|
||||
),
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user