2012-04-22 7 views
0

私のアプリの要素に適用する変換の正しい順序を理解するのに問題があります。アプリケーションには親子関係を持つ要素があり、各要素には変形があります(各要素はローカル空間に描画され、変形されます)。java Affine正しい順序を変換する

私がアーカイブしたいのは、私が親を変換すると、その子もすべて変形する必要があるということです(親を回転させると、子は親の周りを回転する必要があります)。

以下のコードはそれだけですが、問題は親を回転させて子を移動したい場合です。それは間違った方向に移動します(親変換のため)。私は変換のシーケンスを変更しようとしましたが、運はありません(私は最初に変換して変換する必要がありますが、子は親の代わりに独自の軸を中心に回転します)。

コード:

Element e; 
AffineTransform t = new AffineTransform(); 
AffineTransform t3 = new AffineTransform(); 

for (i = 0; i < el.size(); i++) 
{ 
    e = el.get(i); 
    t3.setToIdentity(); 
    t.setToIdentity(); 
    tmp = e.getParent(); 
    while(tmp != null) 
    { 
     t.translate(tmp.getX(), tmp.getY()); 
     t3.rotate(Math.toRadians(tmp.getAngle()),tmp.getAnchorX(), tmp.getAnchorY()); 
     tmp = tmp.getParent(); 
    } 

    t.concatenate(t3); 
    t.translate(e.getX(), e.getY()); 

    t.rotate(Math.toRadians(e.getAngle()),e.getAnchorX(), e.getAnchorY()); 

    e.draw(g2d,t); 
} 

問題: - 二つの要素(他の1子) を与えられた - 親が(40度)回転 ある - 子供は10pxの どのようにすることができますによって移動し、その後で変換を連結して、子供を動かすと回転した方向に動かないようにします。

EDIT:Toriousは(まだ動作していません)投稿 コード:コードの

public AffineTransform getTransformTo(Element ancestor) { 
    AffineTransform t = (AffineTransform)getAffineTransform().clone(); 
    Element parent = getParent(); 
    while (parent != null && parent != ancestor) { 
     t.preConcatenate(parent.getAffineTransform()); 
     parent = parent.getParent(); 
    } 
    return t; 
} 


public void translateInAncestorSpace(Element ancestor, Point translation) { 
    AffineTransform fromAncestor = getTransformTo(ancestor); // to ancestor space 
    try 
    { 
     fromAncestor.invert(); 
    } catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 
    translation = (Point)fromAncestor.transform(translation, new Point()); 

    Transform t1 = new Transform(); 
    t1.translate(translation.x,translation.y); 
    transform(t1); 
} 

出力:

Moving by [x=1,y=1] old position [x=22,y=40] 
Moved by [x=-21,y=-39] new position [x=1,y=1] 
Moving by [x=2,y=2] old position [x=1,y=1] 
Moved by [x=1,y=1] new position [x=2,y=2] 
Moving by [x=4,y=3] old position [x=2,y=2] 
Moved by [x=2,y=1] new position [x=4,y=3] 
+0

