我无法确定应用于应用中元素的正确转换顺序。 app具有父/子关系的元素,每个元素都有一个转换(每个元素都在局部空间中绘制然后转换)。
我要归档的是,如果我变换父项,它的所有子项也应该被变换(所以如果你旋转父项,子项应该围绕父项旋转)。
下面的代码就是这样,但问题是我旋转父级然后想要移动孩子。它向错误的方向移动(由于其父转换)。我已经尝试改变转换的顺序,但没有运气(我知道我应该首先翻译,然后转换,但然后孩子围绕自己的轴旋转 - 而不是父母)。
代码:
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 :(得分:3)
这样的事情:
// 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);
}
答案 1 :(得分: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);
这是你的意思吗?