This is an automated email from the ASF dual-hosted git repository.

leirui pushed a commit to branch research/area-visualization
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit b9109823f632b659bc1c3a1a1077765c1a7d1864
Author: Lei Rui <[email protected]>
AuthorDate: Thu Dec 19 23:40:45 2024 +0800

    add standard implementation
---
 .../groupby/LocalGroupByExecutorTri_Visval.java    |   4 +-
 .../query/simpiece/{Visval.java => VisvalOld.java} |  24 ++-
 .../iotdb/db/query/simpiece/Visval_standard.java   | 202 +++++++++++++++++++++
 3 files changed, 227 insertions(+), 3 deletions(-)

diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/LocalGroupByExecutorTri_Visval.java
 
b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/LocalGroupByExecutorTri_Visval.java
index 8cb330812a6..40793c6651b 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/LocalGroupByExecutorTri_Visval.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/LocalGroupByExecutorTri_Visval.java
@@ -32,7 +32,7 @@ import org.apache.iotdb.db.query.control.QueryResourceManager;
 import org.apache.iotdb.db.query.filter.TsFileFilter;
 import org.apache.iotdb.db.query.reader.series.SeriesReader;
 import org.apache.iotdb.db.query.simpiece.TimeSeriesReader;
-import org.apache.iotdb.db.query.simpiece.Visval;
+import org.apache.iotdb.db.query.simpiece.VisvalOld;
 import org.apache.iotdb.db.query.simpiece.VisvalPoint;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.statistics.MinMaxInfo;
@@ -135,7 +135,7 @@ public class LocalGroupByExecutorTri_Visval implements 
GroupByExecutor {
     }
 
     // Visval
