THIS IS ELLIE

CGAffineTransform 분석하기 본문

개발/iOS

CGAffineTransform 분석하기

Ellie Kim 2022. 3. 20. 20:44

CGAffineTransform 아핀 변환에 대해서 살펴보려 합니다.
CGAffineTransform 관련된 질문을 받게 되었는데 거의 까먹어서 다시 정리
(아이패드로 공부한 내용 그대로 가져오는 거라 발그림 죄송)


아핀 변환 언제 쓰나?
아핀 변환 행렬은 2D 그래픽을 그리는 데 사용됩니다.
rotate, sclae, translate, skew 변환할 때 사용dd

 

CGAffineTransform
여기서 CG는 CoreGraphics를 의미함.
스위프트에서 CGAffineTransform은 구조체로 정의되어 있으며, 아래와 같이 3x3행렬로 표시됩니다.

세 번째 열은 항상 (0,0,1)이므로 CGAffineTransform 데이터 구조에는 처음 두 열에 대한 값만 포함됩니다.


방정식 도출
왼쪽 행렬의 행 [x y 1]에 오른쪽 행렬의 열들 [a c tx] [b d ty] [0 0 1]을 하나씩 가져와 쭈욱 계산해줍니다.
그러면 아래와 같이 방정식이 도출되게 됩니다.
즉 우리는 CGPoint(x, y)와 CGAffineTransform을 곱해서 변환된 CGPoint(x', y')를 얻을 수 있습니다. 

아래 예시를 봐주세요. 

첫 번째 예시에서 그림을 2배로 늘려본다고 가정해봅시다.
그럼 (x: 1, y: 1) 좌표는 어디로 가게 될까요? 
(x: 1, y: 1) 좌표는 아핀 변환 행렬을 곱해 변형된 좌표 값 (x: 2, y:2) 이 나오게 됩니다.

두 번째 예시에서는 y를 1만큼 이동한다고 가정해봅시다.
그럼 (x: 1, y: 1) 좌표는 어디로 가게 될까요? 
(x: 1, y: 1) 좌표는 아핀 변환 행렬을 곱해 변형된 좌표 값 (x: 1, y: 2) 이 나오게 됩니다.

즉 아핀 변환은 한 좌표계의 점이 다른 좌표계의 점에 매핑되는 방법입니다.
위 곱하는 것들 우리가 다 해야 함?? 
ㄴㄴ CGAffineTransform에서 다 초기화나 함수로 제공을 해줍니다.

 

CGAffineTransform의 initializers 살펴보기

위 이미지에서 rotate, scale, translate를 지원하는 것을 확인할 수 있습니다.
추가로 행렬의 원소를 직접 작성해서 변환을 시킬 수도 있습니다.

 

CGAffineTransform의 instance methods 살펴보기

위 이미지에서 rotate, scale, translate를 지원하는 것을 확인할 수 있습니다.
inverted()를 통해 invert(반대?,거꾸러?)한 아핀 변환을 리턴 받는 것도 가능하고
concatenating()을 통해 두 아핀 변환을 결합하는 것도 가능합니다.

 

Identity 사용하기
원상복구 시킬 때 사용 

CGAffineTransform 타입 프로퍼티에 static var로 정의되어 있습니다.
추가로 CGAffineTransform 인스턴스 프로퍼티에 isIdentity도 정의되어 있는데 해당 아핀 행렬이 identity transform 되어있는지 확인 가능합니다.

translate 사용하기
이동할 때 사용

매개변수 tx는 x 이동하는 값이고 ty는 y 이동하는 값입니다.
그리고 새로운 아핀 변환 행렬을 리턴합니다.

 

scale 사용하기
크기를 조정할 때 사용

매개변수 sx는 x축 배율을 조정하는 데 사용하는 값이고 sy는 y축 배율을 조정하는 데 사용하는 사용하는 값입니다.
그리고 새로운 아핀 변환 행렬을 리턴합니다.

 

rotate 사용하기
회전할 때 사용

매개변수 angle은 회전할 각도를 의미합니다.
iOS에서 양수 값은 시계 반대 방향으로 회전하고 음수 값은 시계 방향으로 회전합니다. 
macOS에서는 양수 값이 시계 방향으로 회전하고 음수 값은 시계 반대 방향으로 회전합니다.
플랫폼에 따라서 알아서 실행된다고 합니다. (근데 왜 다르게 해 놨을까)
그리고 새로운 아핀 변환 행렬을 리턴합니다.

 

