Programming Language/C/C++

[C/C++] atan2 함수로 각도 구하기 (극 좌표계)

깐요 2017. 5. 11. 20:28

직각 좌표계? 극 좌표계?

평면 상에서 어떤 점의 위치 또는 원점에 대한 상대적 위치를 나타내야 한다고 할 때 우리는 좌표계를 이용한다

그 좌표계를 표현하는 방법은 대표적으로 2가지가 있다

첫번째로 원점으로부터의 수평 거리와 수직 거리를 이용하여 위치를 표현하는 직각 좌표계(rectangular coordinates)가 있다

그리고 원점으로부터의 거리와 수평축으로부터의 각도를 이용하여 위치를 표현하는 극 좌표계(polar coordinates)가 있다


수평축으로부터의 각도 구하기

직각 좌표계는 고등수학과정에서 많이 다루므로 극 좌표계를 프로그램으로 구현해보자

어떤 한 점 A가 직각 좌표계에서 x, y로 표현된다고 가정한다

원점으로부터의 거리는 피타고라스의 정리로 구할 수 있다

그렇다면 수평축으로부터의 각도를 어떻게 구할까

이 문제는 삼각함수를 이용하면 쉽게 해결이 가능하다

위 그림을 보면

라는 사실을 알 수 있다

여기서 구하고자하는 각도인 θ 를 구하기 위해서는 역함수로 변환하면 된다

tanθ 의 역함수는 arctanθ 이다


arctan? atan2()!

위에서 구한 수학공식을 어떻게 프로그램에서 표현할까?

우선 거리의 값을 구하기 위해서는 제곱근을 표현할 필요가 있다

제곱근은 cmath 헤더 파일을 프로그램에 포함시키면 사용할 수 있는 sqrt() 함수로 표현한다

다음으로 수평축으로부터의 거리를 구할 때는 arctan를 이용했다

arctan는 atan2() 함수로 표현한다

단 atan2() 함수로 구한 각도는 radian 단위를 사용하므로 180/π (약 57.29577951)을 곱해야 도 단위로 구해진다

(atan() 함수도 있지만, 180도 차이가 나는 두 개의 각도를 구별하지 못하여 불활식한 함수이므로 서술하지 않겠다)


실제로 극 좌표를 구해보자

구조체를 이용하여 직각 좌표와 극 좌표를 표현하였고

구조체를 참조하여 직각 좌표를 극 좌표로 변환하는 함수와 극 좌표를 화면에 출력하는 함수를 정의했다

직각 좌표의 x좌표와 y좌표를 입력받고 문자를 입력했을 시에 프로그램을 종료한다

#include <iostream> #include <cmath> //sqrt(), atan2() 함수 struct rect { double x; double y; }; struct polar { double distance; double angle; //radian }; //함수 원형 void show_polar(polar dapos); polar rect_to_polar(rect xypos); // int main(void) { using namespace std; rect rplace; polar pplace; cout << "x값과 y값을 입력하십시오: "; while (cin >> rplace.x >> rplace.y) //직각 좌표 정보를 입력 (다른 형값 입력 시 루프 탈출) { pplace = rect_to_polar(rplace); show_polar(pplace); cout << "x값과 y값을 입력하십시오(끝내려면 q를 입력): "; } cout << "프로그램을 종료합니다.\n"; return 0; } //극 좌표를 화면에 출력 void show_polar(const polar dapos) { using namespace std; const double Rad_to_deg = 57.2957951; // 180/pi cout << "거리 = " << dapos.distance; cout << ", 각도 = " << dapos.angle * Rad_to_deg; cout << "도\n"; } //직각 좌표를 극 좌표로 변환 polar rect_to_polar(rect xypos) { polar answer; answer.distance = sqrt(xypos.x * xypos.x + xypos.y * xypos.y); //피타고라스의 정리 이용 answer.angle = atan2(xypos.y, xypos.x); //arctan 이용 return answer; }

<구조체를 전달하는 경우>

#include <iostream>
#include <cmath>

struct rect
{
	double x;
	double y;
};

struct polar
{
	double distance;
	double angle;            //radian
};

void show_polar(const polar *xypos);
void rect_to_polar(const rect *xypos, polar *dapos);

int main(void)
{
	using namespace std;
	rect rplace;
	polar pplace;

	cout << "x값과 y값을 입력하십시오: ";
	while (cin >> rplace.x >> rplace.y)
	{
		rect_to_polar(&rplace, &pplace);
		show_polar(&pplace);
		cout << "x값과 y값을 입력하십시오(끝내려면 q를 입력): ";
	}
	cout << "프로그램을 종료합니다.\n";
	return 0;
}

void show_polar(const polar *dapos)
{
	using namespace std;
	const double Rad_to_deg = 57.2957951;        // 180 / pi

	cout << "거리 = " << dapos->distance;
	cout << ", 각도 = " << dapos->angle * Rad_to_deg;
	cout << "도\n";
}

void rect_to_polar(const rect *xypos, polar *dapos)
{
	dapos->distance = sqrt(xypos->x * xypos->x + xypos->y * xypos->y);
	dapos->angle = atan2(xypos->y, xypos->x);
}

<구조체의 주소를 전달한 경우>

<실행결과>

320x100