[GIS] XrProjection v3.1

다양한 좌표계 간의 변환 툴입니다. 특히 대한민국에서 사용하는 좌표계에 대해 손쉽게 변환할 수 있는 정보를 기본으로 제공합니다. 투영(Projection)에 사용하는 3, 7, 10 파라메터를 모두 지원합니다. 흔히 좌표 변환에 있어서 변환 파라메터를 고려하지 않는 경우가 많습니다. 변환 파라메터는 GIS 전문가가 아닐 경우 다소 어려운 내용이기는 하지만 해당 SHP 파일을 원하는 좌표계로 정확히 변환하기 위해서는 반드시 고려해야 할 사항입니다. 이 좌표계 변환툴에 대한 개발자임과 동시에 사용자로써 이 툴을 사용해 정확하게 원하는 좌표계로 변환할 수 있을거라 확신합니다.

이 프로그램에 대한 설치 파일은 아래 링크를 통해 다운로드 받으시기 바랍니다.

하나의 SHP 파일에 대한 좌표 변환은 물론 지정된 폴더에 존재하는 모든 SHP 파일에 대한 일괄변환에 대한 편의성을 지원합니다.

사용자 삽입 이미지

또한 간단히 하나의 좌표에 대한 변환과 도분초에 대한 변환에 대한 기능을 지원합니다.

사용자 삽입 이미지

이 툴에 대해 사용하시다가 궁금하신 점은 언제든 메일을 통해 문의하시기 바랍니다.

[C++11] decltype

decltype은 주어진 표현식에 대한 결과의 타입을 컴파일러가 추론하라는 키워드(keyword)입니다. 예를 들어서 다음의 코드를 보면..

#include "stdafx.h"
#include 

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    cout << typeid(decltype(10)).name() << endl;

    return 0;
}

위 코드에서 8번을 보면 decltype(10)이라는 코드가 있는데, 표현식 10에 해당하는 type을 컴파일러가 추론을 하여 해당 타입의 이름을 출력하게 되는 것으로 결과는 'int'를 출력합니다.

또 다른 예를 살펴보면..

#include "stdafx.h"
#include 

using namespace std;

auto func(int a, int b) -> decltype(a + b)
{
    return a + b;
}

int _tmain(int argc, _TCHAR* argv[])
{
    cout << func(100, 200) << endl;

    return 0;
}

6번 코드를 보면 함수의 결과값에 auto를 사용할 수 없음에도 func라는 함수의 반환값이 auto를 사용하고 있습니다. 이것이 가능한 이유는 바로 함수의 정의 뒤에 오는 -> decltype(a+b)에 의해서 입니다. 즉, a+b에 대한 결과값의 타입을 추론하여 ->에 의해 함수의 반환값 추론에 대한 힌트를 제공하는 것입니다. a와 b는 int 타입이고 이 int 값들의 합 역시 int이므로 쉽게 함수의 결과값의 타입은 int라는 것을 추론할 수 있는 것입니다.

[C++11] 람다(Lambda) 표현식

C++11은 람다 표현식 기능을 제공합니다. 람다 표현식은 함수를 미리 정의하지 않고 필요한 시점에서 사용하고 바로 버리는 것으로 생각할 수 있습니다. 람다가 제공되기 이전에 어떤 함수를 사용하고자 했다면, 그 함수를 미리 정의하고 사용하게 됩니다. 사용하고 난 뒤에 그 함수는 계속 존재합니다.아래는 람다 표현식을 이용해 만들어진 함수 예입니다.

#include "stdafx.h"
#include 

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    auto func = []() {
        cout << "Hello World" << endl;
    };

    func();

    return 0;
}

8번 코드에서 람다 표현식을 이용해 함수를 정의하고 있습니다. 정의된 함수는 예제처럼 어떤 변수에 함수를 할당해 놓고 12번 코드에서 실행할 수 도 있지만 어떤 변수에 할당하지 않고 바로 실행할 수 도 있습니다. 즉, 아래처럼 말입니다.

#include "stdafx.h"
#include 

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    []() {
        cout << "Hello World" << endl;
    }();

    return 0;
}

첫번째 예제와는 다르게 이 두번째 예제는 필요한 시점에 함수를 정의하고 바로 실행하고 함수를 폐기하고 있습니다. 8번 코드에서 보는 것처럼 람다 표현식은 2가지로 구성됩니다. []과 {}이며 []는 람다 소개자(Lambda Introducer) 또는 Capture Clause라고 하며 {}는 람다 몸체(Lambda Body)입니다. 람다 몸체에 함수 구현 코드가 존재하며 람다 소개자에 외부 변수를 어떤 식으로 참조할지에 대한 Capture 지정자과 함수에 입력될 인자(Parameter) 리스트가 지정됩니다. 예를 들어 람다 표현식으로 정의한 함수의 인자로 int를 받아 출력하는 함수는 다음과 같습니다.

