在JavaFX中获取屏幕上路径的xy坐标

Ale*_*lho 1 java javafx

JavaFX中有什么方法可以获取我在画布上在屏幕上绘制的路径的x,y坐标吗?

我有一个应用程序,可以在画布上绘制一些圆圈,然后将圆圈与线条连接起来。

之后,我可以通过拖动节点来更改圆圈的位置,并且程序始终重新绘制画布上圆圈之间的线条

但现在我想在这些圆圈之间绘制一条四边形曲线。

public void drawQuadCurveOnCanvas(double startX, double startY, double endX, double endY, double controlX, double controlY) {
        // Set line width
        lineDraw.setLineWidth(Constants.LINE_THICKNESS);
        // Set the Color
        lineDraw.setStroke(Constants.DRAG_COLOR);
        // Start the Path
        lineDraw.beginPath();
        lineDraw.moveTo(startX, startY);
        lineDraw.quadraticCurveTo(controlX, controlY, endX, endY);
        // Draw the Path
        lineDraw.stroke();
    }
Run Code Online (Sandbox Code Playgroud)

我绘制四边形曲线,其中一个圆作为控制点,另外两个圆作为起点和终点坐标。

所以我想沿着我刚刚绘制的四边形曲线获取x,y坐标,这样我就可以在这些坐标上创建一些圆,之后当我将这些圆与线连接时我得到相同的四边形曲线。

我不知道我是否解释得很好,有人知道如何实现我想要的吗?

Jam*_*s_D 5

对于二次 B\xc3\xa9zier 曲线,曲线上的任何点都可以写为

\n
x = (1-t)*(1-t)*startX + 2*t*(1-t)*controlX + t*t*endX\ny = (1-t)*(1-t)*startY + 2*t*(1-t)*controlY + t*t*endY\n
Run Code Online (Sandbox Code Playgroud)\n

其中0\xe2\x89\xa4 t\xe2\x89\xa41

\n

要沿着二次 B\xc3\xa9zier 曲线绘制多个圆,只需选择 0 到 1 之间的一些值,然后创建一堆圆,其中心由上面公式中的坐标给出。如果控制点可能发生变化,您可以使用绑定。这是一个简单的示例,它创建沿着曲线绑定到坐标的圆,线段的端点依次绑定到圆。

\n
import javafx.application.Application;\nimport javafx.beans.binding.Bindings;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.Spinner;\nimport javafx.scene.layout.BorderPane;\nimport javafx.scene.layout.HBox;\nimport javafx.scene.layout.Pane;\nimport javafx.scene.paint.Color;\nimport javafx.scene.shape.Circle;\nimport javafx.scene.shape.Line;\nimport javafx.stage.Stage;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class BezierCurve extends Application {\n\n    private Circle start;\n    private Circle end;\n    private Circle control;\n    private Pane drawingPane;\n    private List<Circle> points;\n    private List<Line> segments;\n\n    private Circle createPoint(double t) {\n        Circle c = new Circle(4);\n        c.setFill(Color.BLACK);\n        c.centerXProperty().bind(Bindings.createDoubleBinding(\n                () -> (1-t)*(1-t)*start.getCenterX() \n                     + 2*t*(1-t)*control.getCenterX() \n                     + t*t*end.getCenterX(),\n                start.centerXProperty(),\n                end.centerXProperty(),\n                control.centerXProperty())\n        );\n        c.centerYProperty().bind(Bindings.createDoubleBinding(\n                () -> (1-t)*(1-t)*start.getCenterY() \n                    + 2*t*(1-t)*control.getCenterY() \n                    + t*t*end.getCenterY(),\n                start.centerYProperty(),\n                end.centerYProperty(),\n                control.centerYProperty())\n        );\n        return c;\n    }\n\n    private Line createSegment(Circle start, Circle end) {\n        Line segment = new Line();\n        segment.startXProperty().bind(start.centerXProperty());\n        segment.startYProperty().bind(start.centerYProperty());\n        segment.endXProperty().bind(end.centerXProperty());\n        segment.endYProperty().bind(end.centerYProperty());\n        return segment ;\n    }\n\n    @Override\n    public void start(Stage stage) throws IOException {\n        drawingPane = new Pane();\n        points = new ArrayList<>();\n        segments = new ArrayList<>();\n\n        start = new Circle(100,100, 10, Color.GREEN);\n        end = new Circle(700, 100, 10, Color.GREEN);\n        control = new Circle(400, 500, 10, Color.GREEN);\n\n        for (Circle c : List.of(start, end, control)) setUpDragging(c);\n\n        Spinner<Integer> numSegmentsSpinner = new Spinner(5, Integer.MAX_VALUE, 25, 5);\n        numSegmentsSpinner.setEditable(true);\n        numSegmentsSpinner.valueProperty().addListener(\n            (obs, oldValue, newValue) -> populatePointsAndSegments(newValue)\n        );\n        HBox ctrls = new HBox(5, new Label("Number of segments:"), numSegmentsSpinner);\n\n        populatePointsAndSegments(numSegmentsSpinner.getValue()); ;\n        drawingPane.getChildren().addAll(start, end, control);\n\n        BorderPane root = new BorderPane();\n        root.setCenter(drawingPane);\n        root.setTop(ctrls);\n        Scene scene = new Scene(root, 800, 800);\n        stage.setScene(scene);\n        stage.show();\n    }\n\n    private void populatePointsAndSegments(int numSegments) {\n\n        drawingPane.getChildren().removeAll(points);\n        drawingPane.getChildren().removeAll(segments);\n        points.clear();\n        segments.clear();\n\n        Circle previousCircle = start ;\n\n        for (int i = 1 ; i < numSegments; i++) {\n            double t = 1.0 * i / numSegments ;\n            Circle c = createPoint(t);\n            points.add(c);\n            segments.add(createSegment(previousCircle, c));\n            previousCircle = c ;\n        }\n        segments.add(createSegment(previousCircle, end));\n        drawingPane.getChildren().addAll(points);\n        drawingPane.getChildren().addAll(segments);\n    }\n\n    private void setUpDragging(Circle c) {\n        c.setOnMouseDragged(e -> {\n            c.setCenterX(e.getX());\n            c.setCenterY(e.getY());\n        });\n    }\n\n    public static void main(String[] args) {\n        launch();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n