[Qgis-user] Maps generation with Python (or Atlas ?)
Benoît Laurent
blaurent at heurisis.eu
Wed May 20 07:38:03 PDT 2015
Le 20/05/2015 15:55, Bernd Vogelgesang a écrit :
> Hi Benoît,
>
> would you mind sharing your hole script as reference for others?
"As reference"... Hum... It would be very presumptuous of me :-).
> I think you touched a common problem which isn't covered with built-in
> functions yet, and not everyone is gifted with profound coding
> abilities in python (like me ;) )
"gifted with profound coding abilities in python". Same comment... :-)
However, I simplified the code a little and translated my comments in
English. By the way, the picture inclusion does not work. If someone can
help me on that point, it would be nice. If it helps, here is my code:
*#!/usr/bin/env Python
# encoding: utf-8
"""
Generate pdf maps
Assumptions :
- the QGis project contains a set of groups of 2
layers, the first one just containting a linear feature, the second
containing points along the track.
- the last group contains raster layers.
"""
from glob import glob
from os import *
from os.path import splitext
from qgis import core
from qgis.core import (QgsComposition,
QgsComposerMap,
QgsComposerLabel,
QgsComposerScaleBar,
QgsComposerPicture,
QgsMapLayer,
QgsRectangle,
QgsComposerArrow,
QGis)
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import os
import sys
import re
import time
def run_script(iface):
## Generator
genCartes = GenCartes(iface)
## Generates the maps
genCartes.generer()
class GenCartes:
"""
***************************************************************************************************************************************************
Constructeur
***************************************************************************************************************************************************
"""
def __init__(self, iface):
### Initialization using qgis.utils.iface
self.iface = iface
# Attribute of the class
self.composerMap = None
"""Compute an extent of geometry, with given margin (in %)
to be able to show it in the selected map item
Deal with non-square geometries to keep same ratio"""
def getNewExtent(self, geom, margin = None):
# compute coordinates and ratio
new_extent = None
x1, y1, x2, y2 = (0, 0, 0, 0)
geom_rect = geom
geom_ratio = geom_rect.width() / geom_rect.height()
xa1 = geom_rect.xMinimum()
xa2 = geom_rect.xMaximum()
ya1 = geom_rect.yMinimum()
ya2 = geom_rect.yMaximum()
map_rect = self.composerMap.boundingRect()
map_ratio = map_rect.width() / map_rect.height()
# geometry height is too big
if geom_ratio < map_ratio:
y1 = ya1
y2 = ya2
x1 = (xa1 + xa2 + map_ratio * (ya1 - ya2)) / 2.0
x2 = x1 + map_ratio * (ya2 - ya1)
new_extent = core.QgsRectangle(x1, y1, x2, y2)
# geometry width is too big
elif geom_ratio > map_ratio:
x1 = xa1
x2 = xa2
y1 = (ya1 + ya2 + (xa1 - xa2) / map_ratio) / 2.0
y2 = y1 + (xa2 - xa1) / map_ratio
new_extent = core.QgsRectangle(x1, y1, x2, y2)
# same ratio: send geom bounding box
else:
new_extent = geom_rect
# add margin to computed extent
if margin:
new_extent.scale(1 + margin / 100.0)
return new_extent
"""
***************************************************************************************************************************************************
Generate the maps
***************************************************************************************************************************************************
"""
def generer(self):
## Makes the vector layer transparent except raster layers
## Hide labels
layers = self.iface.legendInterface().layers()
for layer in layers:
if layer.type() <> QgsMapLayer.RasterLayer:
layer.rendererV2().symbol().setAlpha(0.3)
layer.setCustomProperty("labeling/enabled", "False")
## Creation of QgsComposition
mapRenderer = self.iface.mapCanvas().mapRenderer()
c = QgsComposition(mapRenderer)
## Format of the maps
c.setPaperSize(420, 297)
c.setPlotStyle(QgsComposition.Print)
## Margins
margeBas = 5
margeHaut = 5
margeGauche = 5
margeDroite = 5
margeHautCarte = 0
margeBasCarte = 50
margeSsCarte = 5
## Composer map
x, y = margeGauche, margeHaut
w, h = c.paperWidth()-margeGauche-margeDroite,
c.paperHeight()-margeBasCarte-margeHaut
self.composerMap = QgsComposerMap(c,x,y,w,h)
self.composerMap.setPreviewMode(QgsComposerMap.Cache)
c.addItem(self.composerMap)
## Title
clTitre = QgsComposerLabel(c)
clTitre.setItemPosition(margeGauche, c.paperHeight() -
margeBasCarte + margeSsCarte)
clTitre.setFont(QFont( "Helvetica", 24, QFont.Bold ))
c.addItem(clTitre)
## Logo file
## Does not appear !! I don't know why
nomFichierLogo =
QtGui.QFileDialog.getOpenFileName(None, u"Choose a logo :", 'C:/',
"Image Files (*.png *.jpg *.bmp)")
if nomFichierLogo:
itemLogo = QgsComposerPicture(c)
itemLogo.setItemPosition(c.paperWidth() -
margeDroite - 30, c.paperHeight() + margeSsCarte + 20, 30, 30)
itemLogo.setPicturePath(nomFichierLogo)
itemLogo.updateItem()
c.addItem(itemLogo)
## Output folder
nomRep = QtGui.QFileDialog.getExistingDirectory(None,
u"Choose an output folder :", 'C:/', QtGui.QFileDialog.ShowDirsOnly)
# Printer
printer = QtGui.QPrinter()
printer.setOutputFormat(QtGui.QPrinter.PdfFormat)
printer.setPaperSize(QSizeF(c.paperWidth(),
c.paperHeight()), QtGui.QPrinter.Millimeter)
printer.setFullPage(True)
printer.setColorMode(QtGui.QPrinter.Color)
printer.setResolution(c.printResolution())
## Iterate over groups
legend = self.iface.legendInterface()
groups = legend.groupLayerRelationship()
layers = legend.layers()
nbGroups = len(groups)
nbLayers = len(layers)
if nbLayers > 0 and len(nomRep) > 0 :
# Last group containts rasters => nbGroups - 1
g = 0
#for g in range(0,nbGroups-1):
for g in range(0,2):
# File name
nomCircuit = groups[g][0]
nomCircuit = re.sub("[A-Za-z._\-]", '',
nomCircuit)
print nomCircuit
nomFichier = nomRep + "\\" + nomCircuit
+ ".pdf"
if not os.path.isfile(nomFichier):
## Update title
clTitre.setText("Track " +
nomCircuit)
clTitre.adjustSizeToText()
# Update transparency and labels
# NB : do not use
setLayerTransparency, problem with it I don't know why
layers[2*g].rendererV2().symbol().setWidth(2)
layers[2*g].rendererV2().symbol().setAlpha(1)
layers[2*g+1].setCustomProperty("labeling/enabled", "True")
layers[2*g+1].rendererV2().symbol().setAlpha(1)
rectTrajet =
layers[2*g].extent() # linear
rectPtsArr =
layers[2*g+1].extent() # points
# extent definition
rectGlb = QgsRectangle
xMin =
min(rectTrajet.xMinimum(), rectPtsArr.xMinimum())
xMax =
max(rectTrajet.xMaximum(), rectPtsArr.xMaximum())
yMin =
min(rectTrajet.yMinimum(), rectPtsArr.yMinimum())
yMax =
max(rectTrajet.yMaximum(), rectPtsArr.yMaximum())
rectGlb = QgsRectangle(xMin,
yMin, xMax, yMax)
self.composerMap.setNewExtent(self.getNewExtent(rectGlb, 10))
self.composerMap.cache()
# Filename
printer.setOutputFileName(nomFichier)
# Launch printer
pdfPainter = QPainter(printer)
paperRectMM =
printer.pageRect(QtGui.QPrinter.Millimeter)
paperRectPixel =
printer.pageRect(QtGui.QPrinter.DevicePixel)
c.render(pdfPainter,
paperRectPixel, paperRectMM)
pdfPainter.end()
# Layers back to their initial
state
layers[2*g].rendererV2().symbol().setWidth(1)
layers[2*g].rendererV2().symbol().setAlpha(0.3)
layers[2*g+1].rendererV2().symbol().setAlpha(0.3)
layers[2*g+1].setCustomProperty("labeling/enabled", "False")
*
---
L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast.
http://www.avast.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/qgis-user/attachments/20150520/be804633/attachment.html>
More information about the Qgis-user
mailing list