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 6857dc2e13d65bbe6b074cc49593c85a1d057eb2 Author: Lei Rui <[email protected]> AuthorDate: Tue Jan 21 17:16:58 2025 +0800 add ad --- .../java/org/apache/iotdb/db/query/eBUG/Point.java | 17 ++ .../org/apache/iotdb/db/query/eBUG/Polyline.java | 25 ++ .../java/org/apache/iotdb/db/query/eBUG/Tool.java | 198 +++++++++++++++ .../org/apache/iotdb/db/query/eBUG/Triangle.java | 49 ++++ .../query/{simpiece => eBUG}/Visval_standard.java | 174 ++++--------- .../Visval_standard.java => eBUG/eBUG.java} | 282 ++++++++++----------- 6 files changed, 480 insertions(+), 265 deletions(-) diff --git a/server/src/main/java/org/apache/iotdb/db/query/eBUG/Point.java b/server/src/main/java/org/apache/iotdb/db/query/eBUG/Point.java new file mode 100644 index 00000000000..77ebdb4cb39 --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/query/eBUG/Point.java @@ -0,0 +1,17 @@ +package org.apache.iotdb.db.query.eBUG; + +public class Point { + + double x, y, z; + + public Point(double x, double y) { + this.x = x; + this.y = y; + this.z = Double.POSITIVE_INFINITY; // effective area + } + + @Override + public String toString() { + return "Point: (" + x + ", " + y + ", " + z + ")"; + } +} diff --git a/server/src/main/java/org/apache/iotdb/db/query/eBUG/Polyline.java b/server/src/main/java/org/apache/iotdb/db/query/eBUG/Polyline.java new file mode 100644 index 00000000000..b6e2f231c14 --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/query/eBUG/Polyline.java @@ -0,0 +1,25 @@ +package org.apache.iotdb.db.query.eBUG; + +import java.util.ArrayList; +import java.util.List; + +public class Polyline { + + private List<Point> vertices = new ArrayList<>(); + + public void addVertex(Point point) { + vertices.add(point); + } + + public List<Point> getVertices() { + return new ArrayList<>(vertices); + } + + public int size() { + return vertices.size(); + } + + public Point get(int index) { + return vertices.get(index); + } +} diff --git a/server/src/main/java/org/apache/iotdb/db/query/eBUG/Tool.java b/server/src/main/java/org/apache/iotdb/db/query/eBUG/Tool.java new file mode 100644 index 00000000000..48c1544e76b --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/query/eBUG/Tool.java @@ -0,0 +1,198 @@ +package org.apache.iotdb.db.query.eBUG; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Tool { + // 计算三角形面积 + public static double triArea(Point d0, Point d1, Point d2) { + double dArea = ((d1.x - d0.x) * (d2.y - d0.y) - (d2.x - d0.x) * (d1.y - d0.y)) / 2.0; + return (dArea > 0.0) ? dArea : -dArea; // abs + } + + // 计算多边形面积(鞋带公式) + public static double calculatePolygonArea(List<Point> points) { + // points多边形顶点,按照逆时针或者顺时针的顺序枚举 + int n = points.size(); + double area = 0; + for (int i = 0; i < n; i++) { + int next = (i + 1) % n; + area += points.get(i).x * points.get(next).y - points.get(next).x * points.get(i).y; + } + return Math.abs(area) / 2.0; + } + + // 计算两个向量的叉积 + public static double crossProduct(double x1, double y1, double x2, double y2) { + // >0: (x2,y2)在(x1,y1)的逆时针方向 + // <0: (x2,y2)在(x1,y1)的顺时针方向 + // =0: 平行或共线 + return x1 * y2 - y1 * x2; + } + + // 判断两条线段是否相交并计算交点 + // L1包含一个线段的两个端点,L2包含另一个线段的两个端点 + public static Object[] lineIntersection(Point[] L1, Point[] L2) { + double x1 = L1[0].x, y1 = L1[0].y, x2 = L1[1].x, y2 = L1[1].y; + double x3 = L2[0].x, y3 = L2[0].y, x4 = L2[1].x, y4 = L2[1].y; + + // 判断是否相交(叉积) + double d1 = crossProduct(x2 - x1, y2 - y1, x3 - x1, y3 - y1); + double d2 = crossProduct(x2 - x1, y2 - y1, x4 - x1, y4 - y1); + double d3 = crossProduct(x4 - x3, y4 - y3, x1 - x3, y1 - y3); + double d4 = crossProduct(x4 - x3, y4 - y3, x2 - x3, y2 - y3); + + // 如果叉积条件满足,表示有交点 + // d1*d2<0意味着P3、P4分别在L12的两边 + // d3*d4<0意味着P1、P2分别在L34的两边 + // 两个同时满足说明有交点 + if (d1 * d2 < 0 && d3 * d4 < 0) { + double denominator = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); // 不可能为0(平行或共线),因为已经判断相交了 + double t1 = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator; + double x = x1 + t1 * (x2 - x1); + double y = y1 + t1 * (y2 - y1); + return new Object[]{true, new Point(x, y)}; + } + + // 检查是否起点或终点重合 + if ((x1 == x3 && y1 == y3) || (x1 == x4 && y1 == y4)) { + return new Object[]{true, new Point(x1, y1)}; + } + if ((x2 == x3 && y2 == y3) || (x2 == x4 && y2 == y4)) { + return new Object[]{true, new Point(x2, y2)}; + } + + return new Object[]{false, null}; + } + + // 计算总的多边形面积(通过时间序列扫描交点) + public static double total_areal_displacement(List<Point> points, List<Point> points2, boolean debug) { + double totalArea = 0; + int i = 0, j = 0; // i for points, j for points2 + Point prevIntersection = null; + int prevI = -1, prevJ = -1; + +// List<double[]> intersectionCoords = new ArrayList<>(); + List<Double> areaList = new ArrayList<>(); + + while (i < points.size() - 1 && j < points2.size() - 1) { + if (debug) { + System.out.println("--------- " + i + " " + j + " ------------"); + } + + // 当前线段 + Point[] L1 = {points.get(i), points.get(i + 1)}; + Point[] L2 = {points2.get(j), points2.get(j + 1)}; + + // 判断是否有交点 + Object[] result = lineIntersection(L1, L2); + boolean isIntersect = (boolean) result[0]; + Point intersection = (Point) result[1]; + + if (isIntersect) { +// intersectionCoords.add(intersection); + + if (prevIntersection != null) { + // 构造多边形点集 + List<Point> polygon = new ArrayList<>(); // 按照顺时针/逆时针几何连接顺序枚举多边形的顶点 + polygon.add(prevIntersection); + if (debug) { + System.out.println("- start intersection: " + prevIntersection); + } + polygon.addAll(points.subList(prevI, i + 1)); // 添加当前线段的点,左闭右开 +// polygon.addAll(Arrays.asList(Arrays.copyOfRange(points, prevI, i + 1))); // 添加当前线段的点,左闭右开 + if (debug) { + System.out.println("- one side: " + points.subList(prevI, i + 1)); + } + polygon.add(intersection); + if (debug) { + System.out.println("- end intersection: " + intersection); + } + List<Point> tempPoints2 = points2.subList(prevJ, j + 1); + Collections.reverse(tempPoints2); // 添加另一序列的点 + polygon.addAll(tempPoints2); + if (debug) { + System.out.println("- another side: " + tempPoints2); + } + +// double[][] polygonArray = new double[polygon.size()][2]; +// for (int k = 0; k < polygon.size(); k++) { +// polygonArray[k] = polygon.get(k); +// } + + // 计算多边形面积 + double area = calculatePolygonArea(polygon); + if (debug) { + System.out.println("Area = " + area); + } + totalArea += area; + areaList.add(area); + } + + prevIntersection = intersection; + prevI = i + 1; + prevJ = j + 1; + if (debug) { + System.out.println("This intersection = " + intersection + + ", next polygon: side1 = " + prevI + ", side2 = " + prevJ); + } + } + + + int currentI = i; // 临时存储i + int currentJ = j; // 临时存储j + if (points.get(currentI + 1).x <= points2.get(currentJ + 1).x) { + i += 1; // 基于时间戳严格递增的假设,Line不会回头或者垂直 + } + if (points.get(currentI + 1).x >= points2.get(currentJ + 1).x) { + j += 1; // 基于时间戳严格递增的假设,Line不会回头或者垂直 + } + } // end of while + + if (debug) { + System.out.println(areaList); + } + + return totalArea; + } + + // 测试方法 + public static void main(String[] args) { + // 示例数据 + List<Point> points = new ArrayList<>(); + points.add(new Point(0, 0)); + points.add(new Point(1, 2)); + points.add(new Point(2, -20)); + points.add(new Point(3, 0)); + points.add(new Point(4, -1)); + points.add(new Point(5, -1.5)); + points.add(new Point(6, 0)); + + List<Point> points2 = new ArrayList<>(); + points2.add(points.get(0)); + points2.add(points.get(3)); + points2.add(points.get(6)); +// points2.add(points.get(5)); + + double area = total_areal_displacement(points, points2, true); + System.out.println("Total area: " + area); + +// points = new ArrayList<>(); +// points.add(new Point(0, 0)); +// points.add(new Point(1, 2)); +// points.add(new Point(1.5, -10)); +// double area = calculatePolygonArea(points); +// System.out.println(area); +// +// Point[] L1 = new Point[2]; +// L1[0] = new Point(1, 2); +// L1[1] = new Point(2, -2); +// Point[] L2 = new Point[2]; +// L2[0] = new Point(0, 0); +// L2[1] = new Point(3, 0); +// Object[] res = lineIntersection(L1, L2); +// System.out.println(res[1]); + } +} diff --git a/server/src/main/java/org/apache/iotdb/db/query/eBUG/Triangle.java b/server/src/main/java/org/apache/iotdb/db/query/eBUG/Triangle.java new file mode 100644 index 00000000000..79f7d440c99 --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/query/eBUG/Triangle.java @@ -0,0 +1,49 @@ +package org.apache.iotdb.db.query.eBUG; + +// adapted from the open source C++ code +// https://github.com/ofZach/Visvalingam-Whyatt/blob/master/src/testApp.cpp +public class Triangle { + + int[] indices = new int[3]; + double area; + Triangle prev; + Triangle next; + boolean isDeleted; + + 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; + this.isDeleted = false; // flag for removal. Avoid using heap.remove(x) as it is O(n) complexity + } + + public Triangle(Triangle oldTri) { + // deep copy and inherit connection + + this.indices[0] = oldTri.indices[0]; + this.indices[1] = oldTri.indices[1]; + this.indices[2] = oldTri.indices[2]; + this.area = oldTri.area; + this.prev = oldTri.prev; + this.next = oldTri.next; + + // TODO important! inherit connection relationship to this new point + if (this.prev != null) { // previous point to this new point + this.prev.next = this; + } + if (this.next != null) { // next point to this new point + this.next.prev = this; + } + + this.isDeleted = false; // this new triangle is not deleted + } + + public boolean isValid() { + return !isDeleted; + } + + public void markDeleted() { + this.isDeleted = true; + } +} 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/eBUG/Visval_standard.java similarity index 72% copy from server/src/main/java/org/apache/iotdb/db/query/simpiece/Visval_standard.java copy to server/src/main/java/org/apache/iotdb/db/query/eBUG/Visval_standard.java index 4edf126b531..a85332d3846 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/simpiece/Visval_standard.java +++ b/server/src/main/java/org/apache/iotdb/db/query/eBUG/Visval_standard.java @@ -17,102 +17,18 @@ * under the License. */ -package org.apache.iotdb.db.query.simpiece; +package org.apache.iotdb.db.query.eBUG; import java.io.FileWriter; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; -// 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; - boolean isDeleted; - - 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; - this.isDeleted = false; // flag for removal. Avoid using heap.remove(x) as it is O(n) complexity - } - - public Triangle(Triangle oldTri) { - // deep copy and inherit connection - - this.indices[0] = oldTri.indices[0]; - this.indices[1] = oldTri.indices[1]; - this.indices[2] = oldTri.indices[2]; - this.area = oldTri.area; - this.prev = oldTri.prev; - this.next = oldTri.next; - - // TODO important! inherit connection relationship to this new point - if (this.prev != null) { // previous point to this new point - this.prev.next = this; - } - if (this.next != null) { // next point to this new point - this.next.prev = this; - } - - this.isDeleted = false; // this new triangle is not deleted - } - - public boolean isValid() { - return !isDeleted; - } - - public void markDeleted() { - this.isDeleted = true; - } -} - -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); - } -} +import static org.apache.iotdb.db.query.eBUG.Tool.triArea; 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) { + public static void buildEffectiveArea(Polyline lineToSimplify, List<Point> results) { results.clear(); results.addAll(lineToSimplify.getVertices()); // TODO debug @@ -216,37 +132,37 @@ public class Visval_standard { Polyline polyline = new Polyline(); List<Polyline> polylineList = new ArrayList<>(); Random rand = new Random(1); - int n = 100_0000; + int n = 10_0000; - int p = 1000; + int p = 700; for (int i = 0; i < n; i += p) { Polyline polylineBatch = new Polyline(); for (int j = i; j < Math.min(i + p, n); j++) { double v = rand.nextInt(1000000); - polyline.addVertex(new vPoint(j, v)); + polyline.addVertex(new Point(j, v)); - polylineBatch.addVertex(new vPoint(j, v)); + polylineBatch.addVertex(new Point(j, v)); } polylineList.add(polylineBatch); } -// try (FileWriter writer = new FileWriter("raw.csv")) { -// // 写入CSV头部 -// writer.append("x,y,z\n"); -// -// // 写入每个点的数据 -// for (int i = 0; i < polyline.size(); i++) { -// vPoint point = polyline.get(i); -// writer.append(point.x + "," + point.y + "," + point.z + "\n"); -// } -// System.out.println("Data has been written"); -// } catch (IOException e) { -// System.out.println("Error writing to CSV file: " + e.getMessage()); -// } + try (FileWriter writer = new FileWriter("raw.csv")) { + // 写入CSV头部 + writer.append("x,y,z\n"); + + // 写入每个点的数据 + for (int i = 0; i < polyline.size(); i++) { + Point point = polyline.get(i); + writer.append(point.x + "," + point.y + "," + point.z + "\n"); + } + System.out.println("Data has been written"); + } catch (IOException e) { + System.out.println("Error writing to CSV file: " + e.getMessage()); + } System.out.println("---------------------------------"); - List<vPoint> results = new ArrayList<>(); + List<Point> results = new ArrayList<>(); // 计算运行时间 long startTime = System.currentTimeMillis(); buildEffectiveArea(polyline, results); @@ -258,32 +174,32 @@ public class Visval_standard { if (results.size() <= 100) { System.out.println("+++++++++++++++++++"); for (int i = 0; i < results.size(); i++) { - vPoint point = results.get(i); + Point point = results.get(i); System.out.println("Point: (" + point.x + ", " + point.y + ", " + point.z + ")"); } } -// try (FileWriter writer = new FileWriter("fast.csv")) { -// // 写入CSV头部 -// writer.append("x,y,z\n"); -// -// // 写入每个点的数据 -// for (int i = 0; i < results.size(); i++) { -// vPoint point = results.get(i); -// writer.append(point.x + "," + point.y + "," + point.z + "\n"); -// } -// System.out.println("Data has been written"); -// } catch (IOException e) { -// System.out.println("Error writing to CSV file: " + e.getMessage()); -// } + try (FileWriter writer = new FileWriter("fast.csv")) { + // 写入CSV头部 + writer.append("x,y,z\n"); + + // 写入每个点的数据 + for (int i = 0; i < results.size(); i++) { + Point point = results.get(i); + writer.append(point.x + "," + point.y + "," + point.z + "\n"); + } + System.out.println("Data has been written"); + } catch (IOException e) { + System.out.println("Error writing to CSV file: " + e.getMessage()); + } System.out.println("---------------------------------"); - List<List<vPoint>> resultsBatchList = new ArrayList<>(); + List<List<Point>> resultsBatchList = new ArrayList<>(); // 计算运行时间 int cnt = 0; startTime = System.currentTimeMillis(); for (Polyline polylineBatch : polylineList) { - List<vPoint> resultsBatch = new ArrayList<>(); + List<Point> resultsBatch = new ArrayList<>(); buildEffectiveArea(polylineBatch, resultsBatch); cnt += resultsBatch.size(); resultsBatchList.add(resultsBatch); @@ -295,7 +211,7 @@ public class Visval_standard { System.out.println("---------------------------------"); // 使用 Stream API 合并所有列表 - List<vPoint> mergedList = + List<Point> mergedList = resultsBatchList.stream().flatMap(List::stream).collect(Collectors.toList()); int sameCnt = 0; for (int i = 0; i < mergedList.size(); i++) { @@ -304,6 +220,20 @@ public class Visval_standard { } } System.out.println("sameCnt=" + sameCnt + ", percent=" + sameCnt * 1.0 / mergedList.size()); + + try (FileWriter writer = new FileWriter("batch.csv")) { + // 写入CSV头部 + writer.append("x,y,z\n"); + + // 写入每个点的数据 + for (int i = 0; i < mergedList.size(); i++) { + Point point = mergedList.get(i); + writer.append(point.x + "," + point.y + "," + point.z + "\n"); + } + System.out.println("Data has been written"); + } catch (IOException e) { + System.out.println("Error writing to CSV file: " + e.getMessage()); + } } // float[] vlist = new float[]{11346, 33839, 35469, 23108, 22812, 5519, 5526, 4865, 5842, 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/eBUG/eBUG.java similarity index 57% rename from server/src/main/java/org/apache/iotdb/db/query/simpiece/Visval_standard.java rename to server/src/main/java/org/apache/iotdb/db/query/eBUG/eBUG.java index 4edf126b531..cc512cbcc9c 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/simpiece/Visval_standard.java +++ b/server/src/main/java/org/apache/iotdb/db/query/eBUG/eBUG.java @@ -17,105 +17,50 @@ * under the License. */ -package org.apache.iotdb.db.query.simpiece; +package org.apache.iotdb.db.query.eBUG; import java.io.FileWriter; import java.io.IOException; import java.util.*; -import java.util.stream.Collectors; - -// 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; - boolean isDeleted; - - 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; - this.isDeleted = false; // flag for removal. Avoid using heap.remove(x) as it is O(n) complexity - } - - public Triangle(Triangle oldTri) { - // deep copy and inherit connection - - this.indices[0] = oldTri.indices[0]; - this.indices[1] = oldTri.indices[1]; - this.indices[2] = oldTri.indices[2]; - this.area = oldTri.area; - this.prev = oldTri.prev; - this.next = oldTri.next; - // TODO important! inherit connection relationship to this new point - if (this.prev != null) { // previous point to this new point - this.prev.next = this; - } - if (this.next != null) { // next point to this new point - this.next.prev = this; +import static org.apache.iotdb.db.query.eBUG.Tool.triArea; + + +public class eBUG { + public static List<Point> findEliminated(Polyline lineToSimplify, int[] recentEliminated, + Point pa, Point pi, Point pb) { + // TODO 寻找最近淘汰的e个点,并且是位于pa~pb之间的 + // 性质:最近淘汰的那一个点一定是位于pa~pb之间,因为正是这个点的淘汰才使得pi的significance要更新! + // pi: point need significance updating + // pa: left adjacent non-eliminated point + // pb: right adjacent non-eliminated point + // return a list of points, containing pa,p,pb and points between pa&pa from the e most recently eliminated points, + // order by time in ascending order + List<Point> res = new ArrayList<>(); + for (int idx : recentEliminated) { // e points + if (idx == 0) { // init, not filled by real eliminated points yet + break; + } + Point p = lineToSimplify.get(idx); + if (p.x > pa.x && p.x < pb.x) { + res.add(p); + } } - - this.isDeleted = false; // this new triangle is not deleted + res.add(pa); + res.add(pi); + res.add(pb); + res.sort(Comparator.comparingDouble(p -> p.x)); // 按时间戳排序 TODO 这样的话时间复杂度要变成e*log(e)了吧? + return res; } - public boolean isValid() { - return !isDeleted; - } - - public void markDeleted() { - this.isDeleted = true; - } -} - -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) { + public static void buildEffectiveArea(Polyline lineToSimplify, List<Point> results, int e) { results.clear(); results.addAll(lineToSimplify.getVertices()); // TODO debug + // TODO 需要一个东西来记录最近淘汰的点依次是谁 + int[] recentEliminated = new int[e]; // init 0 points to the first point, skipped in findEliminated + int recentEliminatedIdx = 0; // index in the array, circulate + int total = lineToSimplify.size(); if (total < 3) { return; // 不足 3 个点无法形成三角形 @@ -153,6 +98,16 @@ public class Visval_standard { continue; } + // 真正的淘汰点 + //TODO 记录最近淘汰的点,注意不要重复记录也就是在上面执行之后再确认淘汰 +// popOrder.add(tri.indices[1]); + System.out.println("eliminate " + lineToSimplify.get(tri.indices[1])); + if (e > 0) { + recentEliminated[recentEliminatedIdx] = tri.indices[1]; + recentEliminatedIdx = (recentEliminatedIdx + 1) % e; // 0~e-1 + } + System.out.println(Arrays.toString(recentEliminated)); + // 更新当前点的重要性(z 轴存储effective area,这是一个单调增的指标) if (tri.area > previousEA) { previousEA = tri.area; @@ -171,13 +126,26 @@ public class Visval_standard { tri.prev.markDeleted(); // O(1) 这个点标记为废掉,前后关联都砍断,但是不remove因为那太耗时,只要heap poll到它就跳过就可以 Triangle newPre = new Triangle(tri.prev); // deep copy and inherit connection -// tri.prev = newPre; // replace TODO can omit +// tri.prev = newPre; // replace TODO can omit, because already done by new Triangle(tri.prev) // 2. 处理pi被淘汰引起tri.prev被更新的事情 // 前一个三角形连到后一个三角形 tri.prev.next = tri.next; // ATTENTION!!!: 这里的tri.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])); + + // TODO e parameter + List<Point> pointsForSig = findEliminated(lineToSimplify, recentEliminated, + lineToSimplify.get(tri.prev.indices[0]), + lineToSimplify.get(tri.prev.indices[1]), + lineToSimplify.get(tri.prev.indices[2])); + System.out.println("for updating Point on the left " + lineToSimplify.get(tri.prev.indices[1])); + for (Point point : pointsForSig) { + System.out.println(point); + } + + tri.prev.area = triArea(lineToSimplify.get(tri.prev.indices[0]), + lineToSimplify.get(tri.prev.indices[1]), + lineToSimplify.get(tri.prev.indices[2])); // 重新加入堆 // 在 Java 的 PriorityQueue 中,修改元素的属性不会自动更新堆的顺序 @@ -193,7 +161,7 @@ public class Visval_standard { tri.next.markDeleted(); // O(1) 这个点标记为废掉,前后关联都砍断,但是不remove因为那太耗时,只有poll到它就跳过就可以 Triangle newNext = new Triangle(tri.next); // deep copy and inherit connection -// tri.next = newNext; // replace TODO can omit +// tri.next = newNext; // replace TODO can omit, because already done by new Triangle(tri.prev) if (tri.prev != null) { tri.prev.next = tri.next; // ATTENTION!!!: 这里的tri.next已经被换掉!所以之前的要重新赋值! @@ -202,13 +170,27 @@ public class Visval_standard { // 2. 处理pi被淘汰引起tri.next被更新的事情 tri.next.prev = tri.prev; // 注意此时tri.prev已经是替代后的节点,tri.next也是,从而被标记为废点的前后关联真正砍断 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])); + + // TODO e parameter + List<Point> pointsForSig = findEliminated(lineToSimplify, recentEliminated, + lineToSimplify.get(tri.next.indices[0]), + lineToSimplify.get(tri.next.indices[1]), + lineToSimplify.get(tri.next.indices[2])); + System.out.println("for updating Point on the right " + lineToSimplify.get(tri.next.indices[1])); + for (Point point : pointsForSig) { + System.out.println(point); + } + + tri.next.area = triArea(lineToSimplify.get(tri.next.indices[0]), + lineToSimplify.get(tri.next.indices[1]), + lineToSimplify.get(tri.next.indices[2])); // 重新加入堆 // 在 Java 的 PriorityQueue 中,修改元素的属性不会自动更新堆的顺序 // 所以必须通过add 来显式重新插入修改后的元素 triangleHeap.add(tri.next); // 注意加入的是一个新的对象isDeleted=false } + System.out.println(">>>"); } } @@ -216,40 +198,41 @@ public class Visval_standard { Polyline polyline = new Polyline(); List<Polyline> polylineList = new ArrayList<>(); Random rand = new Random(1); - int n = 100_0000; + int n = 10; - int p = 1000; + int p = 10; for (int i = 0; i < n; i += p) { Polyline polylineBatch = new Polyline(); for (int j = i; j < Math.min(i + p, n); j++) { double v = rand.nextInt(1000000); - polyline.addVertex(new vPoint(j, v)); + polyline.addVertex(new Point(j, v)); - polylineBatch.addVertex(new vPoint(j, v)); + polylineBatch.addVertex(new Point(j, v)); } polylineList.add(polylineBatch); } -// try (FileWriter writer = new FileWriter("raw.csv")) { -// // 写入CSV头部 -// writer.append("x,y,z\n"); -// -// // 写入每个点的数据 -// for (int i = 0; i < polyline.size(); i++) { -// vPoint point = polyline.get(i); -// writer.append(point.x + "," + point.y + "," + point.z + "\n"); -// } -// System.out.println("Data has been written"); -// } catch (IOException e) { -// System.out.println("Error writing to CSV file: " + e.getMessage()); -// } + try (FileWriter writer = new FileWriter("raw.csv")) { + // 写入CSV头部 + writer.append("x,y,z\n"); + + // 写入每个点的数据 + for (int i = 0; i < polyline.size(); i++) { + Point point = polyline.get(i); + writer.append(point.x + "," + point.y + "," + point.z + "\n"); + } + System.out.println("Data has been written"); + } catch (IOException e) { + System.out.println("Error writing to CSV file: " + e.getMessage()); + } System.out.println("---------------------------------"); - List<vPoint> results = new ArrayList<>(); + List<Point> results = new ArrayList<>(); // 计算运行时间 + int eParam = 3; long startTime = System.currentTimeMillis(); - buildEffectiveArea(polyline, results); + buildEffectiveArea(polyline, results, eParam); // 输出结果 long endTime = System.currentTimeMillis(); System.out.println("Time taken to reduce points: " + (endTime - startTime) + "ms"); @@ -258,52 +241,65 @@ public class Visval_standard { if (results.size() <= 100) { System.out.println("+++++++++++++++++++"); for (int i = 0; i < results.size(); i++) { - vPoint point = results.get(i); + Point point = results.get(i); System.out.println("Point: (" + point.x + ", " + point.y + ", " + point.z + ")"); } } -// try (FileWriter writer = new FileWriter("fast.csv")) { + try (FileWriter writer = new FileWriter("fast.csv")) { + // 写入CSV头部 + writer.append("x,y,z\n"); + + // 写入每个点的数据 + for (int i = 0; i < results.size(); i++) { + Point point = results.get(i); + writer.append(point.x + "," + point.y + "," + point.z + "\n"); + } + System.out.println("Data has been written"); + } catch (IOException e) { + System.out.println("Error writing to CSV file: " + e.getMessage()); + } + +// System.out.println("---------------------------------"); +// List<List<Point>> resultsBatchList = new ArrayList<>(); +// // 计算运行时间 +// int cnt = 0; +// startTime = System.currentTimeMillis(); +// for (Polyline polylineBatch : polylineList) { +// List<Point> resultsBatch = new ArrayList<>(); +// buildEffectiveArea(polylineBatch, resultsBatch); +// cnt += resultsBatch.size(); +// resultsBatchList.add(resultsBatch); +// } +// // 输出结果 +// endTime = System.currentTimeMillis(); +// System.out.println("Time taken to reduce points: " + (endTime - startTime) + "ms"); +// System.out.println(cnt); +// +// System.out.println("---------------------------------"); +// // 使用 Stream API 合并所有列表 +// List<Point> mergedList = resultsBatchList.stream().flatMap(List::stream).collect(Collectors.toList()); +// int sameCnt = 0; +// for (int i = 0; i < mergedList.size(); i++) { +// if (mergedList.get(i).z == results.get(i).z) { +// sameCnt += 1; +// } +// } +// System.out.println("sameCnt=" + sameCnt + ", percent=" + sameCnt * 1.0 / mergedList.size()); +// +// try (FileWriter writer = new FileWriter("batch.csv")) { // // 写入CSV头部 // writer.append("x,y,z\n"); // // // 写入每个点的数据 -// for (int i = 0; i < results.size(); i++) { -// vPoint point = results.get(i); +// for (int i = 0; i < mergedList.size(); i++) { +// Point point = mergedList.get(i); // writer.append(point.x + "," + point.y + "," + point.z + "\n"); // } // System.out.println("Data has been written"); // } catch (IOException e) { // System.out.println("Error writing to CSV file: " + e.getMessage()); // } - - System.out.println("---------------------------------"); - List<List<vPoint>> resultsBatchList = new ArrayList<>(); - // 计算运行时间 - int cnt = 0; - startTime = System.currentTimeMillis(); - for (Polyline polylineBatch : polylineList) { - List<vPoint> resultsBatch = new ArrayList<>(); - buildEffectiveArea(polylineBatch, resultsBatch); - cnt += resultsBatch.size(); - resultsBatchList.add(resultsBatch); - } - // 输出结果 - endTime = System.currentTimeMillis(); - System.out.println("Time taken to reduce points: " + (endTime - startTime) + "ms"); - System.out.println(cnt); - - System.out.println("---------------------------------"); - // 使用 Stream API 合并所有列表 - List<vPoint> mergedList = - resultsBatchList.stream().flatMap(List::stream).collect(Collectors.toList()); - int sameCnt = 0; - for (int i = 0; i < mergedList.size(); i++) { - if (mergedList.get(i).z == results.get(i).z) { - sameCnt += 1; - } - } - System.out.println("sameCnt=" + sameCnt + ", percent=" + sameCnt * 1.0 / mergedList.size()); } // float[] vlist = new float[]{11346, 33839, 35469, 23108, 22812, 5519, 5526, 4865, 5842,