#include "stdafx.h"
#include 

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    [](int a) {
        cout << a << endl;
    }();

    return 0;
}

이제 람다 함수(람다 표현식으로 정의된 함수)에 대해 몇가지 예를 통해 좀더 정리해 보겠습니다. 다음 코드를 살펴 보겠습니다.

#include "stdafx.h"
#include 
#include 
#include 

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    vector v { 1, 2, 3, 4, 5 };

    for_each(v.begin(), v.end(), [](int v) {
        cout << v << endl;
    });

    return 0;
}

위의 코드 중 12번의 for_each 함수는 컨테이너의 각 요소를 인자로 어떤 함수(또는 함수객체)를 호출하는 것으로 for_each의 세번째 인자가 바로 호출되는 함수(또는 함수객체)가 됩니다. 일반적으로 호출할 함수를 미리 정의해 두어야 하나 여기서는 람다 함수를 이용해 미리 함수를 정의하지 않고 필요한 시점에 함수를 정의하고 사용하고 있습니다. 다음 예제를 보겠습니다.

#include "stdafx.h"
#include 
#include 
#include 

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    vector v { 1, 2, 3, 4, 5 };

    auto it = find_if(v.begin(), v.end(), [](int v)->bool {
        return (v % 2) == 1;
    });

    cout << *it << endl;

    return 0;
}

위의 코드 중 12번에 있는 find_if 함수는 컨테이너를 구성하는 요소 중 어떤 조건을 만족하는 첫번째 요소의 값을 반환하는 함수인데, 조건을 지정하기 위해 함수 또는 함수 객체를 세번째 인자에 지정됩니다. 여기서는 람다 함수를 통해 조건 함수가 지정되었는데 이 함수의 반환 타입(Type)을 지정하기 위해서 ->bool를 사용함으로써 반환 타입이 bool이라고 명시하고 있습니다. 엄격하게는 이 ->bool 코드를 생략할 수 있는데, 이는 컴파일러가 이 람다함수의 반환타입을 추론할 수 있기 때문입니다. 컴파일러의 추론 대신 직접 반환 타입을 알려주기 위해 ->(type) 연산자를 사용할 수 있다는 것에 대한 예제입니다.

#include "stdafx.h"
#include 
#include 
#include 

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    vector v { 1, 2, 3, 4, 5 };
    int sum = 0;

    for_each(v.begin(), v.end(), [&](int v) {
       if (v % 2 == 0) sum += v;
    });
    
    cout << sum << endl;

    return 0;
}

위 코드 중 13번의 람다 함수를 보면 []에 해당하는 람다소개자의 형태가 [&]처럼 되어 있습니다. 이 [&]의 의미는 람다 함수 앞단에 모든(All) 외부 변수를 참조 타입(Reference Type)으로 잡아(Capture) 사용하겠다는 의미입니다. 실제 람다 함수 구현부를 보면 외부에 존재하는 sum 변수를 사용하고 있습니다. 참조 형태로 사용하겠다고 했으므로 람다 함수 내부에서 변수값을 변경하면 외부에서도 변경되는 것을 알 수 있습니다. 람다 소개자가 []일 경우에는 어떤한 외부 변수도 사용하지 않겠다는 의미이며 [&]는 모든 외부 변수를 참조로 사용하겠다는 것이고, [=]는 모든 외부 변수를 상수값(const)으로 값 자체를 복사(Copy)하여 사용하겠다는 의미입니다. [&a]는 외부 변수 중 a만을 참조값으로 사용하겠다는 의미이고 [&a, =b]는 a는 참조값으로 b는 상수값으로 사용하겠다는 의미입니다.

[C++11] static_assert

static_assert는 컴파일 타임에서 지정한 조건을 만족하지 않을 경우 개발자에게 에러를 제공하는 기능입니다. 한가지 예로 static_assert의 기능을 정리합니다.

#include "stdafx.h"
#include 

using namespace std;

template int func() {
    static_assert(N <= 100, "Less than 100");
    int sum = 0;
    for(int i=1; i<=N; i++) {
        sum += i;
    }

    return sum;
}

int _tmain(int argc, _TCHAR* argv[])
{
    cout << func<10>() << endl;
    cout << func<1000>() << endl;

    return 0;
}

위의 코드에서 7번에 static_assert가 사용되었습니다. 이 static_assert의 첫번째 인자는 조건이고 두번째는 조건이 false일 경우 개발자에게 제공할 Error 메세지입니다. 실제로 18번 코드는 static_assert의 조건을 만족하므로 문제가 없으나 19번 코드는 static_assert의 조건을 만족하지 못하므로 Less than 100이라는 에러 메세지를 개발단계에서 개발자에게 경고를 해주게 됩니다.