CGAffineTransformのパラメータが簡単に理解できるPlayground Code

アフィン変換を行うCGAffineTransformのパラメータをa, b, c, d, tx, tyと全部指定して変換したい場合、やり方がよくわからなくなることがあるので、使い方が簡単に理解できるPlayground Codeを作りました。

### CGAffineTransformのパラメータについての説明

CGAffineTransformのパラメータは、アフィン変換の式にあてはめると次のようになります。

**<アフィン変換の式>**
<img width="600px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116010/4c54cdc9-ec53-21a8-06f6-30160e54a155.png">

拡大の場合は、aにxの拡大量、dにyの拡大量を指定します。
移動の場合は、txにxの移動量、tyにyの移動量を指定します。
回転の場合はパラメータの部分を次のようにします。
<img width="200px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116010/7fb985fe-dd38-060a-23bf-c2ff77a94142.png">

拡大と回転を組み合わせる場合はそれらをかけ合わせる必要があります。

例：x,yを2倍して、角度aだけ回転させる場合
<img width="700px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116010/56d2a6c3-6bca-ebc5-5512-aedfb1d21671.png">

参考：[CGAffineTransformを知る](https://qiita.com/Moto0124/items/bdb5d86b76b522cc6249)

### Playground Codeでしていること

UILabelを５つ作り、何もしない、拡大する、移動する、回転するとそれら全部を組み合わせた組み合わせるといったアフィン変換を使っています。

**＜表示結果＞**
<img width="300px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116010/6f370077-3d17-e284-f14f-3e2ade162090.png">

```swift:Playground
//: A UIKit based Playground for presenting user interface
  
import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    override func loadView() {
        func buildLabel(_ num: Int) -> UILabel {
            let label = UILabel()
            label.frame = CGRect(x: 150, y: num * 100 + 50, width: 100, height: 20)
            label.backgroundColor = .red
            label.textColor = .black
            label.text = "変換なし"

            return label
        }
        func buildView() -> [UILabel]{
            var labels = [UILabel]()
            let view = UIView()
            view.backgroundColor = .white
            for i in 0...4 {
                let label = buildLabel(i)
                view.addSubview(label)
                labels.append(label)
            }
            self.view = view
            return labels
        }

        let labels = buildView()
        
        _ = {
            // 拡大
            let a: CGFloat = 2 // xの拡大量
            let b: CGFloat = 0
            let c: CGFloat = 0
            let d: CGFloat = 2 // yの拡大量
            let tx: CGFloat = 0
            let ty: CGFloat = 0
            
            let transform = CGAffineTransform(
                              a: a,
                              b: b,
                              c: c,
                              d: d,
                              tx: tx,
                              ty: ty
                            )
            labels[1].transform = transform
            labels[1].text = "拡大"
        }()
        _ = {
            // 移動
            let a: CGFloat = 1
            let b: CGFloat = 0
            let c: CGFloat = 0
            let d: CGFloat = 1
            let tx: CGFloat = 30 // xの移動量
            let ty: CGFloat = 30 // yの移動量
            
            let transform = CGAffineTransform(
                              a: a,
                              b: b,
                              c: c,
                              d: d,
                              tx: tx,
                              ty: ty
                            )
            labels[2].transform = transform
            labels[2].text = "移動"
        }()
        _ = {
            // 回転
            let r = -(CGFloat.pi / 4)
            
            let a: CGFloat = cos(r)
            let b: CGFloat = sin(r)
            let c: CGFloat = -sin(r)
            let d: CGFloat = cos(r)
            let tx: CGFloat = 0
            let ty: CGFloat = 0
            
            let transform = CGAffineTransform(
                              a: a,
                              b: b,
                              c: c,
                              d: d,
                              tx: tx,
                              ty: ty
                            )
            labels[3].transform = transform
            labels[3].text = "回転"
        }()
        _ = {
            // 組み合わせ
            let r = -(CGFloat.pi / 4)
            
            let a: CGFloat = 2*cos(r)
            let b: CGFloat = 2*sin(r)
            let c: CGFloat = 2*cos(r)
            let d: CGFloat = 2*cos(r)
            let tx: CGFloat = 30 // xの移動量
            let ty: CGFloat = 30 // yの移動量
            
            let transform = CGAffineTransform(
                              a: a,
                              b: b,
                              c: c,
                              d: d,
                              tx: tx,
                              ty: ty
                            )
            labels[4].transform = transform
            labels[4].text = "組み合わせ"
        }()

    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
```

### 最後に

NoteではiOS開発、とくにCoreML、ARKit、Metalなどについて定期的に発信しています。
https://note.com/tokyoyoshida

Twitterでも発信しています。
https://twitter.com/jugemjugemjugem