java可以移动旋转的形状

java可以移动旋转的形状,java,swing,transform,Java,Swing,Transform,我正在实现一个JavaSwing应用程序,它有一个用作绘图面的JPanel。曲面渲染(活动)不同的元素。每个元素都有自己的形状和用于渲染和碰撞检测的仿射变换(每个元素使用局部坐标绘制,然后使用仿射变换(如opengl)进行变换) 可以在曲面上移动和旋转元素(这是通过变换完成的)。每次应用变换时,都会使用形状和变换创建一个区域对象(用于精确的碰撞检测) 问题是当我旋转元素(45度),然后移动它10像素。当我移动它时,元素以我不想要的旋转方向移动 有什么简单的方法可以克服这个问题吗? (如果我的描述

我正在实现一个JavaSwing应用程序,它有一个用作绘图面的JPanel。曲面渲染(活动)不同的元素。每个元素都有自己的形状和用于渲染和碰撞检测的仿射变换(每个元素使用局部坐标绘制,然后使用仿射变换(如opengl)进行变换)

可以在曲面上移动和旋转元素(这是通过变换完成的)。每次应用变换时,都会使用形状和变换创建一个区域对象(用于精确的碰撞检测)

问题是当我旋转元素(45度),然后移动它10像素。当我移动它时,元素以我不想要的旋转方向移动

有什么简单的方法可以克服这个问题吗?
(如果我的描述不够,我将发布一些示例代码)

编辑:


颠倒应用转换的顺序。或者取消旋转对象,移动对象,然后重新旋转对象。我们真的需要查看您的代码(甚至伪代码),以便为您提供更好的答案。

颠倒您应用转换的顺序。或者取消旋转对象,移动对象,然后重新旋转对象。我们真的需要查看您的代码(甚至伪代码)才能给您提供更好的答案。

我修改了您的代码,提供了
元素
位置
方向
字段,您可能希望通过getter/setter公开这些字段(可能是在返回/设置
点之前防御性地复制
实例)。
updateTransform()
只需基于
元素的当前
位置和
方向重新构建
仿射Transform

public class Element {

    private Point position = new Point();
    private float orientation;

    private AffineTransform transform = new AffineTransform();
    private Shape shape = new Rectangle(0, 0, 100, 100);
    private Area boundingBox;

    public void onMouseDrag(MouseEvent e) {
        translate(dx, dy);
    }

    public void onMouseMove(MouseEvent e) {
        rotate(Math.atan2(dx / dy));
    }

    public void translate(int dx, int dy) {
        position.translate(dx, dy);
        updateTransform();
    }

    public void rotate(double angle) {
        orientation += Math.toRadians(angle);
        updateTransform();
    }

    private void updateTransform() {
        transform.setToIdentity();
        transform.translate(position.x, position.y);
        transform.rotate(orientation);
        // ... update bounding box here ...
    }

    public void draw(Graphics2D g2d) {
        g2d.setTransform(transform);
        g2d.draw(shape);
    }

}

也可以考虑以下方法:

  • draw(Graphics2D)
    更改为
    draw(Graphics2D,仿射变换)
  • 创建
    AffineTransform元素。getCompositeTransform()
    ,它构建当前
    AffineTransform
    并返回它(如
    updateTransform()
  • 元素
    中删除
    变换
    字段
  • 在渲染方法中,执行以下操作:


为什么?这使您可以灵活地从外部控制
元素
的绘图转换。如果要构建节点图(例如
元素
可以有
元素
子元素),这将非常有用您将递归地呈现图形,连接变换。顺便说一句,这种方法在3D编程中非常标准。

我修改了您的代码,给出了
元素
位置
方向
字段,您可能希望通过getter/setter公开这些字段(可能是在返回/设置
点之前防御性地复制
实例)。
updateTransform()
只需基于
元素的当前
位置和
方向重新构建
仿射Transform

public class Element {

    private Point position = new Point();
    private float orientation;

    private AffineTransform transform = new AffineTransform();
    private Shape shape = new Rectangle(0, 0, 100, 100);
    private Area boundingBox;

    public void onMouseDrag(MouseEvent e) {
        translate(dx, dy);
    }

    public void onMouseMove(MouseEvent e) {
        rotate(Math.atan2(dx / dy));
    }

    public void translate(int dx, int dy) {
        position.translate(dx, dy);
        updateTransform();
    }

    public void rotate(double angle) {
        orientation += Math.toRadians(angle);
        updateTransform();
    }

    private void updateTransform() {
        transform.setToIdentity();
        transform.translate(position.x, position.y);
        transform.rotate(orientation);
        // ... update bounding box here ...
    }

    public void draw(Graphics2D g2d) {
        g2d.setTransform(transform);
        g2d.draw(shape);
    }

}

也可以考虑以下方法:

  • draw(Graphics2D)
    更改为
    draw(Graphics2D,仿射变换)
  • 创建
    AffineTransform元素。getCompositeTransform()
    ,它构建当前
    AffineTransform
    并返回它(如
    updateTransform()
  • 元素
    中删除
    变换
    字段
  • 在渲染方法中,执行以下操作:


为什么?这使您可以灵活地从外部控制
元素
的绘图转换。如果要构建节点图(例如
元素
可以有
元素
子元素),这将非常有用您将递归地呈现图形,连接变换。顺便说一句,这种方法在3D编程中非常标准。

用相关代码更新了我的问题。问题是我不知道变换的顺序。+1此相关检查(非交换)转换连接的顺序。用相关代码更新了我的问题。问题是我不知道转换的顺序。+1此相关检查转换连接的(非交换)顺序。使用此代码,可以使用
rotate(θ,x,y)
而不是
rotate(θ)围绕当前位置旋转。无论如何,这样的增量转换是令人沮丧的,您应该考虑给予<代码>元素<代码> A<代码>位置< /代码>和<代码>旋转< /COD>属性,当它们改变时,用于重新计算<代码> > AffixTebug < /代码>,或每帧/更新一次。“在大多数图形工具包(包括Java)中,转换都是按后进先出的顺序应用的。也就是说,代码中列出的最后一个转换是实际应用的第一个转换,而代码中列出的第一个转换是实际应用的最后一个转换。“@Torious如果你想发布一个带有示例的答案,我会接受这个代码,你可以使用
rotate(θ,x,y)
而不是
rotate(θ)围绕当前位置旋转。无论如何,这样的增量转换是令人沮丧的,您应该考虑给予<代码>元素<代码> A<代码>位置< /代码>和<代码>旋转< /COD>属性,当它们改变时,用于重新计算<代码> > AffixTebug < /代码>,或每帧/更新一次。“在大多数图形工具包(包括Java)中,转换都是按后进先出的顺序应用的。也就是说,代码中列出的最后一个转换是实际应用的第一个转换,而代码中列出的第一个转换是实际应用的最后一个转换。“@Torious如果你能用一个例子来回答问题,我会接受它的。我有孩子抚养费,但是收集是z排序的,而不是基于树的。但是
for (Element element : elements) {
    AffineTransform transform = element.getCompositeTransform();
    element.draw(graphics, transform);
}