안드로이드에서 CAD, PDF 등의 파일 보기

안드로이드 디바이스에 저장된 CAD나 PDF 등과 같은 파일을 볼 수 있는 손쉽고 강력하며 안정적인 방법은 각각 파일을 볼 수 있는 책임성이 뛰어난 앱을 활용하는 것이라 할 수 있습니다. 예를 들어서 CAD 파일을 볼 수 있는 앱은 CAD 파일을 개발한 AutoDesk사의 AutoCAD 360이나 AutoDwg사의 DWGSee가 있으며 PDF 파일을 볼 수 있는 앱은 PDF 파일을 개발한 Adobe사의 Adobe Reader가 있습니다.

개발사가 업무용 프로그램을 개발하면서 경험하게 되는 요구사항은 고객이 가지고 있는 데이터 파일을 볼 수 있게 해달라는 것인데, GIS 분야에서는 DWG나 DXF와 같은 CAD 파일과 일반 문서인 PDF 파일이 바로 이러한 요구사항에 해당되는 데이터 파일이라고 할 수 있겠습니다.

이러한 데이터 파일을 별도의 앱과 연동하여 볼 수 있는 샘플 프로그램을 만들어 정리해 봅니다. 화면상에 2개의 버튼을 배치하고 첫번째 버튼을 터치하면 CAD 파일을 보고 두번째 버튼을 터치하면 PDF 파일을 볼 수 있도록 하겠습니다. 아래는 이러한 버튼의 배치 화면입니다.

사용자 삽입 이미지

첫번째 버튼인 CAD File View의 터치 이벤트에서 호출되는 함수입니다.

Intent intent = new Intent(Intent.ACTION_DEFAULT);
File file = new File("/sdcard/mapdata/dwg/samples.dwg");
if(file.exists()) {
    Uri uri = Uri.fromFile(file);
    intent.setData(uri);
    startActivity(intent);
}

이 버튼을 터치하면 아래의 화면 예처럼 지정된 파일을 볼 수 있습니다.

사용자 삽입 이미지

다음은 두번째 버튼인 PDF File View의 터치 이벤트에서 호출되는 함수입니다.

intent = new Intent(Intent.ACTION_DEFAULT);
File file = new File("/sdcard/e10842.pdf");
if(file.exists()) {
    Uri uri = Uri.fromFile(file);
    intent.setData(uri);
    startActivity(intent);
}

이 버튼을 터치하면 아래의 화면 예처럼 지정된 파일을 볼 수 있습니다.

사용자 삽입 이미지

안드로이드에서 이러한 프로그램들의(정확히는 Activity 간의) 연동은 매우 자연스러우며 매우 빠르게 실행됩니다. 그리고 다시 원래의 프로그램으로 자연스럽고 신속하게 복귀되어 마치 하나의 프로그램처럼 연동됩니다.

비록 간단한 내용이지만 고객의 요구사항에 대해서 빠르고 정확하게 수용할 수 있다는 점에서 정리해 봅니다. 그러나 이 방식의 단점은 특정한 데이터 파일을 볼 수 있는 앱을 별도로 설치해줘야 한다는 점입니다. 위의 코드들을 위해 제가 설치한 프로그램은 DWGSee와 Adobe Reader였습니다.

Java에서 POST 방식으로 GeoService-X에 SQL 쿼리 요청

GeoService-Xr 공간서버에 직접 Java 언어로 SELECT 구문과 쿼리를 요청하는 코드 Keeping ..

try {
    URL url = new URL("http://X.X.X.X:8078/Xr?sql|oracle|0");
    HttpURLConnection httpConn = (HttpURLConnection)url.openConnection();
    httpConn.setUseCaches(false);
    httpConn.setDoOutput(true);
    httpConn.setRequestMethod("POST");
    OutputStream outputStream = httpConn.getOutputStream();
    String sql 
        = "SELECT IDN, CDE, MNG FROM TBLNAME WHERE IDN=2437";
    byte[] bytesSql = sql.getBytes();
    ByteBuffer bb = ByteBuffer.allocate(bytesSql.length + 1 + 4);
			
    bb.order(ByteOrder.BIG_ENDIAN);
    bb.putInt(bytesSql.length + 1);
    bb.put(bytesSql);
    bb.put((byte)0);
    bb.flip();
			
    byte[] bytes = bb.array();
    outputStream.write(bytes);
    outputStream.close();
			
    int responseCode = httpConn.getResponseCode();
    if(responseCode == HttpURLConnection.HTTP_OK) {
        BufferedReader reader 
            = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
        System.out.println("Server's response: ");
        while(true) {
            String response = reader.readLine();
            if(response == null) break;
            System.out.println("\t" + response);
        }
    } else {
        System.out.println("Server returned non-Ok code: " + responseCode);
    }
} catch (Exception e) {
    e.printStackTrace();
}

[GIS] 자바 기반의 오픈소스를 이용한 좌표계 변환 정리

안드로이드 기반의 GIS 솔루션인 블랙포인트(BlackPoint-Xr)에는 다양한 좌표계간의 변환을 위한 클래스가 제공됩니다. 이 클래스들은 이미 다음 포스트를 통해 오픈소스 형태로 꽤 오래전부터 소개해 드렸는데요. 이번 기회에 다시한번 종합적으로 정리를 해봅니다.

이 좌표 변환을 위한 클래스를 소개하기 위해서 2가지 시나리오를 정하겠습니다. 첫째는 동일한 타원체를 갖는 서로 다른 좌표계간의 좌표변환이고 둘째는 서로 다른 타원체를 갖는 서로 다른 좌표계간의 좌표변환입니다. 이렇게 두개의 예를 드는 이유는 두개의 좌표계가 서로 다른 타원체를 갖느냐 갖지 않느냐에 따라 좌표변환의 과정이 매우 달라지기 때문입니다.

