WPF: Obtendo novas coordenadas depois de uma rotação
Pergunta
Com referência ao este jogo programação Atualmente, estou construindo.
alt texto http://img12.imageshack.us/img12/2089/shapetransformationf .jpg
Para traduzir uma tela em WPF, estou usando duas formas: TranslateTransform
(para movê-lo), e RotateTransform
(para girá-lo) [ filhos do mesmo TransformationGroup
]
I pode facilmente obter o superior esquerdo coordenadas x, y de uma tela quando o seu não girado (ou girado em 90deg, uma vez que será o mesmo), mas o problema que estou enfrentando é conseguir o canto superior esquerdo (e o outro 3 pontos) coordenadas.
Isso ocorre porque quando um RotateTransform
é aplicada, propriedades TranslateTransform
e X
do Y
não são alterados (e, portanto, ainda indicam que o canto superior esquerdo da praça é como o pontilhada-quadrado (a partir da imagem)
A lona está sendo rodado a partir de seu centro, de modo que é a sua origem.
Assim como posso obter os "novos" x e y coordenadas dos 4 pontos depois de uma rotação ?
[UPDATE]
alt texto http://img25.imageshack.us/img25/8676/shaperotationaltransfor .jpg
Eu encontrei uma maneira de encontrar os superior esquerdo coordenadas após uma rotação (como você pode ver a partir da nova imagem), adicionando a OffsetX e OffsetY da rotação para o X iniciar e Y coordenadas.
Mas agora estou tendo dificuldade para descobrir o resto das coordenadas (os outros 3).
Com esta forma girado, Como posso descobrir as coordenadas X e Y dos 3 cantos restantes?
[EDIT]
Os pontos no 2º imagem NÃO SÃO PONTOS precisas e exatas . Eu fiz os pontos com estimativas na minha cabeça.
[UPDATE] Solução:
Em primeiro lugar, gostaria de agradecer Jason S para esse longo post e muito informativo no qual ele descreve a matemática por trás de todo o processo; Eu certamente aprendi muito lendo seu post e experimentar os valores.
Mas eu tenho encontrado agora um trecho de código (graças a EugeneZ 's menção de TransformBounds
) que faz exatamente o que eu quero:
public Rect GetBounds(FrameworkElement of, FrameworkElement from)
{
// Might throw an exception if of and from are not in the same visual tree
GeneralTransform transform = of.TransformToVisual(from);
return transform.TransformBounds(new Rect(0, 0, of.ActualWidth, of.ActualHeight));
}
Referência: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/86350f19-6457-470e-bde9-66e8970f7059/
Solução
Se entendi sua pergunta certa:
given:
shape has corner (x1,y1), center (xc,yc)
rotated shape has corner (x1',y1') after being rotated about center
desired:
how to map any point of the shape (x,y) -> (x',y') by that same rotation
Eis as equações relevantes:
(x'-xc) = Kc*(x-xc) - Ks*(y-yc)
(y'-yc) = Ks*(x-xc) + Kc*(y-yc)
onde Kc=cos(theta)
e Ks=sin(theta)
e theta
é o ângulo de rotação anti-horário. (Para verificar: se theta = 0 Isso deixa as coordenadas inalteradas, caso contrário, se xc = yc = 0, ele mapeia (1,0) para (cos (teta), sin (theta)) e (0,1) para (- sin (theta), cos (theta)) Advertência:.. isto é para sistemas de coordenadas, onde (x, y) = (1,1) está no quadrante superior direito por seu onde ele está no quadrante inferior direito, theta seria o ângulo de rotação no sentido horário, em vez de rotação anti-horário).
Se você conhece as coordenadas do seu retângulo alinhado com os eixos x-y, xc seria apenas a média das duas coordenadas x e yc seria apenas a média das duas coordenadas y. (Em sua situação, é xc = 75, yc = 85).
Se você sabe theta, agora você tem informações suficientes para calcular as novas coordenadas. Se você não sabe theta, você pode resolver para Kc, Ks. Aqui estão os cálculos relevantes para o seu exemplo:
(62-75) = Kc*(50-75) - Ks*(50-85)
(40-85) = Ks*(50-75) + Kc*(50-85)
-13 = -25*Kc + 35*Ks = -25*Kc + 35*Ks
-45 = -25*Ks - 35*Kc = -35*Kc - 25*Ks
que é um href="http://en.wikipedia.org/wiki/System_of_linear_equations" rel="noreferrer"> sistema que pode ser resolvido (exercício para o leitor: em MATLAB-lo de:
[-25 35;-35 -25]\[-13;-45]
para se obter, neste caso, Kc = 1,027, Ks = 0,3622, que não faz sentido (K 2 = Kc 2 + Ks 2 é suposto igual a 1 para uma rotação pura, neste caso, é K = 1.089) por isso não é uma rotação perfeita em torno do centro do retângulo, que é o seu desenho indica. Também não parece ser uma rotação perfeita em torno da origem. Para verificar, comparar as distâncias do centro de rotação, antes e depois da rotação usando o teorema de Pitágoras, d 2 = deltax 2 + deltay 2 . (Para rotação em torno xc = 75, yc = 85, a distância antes é 43,01, distância depois é 46,84, a proporção é K = 1,089; para rotação em torno da origem, distância antes é 70,71, distância depois é 73,78, proporção é de 1,043 I. podia acreditar rácios de 1,01 ou menos iriam surgir de coordenar o arredondamento para números inteiros, mas este é claramente maior do que um erro de arredondamento)
Então, há alguma informação em falta aqui. Como você conseguiu os números (62,40)?
Essa é a essência básica da matemática por trás rotações, no entanto.
edit: aha, eu não sabia que eles eram estimativas. (Muito perto de ser realista, embora!)
Outras dicas
Eu uso este método:
Point newPoint = rotateTransform.Transform(new Point(oldX, oldY));
onde RotateTransform é a instância em que eu trabalho e definir Angle ... etc.
Olhe para GeneralTransform.TransformBounds () método.
Eu não tenho certeza, mas é isso que você está procurando - a rotação de um ponto no sistema de coordenadas cartesianas: ligação
Você pode usar o método Transform.Transform () no seu ponto com as mesmas transformações para obter um novo ponto para o qual foram aplicadas essas transformações.