[ QGIS 노하우 ] pyQGIS 간단한 사용법

식빵·2022년 12월 31일
0

QGIS

목록 보기
2/4
post-thumbnail

Velog Dark Theme 로 봐야 잘 보입니다 !


작성 계기


최근 python 을 배워봤는데, 이곳 저곳 쓸 수 있는 분야가 많다는 것에 많이 놀란다.
그리고 요즘 조금씩 끄적이고 있는 QGIS 에서도 Python 을 쓸 수 있다는 것을 알아냈다.

배우고 사용해보니, 일일이 손으로 하던 작업을 코드 한방에 해결하니 편한 점이 있었다.
하지만 시간이 지나면 까먹을 거 같아서 미리 기록해두려 한다.

일단은 당장 아는 것 까지만 작성하고, 추후에 뭔가 더 알아내게 되면
계속해서 글을 추가적으로 덧붙이는 식으로 작성하겠다.
(아직 초기여서 내용이 많지 않다 😥)

참고: 여기에서 사용하는 QGIS 버전은 3.22.14-Białowieża 입니다.






사용법 알아보기


📌 PyQGIS 콘솔, 에디터 열기

  • QGIS 실행하고
  • ctrl + alt + p 를 누르면 콘솔 화면이 보인다.
  • 콘솔 화면에서 show editor 버튼 클릭하면 옆에 에디터 화면이 보인다.
  • 참고로 작성한 코드를 실행하려면 ctrl + shift + e 를 누르거나, 콘솔화면 상단의
    초록색 삼각형을 클릭하면 된다.



📌 프로젝트 좌표계 변경

QgsProject.instance().setCrs(QgsCoordinateReferenceSystem(5186))



📌 레이어 목록조회

QGIS 에 위 그림처럼 미리 Layer 를 생성해 두고 아래처럼 코드를 실행해보면...

# 모든 레이어 조회
all_layers = QgsProject.instance().mapLayers().values()
print(all_layers)

# 이름으로 찾는 법. 하지만 이름은 얼마든지 중복될 수 있으니 조심!
specific_named_layers = QgsProject.instance().mapLayersByName('continue_map_layer')
print(specific_named_layers)

# tip: 만약에 특정 문자열이 있는 것을 찾거나 하고 싶다면...
# layerList 
# = [lyr for lyr in QgsProject.instance().mapLayers().values()\
#     if "triangle" in lyr.name()]

print 결과

print(all_layers) 결과:
dict_values([<QgsRasterLayer: 'Google Satellite' (wms)>, <QgsVectorLayer: 'continue_map_layer' (postgres)>, <QgsVectorLayer: 'rectangle_layer' (ogr)>])

print(specific_named_layers) 결과:
[<QgsVectorLayer: 'continue_map_layer' (postgres)>]



📌 각 레이어 좌표계 조회

all_layers = QgsProject.instance().mapLayers().values()

for val in all_layers:
    print(val.crs().authid())

출력은 아래와 같은 형태로 나온다

EPSG:3857
EPSG:5186
EPSG:4326
EPSG:4326



📌 레이어 재투영

# point_4326 이라는 레이어를 조회한다.
point_4326 = QgsProject.instance().mapLayersByName('point_4326')[0]

### 참고:
### PC 에 있는 SHP 파일을 조회해서 바로 reproject 를 하고 싶다면?
### shp_path = 'C:/study/qgis/python/point_4326.shp'
### point_4326 = QgsVectorLayer(shp_path, 'rectangle_layer', 'ogr')

parameter = {
    'INPUT': point_4326,
    'TARGET_CRS': 'EPSG:5186',
    'OUTPUT': 'memory:point_5186' # 실제 shp 파일로 저장하고 싶다면 경로 작성
}
result = processing.run('native:reprojectlayer', parameter)['OUTPUT']
QgsProject.instance().addMapLayer(result)

참고: 지리 좌표계인 레이어는 다른 투영 좌표계를 사용하는 레이어와 거리 연산(그외 벡터 연산 등)을 하기 위해서는 반드시 투영 좌표계로 재투영을 먼저 해줘야 한다.




📌 Layer 생성

>> Vector Layer

shp_path_rectangles = 'C:/study/pyQGIS/rectangles.shp'
vector_layer = QgsVectorLayer(shp_path_rectangles, 'rectangle_layer', 'ogr')
QgsProject.instance().addMapLayer(vector_layer)

QgsVectorLayer 의 2번째 파라미터는 생성될 Layer 의 이름이고
3번째 파라미터는 shp 파일 포맷을 지원하는 라이브러리의 이름을 작성한 것이다.
QgsVectorLayer 가 받는 input(= 1번째 파라미터) 에 따라 3번째 인자값이 다르다.


>> PostGIS Layer

uri = QgsDataSourceUri()

# 파라미터 순서대로...
### 1: host,  2: port  , 3: database ,  4: username,   5.: password
uri.setConnection('localhost', '5432', 'sdb_course', 'postgres', 'root')

# 1번째 인자: 스키마
# 2번째 인자: 테이블 명
# 3번째 인자: 지오메트리 컬럼
# 4번째 인자: where 구분을 작성하는 곳이다. ex) pnu like '4143%'
# 5번째 인자: primary key column
uri.setDataSource('public', 'continue_map', 'geom', '', 'pnu')

postgis_vector_layer = QgsVectorLayer(uri.uri(False), "continue_map_layer", "postgres")

QgsProject.instance().addMapLayer(postgis_vector_layer)

>> XYZ Tiles Layer

# https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z} 중에서 
# 일부만 url encoding 하여 urlWithParams 문자열에 적용
urlWithParams = 'type=xyz&url=https://mt1.google.com/vt/lyrs%3Ds%26x%3D%7Bx%7D%26y%3D%7By%7D%26z%3D%7Bz%7D&zmax=19&zmin=0'
rlayer = QgsRasterLayer(urlWithParams, 'Google Satellite', 'wms')  

if rlayer.isValid():
    QgsProject.instance().addMapLayer(rlayer)
else:
    print('invalid layer')



📌 Layer 삭제

# 전체 삭제
QgsProject.instance().removeAllMapLayers() 

# 특정 하나 삭제
layers = QgsProject.instance().mapLayersByName('continue_map_layer')
QgsProject.instance().removeMapLayer(layers[0].id())



📌 Layer ==> WKT 변환

from qgis.core import *
import qgis.utils
layer = qgis.utils.iface.activeLayer()
for feat in layer.getFeatures():
    print(feat.geometry().asWkt());

PostGIS 테이블의 geometry 정보와 Intersect, Within 같은
공간연산 쿼리로 짜기 위해서 비교대상이 되는 테스트 데이터가 필요한 경우가 많았다.

그럴 때 QGIS 에서 임시 스크래치 레이어 를 생성하고,
레이어에 도형을 그린 위의 Python 코드를 돌려서 WKT 문자열을 구하면 쉽게
PostGIS 에서 테스트를 돌릴 수 있다.

select
st_setsrid(
	st_geomfromewkt('WKT문자열 복붙!') 
, 5186)



그런데 만약 하나의 Geometry 에 대해서만 WKT 의 값을 알고 싶은 것이라면
QGISIdentify Feature 기능을 사용하면 된다. (아래 그림 참고)





참고 링크


profile
백엔드를 계속 배우고 있는 개발자입니다 😊

0개의 댓글