Notice
Recent Posts
Recent Comments
Link
관리 메뉴

뛰는 놈 위에 나는 공대생

[MATLAB] 3D plot을 그릴 때 주의할 점 : X,Y축 반전 본문

프로그래밍 Programming/매트랩 MATLAB

[MATLAB] 3D plot을 그릴 때 주의할 점 : X,Y축 반전

보통의공대생 2022. 5. 20. 11:22

MATLAB에서 3D plot을 그릴 때 주의할 점이 있다.

 

MATLAB에서는 결과값이 행렬로 나올 때 plot을 하면

행(row)을 Y축으로 인식하고, 열(column)을 X축으로 인식한다.

 

그런데 이것은 우리의 직관과 다르다.

 

예를 들어

$f(x_{1},x_{2}) = (1-x_{1})^2+100(x_{2} - x_{1}^{2})^{2}$라는 함수가 있다고 하자.

 

내가 $(x_{1},x_{2})$ 값을 넣을 때

당연히 f라는 변수에 (1,1)항목은 $(x_{1}(1),x_{2}(1))$값을 넣는다. 여기서 $x_{1}(1)$은 $x_{1}$후보 중에 첫 번째 값을 넣는다는 뜻이다.

(2,1)항목에는 $(x_{1}(2),x_{2}(1))$ 를 넣는다.

 

그런데 MATLAB의 변수에서 첫 번째 INDEX는 행을 의미한다.

 

여기서 혼돈이 온다.

 

그래프를 그릴 때 첫 번째 인덱스(=행)은 Y축으로 인식하고, 두 번째 인덱스(=열)은 X축으로 인식한다.

그런데 보통 notation 상 값을 넣을 때는 X에 대응되는 곳은 첫 번째 인덱스, Y에 대응되는 곳은 두 번째 인덱스가 된다.

따라서 실제 값과 MATLAB 3D plot 상에 축이 반대로 되는 현상이 발생한다.

 

 

그래서 surf와 같은 함수를 쓸 때는 반드시 Z축에 plot할 값을 Transpose해줘야 한다.

 

아래는 로젠브록 함수를 surf를 이용해서 그리는 것이다.

 

J = @(x_1,x_2) (1-x_1)^2 + 100*(x_2 - x_1^2)^2 ;

x = -10:0.1:10 ;
[x_1,x_2] = meshgrid(x);

num = length(x) ;
J_eval = zeros(num) ;

for i = 1 : num
    for j = 1 : num
        J_eval(i,j) = J(x(i),x(j)) ;
    end
end

% plot
figure;
s = surf(x_1,x_2,J_eval') ;
s.EdgeColor = 'none';
xlabel('x_1') ;
ylabel('x_2') ;
title('Rosenbrok function') ;

위의 코드를 보면 Z축에 들어가는 J_eval 을 transpose했다

 


보충설명을 하면, 일반적으로 MATLAB의 help 센터에서 surf를 사용할 때는 다음과 같이 z값을 구해서 하기를 권한다.

 

J = @(x_1,x_2) (1-x_1)^2 + 100*(x_2 - x_1^2)^2 ;

x = -10:0.1:10 ;
[x_1,x_2] = meshgrid(x);

J_eval = (1-x_1).^2 + 100*(x_2 - x_1.^2).^2 ;

% plot
figure;
s = surf(x_1,x_2,J_eval) ;
s.EdgeColor = 'none';
xlabel('x_1') ;
ylabel('x_2') ;
title('Rosenbrok function') ;

위 코드처럼 계산하면 굳이 transpose를 해줄 필요가 없다.

 

아래 그림은 help에 있는 예시이다.

위의 meshgrid 코드를 실행해서 x_1을 열어보면

 

다음처럼 열을 기준으로 값이 바뀌는 것을 확인할 수 있다. x_1은 x축에, x_2는 y축에 들어가는데 x_1이 열 기준으로 -10,-9.9... 바뀌는 것을 보면 x_1, x_2를 가지고 계산하는 것이 더 속편할 수도 있다.

 

 

그런데 나의 경우에는 위 코드처럼 surf를 쓰려는 게 아니라 다른 코드에서 데이터를 수집해서 z축 값을 저장한 다음에, surf를 쓰려고 하다보니 축에 혼동이 온 경우라서, 나같은 사람을 위해 글을 작성한다.

Comments