[GIS] 좌표계(Coordinate System)의 종류

좌표계는 단순히 어떤 중심을 기준으로.. 즉 원점에 대해 공간적 속성을 설명하는 방법으로 다음 세가지로 정의할 수 있습니다.

사용자 삽입 이미지

지구의 중심을 원점으로 (X,Y,Z) 좌표에 기반하는 Geocentric coordinate system(지심좌표계)로써 이 좌표계는 GPS가 내부적으로 좌표를 계산하기 위해 사용됩니다. 하지만 일반인에게는 그다지 실용적이 않은데.. 동쪽, 서쪽, 위, 아래에 대한 개념이 아리송하기 때문입니다. 해서.. 이 좌표계는 좀처럼 사용자에게 언급되지 않지만 어떤 좌표계를 또다른 좌표계로 변환하기 위해 거치는 중간 단계의 좌표계로 사용자에게 언급됩니다.

사용자 삽입 이미지

Spherical Coordinate System(구체 좌표계), 같은 용어로 Geographic Coordinate System(지리적 좌표계)는 일반적으로 잘 알려진 좌표계입니다. 본초 좌오선(prime meridian)과 Equator(적도)를 기준으로 보통 Longitute(경도), Latitude(위도)와 같은 각도값으로 좌표를 나타냅니다. 높이는 평균해수면(mean sea level)이나 사용자가 정의한 Datum을 기준으로 나타냅니다.

사용자 삽입 이미지

Cartesian Coordinate System(데카르트 좌표계, 직각 좌표계)는 지구의 표면에 대한 “평편”한 좌표계로 생각할 수 있습니다. 지구는 원래 평편하지 않고 어떤 한 방향에 대해서 curvature(곡률)을 가지고 있으므로 scale-error(축척 에러)라고 알려진.. 원점에서 멀어질 수록 오차가 점점 더 크게 발생하는 좌표계입니다. 데카르트 좌표계로써 가장 잘 알려진 것이 바로 Universal Transverse Mercator(UTM)이지만, 각 국가 또는 지역, 개인들은 그들 나름대로의 데카르트 좌표계를 정의해서 사용합니다. 오차의 문제가 있으나 거리, 각도 그리고 넓이와 같은 계산을 매우 직관적으로  매우 정확하게 측정할 수 있다는 장점이 있습니다.

[C++] STL 함수 객체(functor)

STL에서 제공하는 함수 중 for_each라는 녀석이 있습니다. 컨테이너에 담긴 데이터 하나하나에 대해 처리해야할 연산을 지정해 주는 함수인데.. 이 for_each는 세개의 인자를 갖습니다. 첫번째 인자와 두번째 인자는 컨테이너에 저장된 데이터의 범위이고 세번째가 데이터 하나하나에 대해 수행될 연산인데.. 함수나 함수 객체를 인자로 받습니다. 예를 들어 list 컨테이너에 다음과 같은 데이터를 담아 보는 것으로 시작해 보겠습니다.

 list values;

 values.push_back(100);
 values.push_back(200);
 values.push_back(150);
 values.push_back(250);

총 4개의 데이터가 저장된 상태인데.. 이 4개의 데이터 각각에 값 10을 더해 주는 연산을 for_each 함수를 이용해 만들어 보면…

void add10(int& elem)
{
    elem += 10;
}

int main()
{
    ....

    for_each(values.begin(), values.end(), add10);
}

여기서 한발짝 더 나아가.. 재활용을 고려해 10이라는 값의 증가가 아닌 그때 그때 마다 원하는 값만큼 증가시키고자할때.. 함수 객체를 사용하면 매우 유연하게 활용할수있습니다.

class Add {
private:
    int _v;

public:
    Add(int v):_v(v) {}
    void operator() (int &elem) const {
        elem += _v;
    }
};

int main()
{
    ....

    for_each(values.begin(), values.end(), Add(10));
}

즉, 어떤 함수를 만들어 놓고.. 증가하고자 하는 값을 클래스에 대한 필드로 가지도록 하고 () 연산자의 기능을 재정의해줌으로써 클래스 객체를 마치 함수처럼 사용할수있도록 했습니다.

끝으로 함수 객체말고도.. 가장 처음 언급한 함수를 템플릿으로 정의함으로써 원하는 값만큼 증가시키는 기능의 구현도 가능한데.. 아래와 같습니다.

template void add(int &elem)
{
    elem += v;
}

int main()
{
    ....

    for_each(values.begin(), values.end(), add);
}

STL.. 기본만 알아도 무척 편리한데.. 좀더 알면 알수록.. 재미있습니다. 손맛이라고 해야 하나.. C++ 참.. 손맛 나는 언어입니다..

[C++] STL 알고리즘 기본

STL을 사용함에 있어서 STL을 자료구조로써만 바라봤고 자료구조로써만 사용했습니다. 견고하면서 빠르며 융통성이 뛰어난 자료구조로써 말입니다. 이 자료구조에 대한 연산, 즉 알고리즘에 대해서는 간과했고.. 필요한 연산은 STL에서 제공해주고 있다는 것을 알고 있음에도 그냥 제 스스로 코드를 만들 써 왔습니다.

예를 들어서 자료구조로써 링크드 리스트(Linked List)는 STL에서 list 입니다. 자료구조로써 아래와 같이.. 저에겐 매우 익숙한 코드로 데이터를 저정합니다.

#include 
#include 

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    list values;
 
    values.push_back(100);
    values.push_back(200);
    values.push_back(150);
    values.push_back(250);

    ... // values의 사용

    return 0;
}

링크드 리스트라는 자료구조가 필요했고.. 매우 효율적이면서도 매우 견고한 링크드 리스트의 구현체로써 STL을 사용해 데이터를 저장합니다. 여기서 저장된 데이터 중 가장 큰 값이 필요할 경우 저는 의례 다음처럼 코딩을 해왔습니다.

list::iterator it;
double minValue = DBL_MAX;
for(it=values.begin(); it!=values.end(); ++it) {
    if(*it < minValue) minValue = *it;
}

printf("%lf\n", minValue);

실제로.. 이렇게 사용해 왔는데요. 아마도 STL을 저보다 더 잘 사용하시는, 대부분 그러하시겠지만.. 정말 이렇게 코딩을 했다고? 하며 실소를 금치 못하실거라 생각됩니다. 네.. 반성중입니다. 다시 초심으로 돌아가서.. 이러한 무지를 버리고 STL에서 제공하는 본연의 기본 알고리즘을 활용하려기에 이 글을 작성해 봅니다.

그렇다면 위의 최소값을 얻기 위한 STL의 방식은 무엇일까요? 아래와 같이 최적화되었으며 빠르며 명확한 방법을 제공합니다.

    list::iterator it;

    it = min_element(values.begin(), values.end());
    printf("%lf\n", *it);

최소값이 아닌 최대값을 구하는 함수는 max_element입니다.

이외에도 어떤 값을 갖는지를 판단하는 함수의 경우는 다음 코드와 같습니다.

    list::iterator it;

    it = find(values.begin(), values.end(), 200);
    if(it != values.end())
    {
        printf("Got it!");
    }

STL에서는 이처럼 매우 효율적인 방식의 알고리즘 함수를 많이 제공하지만 끝으로 정렬 함수를 소개하면서 마무리 하고자 합니다.

sort(values.begin(), values.end());

이제.. 이렇게 블로그를 통해 정리를 해 놓았으니 향후 STL을 이용해 자료구조로써 뿐만 아니라 알고리즘 연산에 대해서도 최대한 STL을 사용해 봐야겠습니다.