使用旋转围绕其中心旋转多边形

Rotate a polygon around its center using Rotate

我想在变换后跟踪多边形 class 中的点。我使用来自 JavaFX 的 Rotate class 的问题是通过在 Piece class:[=19= 中做这样的事情来获得旋转后的点位置]

double x = this.getPoints().get(0) + this.getLocalToParentTransform().getTx()
double y = this.getPoints().get(1) + this.getLocalToParentTransform().getTy()

它可以使用 Translate class,但是当我旋转时,坐标将随着旋转而旋转,并带有一个奇怪的轴心点,并且根本不会跟随多边形,除非它是旋转 360 度。 PiecePolygon 的子 class。

    private double originalX;
    private double originalY;
    private double centerX;
    private double centerY;

    private void initializePiece(Piece piece, Pane pane, int i) {
        piece.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                originalX = event.getSceneX();
                originalY = event.getSceneY();
                centerX = piece.getCenterX();
                centerY = piece.getCenterY();
            }
        });

        piece.setOnMouseDragged(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if (event.getButton() == MouseButton.PRIMARY) {
                    // Position of piece wrt. picked up position
                    double deltaX = event.getSceneX() - originalX;
                    double deltaY = event.getSceneY() - originalY;

                    Translate translate = new Translate();
                    translate.setX(deltaX);
                    translate.setY(deltaY);
                    piece.getTransforms().addAll(translate);

                    originalX = event.getSceneX();
                    originalY = event.getSceneY();
                }

                if (event.getButton() == MouseButton.SECONDARY) {
                    double deltaY = event.getSceneY() - originalY;
                    Rotate rotation = new Rotate(deltaY, centerX, centerY);
                    piece.getTransforms().add(rotation);
                    originalY = event.getSceneY();
                }
            }
        });
    }

这是 Piececlass 的片段。

    public double getCenterX() {
        double avg = 0;
        for (int i = 0; i < this.getPoints().size(); i += 2) {
            avg += this.getPoints().get(i) + this.getLocalToParentTransform().getTx();
        }
        avg = avg / (this.getPoints().size() / 2);
        
        return avg;
    }

    public double getCenterY() {
        double avg = 0;
        for (int i = 1; i < this.getPoints().size(); i += 2) {
            avg += this.getPoints().get(i) + this.getLocalToParentTransform().getTy();
        }
        avg = avg / (this.getPoints().size() / 2);
        return avg;
    }

所有变换都应用在局部坐标中,因此轴心点应在多边形的局部坐标系中给出,多边形“不知道”应用到它的变换。 IE。您应该只在多边形自己的坐标系中计算多边形的中心,而不是在其父坐标系中。

鼠标事件的getX()getY()方法会给出事件源节点在坐标系中的坐标,使用这些方法计算起来比较容易。这是一个简单的例子(我计算了当前鼠标按下和多边形中心之间的角度,然后计算了拖动时角度的变化,而不是仅仅使用y坐标;这样感觉更自然。)

import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class DraggingTransforms extends Application {
    
    public static void main(String[] args) {
        Application.launch(args);
    }
    
    private double pressX ;
    private double pressY ;
    private double angle ;

    @Override
    public void start(Stage stage) throws Exception {
        Polygon poly = new Polygon(10, 10, 50, 10, 50, 0, 70, 20, 50, 40, 50, 30, 10, 30, 10, 10);
        poly.setFill(Color.web("#00b140"));
        Pane root = new Pane(poly);
        
        poly.setOnMousePressed(e -> {
            pressX = e.getX();
            pressY = e.getY();
            angle = computeAngle(poly, e);
        });
        
        poly.setOnMouseDragged(e -> {
            if (e.getButton() == MouseButton.PRIMARY) {
                poly.getTransforms().add(new Translate(e.getX() - pressX, e.getY()-pressY));
            } else {
                double delta = computeAngle(poly, e) - angle;
                Rotate rotation = new Rotate(delta, computeCenterX(poly), computeCenterY(poly));
                poly.getTransforms().add(rotation);
            }
        });
        
        Scene scene = new Scene(root, 800, 800);
        stage.setScene(scene);
        stage.show();
    }

    private double computeAngle(Polygon poly, MouseEvent e) {
        return new Point2D(computeCenterX(poly), computeCenterY(poly))
                   .angle(new Point2D(e.getX(), e.getY()));
    }
    
    private double computeCenter(int offset, Polygon poly) {
        double total = 0 ;
        for (int i = offset ; i < poly.getPoints().size(); i+=2) {
            total += poly.getPoints().get(i);
        }
        return total / (poly.getPoints().size() / 2);
    }
    
    private double computeCenterX(Polygon poly) {
        return computeCenter(0, poly);
    }
    private double computeCenterY(Polygon poly) {
        return computeCenter(1, poly);
    }

}

请注意,如果您确实需要将形状中的某个点的坐标转换为父坐标系,您需要做的就是,例如,

poly.getLocalToParentTransform()
     .transform(
          poly.getPoints().get(0), 
          poly.getPoints().get(1)
     )