package org.example;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

public class LttbUtils {
    /**
     * LTTB算法,用于优化抽样,入参为两个double值,第一个是时间戳,第二个是要抽样的变量值
     * @param data
     * @param threshold
     * @return
     */
    public static List<double[]> lttb(List<double[]> data, int threshold) {
        // Step 1: Sort the data by x-axis (ascending order)
        data.sort(Comparator.comparingDouble(a -> a[0]));

        // Step 2: Divide the data into buckets
        int bucketSize = (int) Math.ceil(data.size() / (double) threshold);
        List<List<double[]>> buckets = new ArrayList<>(bucketSize);
        for (int i = 0; i < data.size(); i += bucketSize) {
            buckets.add(data.subList(i, Math.min(i + bucketSize, data.size())));
        }

        // Step 3: Compute the largest triangle in each bucket
        List<double[]> result = new ArrayList<>(threshold);
        for (List<double[]> bucket : buckets) {
            if (bucket.size() < 3) {
                result.addAll(bucket);
                continue;
            }
            double areaMax = 0;
            int indexMax = 0;
            //增加极值
            //在找到每个 bucket 中最大三角形面积时,不仅记录最大面积和对应索引,还需要记录包含该最大面积的三角形的三个点。
            //将这些记录下来的三角形点加入结果集中,而不仅仅只是最大面积对应的点。
//            double[] p0Max = null;
//            double[] p1Max = null;
//            double[] p2Max = null;
            //
            for (int i = 1; i < bucket.size() - 1; i++) {
                double[] p0 = bucket.get(0);
                double[] p1 = bucket.get(i);
                double[] p2 = bucket.get(i + 1);
                double area = Math.abs((p1[0] - p0[0]) * (p2[1] - p0[1]) - (p2[0] - p0[0]) * (p1[1] - p0[1])) / 2.0;
                if (area > areaMax) {
                    areaMax = area;
                    indexMax = i;
                    //增加极值
//                    p0Max = p0;
//                    p1Max = p1;
//                    p2Max = p2;
                    //
                }
            }
            // 增加极值
//            if (p0Max != null)
//                result.add(p0Max);
//            if (p1Max != null)
//                result.add(p1Max);
//            if (p2Max != null)
//                result.add(p2Max);
            //
            result.add(bucket.get(indexMax));
        }

//        // Step 4: Interpolate the data points
//        LinearInterpolator interpolator = new LinearInterpolator();
//        PolynomialSplineFunction function = interpolator.interpolate(result.stream().mapToDouble(p -> p[0]).toArray(),
//                result.stream().mapToDouble(p -> p[1]).toArray());
//
//        // Step 5: Sample the interpolated function to get the final output
//        List<double[]> output = new ArrayList<>(threshold);
//        double step = (result.get(result.size() - 1)[0] - result.get(0)[0]) / (double) (threshold - 1);
//        for (int i = 0; i < threshold; i++) {
//            double x = result.get(0)[0] + i * step;
//            output.add(new double[]{x, function.value(x)});
//        }
//        return output;
        return result;
    }

    public static String formatTimestampToTime(double timestamp) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/M/d H:mm:ss");
        Date date = new Date((long) timestamp);
        return dateFormat.format(date);
    }

    public static double parseTimeToTimestamp(String timeString) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/M/d H:mm:ss");
        try {
            Date date = dateFormat.parse(timeString);
            return date.getTime(); // Convert milliseconds to seconds
        } catch (ParseException e) {
            e.printStackTrace();
            return 0; // Return 0 if parsing fails
        }
    }
}

更多推荐