concatenating 사용하기
두 아핀 변환 결합할 때 사용

매개변수 t2는 기존 아핀 변환에 연결할 아핀 변환입니다.
그리고 새로운 아핀 변환 행렬 t'을 리턴합니다.
(t' = t1 * t2) 

행렬의 곱셈에서는 교환 법칙이 성립하지 않습니다.
t1 행렬에 t2 행렬을 곱한 값이 t2 행렬에 t1행렬을 곱한 값과 반드시 같지는 않다는 의미입니다.
관련해서 예시를 가져와보겠습니다.
아래는 translate, scale 행렬을 곱한 결과입니다.

첫 번째 예제는 scale 후 translate 결과
두 번째 예제는 translate 후 scale 결과
결과 값이 다르죠?

순서에 따라서 결과가 다를 수 있다는 것을 알아야 합니다.
그리고 행렬을 연결하는 순서가 중요합니다.

 

skew(shear) 사용하기
현시점 iOS에서는 rotate, scale, translate는 초기화나 함수로 지원을 해주고 있는데 skew는 지원을 안 해주는 것 같습니다.
만약 skew를 사용해보고 싶다면 아래와 같이 사용하면 skew효과를 낼 수 있습니다.
shear(skew) 값을 적절하게 변경해보면서 원하는 모양으로 만들면 됩니다.

let shear = CGFloat(0.5)
let shearTransform = CGAffineTransform(a: 1, b: shear, c: 0, d: 1, tx: 0, ty: 0)
myView.transform = shearTransform

 

 

다양한 아핀 변환

다양한 아핀 변환을 해보고 실험해보고 싶으시다면, 위 이미지와 같이 행렬 원소를 수정해보는 것도 좋을 듯합니다.

 

resource
https://developer.apple.com/documentation/coregraphics/cgaffinetransform/1454909-init
https://developer.apple.com/documentation/coregraphics/cgaffinetransform/1455016-init
https://developer.apple.com/documentation/coregraphics/cgaffinetransform/1455666-init
https://developer.apple.com/documentation/coregraphics/cgaffinetransformhttps://en.wikipedia.org/wiki/Affine_transformation
https://developer.apple.com/documentation/coregraphics/cgaffinetransform#declaration
https://kr.mathworks.com/discovery/affine-transformation.html


버전에 따라 다른 동작성?
CGAffineTransform이 동작하는 방식이 버전에 따라 달라진다고?
2019.01.13 - [개발/iOS] - iOS CGAffineTransform 사용하기
모르고 있었는데 어떤 분이 감사하게도 이전 포스팅 보고 알려주셔서 실행해보니 진짜 달라졌네요;
동일한 코드 동일한 CGAffineTransform결과 값임에도 불구하고 동작성이 달라졌더라고요.
medium, stackoverflow에도 버전에 따라서 동작성이 달라지는 말들이 있는데...
(버전에 따라 달라진다는 말만 있지 어떻게 달라진지는 안 나와있음 ㅜ 애플만 알겠지?)

일단 scale, rotate 결합하는 것은 내 예상과 동일하게 진행
rotate, translate 결합하면 내가 예상하지 못한 결과로 실행
(이 부분이 버전에 따라 다른 동작성을 가지는 부분이기도 함)
(예전 버전에서는 회전하면서 translate지점까지 직선으로 이동함)
(지금은 원형을 크게 돌면서 translate지점까지 이동함)

일단 아핀 변환 행렬 특성상 scale과 rotate는 중심점이 달라지지 않음.
하지만 translate은 중심점이 달라짐.
중심점이 그대로면 왼쪽과 같이 중심점을 기준으로 회전을 함.
오른쪽과 같이 중심점이 달라진다면 원을 크게 도는 형태로 회전을 함.
그럼 애플이 중심점에 대한 동작성을 바꾼 걸까?????
그런 걸까??????

조심스럽게 추측해 봤지만,,, 추측은 추측​
CoreGraphics를 까 볼 수도 없고 정답 아시는 분?? 누가 좀 알려주세요.

반응형