1

描画面として機能するJPanelを持つJavaSwingアプリケーションを実装しています。サーフェスは(アクティブな)さまざまな要素をレンダリングします。各要素には独自の形状と、レンダリングと衝突検出に使用されるアフィン変換があります(各要素はローカル座標で描画され、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); 
        ...
      }

 } 
4

2 に答える 2

2

私はあなたがゲッター/セッターを通して公開したいと思うかもしれないフィールドを与えることによってあなたのコードを修正しました(おそらくそれを返す/設定する前にインスタンスを防御的にコピーしElement positionます)。の現在のおよびに基づいてを再構築するだけです。orientationPointupdateTransform()AffineTransformElementpositionorientation

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
  • renderメソッドで、次のようにします。

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

なんで?Elementこれにより、描画変換を外部で制御する柔軟性が得られます。これは、ノードグラフを作成し(が子を持つElementことができる場合Elementなど)、変換を連結してグラフを再帰的にレンダリングする場合に便利です。ところで、このアプローチは3Dプログラミングではほとんど標準です。

于 2012-04-18T23:48:53.433 に答える
2

変換を適用する順序を逆にします。または、オブジェクトの回転を解除して移動してから、オブジェクトを再回転します。これよりも良い答えを出すには、実際にコード(または擬似コード)を確認する必要があります。

于 2012-04-18T22:44:39.420 に答える