JavaFX代码无法正确识别并连接极大点问题求助
课程项目问题:极大点识别与连线错误修复
项目要求:识别点集中的所有极大点(定义为没有其他点在其上方或右侧的点),并将这些极大点用线连接。我研究数日仍无法解决当前代码的错误输出问题。
预期与实际输出
- 预期正确输出:

- 当前错误输出:

测试点集
200.0 300.0 250.0 300.0 330.0 270.0 150.0 380.0 126.0 172.0 397.0 379.0 334.0 441.0 53.0 288.0 89.0 433.0 182.0 215.0 251.0 414.0
现有代码
Main.java
//Main.java package application; import javafx.application.Application; import javafx.scene.Scene; import javafx.stage.Stage; import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main extends Application { @Override public void start(Stage primaryStage) { List<Point> points = readPointsFromFile("points.txt"); MaximalPointsPane pane = new MaximalPointsPane(points); Scene scene = new Scene(pane); primaryStage.setTitle("Maximal Points Visualization"); primaryStage.setScene(scene); primaryStage.show(); } private List<Point> readPointsFromFile(String filename) { List<Point> points = new ArrayList<>(); try (Scanner scanner = new Scanner(new File(filename))) { while (scanner.hasNextDouble()) { double x = scanner.nextDouble(); double y = scanner.nextDouble(); points.add(new Point(x, y)); } } catch (FileNotFoundException e) { System.out.println("File not found: " + filename); } return points; } public static void main(String[] args) { launch(args); } }
MaximalPointsPane.java
//MaximalPointsPane.java package application; import javafx.scene.layout.Pane; import javafx.scene.shape.Circle; import javafx.scene.shape.Line; import javafx.scene.paint.Color; import javafx.scene.input.MouseButton; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class MaximalPointsPane extends Pane { private List<Point> points = new ArrayList<>(); public MaximalPointsPane(List<Point> initialPoints) { this.points.addAll(initialPoints); setPrefSize(500, 500); draw(); setOnMouseClicked(event -> { double x = event.getX(); double y = event.getY(); if (event.getButton() == MouseButton.PRIMARY) { points.add(new Point(x, y)); // Add point } else if (event.getButton() == MouseButton.SECONDARY) { points.removeIf(p -> Math.hypot(p.getX() - x, p.getY() - y) < 10); // Remove closest point } draw(); }); } private void draw() { getChildren().clear(); // Draw points for (Point p : points) { Circle circle = new Circle(p.getX(), p.getY(), 4, Color.BLACK); getChildren().add(circle); } // Find maximal points and draw connecting lines List<Point> maximalPoints = findMaximalPoints(); for (int i = 0; i < maximalPoints.size() - 1; i++) { Point p1 = maximalPoints.get(i); Point p2 = maximalPoints.get(i + 1); Line line = new Line(p1.getX(), p1.getY(), p2.getX(), p2.getY()); line.setStroke(Color.BLACK); getChildren().add(line); } } private List<Point> findMaximalPoints() { List<Point> maximal = new ArrayList<>(); for (Point p1 : points) { boolean isMaximal = true; for (Point p2 : points) { if (p1.isDominatedBy(p2)) { isMaximal = false; break; } } if (isMaximal) maximal.add(p1); } Collections.sort(maximal); return maximal; } }
Point.java
//Point.java package application; import java.util.Objects; public class Point implements Comparable<Point> { private final double x; private final double y; public Point(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } public boolean isDominatedBy(Point other) { return (this.x < other.x && this.y <= other.y) || (this.x <= other.x && this.y < other.y); } @Override public int compareTo(Point other) { return Double.compare(this.x, other.x); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Point point = (Point) obj; return Double.compare(point.x, x) == 0 && Double.compare(point.y, y) == 0; } @Override public int hashCode() { return Objects.hash(x, y); } }
问题根源与修复方案
1. 极大点排序逻辑错误
当前代码仅按x坐标升序排序极大点,导致连线顺序错误。正确的做法是按x坐标降序排序,x相同时按y坐标降序排序,这样连线才能形成从最右上角到最左上角的轮廓线。
修改findMaximalPoints方法中的排序代码:
// 替换原Collections.sort(maximal);代码 Collections.sort(maximal, (p1, p2) -> { int xCompare = Double.compare(p2.getX(), p1.getX()); if (xCompare != 0) { return xCompare; } return Double.compare(p2.getY(), p1.getY()); });
2. 其他说明
isDominatedBy方法的判断逻辑是正确的,符合极大点的定义。- JavaFX坐标系原点在左上角,y轴向下,代码中对“上方”的判断(y值更小)已经适配,无需修改。
修复后,极大点会按正确顺序排列,连线将与预期输出一致。
内容的提问来源于stack exchange,提问作者Elaine Shields
相关产品推荐
相关产品推荐

