Javafx:用角度拉近两点

Javafx: Bringing two points closer to each other with angle

提问人:FarHooD 提问时间:10/23/2023 最后编辑:FarHooD 更新时间:10/24/2023 访问量:77

问:

您好,所有 Stackoverflow 用户,我有多边形形状(或三角形),我需要在它的侧中心添加一些标签,想象一下我有框架,如果剪辑形状从中删除其他区域,问题是如果剪辑我的 GraphicContext 的标签将从我创建的形状中删除,为了说出我遇到的问题,我希望标签靠近形状中心,有一些间隙我添加了它(如 24px 72px 等),但我发现如果我想这样做,需要调整角度并将比例添加到间隙中以封闭到中心,但我不知道该怎么做?我的数学很差:))谁能给我小费?

我添加的形状只是我需要的示例,而我向您展示的代码只是一些肮脏的工作。

enter image description here

enter image description here

         private int[] pointLocateForExportLabel(Point2D a1, Point2D a2, Point2D centerPoint, int fontMetric) {
        int gapIntoShape = (int) (fontMetric) * 9;
        App.logger.debug("The Center point : " + centerPoint);
        App.logger.debug("The A1 of point : " + a1);
        App.logger.debug("The A2 of point : " + a2);
        App.logger.debug("==============================");
        int poX = (int) (((a1.getX() + a2.getX()) / 2));
        int poY = (int) (((a1.getY() + a2.getY()) / 2));
        Point c1 = new Point(poX, poY);
        double deltaX = centerPoint.getX() - c1.getX();
        double deltaY = centerPoint.getY() - c1.getY();
        double coeff = 0.05;
        Point2D c = null;
        if (centerPoint.getX() > c1.getX()) {
            c = new Point2D(c1.getX() + coeff * deltaX, c1.getY() + coeff * deltaY);
        } else {
            c = new Point2D((c1.getX() + coeff * deltaX) - gapIntoShape, c1.getY() + coeff * deltaY);
        }
        return new int[]{(int) c.getX(), (int) c.getY()};
    }

更新: 为了更好地理解,我需要将接近点带入接近另一个点!但不是两个方向(x 和 y)的一个方向(只是 x 或 y),这是一个简单的问题,IDK 如何太固定了。

enter image description here

java 数学 javafx

评论

0赞 jewelsea 10/23/2023
您可以使用公几何计算质心。一旦你有了它,你就可以计算边的中点,并沿着质心和边中点之间的线插值一个点。
0赞 ControlAltDel 10/25/2023
正确的解决方案 (IMO) 是创建可缩放矢量图形 (SVG)

答:

2赞 ControlAltDel 10/23/2023 #1

这在 StackExchange 上的 Mathmatics 上可能会更好。

但我认为这就是如何做到的(仅适用于等边三角形)

  1. 计算多边形的中点:您可以将中点计算为所有顶点的平均值

  2. 计算文本的绘制点:这很棘手,因为线条的起点取决于 FontMetrics 的高度。将文本放入空间取决于 FontMetrics.charWidth。因此,我认为它的计算是一个微分方程(或者你可以进行测试并迭代调整)

老实说,这是一个非常棘手的问题,仅适用于这种独特的形状。这对你来说值得吗?

同样,我建议你试试数学,看看他们是否有更好的答案。

评论

0赞 FarHooD 10/23/2023
它不是完整的数学问题,可以用java自己完成。为此,我写在这里。第一名完成了第二名,我添加了差距,它适用于 FontMetrics,但接近两个 point2d,它们与中心有角度,这是在这里找到的问题。(从线中心到形状中心)
0赞 FarHooD 10/23/2023
是的,这对我来说值得吗,谢谢你帮助我
2赞 James_D 10/23/2023
注意 Point2D 类提供所需的所有矢量功能。给定,你可以做到Point2D startPoint2D centerPoint2D needed = center.add(start.subtract(center).multiply(coeff));
3赞 James_D 10/24/2023 #2

Point2D 类实现了许多基本的向量代数运算。

在数学上,if 和 是点,则表示从 到 的向量。对于标量,abb-aabt

a + t(b-a) = (1-t)a + tb

表示直线上经过 和 的点(直观地说,从 开始并将向量的倍数从 移动到 )。当 和 当 , .abaabt=0(1-t)a +tb = at=1(1-t)a + tb = b

在本例中,是线的中心点,是形状的中心,并且是您在代码中调用的值。abtcoeff

因此,在 Java 代码中,它看起来像:

Point2D centerLine = new Point2D(...) ;
Point2D centerShape = new Point2D(...) ;
Point2D requiredPoint = centerLine.multiply(1-coeff).add(centerShape.multiply(coeff));

如前所述,您可以简单地将线的中心作为端点的平均值,将形状的中心作为顶点的平均值。

下面是一个演示:

package com.example.vectors;

import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.control.Spinner;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polyline;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {

    private Point2D centerLine ;
    private Point2D centerShape;

    private Circle point = new Circle(5);

    @Override
    public void start(Stage stage) throws IOException {
        Spinner<Integer> numVertexesSpinner = new Spinner<>(3, 10, 5);
        Slider pointSlider = new Slider(0, 1, 0.5);
        VBox controls = new VBox(5, numVertexesSpinner, pointSlider);
        Pane drawingPane = new Pane();
        drawingPane.setPrefSize(420, 420);
        drawShapes(numVertexesSpinner.getValue(), pointSlider.getValue(), drawingPane);

        BorderPane root = new BorderPane();
        root.setTop(controls);
        root.setCenter(drawingPane);

        numVertexesSpinner.valueProperty().addListener((obs, oldValue, newValue) ->
                drawShapes(newValue, pointSlider.getValue(), drawingPane)
        );

        pointSlider.valueProperty().addListener((obs, oldValues, newValue)  -> updatePoint(newValue.doubleValue()));

        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    private void drawShapes(int numVertexes, double pointPos, Pane pane) {
        pane.getChildren().clear();
        final double radius = 200 ;
        Point2D[] vertexes =  new Point2D[numVertexes];
        double[] coords = new double[numVertexes * 2 + 2];
        for (int i = 0 ; i<vertexes.length; i++) {
            double angle = 2 * Math.PI * i / numVertexes;
            double x = radius + radius * Math.cos(angle);
            double y = radius + radius * Math.sin(angle);
            vertexes[i] = new Point2D(x, y);
            coords[2*i] = x ;
            coords[2*i+1] = y ;
        }
        coords[numVertexes * 2] = coords[0];
        coords[numVertexes * 2 + 1] = coords[1];
        Polyline poly = new Polyline(coords);
        pane.getChildren().add(poly);
        centerLine = vertexes[0].add((vertexes[1])).multiply(0.5);
        centerShape = new Point2D(0,0);
        for (Point2D vertex : vertexes) {
            centerShape = centerShape.add(vertex);
        }
        centerShape = centerShape.multiply(1.0 / numVertexes);
        pane.getChildren().addAll(new Circle(centerLine.getX(), centerLine.getY(), 5));
        pane.getChildren().addAll(new Circle(centerShape.getX(), centerShape.getY(), 5));
        pane.getChildren().add(point);
        updatePoint(pointPos);
    }

    private void updatePoint(double pointPos) {
        Point2D pos = centerLine.multiply(1-pointPos).add(centerShape.multiply(pointPos));
        point.setCenterX(pos.getX());
        point.setCenterY(pos.getY());
    }

    public static void main(String[] args) {
        launch();
    }
}