-    List<VisvalPoint> reducedPoints = Visval.reducePoints(points, m);
+    List<VisvalPoint> reducedPoints = VisvalOld.reducePoints(points, m);
 
     for (VisvalPoint p : reducedPoints) {
       series.append(p.y).append("[").append(p.x).append("]").append(",");
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/simpiece/Visval.java 
b/server/src/main/java/org/apache/iotdb/db/query/simpiece/VisvalOld.java
similarity index 70%
rename from server/src/main/java/org/apache/iotdb/db/query/simpiece/Visval.java
rename to server/src/main/java/org/apache/iotdb/db/query/simpiece/VisvalOld.java
index 62b3019edac..9f6e80897b0 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/simpiece/Visval.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/simpiece/VisvalOld.java
@@ -19,10 +19,12 @@
 
 package org.apache.iotdb.db.query.simpiece;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Random;
 import java.util.concurrent.ConcurrentSkipListMap;
 
-public class Visval {
+public class VisvalOld {
 
   public static List<VisvalPoint> reducePoints(List<VisvalPoint> points, int 
targetCount) {
     if (points.size() <= targetCount) {
@@ -39,6 +41,8 @@ public class Visval {
     }
 
     while (points.size() > targetCount) {
+      // 这里有个问题:points 
remove和heap不对齐,因为有可能heap里有多个点的area相同就一起被remove了,但是points里还没有remove
+      System.out.println(points.size());
       VisvalPoint p = minHeap.pollFirstEntry().getValue();
       if (p == null) {
         return points;
@@ -67,4 +71,22 @@ public class Visval {
   private static double calculateArea(VisvalPoint a, VisvalPoint b, 
VisvalPoint c) {
     return Math.abs(a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)) 
/ 2.0;
   }
+
+  public static void main(String[] args) {
+    List<VisvalPoint> points = new ArrayList<>();
+    // 添加点到列表 points 100万数据
+    Random rand = new Random();
+    int n = 10000;
+    int m = 1;
+    for (int i = 0; i < n; i++) {
+      points.add(new VisvalPoint(i, rand.nextInt(1000)));
+    }
+    // 计算运行时间
+    long startTime = System.currentTimeMillis();
+    List<VisvalPoint> reducedPoints = VisvalOld.reducePoints(points, m);
+    // 输出结果
+    System.out.println(reducedPoints.size());
+    long endTime = System.currentTimeMillis();
+    System.out.println("Time taken to reduce points: " + (endTime - startTime) 
+ "ms");
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/simpiece/Visval_standard.java 
b/server/src/main/java/org/apache/iotdb/db/query/simpiece/Visval_standard.java
new file mode 100644
index 00000000000..98fdb790057
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/simpiece/Visval_standard.java
@@ -0,0 +1,202 @@
+package org.apache.iotdb.db.query.simpiece;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.PriorityQueue;
+import java.util.Random;
+
+// adapted from the open source C++ code 
https://github.com/ofZach/Visvalingam-Whyatt/blob/master/src/testApp.cpp
+class Triangle {
+
+  int[] indices = new int[3];
+  double area;
+  Triangle prev;
+  Triangle next;
+
+  public Triangle(int index1, int index2, int index3, double area) {
+    this.indices[0] = index1;
+    this.indices[1] = index2;
+    this.indices[2] = index3;
+    this.area = area;
+  }
+}
+
+class vPoint {
+
+  double x, y, z;
+
+  public vPoint(double x, double y) {
+    this.x = x;
+    this.y = y;
+    this.z = Double.POSITIVE_INFINITY;// effective area
+  }
+}
+
+class Polyline {
+
+  private List<vPoint> vertices = new ArrayList<>();
+
+  public void addVertex(vPoint point) {
+    vertices.add(point);
+  }
+
+  public List<vPoint> getVertices() {
+    return new ArrayList<>(vertices);
+  }
+
+  public int size() {
+    return vertices.size();
+  }
+
+  public vPoint get(int index) {
+    return vertices.get(index);
+  }
+}
+
+public class Visval_standard {
+
+  // 计算三角形面积
+  private static double triArea(vPoint d0, vPoint d1, vPoint d2) {
+    double dArea = ((d1.x - d0.x) * (d2.y - d0.y) - (d2.x - d0.x) * (d1.y - 
d0.y)) / 2.0;
+    return (double) ((dArea > 0.0) ? dArea : -dArea); // abs
+  }
+
+  public static void buildEffectiveArea(Polyline lineToSimplify, List<vPoint> 
results) {
+    results.clear();
+    results.addAll(lineToSimplify.getVertices());
+
+    int total = lineToSimplify.size();
+    if (total < 3) {
+      return; // 不足 3 个点无法形成三角形
+    }
+
+    int nTriangles = total - 2;
+    Triangle[] triangles = new Triangle[nTriangles];
+
+    // 创建所有三角形并计算初始面积
+    for (int i = 1; i < total - 1; i++) {
+      int index1 = i - 1, index2 = i, index3 = i + 1;
+      double area = triArea(lineToSimplify.get(index1), 
lineToSimplify.get(index2),
+          lineToSimplify.get(index3));
+      triangles[i - 1] = new Triangle(index1, index2, index3, area);
+    }
+
+    // 设置三角形的前后关系
+    for (int i = 0; i < nTriangles; i++) {
+      triangles[i].prev = (i == 0 ? null : triangles[i - 1]);
+      triangles[i].next = (i == nTriangles - 1 ? null : triangles[i + 1]);
+    }
+
+    // 使用优先队列构建 minHeap
+    PriorityQueue<Triangle> triangleHeap = new PriorityQueue<>(
+        Comparator.comparingDouble(t -> t.area));
+    Collections.addAll(triangleHeap, triangles);
+
+    double previousEA = -1;
+    while (!triangleHeap.isEmpty()) {
+      // 注意peek只需要直接访问该位置的元素,不涉及任何重排或堆化操作
+      // 而poll是删除堆顶元素,需要重新堆化以维护堆的性质,复杂度是O(logk),k是当前堆的大小
+      Triangle tri = triangleHeap.poll();
+
+      // 更新当前点的重要性(z 轴存储effective area,这是一个单调增的指标)
+      if (tri.area > previousEA) {
+        previousEA = tri.area;
+      }
+      results.get(tri.indices[1]).z = previousEA;
+//      System.out.println(tri.indices[1] + "," + previousEA);
+
+      // 更新相邻三角形
+      if (tri.prev != null) {
+        // 前一个三角形连到后一个三角形
+        tri.prev.next = tri.next;
+        tri.prev.indices[2] = tri.indices[2];
+        tri.prev.area = triArea(
+            lineToSimplify.get(tri.prev.indices[0]),
+            lineToSimplify.get(tri.prev.indices[1]),
+            lineToSimplify.get(tri.prev.indices[2])
+        );
+
+        // 重新加入堆
+        // 在 Java 的 PriorityQueue 中,修改元素的属性不会自动更新堆的顺序
+        // 所以必须通过 remove 和 add 来显式重新插入修改后的元素
+        triangleHeap.remove(tri.prev);
+        triangleHeap.add(tri.prev);
+      }
+
+      if (tri.next != null) {
+        // 后一个三角形连到前一个三角形
+        tri.next.prev = tri.prev;
+        tri.next.indices[0] = tri.indices[0];
+        tri.next.area = triArea(
+            lineToSimplify.get(tri.next.indices[0]),
+            lineToSimplify.get(tri.next.indices[1]),
+            lineToSimplify.get(tri.next.indices[2])
+        );
+
+        // 重新加入堆
+        triangleHeap.remove(tri.next);
+        triangleHeap.add(tri.next);
+      }
+    }
+  }
+
+  public static void main(String[] args) {
+    Polyline polyline = new Polyline();
+//    polyline.addVertex(new ofPoint(0, 0));
+//    polyline.addVertex(new ofPoint(1, 0));
+//    polyline.addVertex(new ofPoint(1, 1));
+//    polyline.addVertex(new ofPoint(0, 1));
+
+    Random rand = new Random();
+    int n = 10000;
+    for (int i = 0; i < n; i++) {
+      polyline.addVertex(new vPoint(i, rand.nextInt(1000)));
+    }
+
+//    float[] vlist = new float[]{11346, 33839, 35469, 23108, 22812, 5519, 
5526, 4865, 5842, 23089};
+//    for (int i = 0; i < vlist.length; i++) {
+//      polyline.addVertex(new vPoint(i, vlist[i]));
+//    }
+
+//    ArrayList<Double> v = new ArrayList<>();
+//    String filePath = "D://desktop//数据集//New York Stock 
Exchange//merged_prices.csv";
+//    try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
+//      String line;
+//      int count = 0;
+//      while ((line = br.readLine()) != null && count < 1000) {
+//        String[] columns = line.split(","); // 假设 CSV 文件以逗号分隔
+//        v.add(Double.parseDouble(columns[0])); // 读取第一列数据
+//        count++;
+//      }
+//    } catch (Exception e) {
+//      e.printStackTrace();
+//    }
+//    // 打印数据长度
+//    System.out.println("Data length: " + v.size());
+//    for (int i = 0; i < v.size(); i++) {
+//      polyline.addVertex(new vPoint(i, v.get(i)));
+//    }
+
+    List<vPoint> results = new ArrayList<>();
+
+    // 计算运行时间
+    long startTime = System.currentTimeMillis();
+
+    buildEffectiveArea(polyline, results);
+
+    // 输出结果
+    long endTime = System.currentTimeMillis();
+    System.out.println("Time taken to reduce points: " + (endTime - startTime) 
+ "ms");
+    System.out.println(results.size());
+
+//    for (int i = 0; i < results.size(); i++) {
+//      vPoint point = results.get(i);
+//      System.out.println("Point: (" + point.x + ", " + point.y + ", " + 
point.z + ")");
+//    }
+  }
+}
+

Reply via email to