java移动一个旋转的形状 [英] java move a rotated shape

查看:34
本文介绍了java移动一个旋转的形状的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am implementing a java swing application which has a JPanel that serves as a drawing surface. The surface renders (active) different elements. Each element has its own shape and an affine transform which is used for rendering and collision detection (each element is drawn with local coordinates and than transformed with the affine transform - like opengl).

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

The elements can be moved and rotated on the surface (this is done through transforms). Every time a transform is applied a Area object is created with the shape and the transformation (for accurate collision detection).

问题是当我旋转元素(45 度)然后将其移动 10 像素时.当我移动它时,元素会在我不想要的旋转方向上移动.

The problem is when I rotate the element (for 45 degrees) and then move it by 10 px. When I move it the element moves in the rotated direction which I don't want.

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

Is there any simple way I can overcome this?
(If my description isnt enough I'll post some example code).

 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); 
        ...
      }

 } 

推荐答案

我修改了你的代码,给出了 Element positionorientation字段,您可能希望通过 getter/setter 公开(可能在返回/设置之前防御性地复制 Point 实例).updateTransform() 根据 Element 的当前 positionorientation 简单地重新构建 AffineTransform.

I've modified your code by giving Element position and orientation fields, which you might want to expose through getters/setters (probably defensively copying the Point instance before returning/setting it). updateTransform() simply re-builds the AffineTransform based on the Element's current position and 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);
    }

}

另外,请考虑以下方法:

Also, consider the following approach:

  • draw(Graphics2D) 改为 draw(Graphics2D, AffineTransform transform)
  • 创建 AffineTransform Element.getCompositeTransform(),它构建当前的 AffineTransform 并返回它(如 updateTransform()).
  • Element 中移除 transform 字段.
  • 在您的渲染方法中,执行以下操作:
  • Change draw(Graphics2D) to draw(Graphics2D, AffineTransform transform)
  • Create AffineTransform Element.getCompositeTransform() which builds the current AffineTransform and returns it (like updateTransform()).
  • Remove the transform field from Element.
  • In your render method, do something like:

.

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

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

Why? This gives you the flexibility to control Element's drawing transform externally. This is useful if you'll build a node graph (like when an Element can have Element children) and you'll recursively render the graph, concatenating transforms. Btw, this approach is pretty much standard in 3D programming.

这篇关于java移动一个旋转的形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