본문 바로가기

Enginius/Matlab

두 선분 사이의 각도를 구해보자.

두 선분 사이의 각도는 내적의 arc cos을 통해서 쉽게 구할 수 있다. 

하지만 문제는 어느 방향으로 회전했는가이다. 즉 acos의 range는 0~180이기 때문에 360도를 모두 표현하기 힘들다. 그래서 이를 처리하는 매트랩 함수를 만들어 봤다. 


수행 동영상

테스트 코드 

%% getDegBtwLines 를 테스트

clc;

clear all

close all;


%%

saveVideo = 1;

if saveVideo

    vidObj = VideoWriter('vids/getDegBtwLines.avi');

    vidObj.FrameRate = 10;

    open( vidObj );

end 


%%

org = [10 -10];

nr_data = 40;

rads = degspace(0, 360, nr_data)*pi/180;

pntA_list = repmat([20 10], nr_data, 1);

pntB_list = repmat(org, nr_data, 1) + [10*cos(rads) 10*sin(rads) ];


fig = figure(1);

for i = 1:nr_data

    pntA = pntA_list(i, :);

    pntB = pntB_list(i, :);

    

    deg_diff = getDegBtwLines(org, pntA, pntB);

    

    clf;

    hold on;

    plot(org(1), org(2), 'ro', 'MarkerFaceColor', 'r');

    text(org(1), org(2), '  O');

    plot(pntA(1), pntA(2), 'go', 'MarkerFaceColor', 'g');

    text(pntA(1), pntA(2), '  A');

    plot([org(1) pntA(1)], [org(2) pntA(2)], 'g');

    plot(pntB(1), pntB(2), 'bo', 'MarkerFaceColor', 'b');

    text(pntB(1), pntB(2), '  B');

    plot([org(1) pntB(1)], [org(2) pntB(2)], 'b');

    hold off; axis([-15 40 -30 25]); % axis equal; 

    grid on;

    title(sprintf('OA를 기준으로 OB의 각도: %.1f deg', deg_diff) ...

        , 'FontSize', 12);

    drawnow; 

    if saveVideo

        writeVideo( vidObj, getframe(gcf) );

    end

    pause(.1);

end  

if saveVideo

    close( vidObj );

end


getDegBtwLines 함수

function deg_diff = getDegBtwLines(org, pntA, pntB)

%

% org를 기준으로 하는 pntA와 pntB를 잇는 두 선 사이의 각도를 구한다. 

%


% 원점 기준으로 변경한다. 

pntA = pntA - org;

pntB = pntB - org;


% 길이를 1로 normalize한다. 

pntA = pntA / norm(pntA);

pntB = pntB / norm(pntB);


% 방향을 확인하기 위한 변수 (A를 90도 회전)

pntC = [-pntA(2) pntA(1)];

flag = sign(pntB(1)*pntC(1) + pntB(2)*pntC(2));


% 각도를 구한다. 

deg_diff = flag*acos(pntA(1)*pntB(1) + pntA(2)*pntB(2))*180/pi;