개요
- qgis 3.22버전에서 새롭게 annotation layer라는 layer가 새로 생겼다.
qgis에서 annotation layer가 포함된 qgs를 열면 다음과 같이 보인다. raster와 qgs가 한 쌍으로 움직인다. - 이 layer는 벡터 데이터가 아니며, qgis project file(qgs)에 xml로 도형을 기록한다
- 어떻게 annotation의 geometry를 추출할 수 있는가?
참고 자료
- qgis annotation layer란?
- 3.22에는 annotation layer을 대응할 수 있는 tool bar가 있는 것으로 보이나, 내가 쓰는 QGIS 3.26 버전에서는 찾을 수 없었다.
- (수정 : 22.11.18) macos QGIS 3.28 버전 기준, View > Toolbar > annotation toolbar(주석 툴바)로 추가하시면 다음의 툴바를 확인할 수 있습니다. 글 작성 시점으로는 3.29까지 나왔습니다.

- annotation layer 정보는 qgs 내에 xml로 기술되어있다.
위 그림에서 볼 수 있듯, qgs내에 기술된 annotation layer와 qgs가 바라보는 raster layer 두 레이어가 뜨나, qgz를 압축해제해서 얻은 결과는 qgs와 링크된 raster 데이터 둘 뿐이었다.
코드
import shapely.wkt
import xml.etree.ElementTree as elemTree
from osgeo import ogr
import geopandas as gpd
'''
box, polygon, mask
'''
'''
parse_annotation은 여기서 qgs 내에 xml으로 기술되어있는 프로젝트 정보 중 'layer'단위의 xml을 파싱한다.
return : annotation 파일 내의 geometry를 모아서 shapely.geometry 타입으로 list를 반환
'''
def parse_annotation(elem) :
items = elem.findall('.//items/item[@wkt]')
wkts = [x.get('wkt') for x in items]
geoms = list()
for wkt in wkts :
if 'Curve' in wkt :
try :
geom = ogr.CreateGeometryFromWkt(wkt)
geom_approx = geom.GetLinearGeometry()
geom_shapely = shapely.wkt.loads(geom_approx.ExportToWkt())
geoms.append(geom_shapely)
except :
print(wkt)
else :
geom_shapely = shapely.wkt.loads(wkt)
geoms.append(geom_shapely)
return geoms
'''
path : 파일의 위치
return : annotation 파일 내의 전체 geometry를 list로 반환
'''
def parse_qgs_for_annotation(path) :
tree = elemTree.parse(path)
root = tree.getroot()
main_annotation_layer = root.findall('.//main-annotation-layer')[0]
extra_annotation_layers = root.findall(".//projectlayers/*[@type='annotation']")
geoms = list()
geoms.extend(parse_annotation(main_annotation_layer))
for extra_annotation_layer in extra_annotation_layers :
geoms.extend(parse_annotation(extra_annotation_layer))
return geoms
주의사항
CurvePolygon 때문에 ogr 모듈을 썼다. esri shapefile format에서는 geometry에서 curve 타입을 지원하지 않는다고 했기 때문에, shapefile 말고 geojson으로 내보내길
용례
tree = elemTree.parse(path)
root = tree.getroot()
srid = root.find('./projectCrs//srid')
srid = int(srid.text)
res = parse_qgs_for_annotation(path)
gdf = gpd.GeoDataFrame(geometry=res)
gdf = gdf.set_crs(f'epsg:{srid}')
gdf.to_file("test.geojson", driver='GeoJSON')
'GIS' 카테고리의 다른 글
[GIS] gcp로 georeference 하기, lcc 좌표계에서 EPSG:4326으로 reproject 하기 (1) | 2023.02.28 |
---|---|
[ArcGIS] ArcGIS python API 기초 예제 (2) | 2023.01.31 |
[GIS] 당신이 겪을 수 있는 georeference 문제들과 내 해결법 (0) | 2022.11.16 |
[KML] Python으로 KML 쓰기, 읽기, 수정하기 (0) | 2022.02.08 |
[GIS 일기] PostGIS에서 Polygon에서 각 변의 길이 불러오기 (0) | 2022.01.03 |
개요
- qgis 3.22버전에서 새롭게 annotation layer라는 layer가 새로 생겼다.
qgis에서 annotation layer가 포함된 qgs를 열면 다음과 같이 보인다. raster와 qgs가 한 쌍으로 움직인다. - 이 layer는 벡터 데이터가 아니며, qgis project file(qgs)에 xml로 도형을 기록한다
- 어떻게 annotation의 geometry를 추출할 수 있는가?
참고 자료
- qgis annotation layer란?
- 3.22에는 annotation layer을 대응할 수 있는 tool bar가 있는 것으로 보이나, 내가 쓰는 QGIS 3.26 버전에서는 찾을 수 없었다.
- (수정 : 22.11.18) macos QGIS 3.28 버전 기준, View > Toolbar > annotation toolbar(주석 툴바)로 추가하시면 다음의 툴바를 확인할 수 있습니다. 글 작성 시점으로는 3.29까지 나왔습니다.

