10. 맵 렌더링 및 출력
힌트
The code snippets on this page need the following imports:
1import os
2
3from qgis.core import (
4 QgsGeometry,
5 QgsMapSettings,
6 QgsPrintLayout,
7 QgsMapSettings,
8 QgsMapRendererParallelJob,
9 QgsLayoutItemLabel,
10 QgsLayoutItemLegend,
11 QgsLayoutItemMap,
12 QgsLayoutItemPolygon,
13 QgsLayoutItemScaleBar,
14 QgsLayoutExporter,
15 QgsLayoutItem,
16 QgsLayoutPoint,
17 QgsLayoutSize,
18 QgsUnitTypes,
19 QgsProject,
20 QgsFillSymbol,
21)
22
23from qgis.PyQt.QtGui import (
24 QPolygonF,
25 QColor,
26)
27
28from qgis.PyQt.QtCore import (
29 QPointF,
30 QRectF,
31 QSize,
32)
There are generally two approaches when input data should be rendered as a map:
either do it quick way using QgsMapRendererJob or produce more fine-tuned
output by composing the map with the QgsLayout
class.
10.1. 단순 렌더링
The rendering is done creating a QgsMapSettings
object to define the rendering settings,
and then constructing a QgsMapRendererJob
with those settings. The latter is then
used to create the resulting image.
다음은 그 예시입니다.
1image_location = os.path.join(QgsProject.instance().homePath(), "render.png")
2
3vlayer = iface.activeLayer()
4settings = QgsMapSettings()
5settings.setLayers([vlayer])
6settings.setBackgroundColor(QColor(255, 255, 255))
7settings.setOutputSize(QSize(800, 600))
8settings.setExtent(vlayer.extent())
9
10render = QgsMapRendererParallelJob(settings)
11
12def finished():
13 img = render.renderedImage()
14 # save the image; e.g. img.save("/Users/myuser/render.png","png")
15 img.save(image_location, "png")
16
17render.finished.connect(finished)
18
19# Start the rendering
20render.start()
21
22# The following loop is not normally required, we
23# are using it here because this is a standalone example.
24from qgis.PyQt.QtCore import QEventLoop
25loop = QEventLoop()
26render.finished.connect(loop.quit)
27loop.exec_()
10.2. 서로 다른 좌표계를 가진 레이어들을 렌더링하기
If you have more than one layer and they have a different CRS, the simple example above will probably not work: to get the right values from the extent calculations you have to explicitly set the destination CRS
layers = [iface.activeLayer()]
settings = QgsMapSettings()
settings.setLayers(layers)
settings.setDestinationCrs(layers[0].crs())
10.3. Output using print layout
Print layout is a very handy tool if you would like to do a more sophisticated output than the simple rendering shown above. It is possible to create complex map layouts consisting of map views, labels, legend, tables and other elements that are usually present on paper maps. The layouts can be then exported to PDF, raster images or directly printed on a printer.
The layout consists of a bunch of classes. They all belong to the core library. QGIS application has a convenient GUI for placement of the elements, though it is not available in the GUI library. If you are not familiar with Qt Graphics View framework, then you are encouraged to check the documentation now, because the layout is based on it.
The central class of the layout is the QgsLayout
class, which is derived from the Qt QGraphicsScene
class. Let us create an instance of it:
project = QgsProject.instance()
layout = QgsPrintLayout(project)
layout.initializeDefaults()
This initializes the layout with some default settings, specifically by adding
an empty A4 page to the layout. You can create layouts without calling the
initializeDefaults()
method,
but you’ll need to take care of adding pages to the layout yourself.
The previous code creates a “temporary” layout that is not visible in the GUI. It can be handy to e.g. quickly add some items and export without modifying the project itself nor expose these changes to the user. If you want the layout to be saved/restored along with the project and available in the layout manager, then add:
layout.setName("MyLayout")
project.layoutManager().addLayout(layout)
Now we can add various elements (map, label, …) to the layout. All these objects
are represented by classes that inherit from the base QgsLayoutItem
class.
Here’s a description of some of the main layout items that can be added to a layout.
map — Here we create a map of a custom size and render the current map canvas
1map = QgsLayoutItemMap(layout) 2# Set map item position and size (by default, it is a 0 width/0 height item placed at 0,0) 3map.attemptMove(QgsLayoutPoint(5,5, QgsUnitTypes.LayoutMillimeters)) 4map.attemptResize(QgsLayoutSize(200,200, QgsUnitTypes.LayoutMillimeters)) 5# Provide an extent to render 6map.zoomToExtent(iface.mapCanvas().extent()) 7layout.addLayoutItem(map)
라벨 — 라벨을 표출할 수 있도록 해줍니다. 폰트, 색상, 정렬 및 여백을 수정할 수 있습니다.
label = QgsLayoutItemLabel(layout) label.setText("Hello world") label.adjustSizeToText() layout.addLayoutItem(label)
범례
legend = QgsLayoutItemLegend(layout) legend.setLinkedMap(map) # map is an instance of QgsLayoutItemMap layout.addLayoutItem(legend)
축척막대(scale bar)
1item = QgsLayoutItemScaleBar(layout) 2item.setStyle('Numeric') # optionally modify the style 3item.setLinkedMap(map) # map is an instance of QgsLayoutItemMap 4item.applyDefaultSize() 5layout.addLayoutItem(item)
화살표
그림
basic shape
nodes based shape
1polygon = QPolygonF() 2polygon.append(QPointF(0.0, 0.0)) 3polygon.append(QPointF(100.0, 0.0)) 4polygon.append(QPointF(200.0, 100.0)) 5polygon.append(QPointF(100.0, 200.0)) 6 7polygonItem = QgsLayoutItemPolygon(polygon, layout) 8layout.addLayoutItem(polygonItem) 9 10props = {} 11props["color"] = "green" 12props["style"] = "solid" 13props["style_border"] = "solid" 14props["color_border"] = "black" 15props["width_border"] = "10.0" 16props["joinstyle"] = "miter" 17 18symbol = QgsFillSymbol.createSimple(props) 19polygonItem.setSymbol(symbol)
표
Once an item is added to the layout, it can be moved and resized:
item.attemptMove(QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters))
item.attemptResize(QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters))
A frame is drawn around each item by default. You can remove it as follows:
# for a composer label
label.setFrameEnabled(False)
Besides creating the layout items by hand, QGIS has support for layout templates which are essentially compositions with all their items saved to a .qpt file (with XML syntax).
Once the composition is ready (the layout items have been created and added to the composition), we can proceed to produce a raster and/or vector output.
10.3.1. Exporting the layout
To export a layout, the QgsLayoutExporter
class must be used.
1base_path = os.path.join(QgsProject.instance().homePath())
2pdf_path = os.path.join(base_path, "output.pdf")
3
4exporter = QgsLayoutExporter(layout)
5exporter.exportToPdf(pdf_path, QgsLayoutExporter.PdfExportSettings())
Use the exportToImage()
in case you want to export to an image instead of a PDF file.
10.3.2. Exporting a layout atlas
If you want to export all pages from a layout that has the atlas option
configured and enabled, you need to use the atlas()
method in the exporter (QgsLayoutExporter
) with small adjustments. In the following
example, the pages are exported to PNG images:
exporter.exportToImage(layout.atlas(), base_path, 'png', QgsLayoutExporter.ImageExportSettings())
Notice that the outputs will be saved in the base path folder, using the output filename expression configured on atlas.