午後わてんのブログ

ベランダ菜園とWindows用アプリ作成(WPFとC#)

WPFとVB.NET、TransformGroupのChildrenにAddする順番で結果が変わる

TransformGroupのChildrenにAddする順番で結果が変わる
 
RenderTransformをデザイン画面で指定しているときは自動で適当な順番になるから気にしていなかった、というか順番で結果が変わるとは思っていなかった
なのでコードで書くときにも順番を気にしないで書いていたら期待した形と違ったものが表示されておかしいなあ、ってなかなか気づけなかったのでメモ
 
 

f:id:gogowaten:20191030120546p:plain

同じ値を指定しても順番を帰ると結果も変わる
元の形は正方形、これを変形
指定している値は同じで回転角度30、横拡大率0.5、縦拡大率1.2
 
プロパティの変換の項目で指定した時の順番は自動で
Scale→Skew→Rotate→Translateになる
拡大→傾斜→回転→位置
これの順番を入れ替えてRotateを先頭にすると
左のようなひし形になる
 
 
VBコードでBorderに
回転角度30、横拡大率0.5、縦拡大率1.2する場合は
Dim tg As New TransformGroup
tg.Children.Add(New ScaleTransform(0.5, 1.2))
tg.Children.Add(New RotateTransform(30))
Dim b As New Border
b.RenderTransform = tg
こんな感じでOK
TransformGroupのChildrenにAddする順番が大切
 
 
 
ここからは蛇足
イメージ 2
TransformGroupのChildrenの順番
左 RotateTransform→ScaleTransform
右 ScaleTransform→RotateTransform
 
 
デザイン画面とXAML

f:id:gogowaten:20191030120557p:plain

 
VBコード

f:id:gogowaten:20191030120606p:plain

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
 
 
コード一式
 
続いているグループ化のテストの途中で気づいたんだけど、色いろあるねえ
アフィン変換ってのが変形に関わっているみたいなんだけど難しくて諦めた、これが理解できれば今回のことは当たり前なのかも?
 
 
 
関連記事
2017/06/19は25日後
WPF、AnglePropertyと作成した依存プロパティをバインディング - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/14979329.html