Win7 홈(Home)에서 원격데스크탑 기능 추가시키기

Win7 홈 에디션에는 원격데스크탑 기능이 없습니다. 개발자에게 원격데스크탑은 매우 유용한 기능입니다. 물론.. 이 기능이 없다면 자리에서 자주 일어나 이 PC 저 PC로 옮겨다니며 역동적으로 일을 할 수 있겠지만 말입니다.

여튼.. 이 유용한 원격데스크탑 기능을 Win7 홈 에디션에 직접 추가시키는 방법입니다. 저 같은 경우 Windows 7 Home Premium 64 bits 입니다.

먼저 시스템 속성의 원격 탭에서 이 컴퓨터에 대한 원격 지원 연결 허용을 활성화 시킵니다.

사용자 삽입 이미지
다음으로 첨부 파일을 다운받아 압축을  풀고 Install.cmd를 실행해 주면 됩니다. 참고로 이 첨부파일은 Win7의 서비스팩1이 적용된 경우에만 가능합니다.

[GIS] 가벼운 좌표 변환 Java 오픈소스

오픈소스를 검색하고 사용할만하다.. 라는 항목 중에 하나가 “가볍다”입니다. 필요한 기능은 “딱” 하나인데.. 이 하나의 기능을 사용하기 위해 다른 라이브러리가 덕지 덕지 붙어야만 하는 라이브러리는 아무리 기능이 좋아도 사용할 수 없는 상황(모바일 GIS 개발)입니다..

GPS로부터 받은 WGS84 경위도좌표를 우리나라에서 흔히 사용하는 좌표계로 변환하기 위한 자바 기반의 오픈소스를 검색하던 중.. 가벼운 녀석을 찾았고.. 다시 몇일 동안의 검증을 통해 사용하기로 결정된 좌표변환 오픈소스가 바로 Java Map Projection Library입니다.

이 오픈소스가 참조하고 있는 또 다른 오픈소스 라이브러리는 행렬계산을 위한 Jama라는 오픈소스 라이브러리입니다. Jama는 이미 행렬계산을 위해 제가 예전부터 사용하고 있던터라.. 문제가 없었습니다. 아래는 간단히 경위도 좌표를 카텍 좌표계로 투영하는 코드의 예입니다.

import java.awt.geom.Point2D;
import com.jhlabs.map.proj.Projection;
import com.jhlabs.map.proj.ProjectionFactory;

public class EntryMain { 
    public static void main(String[] args) {
        String[] params = {
            "+proj=tmerc",
            "+lat_0=38N",
            "+lon_0=128E",
            "+ellps=bessel",
            "+x_0=400000",
            "+y_0=600000",
            "+k=0.9999",
            "+unit=m"
        };
  
        Projection katec = ProjectionFactory.fromPROJ4Specification(params);
        Point2D.Double pKatec = new Point2D.Double();
        katec.transform(128, 38, pKatec);
        System.out.println("result(" + pKatec.getX() +", " + pKatec.getY() +")");
    }
}

경도 128, 위도 38이 (400000, 600000)으로 투영되는 카텍좌표 투영에 대한 정보에 대한 인자로써 7~16라인의 코드에 params라는 문자 배열로 정의하고 있습니다. 이러한 인자값은 C언어 기반의 PROJ.4의 인자.. 바로 그것입니다. PROJ.4를 유용하고 사용하고 있는 저에게는 매우 반가운 방법입니다. 실제로 투영을 위한 Projection이라는 클래스의 객체를 생성하는 코드는 18번으로 앞서 정의한 인자값을 인자로 받습니다. 그리고 경도 128, 위도 38에 대한 좌표 변환은 20번 코드이고.. 21번 코드를 통해 화면에 출력해 확인하고 있습니다.

사용자 삽입 이미지

네, 위의 화면이 실행결과입니다. 그런데 석연치 않은 부분이 있습니다. 바로 20번 코드의 transform의 입력 인자로 받은 경도 128, 위도 38에 해당하는 타원체가 무엇인지에 대한 것입니다. WGS84 타원체일까… 아니면 Bessel 타원체 일까… 답은 Bessel인데요. 이유는 Projection 클래스의 객체를 생성하기 위해 정의했던 인자들 중 11번째 코드의 +ellips=bessel에 따릅니다. 그렇다면 앞서 말씀드렸던 목표.. GPS에서 수신받은 좌표체계인 WGS84 경위도가 아니라는 것입니다.

그렇다면 WGS84 경위도좌표계를 Bessel 경위도좌표계로 변환하고 이렇게 변환된 경위좌표를 카텍으로 변환해 주면 되겠군요. 하지만 여기서 문제는 이 Java Map Porjection 오픈소스가 타원체 간의 경위도 좌표 변환을 지원하지 않는다는 점입니다. 여기에 대한 해결점은 또 다른 포스팅(타원체간의 경위도 좌표계 변환 오픈소스 라이브러리)을 통해 공유해 드리겠습니다.

[Android] OpenGL ES에서 텍스쳐맵핑용 비트맵 생성

