105 lines
2.7 KiB
Dart
105 lines
2.7 KiB
Dart
|
|
// Tests for RDP stroke simplification (R1/R10 perf).
|
||
|
|
|
||
|
|
import 'package:flutter_test/flutter_test.dart';
|
||
|
|
|
||
|
|
import 'package:badnote/editor/engine/stroke_model.dart';
|
||
|
|
import 'package:badnote/editor/engine/stroke_simplify.dart';
|
||
|
|
|
||
|
|
EditorStroke _stroke(List<List<double>> pts, {List<double?>? pressures}) =>
|
||
|
|
EditorStroke.create(
|
||
|
|
id: 's',
|
||
|
|
points: [
|
||
|
|
for (var i = 0; i < pts.length; i++)
|
||
|
|
EditorPoint(
|
||
|
|
x: pts[i][0],
|
||
|
|
y: pts[i][1],
|
||
|
|
pressure: pressures?[i],
|
||
|
|
),
|
||
|
|
],
|
||
|
|
);
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
test('collinear points collapse to the two endpoints', () {
|
||
|
|
final s = _stroke([
|
||
|
|
[0.0, 0.0],
|
||
|
|
[0.1, 0.1],
|
||
|
|
[0.2, 0.2],
|
||
|
|
[0.3, 0.3],
|
||
|
|
]);
|
||
|
|
final out = simplifyStroke(s, tolerance: 0.0008);
|
||
|
|
expect(out.points.length, 2);
|
||
|
|
expect(out.points.first.x, 0.0);
|
||
|
|
expect(out.points.last.x, 0.3);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('a perceptually significant peak is kept', () {
|
||
|
|
final s = _stroke([
|
||
|
|
[0.0, 0.0],
|
||
|
|
[0.5, 0.5], // far off the (0,0)-(1,0) line → kept
|
||
|
|
[1.0, 0.0],
|
||
|
|
]);
|
||
|
|
final out = simplifyStroke(s, tolerance: 0.0008);
|
||
|
|
expect(out.points.length, 3);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('a deviation within tolerance is dropped', () {
|
||
|
|
final s = _stroke([
|
||
|
|
[0.0, 0.0],
|
||
|
|
[0.5, 0.0001], // perp dist 0.0001 < 0.0008 → dropped
|
||
|
|
[1.0, 0.0],
|
||
|
|
]);
|
||
|
|
final out = simplifyStroke(s, tolerance: 0.0008);
|
||
|
|
expect(out.points.length, 2);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('<= 2 points are returned unchanged (same instance)', () {
|
||
|
|
final s = _stroke([
|
||
|
|
[0.1, 0.1],
|
||
|
|
[0.2, 0.2],
|
||
|
|
]);
|
||
|
|
expect(identical(simplifyStroke(s), s), isTrue);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('non-positive tolerance is a no-op', () {
|
||
|
|
final s = _stroke([
|
||
|
|
[0.0, 0.0],
|
||
|
|
[0.1, 0.11],
|
||
|
|
[0.2, 0.2],
|
||
|
|
]);
|
||
|
|
expect(identical(simplifyStroke(s, tolerance: 0), s), isTrue);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('pressure rides along on retained points', () {
|
||
|
|
final s = _stroke([
|
||
|
|
[0.0, 0.0],
|
||
|
|
[0.5, 0.5],
|
||
|
|
[1.0, 0.0],
|
||
|
|
], pressures: [
|
||
|
|
0.2,
|
||
|
|
0.9,
|
||
|
|
0.3,
|
||
|
|
]);
|
||
|
|
final out = simplifyStroke(s, tolerance: 0.0008);
|
||
|
|
expect(out.points.map((p) => p.pressure), [0.2, 0.9, 0.3]);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('metadata (color/width/tool/id) is preserved', () {
|
||
|
|
final s = EditorStroke.create(
|
||
|
|
id: 'keep-me',
|
||
|
|
color: 0xFF112233,
|
||
|
|
width: 0.02,
|
||
|
|
tool: EditorTool.highlighter,
|
||
|
|
points: [
|
||
|
|
const EditorPoint(x: 0, y: 0),
|
||
|
|
const EditorPoint(x: 0.1, y: 0.1),
|
||
|
|
const EditorPoint(x: 0.2, y: 0.2),
|
||
|
|
],
|
||
|
|
);
|
||
|
|
final out = simplifyStroke(s, tolerance: 0.0008);
|
||
|
|
expect(out.id, 'keep-me');
|
||
|
|
expect(out.color, 0xFF112233);
|
||
|
|
expect(out.width, 0.02);
|
||
|
|
expect(out.tool, EditorTool.highlighter);
|
||
|
|
});
|
||
|
|
}
|