2013년 10월 11일 금요일

uDig GeoScript 소개

uDig도 QGIS의 PyQGIS 처럼 일반적인 작업을 자동화할 수 있는 강력한 스크립팅 기능이 있습니다. HydroGISAndrea Antonello 님께 감사드립니다.

PyQGIS가 Python을 사용한다면 uDig의 GeoScript는 Groovy(그루비는 자바파이썬, 루비, 스몰토크등의 특징을 더한 동적 객체 지향 프로그래밍 언어, 출처: 위키백과)를 활용하며, GeoTools가 가진 거의 모든 기능을 사용할 수 있습니다.

uDig에서 GeoScript 편집 환경
 ⊙ 편집기에 자동완성 및 구문강조 기능 포함

▣ Geometry Plot
 - Geometry를 생성하고 연산 수행 후 보기

▣ MapWindow
 - 레이어(Shapefile 등)를 불러와서 스타일 적용 후 지도 보기 및 이미지 저장 등

▣ 기타
  - 스타일, 렌더링, Geometry, 분석, 변환 등 GeoTools가 수행하는 거의 모든 기능 사용
  - GeoTools 프로세스 및 JGrass 분석 기능 사용

▣ 참고
 ⊙ Geographic scripting in uDig, FOSS4G Nottingham 2013


 ⊙ uDig User Guide
- uDig User Guide : GeoScript Introduction

 ⊙ GeoScript
  - http://geoscript.org/
  - 더 많은 예는 https://github.com/jericks/geoscript-groovy 에서 확인

▣ Example
 - Point Shapefile을 열고 NAM 이라는 필드가 NULL이 아닌 모든 피처를 1,500 지도 단위로 버퍼링한 Shapefile 생성하고 원본과 함께 지도에 표출

import geoscript.workspace.*
import geoscript.layer.*
import geoscript.feature.*
import geoscript.filter.*
import geoscript.geom.*
import geoscript.proj.*
import geoscript.render.*
import geoscript.style.*
import geoscript.style.io.*
import geoscript.viewer.*

//==========================================================
// Simple Buffer Process
//==========================================================
// Open Shapefile workspace
path = "C:/data/seoul/"
URL url = new File(path).toURL()
Workspace workspace = new Workspace("url='${url}' 'charset'='x-windows-949'")

// Open Shapefile layer we want to process
input_layer = workspace["wardoffice"]  // or workspace.get("wardoffice")
println "input feature count = " + input_layer.count()

// Create a new Schema (based on the Shapefile) but with Polygon Geometry
Schema schema = input_layer.schema.changeGeometryType('Polygon','wardoffice_buffer_1500')
println schema

// Create a new Layer
Layer output_layer = workspace.create(schema)

// Use the Cursor to loop through each Feature in the Shapefile
def filter = new Filter("NAM IS NOT NULL")
Cursor cursor = input_layer.getCursor(filter)   // or cursor
while(cursor.hasNext()) {
    // Get the next Feature
    Feature feature = cursor.next()

    // Create a Map for the new attributes
    attributes = [:]

    // For each attribute in the shapefile
    feature.attributes.each{k,v ->
        // If it's Geometry, process geometry
        if (v instanceof Geometry) {
            attributes[k] = v.buffer(1500)
            // v.bounds.geometry
        } else {
            attributes[k] = v
        }
    }

    // Create a new Feature with the new attributes
    Feature new_feature = schema.feature(attributes, feature.id)

    // Add it to the layer
    output_layer.add(new_feature)
}

// Always remember to close the cursor
cursor.close()

println "output feature count = " + output_layer.count()

// Apply layer's styles
output_layer.style = new Fill("#00ffff", 0.5) + new Stroke("silver", 0.1)

input_layer.style = new Shape("red", 4, "circle")
input_layer.style += new Label("NAM").font(family: "나눔고딕", size:12).point(anchor:[-0.25,0.5])
input_layer.style += new Halo(new Fill("white"), 1.0)

// Show map window
def map = new Map(width:900, height:600)
map.bounds = output_layer.bounds
map.addLayer(output_layer)
map.addLayer(input_layer)

new MapWindow(map)