pyQGIS Tip

특정 Feature를 확대하기

아래의 코드는 선택된 Feature를 확대합니다.

canvas = iface.mapCanvas()
id = 0
#canvas.setSelectionColor(QColor("red"))
layer.select(id)
canvas.zoomToSelected(layer)

아래의 코드는 Feature를 선택하지 않고 FID가 0인 Feature를 확대합니다.

canvas = iface.mapCanvas()
id = 0
feat = layer.getFeature(id)
geom = feat.geometry()
bbox = geom.boundingBox()
canvas.setExtent(bbox)
canvas.refresh()

특정 Feature를 깜박이게 하기

canvas = iface.mapCanvas()
id = 0
canvas.flashFeatureIds(layer, [id])

화면 좌표와 지도 좌표 간의 변환

아래의 코드는 화면 좌표 (100, 20)을 지도 좌표로 변환하고 다시 변환된 지도 좌표를 화면 좌표로 변환하는 코드입니다.

ptView = QPoint(100, 20)
ptMap = canvas.getCoordinateTransform().toMapCoordinates(ptView)
print(ptMap.x(), ptMap.y())

ptMap2 = QgsMapTool(canvas).toCanvasCoordinates(ptMap)
print(ptMap2.x(), ptMap2.y())

다양한 형태의 지오메트리 생성

좌표를 지정해서 다양한 형태의 지오메트리를 생성하는 코드입니다.

geomPoint = QgsGeometry.fromPointXY(QgsPointXY(10000, 15000))

geomMultiPoint = QgsGeometry.fromMultiPointXY(
    [
        QgsPointXY(10000, 15000),
        QgsPointXY(11000, 16000),
    ]
)

geomPolyline = QgsGeometry.fromPolylineXY(
    [
        QgsPointXY(10000, 15000),
        QgsPointXY(11000, 16000),
        QgsPointXY(12000, 17000),
        QgsPointXY(13000, 18000),
    ]
)

geomPolyline = QgsGeometry.fromMultiPolylineXY(
    [
        [
            QgsPointXY(10000, 15000),
            QgsPointXY(11000, 16000),
            QgsPointXY(12000, 17000),
            QgsPointXY(13000, 18000),
        ]
    ]
)

pX = 971195
pY = 1841488

geomPolygon = QgsGeometry.fromPolygonXY(
    [
        [
            QgsPointXY(pX, pY),
            QgsPointXY(pX+1000, pY),
            QgsPointXY(pX+1000, pY+1000),
            QgsPointXY(pX, pY+1000),
        ],
        [
            QgsPointXY(pX+100, pY+100),
            QgsPointXY(pX+900, pY+100),
            QgsPointXY(pX+900, pY+900),
            QgsPointXY(pX+100, pY+900),
        ]
    ]
)

geomPolygon = QgsGeometry.fromMultiPolygonXY(
    [
        [
            [
                QgsPointXY(pX, pY),
                QgsPointXY(pX+1000, pY),
                QgsPointXY(pX+1000, pY+1000),
                QgsPointXY(pX, pY+1000),
            ],
            [
                QgsPointXY(pX+100, pY+100),
                QgsPointXY(pX+900, pY+100),
                QgsPointXY(pX+900, pY+900),
                QgsPointXY(pX+100, pY+900),
            ]
        ]
    ]
)

아래는 Python 언어의 특징을 이용한 효율적인 코드 작성입니다.

pts = [
    (583899.8, 8177297.19), 
    (583900.23, 8177262.52), 
    (583896.49, 8177262.47), 
    (583895.96, 8177297.29), 
    (583899.8, 8177297.19)
]

geomPolygon = QgsGeometry.fromPolygonXY( [[ QgsPointXY( xy[0], xy[1] ) for xy in pts ]] ) 

HDRI 제작하기

먼저 원하는 장면을 아래의 예시처럼 구성합니다.

카메라를 장면의 중심(대부분 원점)에 배치하고 회전 값을 다음처럼 설정합니다.

카메라의 속성을 다음처럼 지정합니다. 아래의 속성 구성(Panorama Type)을 위해서 렌더링은 Cycles로 지정되어 있어야 합니다.

출력(Output) 속성은 다음과 같습니다. Resolution을 변경했으며 File Format 역시 변경했습니다.

국토교통부 연속지적도 좌표계 변경 아주! 칭찬해!

짝짝짝! 참 잘했어요!

