java移动旋转的形状

时间:2012-04-18 22:36:31

标签: java swing transform

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

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

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

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

编辑:

 class Element
 {
     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); // dx,dy are calculated from event
     }

     public void onMouseMove(MouseEvent e)
     {
        rotate(Math.atan2(dx/dy); // dx,dy are calculated from event
     }

     public void translate(int dx,int dy)
     {
        transform.translate(dx,dy);
        boundingBox = new Area(shape);
        boundingBox.transform(transform);
     }

     public void rotate(double angle)
     {
         transform.rotate(Math.toRadians(angle));
         boundingBox = new Area(shape);
         boundingBox.transform(transform);
     }

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

         g2d.draw(shape); 
        ...
      }

 } 

2 个答案:

答案 0 :(得分:2)

撤消您正在应用转换的顺序。或者取消旋转对象,移动它,然后重新旋转对象。我们真的需要看到你的代码(甚至伪代码)给你一个比这个更好的答案。

答案 1 :(得分:2)

我已经通过提供Element positionorientation字段修改了您的代码,您可能希望通过getter / setter公开这些字段(可能是在防御性地复制Point实例在返回/设置之前)。 updateTransform()只需根据AffineTransform的当前Elementposition重新构建orientation

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 transform)
  • 创建AffineTransform Element.getCompositeTransform(),构建当前AffineTransform并返回它(如updateTransform())。
  • transform
  • 中删除Element字段
  • 在渲染方法中,执行以下操作:

for (Element element : elements) {
    AffineTransform transform = element.getCompositeTransform();
    element.draw(graphics, transform);
}

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