すぐに役立つように、[SSCCE](http://sscce.org/)を投稿してください。ところで - あなたは質問がありますか? –

答えて

2

このような何か:

// get composite transform for 'e' 
t.setToIdentity(); 
t.translate(e.getX(), e.getY()); 
t.rotate(...); 

tmp = e.getParent(); 
while (tmp != null) { 

    // get composite transform for parent 
    t3.setToIdentity(); 
    t3.translate(tmp.getX(), tmp.getY()); 
    t3.rotate(...); 
    tmp = tmp.getParent(); 

    t.preConcatenate(t3); // t3 is applied after t 
} 

e.draw(g2d, t); 

編集: 'グローバル空間'内の要素を移動する場合それは実際には別の要素の子だ、私はそれは単にその翻訳に追加することができるので、エレメントスペースに所望の動きを変換することをお勧めしたい:

(未テストコード)

// Element.getTransformTo: get transform to ancestor or root (null) 
public AffineTransform getTransformTo(Element ancestor) { 
    AffineTransform t = getCompositeTransform(); 
    Element parent = getParent(); 
    while (parent != null && parent != ancestor) { 
     t.preConcatenate(parent.getCompositeTransform()); 
     parent = parent.getParent(); 
    } 
} 

// Element.translateInAncestorSpace 
// ancestor may be null for root/global space 
public void translateInAncestorSpace(Element ancestor, Point translation) { 
    AffineTransform fromAncestor = getTransformTo(ancestor); // to ancestor space 
    fromAncestor.invert(); // from ancestor space 

    // [NEW] re-apply element rotation since translation occurs after rotation 
    fromAncestor.rotate(Math.toRadians(angle), anchor.x, anchor.y); 

    translation = fromAncestor.deltaTransform(translation, new Point()); 

    // translation is now in element space; add to existing translation 
    element.setX(element.getX() + translation.x); 
    element.setY(element.getY() + translation.y); 
} 

// example usage: 
// (this should move the element 10px to the right, regardless 
// of parent transforms) 
element.translateInAncestorSpace(null, new Point(10, 0)); 

また、実装を検討しますAffineTransform Element.getCompositeTransform()メソッドは、あなたの人生をより簡単にするでしょう。あなたはこのような何かを取得したいので

また、リーフノードにルートノードからあなたの「要素ツリー」をレンダリング考える:

public void render(Element node, AffineTransform transform) { 

    AffineTransform nodeTransform = node.getCompositeTransform(); 
    nodeTransform.preConcatenate(transform); 

    node.draw(g2d, nodeTransform); 

    for (Element child : node.children()) 
     render(child, nodeTransform); 
} 
+0

ありがとうございます。あなたはそれが動作するように "テストされていない"を削除することができます。 "要素ツリー"の問題は、要素がzインデックス順にレンダリングされなければならないため、要素をツリーとしてレンダリングできないことです。 – blejzz

+0

はすぐに適切にテストすることなく話しました。問題は、親が40度回転し、子を10px移動したい場合、回転した方向に移動することです。 – blejzz

+0

これは、子が親の座標系の中にあるので、私がポストしたコードで起こるはずです。なぜあなたは独立して翻訳したいのですが、依存して回転したいのですか? – Torious

1

を[OK]を、私はあなたが今欲しいものを理解すると思います。 以下のコードは、(テストされていない)の翻訳を連結しますが、回転は連結しません。各要素は、それ自身の回転によってのみ影響を受けます。

コードの意図が私の以前の回答のコードと異なるため、これを新しい回答として投稿しました。

このコードでは、要素のxとyを設定して変換するだけです。

// set e's translation 
t.setToIdentity(); 
t.translate(e.getX(), e.getY()); 

// add ancestor translations (order is irrelevant) 
Element parent = e.getParent(); 
while (parent != null) { 
    t.translate(parent.getX(), parent.getY()); 
    parent = parent.getParent(); 
} 

// append e's rotation (applied first) 
t.rotate(...); 

e.draw(g2d, t); 

これはこの意味ですか?

+0

各要素は、それ自身とその親ローテーションの影響を受けます。あなたの以前の回答は順調でした。唯一の問題は、要素がx、y方向に移動しないために要素が移動されている場合です。たとえば、10,10と30の1つの要素、およびその他の要素は10,10と30の最初の要素の子です(グローバル値は20,20と60です)。そして私は子供を右に10ピクセル移動させたい。しかし、要素を10ピクセル右に移動すると、10ピクセルが60度回転して移動します。 – blejzz

+0

'transform()'メソッドは何をしますか? 'transform()'の代わりに 'translateInAncestorSpace()'のようにx/yを設定してください。 – Torious

+0

現在の位置にdxとdyを追加するだけです。あなたのコードと同じです。 – blejzz

関連する問題