들어가기
행렬 회전은 행렬 전체가 가운데 기준을 가지고 왼쪽 혹은 오른쪽으로 90도 회전하는 것을 말한다. 행렬을 회전하는 방법은 직접 위치를 이동하거나 전치행렬을 이용한 방식이 있다. 하나씩 살펴보자.
작성자: http://ospace.tistory.com/ (ospace114@empal.com)
직접 이동으로 행렬 회전
행렬 회전을 살펴보자. 회전은 오른쪽 방향과 왼쪽 방향으로 나눌 수 있다. 아래 그림은 3차 정방행렬의 회전을 나타내고 있다.
회전을 잘 살펴보면, 행벡터가 열벡터로 변화되는 것을 알 수 있다. 물론 반대로 생각할 수도 있다. 여기서는 행벡터를 열벡터로 변화를 다룰려고 한다.
먼저 오른쪽 회전을 보자. 첫번째 행벡터인 [1,2,3]가 열벡터 [1,2,3]로 변화된다. 이때 변화할때 성분 위치 변경은 없고 행벡터를 열벡터로 변환하면 된다. 그리고 첫번째 행벡터는 마지막 열벡터가 된다. 즉, 행벡터 배치 순서가 열벡터 배치 순서와 반대방향으로 된다. 의사코드를 작성하면 다음과 같다.
"result" 행렬 초기화
FOR I=1 to 행 개수
FOR J=1 to 열 개수
// 행백터를 열벡터로 변환하고 열벡터를 위치를 마지막부터 배치
SET result[열 개수+1-J, I] to 행렬[I, J]
END FOR
END FOR
RETURN result
다음으로 왼쪽 회전을 보자. 첫번째 행벡터인 [1,2,3]이 왼쪽으로 회전하면 열벡터 [3,2,1]로 바뀐다. 즉, 행벡터에 성분 위치가 열벡터에서 반대로 된다. 그리고 열벡터는 첫번째 열벡터에 배치된다. 즉, 성분 위치는 반대로 되지만 열벡터 배치 위치는 그대로 유지된다. 의사 코드로 작성하면 다음과 같다.
"result" 행렬 초기화
FOR I=1 to 행 개수
FOR J=1 to 열 개수
// 행백터를 열벡터로 역순변환하고 열벡터를 위치를 순서대로 배치
SET result[J, 행 개수+1-I] to 행렬[I, J]
END FOR
END FOR
RETURN result
회전 방향에 따라서 성분 위치 계산하는 연산이 달라진다.
전치행렬 이용한 회전
이번에는 전치행렬을 이용한 회전을 보자. 전치행렬은 대각성분의 위치가 서로바뀐 행렬이다. 변환된 전치행렬를 가지고 행방향 또는 열방향으로 역순으로 변경하면 된다. 아래 그림이 앞에서 말한 작업을 표현하였다.
먼저 행렬을 전치행렬로 변환한다. 변환하는 작업은 어렵지 않다. 대각 성분 위치만 바꾸면 된다. 그런 후에 오른쪽 회전인 경우 행벡터의 성분 위치를 반대로 바꾼다. 만약, 왼쪽 회전인 경우는 열벡터의 성분 위치를 반대로 바꾼다. 이를 의사코드로 작성해보자.
"result" 행렬 초기화
// 전치행렬 변환
FOR I=1 to 열 개수
FOR J=1 to I
SET result[I, J] to 행렬[I, J]
SET result[J, I] to 행렬[I, J]
END FOR
END FOR
IF 오른쪽 회전 THEN
CALL 행벡터 역순(result)
ELSE
CALL 열벡터 역순(result)
END IF
RETURN result
전치행렬을 이용하면 단순하게 오른쪽 회전과 왼쪽 회전을 같이 처리할 수 있다. 여기서 행벡터와 열벡터 역순을 처리하는 함수는 단순하기 때문에 별도로 다루지 않는다.
마무리
지금까지 행렬 회전을 살펴보았다. 실제 구현 측면에서 성능 측면을 보면 직접 이동이 더 좋아보인다. 전치행렬을 사용할 경우 행렬 순회가 여러번 발생하고 할당작업도 더 많아지게 된다. 즉, 성능 측면에서는 안 좋을 수 밖에 없다. 그러나 코드 재사용성이나 구조적인 측면으로는 전치행렬이 더 좋아 보인다. 이 것은 직관적으로 판단한 부분이고 실제 성능은 행렬의 자료구조와 실제 로직을 가지고 판단해야 한다.
앞의 의사코드에서 여러가지 변화가 있을 수 있다. 여기서는 결과값을 별도로 저장해서 리턴했지만, 직접 행렬 자체를 변경할 수도 있다. 직접 행렬을 변경하는 경우, 값을 할당하는 로직도 다소 변경이 있을 수 있다. 이럴 경우 값을 스왑하는 기술을 적용해야 한다. 스왑은 언어에 따라서 처리하는 방식이 달라지기에 이런 부분까지 다루기 복잡해져서 단순히 별도로 결과를 저장하는 방식을 사용했다.
추가로, 행벡터와 열벡터 역순 처리를 단순한 함수 호출로 처리했지만, 경우 따라서는 매우 단순한 코드로 작성될 수 있다. 이런 부분이 의사코드의 한계인 듯 하다. 즉, 언어에 따라서 정말 단순하게 처리할 수도 있다. 예를 들어 자바스크립트인 경우를 보자.
// 행벡터 역순
result.forEach((col)=>col.reverse());
// 열벡터 역순
result.reverse();
언어 또는 라이브러리에 따라서 처리하는 방식이 전혀달라지기 때문에 이런 부분의 구현 측면은 상황에 맞게 적절하게 선택해야 한다. 부족한 글이지만 여러분에게 참고가 되었으면 하네요. 모두 즐거운 코딩생활하세요. ospace.
참고
[1] Google Search Labs AI, https://www.google.com/search?q=javascript+행렬+회전&rlz=1C1CHZL_koKR763KR763&oq=javascript+행렬+회전&gs_lcrp=EgZjaHJvbWUyBggAEEUYOdIBCDQ1MDVqMGo0qAIAsAIB&sourceid=chrome&ie=UTF-8, 2025.04.11
'6.수학과 알고리즘' 카테고리의 다른 글
[그래픽] 폴리라인에서 오프셋 (0) | 2025.04.04 |
---|---|
[그래픽] 폴리라인에서 곡선처리 (1) | 2025.04.02 |
수학기초 8 - 확률과 통계 2 (0) | 2025.03.27 |
수학기초 7 - 확률과 통계 1 (0) | 2025.03.19 |
수학기초 6 - 행렬2 (3) | 2025.03.12 |