TransformGroupのChildrenにAddする順番で結果が変わる
RenderTransformをデザイン画面で指定しているときは自動で適当な順番になるから気にしていなかった、というか順番で結果が変わるとは思っていなかった
なのでコードで書くときにも順番を気にしないで書いていたら期待した形と違ったものが表示されておかしいなあ、ってなかなか気づけなかったのでメモ
同じ値を指定しても順番を帰ると結果も変わる
元の形は正方形、これを変形
指定している値は同じで回転角度30、横拡大率0.5、縦拡大率1.2
プロパティの変換の項目で指定した時の順番は自動で
Scale→Skew→Rotate→Translateになる
拡大→傾斜→回転→位置
これの順番を入れ替えてRotateを先頭にすると
左のようなひし形になる
VBコードでBorderに
回転角度30、横拡大率0.5、縦拡大率1.2する場合は
Dim tg As New TransformGroupこんな感じでOK
tg.Children.Add(New ScaleTransform(0.5, 1.2))
tg.Children.Add(New RotateTransform(30))
Dim b As New Border
b.RenderTransform = tg
TransformGroupのChildrenにAddする順番が大切
ここからは蛇足
左RotateTransform→ScaleTransform
右ScaleTransform→RotateTransform
デザイン画面とXAML
VBコード
Class MainWindow
Private mihonRotateScale As Border
Private mihonScaleRotate As Border
''' <summary>
''' TransformGroupの中から指定したTransformを返す
''' </summary>
''' <param name="tGroup">RenderTransformとか指定</param>
''' <param name="tType">取得したいTransformの指定、RotateTransformとか</param>
''' <returns></returns>
Private Function GetTransform(tGroup As TransformGroup, tType As Type) As Transform
For Each c As Transform In tGroup.Children
If tType = c.GetType Then
Return c
Exit For
End If
Next
Return Nothing
End Function
Private Function ResetScaleRotate() As TransformGroup
Dim tg As New TransformGroup
tg.Children.Add(New ScaleTransform(1, 1))
tg.Children.Add(New RotateTransform(0))
Return tg
End Function
Private Function ResetRotateScale() As TransformGroup
Dim tg As New TransformGroup
tg.Children.Add(New RotateTransform(0))
tg.Children.Add(New ScaleTransform(1, 1))
Return tg
End Function
Private Function GetBorder(tg As TransformGroup) As Border
Dim b As New Border
With b
.Width = 100
.Height = 100
.Background = Brushes.Red
.RenderTransformOrigin = New Point(0.5, 0.5)
.RenderTransform = tg
End With
Return b
End Function
Private Sub SetBorder(b As Border, x As Double, y As Double)
Canvas.SetLeft(b, x)
Canvas.SetTop(b, y)
canvas1.Children.Add(b)
End Sub
Private Sub ChangeAngle(b As Border)
Dim tg As TransformGroup = b.RenderTransform
Dim ro As RotateTransform = GetTransform(tg, GetType(RotateTransform))
ro.Angle = 30
End Sub
Private Sub ChangeScale(b As Border)
Dim tg As TransformGroup = b.RenderTransform
Dim s As ScaleTransform = GetTransform(tg, GetType(ScaleTransform))
s.ScaleX = 0.5
s.ScaleY = 1.2
End Sub
Private Sub MainWindow_ContentRendered(sender As Object, e As EventArgs) Handles Me.ContentRendered
Dim b As Border = GetBorder(ResetRotateScale)
mihonRotateScale = b
Call SetBorder(b, 30, 50)
b = GetBorder(ResetScaleRotate)
mihonScaleRotate = b
Call SetBorder(b, 200, 50)
End Sub
Private Sub bt1_Click(sender As Object, e As RoutedEventArgs) Handles bt1.Click
mihonRotateScale.RenderTransform = ResetRotateScale()
End Sub
Private Sub bt2_Click(sender As Object, e As RoutedEventArgs) Handles bt2.Click
Call ChangeAngle(mihonRotateScale)
End Sub
Private Sub bt3_Click(sender As Object, e As RoutedEventArgs) Handles bt3.Click
Call ChangeScale(mihonRotateScale)
End Sub
Private Sub bt4_Click(sender As Object, e As RoutedEventArgs) Handles bt4.Click
mihonScaleRotate.RenderTransform = ResetScaleRotate()
End Sub
Private Sub bt5_Click(sender As Object, e As RoutedEventArgs) Handles bt5.Click
Call ChangeAngle(mihonScaleRotate)
End Sub
Private Sub bt6_Click(sender As Object, e As RoutedEventArgs) Handles bt6.Click
Call ChangeScale(mihonScaleRotate)
End Sub
Private Sub sld1_ValueChanged(sender As Object, e As RoutedPropertyChangedEventArgs(Of Double)) Handles sld1.ValueChanged
Dim tg As TransformGroup = mihonRotateScale.RenderTransform
Dim r As RotateTransform = GetTransform(tg, GetType(RotateTransform))
r.Angle = sld1.Value
End Sub
End Class
コード一式
Wpf_test122_TransformGroupにAddする順番 - Visual Studio Team Services
https://gogowaten.visualstudio.com/WPF/_git/WPF_test7?path=%2FWpf_test122_TransformGroup%E3%81%ABAdd%E3%81%99%E3%82%8B%E9%A0%86%E7%95%AA&version=GBmaster&_a=contents
続いているグループ化のテストの途中で気づいたんだけど、色いろあるねえ
アフィン変換ってのが変形に関わっているみたいなんだけど難しくて諦めた、これが理解できれば今回のことは当たり前なのかも?