앞서 언급한 두가지 시나리오 중에서 첫번째인 동일한 타원체를 갖는 서로 다른 좌표계간의 좌표변환으로써 Bessel1841 타원체인 UTMK 좌표계에서 역시 Bessel1841 타원체를 갖는 카텍 좌표계로 변환하는 코드를 예로 살펴보겠습니다. 이 두 좌표계 간의 변환은 크게 2가지로 구분됩니다.

  1. UTMK 좌표계를 Bessel1841의 경위도 좌표계로 변환
  2. Bessel1841의 경위도 좌표를 카텍 좌표계로 변환

먼저 1. 번에 대한 코드는 다음과 같습니다.

String[] projParamsUTMK_B = {   
    "+proj=tmerc",   
    "+lat_0=38N",   
    "+lon_0=127.50289E",   
    "+ellps=bessel",   
    "+x_0=1000000",   
    "+y_0=2000000",   
    "+k=0.9996",   
    "+unit=m"  
};   
			    		     
Projection projUTMK_B 
    = ProjectionFactory.fromPROJ4Specification(projParamsUTMK_B);
			    		
Point2D.Double in = new Point2D.Double(986967, 1817577);
Point2D.Double out = new Point2D.Double();
projUTMK_B.inverseTransform(in, out);

1~10번 코드는 UTMK 좌표계를 정의하는 PROJ.4 형식의 파라메터입니다. 전세계에 존재하는 대부분의 좌표계는 위와 같은 파라메터로 구성이 가능합니다. 위의 코드는 UTMK 좌표계인 (986967, 1817577)를 in 객체에 담아 카텍으로 변환하여 out 객체에 저장하는 코드입니다. 이제 2. 번에 대한 코드는 다음과 같습니다.

String[] projParams_KATECH = {   
    "+proj=tmerc",   
    "+lat_0=38N",   
    "+lon_0=128E",   
    "+ellps=bessel",   
    "+x_0=400000",   
    "+y_0=600000",   
    "+k=0.9999",   
    "+unit=m"  
};   
			        	     
Projection projKatech 
    = ProjectionFactory.fromPROJ4Specification(projParams_KATECH);

in.x = out.x;
in.y = out.y;
projKatech.transform(in, out);

이 코드는 1. 에서 얻는 경위도 좌표가 담긴 out 객체를 다시 in 객체에 복사하고 카텍 좌표계로 변환합니다. 최종적으로 out 객체에 변환된 카텍 좌표가 저장되어 있습니다.

두번째 시나리오는 Bessel1841 타원체인 카텍 좌표계에서 WGS84 타원체인 UTM 52Zone 좌표계로 변환하는 내용입니다. 이 두개의 타원체는 서로 다른 타원체를 갖으며 이렇게 서로 다른 타원체를 갖는 좌표계 간의 변환은 다음과 같은 절차를 갖습니다.

  1. 카텍 좌표를 Bessel1841의 경위도 좌표계로 변환
  2. Bessel1841의 경위도 좌표를 WGS84 경위도로 변환
  3. WGS84 경위도를 UTM 52Zone 좌표계로 변환

동일한 타원체를 갖는 좌표계간의 변환에서 한단계(2번)가 추가되었습니다. 위의 세가지 단계에 대해서 하나 하나 코드를 통해 살펴보겠습니다. 먼저 1. 번에 대한 코드는 다음과 같습니다.

String[] projParams_KATECH = {   
    "+proj=tmerc",   
    "+lat_0=38N",   
    "+lon_0=128E",   
    "+ellps=bessel",   
    "+x_0=400000",   
    "+y_0=600000",   
    "+k=0.9999",   
    "+unit=m"  
};   
			        	     
Projection projKatech 
    = ProjectionFactory.fromPROJ4Specification(projParams_KATECH);
			        	
Point2D.Double in = new Point2D.Double(342353, 417704);
Point2D.Double out = new Point2D.Double();
projKatech.inverseTransform(in, out);

다음으로 2. 번에 대한 코드입니다.

Ellipsoid bessel1841 = new Ellipsoid(6377397.155, 1.0 / 299.1528128254262);
Ellipsoid wgs1984 = new Ellipsoid(6378137, 1.0 / 298.257223563);   
Parameters7 params = 
    new Parameters7(-145.907, 505.034, 685.756, -1.162, 2.347, 1.592, 6.342);   
Ellip2Ellipsoid ellip2ellip = new Ellip2Ellipsoid(bessel1841, wgs1984, params);
Values3 src = new Values3(out.y, out.x, 0);
Values3 dst = new Values3();
ellip2ellip.transform(src, dst);

위의 코드를 보면 타원체 간의 변환에 필요한 7개의 파라메터가 사용되고 있음을 알 수 있습니다. 파라메터가 필요없다면 7개의 값을 모두 0으로 지정하면 됩니다. 이제 3. 번에 대한 코드입니다.

String[] projParams_UTM52 = {   
    "+proj=tmerc",   
    "+lat_0=0",   
    "+lon_0=129E",   
    "+ellps=WGS84",   
    "+x_0=500000",   
    "+y_0=0",   
    "+k=0.9996",   
    "+unit=m",
    "+no_defs"
};   
			        	     
Projection projUTM52 
    = ProjectionFactory.fromPROJ4Specification(projParams_UTM52);
			        	
in.x = dst.V2;
in.y = dst.V1;
projUTM52.transform(in, out);

이상으로 서로 다른 좌표계간의 좌표변환에 대한 내용을 마칩니다.