- annotation layer 정보는 qgs 내에 xml로 기술되어있다.
위 그림에서 볼 수 있듯, qgs내에 기술된 annotation layer와 qgs가 바라보는 raster layer 두 레이어가 뜨나, qgz를 압축해제해서 얻은 결과는 qgs와 링크된 raster 데이터 둘 뿐이었다.
코드
import shapely.wkt
import xml.etree.ElementTree as elemTree
from osgeo import ogr
import geopandas as gpd
'''
box, polygon, mask
'''
'''
parse_annotation은 여기서 qgs 내에 xml으로 기술되어있는 프로젝트 정보 중 'layer'단위의 xml을 파싱한다.
return : annotation 파일 내의 geometry를 모아서 shapely.geometry 타입으로 list를 반환
'''
def parse_annotation(elem) :
items = elem.findall('.//items/item[@wkt]')
wkts = [x.get('wkt') for x in items]
geoms = list()
for wkt in wkts :
if 'Curve' in wkt :
try :
geom = ogr.CreateGeometryFromWkt(wkt)
geom_approx = geom.GetLinearGeometry()
geom_shapely = shapely.wkt.loads(geom_approx.ExportToWkt())
geoms.append(geom_shapely)
except :
print(wkt)
else :
geom_shapely = shapely.wkt.loads(wkt)
geoms.append(geom_shapely)
return geoms
'''
path : 파일의 위치
return : annotation 파일 내의 전체 geometry를 list로 반환
'''
def parse_qgs_for_annotation(path) :
tree = elemTree.parse(path)
root = tree.getroot()
main_annotation_layer = root.findall('.//main-annotation-layer')[0]
extra_annotation_layers = root.findall(".//projectlayers/*[@type='annotation']")
geoms = list()
geoms.extend(parse_annotation(main_annotation_layer))
for extra_annotation_layer in extra_annotation_layers :
geoms.extend(parse_annotation(extra_annotation_layer))
return geoms
주의사항
CurvePolygon 때문에 ogr 모듈을 썼다. esri shapefile format에서는 geometry에서 curve 타입을 지원하지 않는다고 했기 때문에, shapefile 말고 geojson으로 내보내길
용례
tree = elemTree.parse(path)
root = tree.getroot()
srid = root.find('./projectCrs//srid')
srid = int(srid.text)
res = parse_qgs_for_annotation(path)
gdf = gpd.GeoDataFrame(geometry=res)
gdf = gdf.set_crs(f'epsg:{srid}')
gdf.to_file("test.geojson", driver='GeoJSON')
'GIS' 카테고리의 다른 글
[GIS] gcp로 georeference 하기, lcc 좌표계에서 EPSG:4326으로 reproject 하기 (1) | 2023.02.28 |
---|---|
[ArcGIS] ArcGIS python API 기초 예제 (2) | 2023.01.31 |
[GIS] 당신이 겪을 수 있는 georeference 문제들과 내 해결법 (0) | 2022.11.16 |
[KML] Python으로 KML 쓰기, 읽기, 수정하기 (0) | 2022.02.08 |
[GIS 일기] PostGIS에서 Polygon에서 각 변의 길이 불러오기 (0) | 2022.01.03 |