[C#] C++의 multimap 컨테이너

C++의 STL에 multimap이라는 컨테이너가 존재합니다. 이 컨테이너는 키(key)와 값(value)의 쌍으로 구성된 요소를 저장하고 있으며 key 값으로 정렬 되어 있습니다. 여기서 중요한 것은 이 키가 유일하지 않다는 점입니다. 즉 중복될 수 있다는 점인데요. 이러한 C++의 multimap의 성질을 갖는 컨터이너가 C#에는 기본적으로 존재하지 않습니다. 해서 이러한 컨터이너를 직접 개발자가 만들어 써야 하는데.. 다행히 C#에서 어렵지 않게 구현할 수 있습니다.

C#에서 제공하는 컨테이너(NET에서는 컬렉션(Collection)이라는 다른 이름을 사용) 중에 List와 SortedDictionary 컬렉션을 조합하여 우리가 원하는 C++의 multimap 컨테이너를 만들 수 있습니다. 아래는 이렇게 구현한 컬렉션으로 클래스 이름을 .NET의 이름에 맞게 MultiSortedDictionary라고 지었습니다.

class MultiSortedDictionary;
{
    private SortedDictionary dic_ = null;

    public MultiSortedDictionary() 
    {
        dic_ = new SortedDictionary();
    }

    public MultiSortedDictionary(IComparer comparer)
    {
        dic_ = new SortedDictionary(comparer);
    }

    public void Add(Key key, Value value)
    {
        List list = null;

        if(dic_.TryGetValue(key, out list))
        {
            list.Add(value);
        }
        else
        {
            list = new List();
            list.Add(value);
            dic_.Add(key, list);
        }
    }

    public bool ContainsKey(Key key)
    {
        return dic_.ContainsKey(key);
    }

    public List this[Key key]
    {
        get
        {
            List list = null;
            if (!dic_.TryGetValue(key, out list))
            {
                list = new List();
                dic_.Add(key, list);
            }

            return list;
        }
    }

    public IEnumerable keys
    {
        get
        {
            return dic_.Keys;
        }
    }
}

MultiSortedDictionary 클래스의 코드가 그리 길지 않습니다. C#은 이미 매우 잘 만들어진 컬렉션 클래스를 가지고 있으므로 이들을 조합하여 쉽게 구현할 수 있었기 때문입니다. 이제 MultiSortedDictionary 클래스를 사용해 보겠습니다.

먼저 요소를 추가합니다. 요소의 키는 정수(int)이고 값(value)은 POINT라는 사용자 정의 구조체로 하겠습니다. 먼저 POINT 타입의 구조체는 아래와 같습니다.

struct POINT
{
    public int x;
    public int y;

    public POINT(int x, int y) 
    {
        this.x = x;
        this.y = y;
    }

    override public string ToString()
    {
        return String.Format("({0:D},{1:D})", x, y);
    }
}

이제 MuiltiSortedDictionary 클래스의 인스턴스를 생성하고 몇가지 요소를 추가하는 코드를 작성해 보면 아래와 같습니다.

static void Main(string[] args)
{
    MultiSortedDictionary msd_ 
        = new MultiSortedDictionary();

    POINT pt1 = new POINT(100, 100);
    POINT pt2 = new POINT(100, 200);
    POINT pt3 = new POINT(100, 300);
    POINT pt4 = new POINT(100, 100);
    POINT pt5 = new POINT(100, 200);
    POINT pt6 = new POINT(100, 300);

    msd_.Add(30, pt6);
    msd_.Add(20, pt4);
    msd_.Add(10, pt1);
    msd_.Add(10, pt3);
    msd_.Add(20, pt5);
    msd_.Add(10, pt2);

실제로 키에 대해 정렬이 되어 있는지를 살펴보기 위해 임의로 요소를 추가할때 키의 순서를 정렬되지 않은 키값 순서로 추가하고 있습니다. 실제로 키 값이 정렬되어 있는지 파악하는 코드는 아래와 같습니다.

IEnumerator iter = msd_.keys.GetEnumerator();
iter.Reset();
Console.Write("key list : ");
while(iter.MoveNext()) 
{
    Console.Write(iter.Current + " ");
}
Console.WriteLine();

실행 결과는 아래와 같습니다.

사용자 삽입 이미지
결과를 보면 요소에 대한 키의 순서가 옳바르게 정렬되어 있다는 것을 알 수 있습니다. 염두할 점은 C++의 경우라면 그 결과가 10 10 10 20 20 30 이라는 점입니다.  이제 이렇게 저장된 요소 중에 키가 10인 요소에 대한 값을 얻는 코드를 살펴보면 아래와 같습니다.

List list = msd_[10];
Console.Write("key 10 [ ");
for(int i=0; i

실행 결과는 아래와 같습니다.

사용자 삽입 이미지

키가 10인 요소에 대한 값이 모두 3개인데, 생각했던 올바른 결과가 나온 것을 확인할 수 있습니다. C#에서 .NET을 살펴보면 볼수록 참으로 체계적이고 멋진 언어 그리고 프레임워크라고 생각됩니다.

“OpenGL ES와 M3G를 이용한 모바일 3D 그래픽스” 정오표

이번에 출간된 OpenGL ES와 M3G를 이용한 모바일 3D 그래픽스에 대한 정오표입니다. 역자로써 좀 더 꼼꼼하게 챙기지 못한 점 사과드리고.. 이로 인해 당연히 불편하게 해 드린 독자분에게 이 자리를 빌어 다시 한번 사과드립니다… 향후에 이 블로그를 통해 지속적으로 모바일 3D 그래픽스에 대한 책의 오류 부분에 대한 내용을 추가해 나가도록 하겠습니다.

사용자 삽입 이미지

사용자 삽입 이미지

사용자 삽입 이미지

사용자 삽입 이미지

MS Word 2007로 작성된 파일을 다운로드 받으시면 되고.. 혹 프로그램이 없는 분은 이미지를 통해 살펴볼 수 있습니다. 이미지를 클릭하여 원래 크기로 보실 수 있습니다.

책을 읽다가 오타나 이상한 부분에 대해 질문이 있으면 저에게 메일로 전달해 주시기 바랍니다. 하면 그에 대해서 답변하도록 하겠습니다.

iPhone에서 내 위치 찾아보니..

오늘 iPhone으로 핸드폰을 바꿨습니다. 이것 저것 만지작 거리다가 나침판 기능이 있글레 한번 실행해 보았습니다. 핸드폰을 이리 저리 돌려가면서 살펴보니 화면상의 나침판 화살이 계속 한쪽 방향만을 가리켜 줍니다. 이 방향이 북쪽이라는 의미겠지요. 참 기특하긴 한데… 근데… 정말 이 방향이 북쪽인지는 모르죠.. 뭐 그런가부다하고.. 있다가..

여기서 뭔 버튼을 하나 누르니.. 구글맵이 뜹니다. 그리고.. 내 위치라고 하면서 표시가 되는데.. 상당히 정확하게 나타냅니다. 여긴 실내인데… 어떻게 이렇게 정확하게? 오로지 GPS 기능만 가지고 이렇게 한건가? 근데 GPS에 북쪽 방향을 알아내는 정보가 원래 있었나?

사용자 삽입 이미지
예전에 휴대용 GPS 로거를 사려고 했던 적이 있었습니다. GPS 로거를 가지고 다니면 나의 행적을 좌표로 뽑아 낼 수 있거든요. 하지만 이젠 iPhone의 기능을 이용하면 GPS 로거의 기능은 충분히 할 수 있을 듯합니다. 이거 응용해 보려면 직접 만들어(개발해)보면 좋겠다 싶습니다. 머리속에서 한번도 생각치도 않은 해킨토시가 아른거리네요.. 아이폰 개발은 Object C++인가를 쓴다는데…

모바일 3D 그래픽스 출간

드디어 책이 출간되었습니다. 그제 출간되었다는 연락을 받았을 때는 매우 기뻤는데, 또 막상 출간된것을 확인하고 보니 좋습니다. 아마 처음으로 번역이라는 것을 해봐서 그런지 출간까지의 소소한 과정들이 여러가지 큰 기분으로 다가서는 듯 합니다.

사용자 삽입 이미지

이번에 구글 안드로이드 폰이 국내에 출시되면 구입하려고 벼르고 있습니다. 모토롤라에서 모토로이라는 안드로이드 OS가 탑재된 폰이 2월 초부터 판매된다고 하니… 이미 2년 약정기간이 지난 제 폰을 바꿀 수 있을듯합니다.

안드로이드 폰 쪽으로  개발에 시간을 내 해보려고 하는데요. 그에 대한 연장선으로 모바일에서 3D 그래픽을 적용해 볼 수 있을 듯합니다.

참고로 아이폰이나 Windows Mobile에서도 OpenGL ES를 지원하니 이 책의 내용을 적용해 3D 그래픽을 적용할 수 있습니다. 관심있으신 분들은 살펴보시기 바랍니다.

[C#] 동적 Bitmap 생성

.NET에서 C# 코드로 비트맵을 생성하고 생성한 이 비트맵에 원하는 그래픽 요소를 그린 후 스트림에 전송하는 방법에 대한 정리입니다. 매우 간단한 내용이지만 그래픽에 대해 관심이 많은 개발자로써 천천히 정리해 봤습니다.

int w = 100;
int h = 100;

Image img = new Bitmap(w, h);
Graphics grp = Graphics.FromImage(img);

위의 코드는 100×100 크기의 비트맵 이미지를 생성하고 이 이미지에 그래픽 요소를 그리기 위한 Graphics 클래스의 인스턴스와 바인딩 합니다. 이제 Graphics 클래스의 인스턴스 변수인 grp를 이용해 우리가 원하는 그래픽 요소를 그릴 수 있습니다. 아래는 간단하게 선을 그리고 파일로 저장하는 코드입니다.

grp.DrawLine(Pens.Aqua, 10, 10, 90, 90);
img.Save("d:/a.bmp");

저장된 파일은 아래와 같습니다.

그림을 살펴보면.. 그래픽 객체로 직접 선을 그린 픽셀을 제외하고 나머지 픽셀들은 모두 투명이라는 것을 알 수 있습니다. 그리고 아래의 코드는 비트맵 이미지를 구성하는 픽셀 하나 하나에 대한 색상 정보를 가져올 수 있는 힌트를 제공하는 코드입니다.

Bitmap bmp = img as Bitmap;
Color clr = bmp.GetPixel(10, 10);
MessageBox.Show(clr.ToString());

MessageBox를 통해 Color타입의 clr을 toString 매서드를 통해 얻은 값은 아래 그림과 같습니다. 자바와 같이 C# 역시 모든 객체에 대해 toString() 매서드를 제공하여 자신에 대한 정보를 사용자가 읽어 파악할 수 있는 문자열 형태의 값을 제공하고 있습니다.

사용자 삽입 이미지
끝으로 픽셀값을 Color 타입으로 가져오고 있습니다. Color는 퍼포먼스를 위해서 클래스가 이난 구조체 타입으로 선언되어 있습니다.