You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 15:15:11