국토교통부에서 제공하는 연속지적도의 좌표계에서 사용하는 타원체를 Bessel1841에서 GRS80으로 변경된 것을 확인했습니다. 정확도면에서 어떻게 향상되었는지 기존의 다른 좌표계로 된 건물을 지적도와 함께 중첩해 보았습니다.

먼저 예전 Bessel1841 타원체를 사용하는 지적도와 UTM-K 좌표계인 건물을 중첩해 보면 다음과 같습니다.

확인해 보면 지적도의 필지와 건물이 상당히 어긋납니다. 늘 그래왔고 그려러니…. 했죠. 이제 최근 변경된 지적도와 건물 중첩을 보겠습니다.

완벽해! 드디어 해냈구나! 근데.. 왜 이렇게 늦었니? 아무튼… 이제 지적도에 대한 좌표계 이슈는 해결된 것 같습니다.

Python 가상환경 만들고 VS.Code에서 사용하기

가상환경 생성하고 VS.Code에서 원하는 가상환경을 선택하도록 하는 과정을 정리해 둡니다.

일단 콘설창을 실행하고, 생성하고자 하는 가상환경 가상환경이 저장될 폴더로 이동한 뒤 아래의 명령을 입력합니다.

python -m venv python_virtualenv

그러면 python_virtualenv 폴더가 생성된 것을 확인할 수 있습니다. 여기까지가 파이선에서 가상환경 생성의 전부입니다.

이제 VS.Code에서 이 가성환경을 통해 코드를 실행하기 위한 설정입니다.

VS.Code를 실행하고 단축키 F1를 누르면 Python에 대한 인터프리터를 선택할 수 있는 항목이 표시됩니다. 이 항목을 클릭합니다.

“+ 인터프리터 경로 입력…”을 클릭하고 “찾기…”에서 이전에 생성한 가상환경 폴더에 위치한 Scripts/python.exe 파일을 선택합니다.

이제 새로운 터미널이 표시될때마다 다음처럼 가상환경 이름 표시와 함께 명령 프롬프트가 표시됩니다.

그리고 GDAL 설치는 다음과 같습니다.

먼저 WHL 파일을 다운로드(https://www.lfd.uci.edu/~gohlke/pythonlibs/#gdal) 받고 다음 명령으로 설치하면 됩니다.

pip install .\GDAL-3.4.3-cp311-cp311-win_amd64.whl

GDAL API를 JAVA에서 사용하기 (Windows 환경)

#1 컴파일된 GDAL 다운로드

다음 사이트를 통해 미리 컴파일된 GDAL을 내려 받는다. MSVC2022로 컴파일된 x64를 선택한 뒤 release-1930-x64-gdal-3-5-3-mapserver-8-0-0.zip를 다운로드 받았음 : https://www.gisinternals.com/release.php

#2 GDAL dll의 PATH 지정

내려받은 파일의 압축을 풀면 bin 폴더에 gdal에 대해 컴파일된 dll 파일이 존재하는데, 이 bin 폴더를 path에 지정한다. (gdalalljni.dll에서 이 폴더의 dll을 참조함)

#3 이클립스에서 라이브러리 참조 및 glue dll 참조 설정

bin/gdal/java 폴더에는 gdal.jar와 gdal에 대한 glue dll인 gdalalljni.dll이 존재하는 것을 확인할 수 있다. 이클립스에서 프로젝트를 생성하고 라이브러리로 gdal.jar를 참조한다. 그리고 gdal.jar가 참조하는 gdalalljni.dll 파일을 JRE가 파악할 수 있도록 이 파일의 경로(d:/path1/path2 라고 하자)를 VM arguments에 -Djava.library.path=d:/path1/path2 를 입력한다. (만약 path에 이 경로가 지정되어 있다면 생략해도 됨)

#4 코드 테스트

테스트 코드는 다음과 같다.

package tstGDAL;

import org.gdal.gdal.Dataset;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;

public class MainEntry {
    Dataset hDataset;
    int numBands;
	 
    public MainEntry(String filename) {
        gdal.AllRegister();
        hDataset = gdal.Open(filename, gdalconstConstants.GA_ReadOnly);
        this.numBands = hDataset.getRasterCount();
    }
	 
    public static void main(String[] args) {
        String path = "d:/sample.tif";
        MainEntry instance = new MainEntry(path);
        System.out.println(instance.numBands);
    }
}