몇일전.. 안드로이드에서 OpenGL ES의 텍스쳐 맵핑을 살펴보고 실습을 해보면서.. 아무리 해도 텍스쳐가 맵핑되지 않았습니다.. 일단 OpenGL에서 텍스쳐맵핑을 위한 OpenGL의 API의 사용순서에 문제가 있겠거니.. 하며 문제를 파악해 나갔지만.. 도통 모르겠다 싶었구요.. 그러던중.. 문제를 해결.. ㅜㅜ

텍스쳐 맵핑을 하기위한 준비 과정으로 먼저 Bitmap 객체를 하나 생성해야 하는데.. 아래의 코드를 통해 Bitmap 객체를 생성했었습니다.

Bitmap bitmap = 
    BitmapFactory.decodeResource(context.getResources(), R.drawable.texture);

이 한줄로 비트맵을 포맷에 상관없이 읽을 수 있는 안드로이드의 API에 감탄을 했던것같은데.. 바로 문제는 여기에 있었습니다.. 이 코드를 아래 코드로 변경해야 텍스쳐가 맵핑됩니다.

Bitmap bitmap = null;
InputStream is = context.getResources().openRawResource(R.drawable.texture);
try {
    bitmap = BitmapFactory.decodeStream(is);
} finally {
    try {
        is.close();
        is = null;
    } catch(IOException e) {
        //.
    }
}

감탄했던 단 한줄의 코드 대신.. 원시 데이터로써 비트맵을 읽어 스트림을 만들고 이 스트림을 통해 비트맵을 만드는 제법 복잡다단한 방법이 바로 옳바른 방법이였습니다.. 아래는 그토록 보고 싶어라 했던 텍스쳐가 맵핑된 화면 결과…

사용자 삽입 이미지
흠…. 답답했던 때가 언제었냐는듯.. 눈이 맑아집니다.. ㅎㅎ 만약 첫번째 방식으로 하여 텍스쳐맵핑이 않되시는 분이 계시다면 두번째 방법으로 접근해 보시기 바랍니다.

애플이 주장한 삼성전자 ‘갤럭시탭10.1’ 특허 침해 사례 외…

애플이 독일서 주장한 삼성전자 ‘갤럭시탭10.1’ 특허 침해 사례라고 합니다.

  1. 네 모통이가 고르게 둥글게 만들어진 직사각형
  2. 제품의 앞 부분이 평평하고 투명
  3. 평평하고 투명한 앞표면 주변에 눈에 띄는 금속
  4. 맑은 표면을 가진 디스플레이가 화면 가운데 위치
  5. 투명한 앞표면 아래 놓여 있는 디스플레이가 명확하고 중립적인 경계에 위치
  6. 제품 전원을 켰을 때 색상이 있는 아이콘이 등장

어떻게 보십니까? 뭐가 독창적인 항목이란게 있나요? 몇일전 건대쪽 애플 매장에 들렸습니다.. iOS쪽 개발과 Objective C 언어에 대한 관심… 그리고 라이언이라는 새로운 OS의 출시와 함께.. 맥OS를 사용해보고.. “개발자”로써 익히고 배워 보고자.. 마침 새로 출시한 맥북에어를 구매하기 위해서였습니다.. 그족 매장 직원이 나에게 요구했던 황당한 행동..

  1. 제품을 구매하기 위해 결제하는데 신분증 제출 요구
  2. 스킨을 붙여 준다는데 수고비 만오천원 요구. 어렵게 붙일 수 있는 스킨이 아닌 쉽게 할 수 있는 제품은 아예 판매 조차 하지 않음
  3. 제품 개봉은 사무실에서 하려고 했는데 직원은 매장에서 개봉해 보고 하자가 있는지 확인할 것을 권유.. 불량화소는 제품하자가 아님. 빛샘 현상은 하자가 아니라면서 직접 개봉하라면서 칼을 내 손에 쥐어줌

소비자의 입장에서 어떤 제품을 구매한다는 것은 기대치로 인한 설레임이 어느 정도 있는데.. 이러한 애플의 서비스 정책으로 설레임이 아닌 한마디로 매우 불쾌했습니다.. 제품에 대한 설레임이 애플 서비스 정책으로 인해 불쾌함으로 변질되는 순간이였습니다. 애플의 서비스, 전략은 모두 우수한 제품에 기반해 성공한 것이지 애플의 서비스 전략 자체만을 놓고 보면 형편없기 짝이 없다고 생각 합니다. 애플의 마케팅 정책은 반면교사일뿐 모범으로써 따를 가치가 없습니다.

[Android] 사용자 정의 이벤트 추가

자바에서 사용자 정의 이벤트를 추가하는 방법에 대한 글(자바에서 사용자정의 이벤트 추가하기)을 남긴 적이 있습니다. 그 글에서 소개한 사용자 정의 이벤트 추가 방식은 안드로이드에서는 추천하지 않는다는 글로 정리를 했습니다.

