2012-04-22 4 views
0

내 응용 프로그램의 요소에 적용 할 올바른 변환 순서를 알아내는 데 문제가 있습니다. app에는 부모/자식 관계가있는 요소가 있으며 각 요소에는 변형이 있습니다 (각 요소는 로컬 공간에 그려지고 변형됩니다).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); 
} 
문제

: - 주어진 두 개의 요소 (다른 하나의 자식) - 부모 (40도에서) 회전이다 - 아이가 다음 10px 에 의해 이동되고 내가 어떻게 할 수있는 변환을 연결하여 아이를 움직일 때 회전 된 방향으로 움직이지 않습니까?

편집 : 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/)를 게시하십시오. BTW - 질문 있니? –

답변

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

좋아, 난 당신이 지금 원하는 것을 이해하고 생각합니다. 아래 코드는 (테스트되지 않음)에서 병합하지 않고 병합을 병합해야합니다. 각 요소는 자체 회전에 의해서만 영향을받습니다.

코드의 의도가 이전 답변의 코드와 다르기 때문에 나는 이것을 새로운 대답으로 게시했습니다.

이 코드를 사용하면 요소의 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의 한 요소와 다른 요소는 10,10 및 30의 첫 번째 요소 (그의 전역 값은 20, 20 및 60 임)의 하위 요소입니다. 그리고 저는 그 아이를 10 px만큼 오른쪽으로 옮기고 싶습니다. 하지만 요소를 오른쪽으로 10 픽셀 씩 이동하면 10 픽셀이 60도 회전합니다. – blejzz

+0

'transform()'메서드는 무엇을합니까? 아마'transform()'을 호출하는 대신'translateInAncestorSpace()'에서했던 것처럼 x/y를 설정해야합니다. – Torious

+0

그냥 dx와 dy를 현재 위치에 추가합니다. 코드와 동일합니다. – blejzz