Рендерінг карти та друк

Загалом існує два способи отримати друковану карту: швидкий, за допомогою QgsMapRenderer, або підготовка макета за допомогою QgsComposition та супутніх класів.

Просте відображення

Відобразити шари за допомогою QgsMapRenderer дуже просто — створюється вихідний пристрій (QImage, QPainter тощо), вказується список шарів, охоплення, розмір вихідного зображення та запускається рендерінг

# create image
img = QImage(QSize(800,600), QImage.Format_ARGB32_Premultiplied)

# set image's background color
color = QColor(255,255,255)
img.fill(color.rgb())

# create painter
p = QPainter()
p.begin(img)
p.setRenderHint(QPainter.Antialiasing)

render = QgsMapRenderer()

# set layer set
lst = [ layer.getLayerID() ]  # add ID of every layer
render.setLayerSet(lst)

# set extent
rect = QgsRect(render.fullExtent())
rect.scale(1.1)
render.setExtent(rect)

# set output size
render.setOutputSize(img.size(), img.logicalDpiX())

# do the rendering
render.render(p)

p.end()

# save image
img.save("render.png","png")

Відображення за допомогою макетів

Редактор макетів стає у нагоді коли вам необхідно отримати щось складніше, ніж дозволяє простий рендерінг, описаний вище. Використовуючи редактор макетів можна створити складний макет, що містить декілька карт, підписи, легенду, таблиці та інші елементи, які ми звичайно бачимо на друкованих картах. Макети можна експортувати у PDF, растрові зображення або роздруковувати напряму.

Редактор макетів складається з багатьох класів. Всі вони знаходяться у бібліотеці ядра. У QGIS існує зручний графічний інтерфейс, який полегшує розміщення елементів, але на жаль, він поки не доступний у бібліотеці графічного інтерфейсу. Якщо ви не знайомі з фремворком`Qt Graphics View <http://doc.qt.nokia.com/stable/graphicsview.html>`_, радимо переглянути його документацію зараз, оскільки редактор макетів побудовано на ньому.

Основним класом редактора макетів є QgsComposition, який походить від QGraphicsScene. Створимо екземпляр цього класу

mapRenderer = iface.mapCanvas().mapRenderer()
c = QgsComposition(mapRenderer)
c.setPlotStyle(QgsComposition.Print)

Зверніть увагу, що макет приймає в якості параметра екземпляр QgsMapRenderer. Ми припускаємо, зо код буде виконуватися безпосередньо в QGIS, тому використовуємо ренедерер активної карти. Макет використовує різноманітні параметри рендерера, найголовніші з них — список шарів карти та поточне охоплення. Якщо макети використовуються в автономній програмі, вам необхідно створити свій власний екземпляр рендерера, як було показано в попередньому розділі, та передати його до макета.

На макет можна додавати різні елементи (карту, підписи, ...) — ці елементи є похідними від класу QgsComposerItem. На сьогодні доступні такі елементи:

  • map — this item tells the libraries where to put the map itself. Here we create a map and stretch it over the whole paper size

    x, y = 0, 0
    w, h = c.paperWidth(), c.paperHeight()
    composerMap = QgsComposerMap(c, x,y,w,h)
    c.addItem(composerMap)
    
  • label — allows displaying labels. It is possible to modify its font, color, alignment and margin

    composerLabel = QgsComposerLabel(c)
    composerLabel.setText("Hello world")
    composerLabel.adjustSizeToText()
    c.addItem(composerLabel)
    
  • legend

    legend = QgsComposerLegend(c)
    legend.model().setLayerSet(mapRenderer.layerSet())
    c.addItem(legend)
    
  • scale bar

    item = QgsComposerScaleBar(c)
    item.setStyle('Numeric') # optionally modify the style
    item.setComposerMap(composerMap)
    item.applyDefaultSize()
    c.addItem(item)
    
  • стрілка

  • зображення

  • фігура

  • таблиця

За замовчанням щойно створені елементи мають нульове положення (лівий верхній куточок сторінки) та нульовий розмір. Положення та розміри завжди задаються у міліметрах

# set label 1cm from the top and 2cm from the left of the page
composerLabel.setItemPosition(20,10)
# set both label's position and size (width 10cm, height 3cm)
composerLabel.setItemPosition(20,10, 100, 30)

Також за замовчанням навколо кожного елемента відображається рамка. Прибрати її можна так

composerLabel.setFrame(False)

Крім створення макетів вручну QGIS має підтримку шаблонів макетів. Шаблони це звичайні макети, збережені у вигляді файлів .qpt (формат XML). На жаль, цей функціонал поки недоступний через API.

Після того як макет підготований (всі елементи створено та розміщено в необхідних місцях), можна переходити до генерації вихідного растрового чи векторного файлу.

За замовчанням для виводу використовується аркуш розміру A4 та роздільна здатність 300 DPI. При необхідності ці параметри змінюються. Розмір паперу задається в міліметрах

c.setPaperSize(width, height)
c.setPrintResolution(dpi)

Друк у растр

Наступний фрагмент коду показує як згенерувати растрове представлення макету

dpi = c.printResolution()
dpmm = dpi / 25.4
width = int(dpmm * c.paperWidth())
height = int(dpmm * c.paperHeight())

# create output image and initialize it
image = QImage(QSize(width, height), QImage.Format_ARGB32)
image.setDotsPerMeterX(dpmm * 1000)
image.setDotsPerMeterY(dpmm * 1000)
image.fill(0)

# render the composition
imagePainter = QPainter(image)
sourceArea = QRectF(0, 0, c.paperWidth(), c.paperHeight())
targetArea = QRectF(0, 0, width, height)
c.render(imagePainter, targetArea, sourceArea)
imagePainter.end()

image.save("out.png", "png")

Друк у PDF

Наступний фрагмент коду показує як отримати файл формату PDF

printer = QPrinter()
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName("out.pdf")
printer.setPaperSize(QSizeF(c.paperWidth(), c.paperHeight()), QPrinter.Millimeter)
printer.setFullPage(True)
printer.setColorMode(QPrinter.Color)
printer.setResolution(c.printResolution())

pdfPainter = QPainter(printer)
paperRectMM = printer.pageRect(QPrinter.Millimeter)
paperRectPixel = printer.pageRect(QPrinter.DevicePixel)
c.render(pdfPainter, paperRectPixel, paperRectMM)
pdfPainter.end()