안드로이드에서는 어떤 식으로 사용자 정의 이벤트를 남기면 좋을까에 대한 것이 이 글의 주제입니다. 일반적인 자바에서 사용자 정의 이벤트는 이벤트 리스트에 여러개의 이벤트를 등록하게 됩니다. 예를 들어서 특정한 뷰에 대한 마우스 클릭에 대한 이벤트라면.. 여러개의 이벤트를 등록하게 하는 방식입니다. 하지만 안드로이드라는 환경은 한정된 리소스를 가지고 있음으로 해서.. 예로 든 특정 뷰에 대한 마우스 클릭에 대한 이벤트에 대해 ‘하나’만을 등록하는 방식이 더 적당하다고 할 수 있습니다. 물론… 필요하다면 자바에서 일반적인 사용자 정의 이벤트를 추가하는 방식을 안드로이드에서 사용해도 됩니다. 그럼.. 안드로이드에서 적합한 사용자 정의 이벤트를 추가하는 방식에 대해 정리해 보겠습니다.

먼저 새롭게 추가할 이벤트가 무엇인지 확인해 봅니다. 예를 들어 맵엔진 개발에 있어서 맵의 축척이 변경되었을때 발생하는 이벤트를 추가하는 예를 통해 살펴보겠습니다. 1개의 클래스와 또 다른 한개의 인터페이스를 추가해야 하는데.. 새롭게 추가할 클래스는 이벤트 객체에 대한 클래스이며 새롭게 추가할 인터페이스는 이벤트 리스너입니다. 이 둘은 일반적인 자바에서의 사용자 정의 이벤트에 대해서 동일한 내용입니다. 다른게 없습니다.

아래는 축척 변경 이벤트에 대한 이벤트 객체 클래스 소스입니다.

package geoservice.blackpoint.events;

import geoservice.blackpoint.XrMap;
import java.util.EventObject;

public class MapEvent extends EventObject {
    public MapEvent(Object source) {   
        super(source);   
    }   
 
    public XrMap getMap() {
        XrMap map = (XrMap)getSource(); 
        return map;
    }
}

이벤트 객체는 이벤트를 발생시킨 주체(getSource 매서드를 통해 반환됨)를 기본적인 내용으로 하며 그외 더 필요한 정보를 담을 수 있습니다. 다음으로 이벤트 리스너에 대한 인터페이스입니다.

package geoservice.blackpoint.events;

import java.util.EventListener;

public interface OnMapScaleChangedEventListener extends EventListener {
    void onMapScaleChanged(MapEvent event);
}

이벤트 리스너 인터페이스에는 여러개의 이벤트를 넣을 수 있는데.. 이 경우 맵축척 변경에 대한 이벤트만이 있습니다. 이제 축척 변경에 대한 이벤트에 필요한 클래스와 인터페이스가 준비되었습니다.

그럼 맵엔진 단에서 맵 축척이 변경되었을때 이벤트를 발생시키는 것에 대해 코드를 통해 살펴보겠습니다.

class XrMap {
    // 이벤트 코드에만 집중하자

    public OnTapUpEventListener onTapUpEventListener = null;    
    public void setOnTapUpListener(OnTapUpEventListener listener) {
        onTapUpEventListener = listener;
    }

    private void __맵축척을변경시키는부분__ {
        if(onMapScaleChangedEventListener != null) {
            MapEvent event = new MapEvent(this);
            onMapScaleChangedEventListener.onMapScaleChanged(event);
        }
    }

    // 이벤트 코드에만 집중하자
}

보시는 것처럼.. 이벤트 리스너에 대한 변수와 이 이벤트 리스너를 할당시키기 위한 매서드 끝으로 실제 이벤트가 발생될때 이벤트 리스너를 실행해 주는 코드로 구성되어 있습니다. 여기까지가 일반적으로 안드로이드에서 사용자 정의 이벤트를 만들어 주는 방식입니다. 그럼.. 이 맵축척이 변경되었을때 발생하는 이벤트에서 원하는 코드를 작성해보는 샘플 코드는 어떻게 될까.. 아래 코드를 통해 살펴보시기 바랍니다.

map.setOnMapScaleChangedListener(
    new OnMapScaleChangedEventListener() {
        public void onMapScaleChanged(MapEvent event) {
            Toast.makeText(
                XrMapTest.this, 
                "SCALE CHANGED", 
                Toast.LENGTH_SHORT).show();
       }
    }
);

map은 앞서 XrMap 클래스에 대한 변수입니다. 축척이 변경될때마다 화면에 SCALE CHANGED라는 메세지를 토스트를 통해 띠웁니다.. 끝으로 안드로이드에서 버튼을 클릭했을 때 이벤트를 할당하는 코드를 살펴보고.. 위의 맵축척 변경 이벤트 할당 코드와 비교해 보시기 바랍니다.

Button btnro= (Button)findViewById(R.id.ro);
btnro.setOnClickListener(
    new Button.OnClickListener() {
        public void onClick(View v) {
            CoordMapper cm = map.getRendererManager().getCoordMapper();
            cm.rotate(15);
            map.update();
        }
    }
);

보시는 것처럼.. 이벤트를 할당하는 두개의 구조가 모두 동일함을 알 수 있습니다. 이상으로 안드로이드에서 사용자 정의 이벤트를 할당하는 방법에 대한 정리를 마치도록 하겠습니다.