douglasPeucker function
Ramer-Douglas-Peucker algorithm implementation. Reduces number of points while preserving the overall shape.
Implementation
List<MapEntry<DateTime, double>> douglasPeucker(
List<MapEntry<DateTime, double>> points,
int targetCount,
) {
if (points.length <= targetCount) return points;
// Calculate appropriate epsilon (tolerance) based on data range.
final values = points.map((e) => e.value).toList();
final minVal = values.reduce((a, b) => a < b ? a : b);
final maxVal = values.reduce((a, b) => a > b ? a : b);
final range = maxVal - minVal;
// Start with a small epsilon and increase until we reach target count.
var epsilon = range * 0.01;
var result = rdpRecursive(points, epsilon);
// Adjust epsilon to get closer to target count.
var iterations = 0;
while (result.length > targetCount && iterations < 10) {
epsilon *= 1.5;
result = rdpRecursive(points, epsilon);
iterations++;
}
// If still too many points, fall back to uniform sampling.
if (result.length > targetCount) {
final step = result.length / targetCount;
final uniformSampled = <MapEntry<DateTime, double>>[];
for (var i = 0; i < targetCount; i++) {
final index = (i * step).round();
if (index < result.length) {
uniformSampled.add(result[index]);
}
}
return uniformSampled;
}
return result;
}