[Gfoss] Calcolare le dimensioni di stampa in scala a partire da una geometria con pyQgis

Salve a tutti,
vorrei poter realizzare tramite pyQgis un sistema di stampa delle mie
geometrie che mi esportino le piante in una scala prescelta
(possibilmente 1:20).

Per esempio:

se ho una geometria che è racchiusa in un box che misura 1 x 1 metri,
per stamparla in scala 1:20, dovrei caricare un foglio di 5 x 5 cm e
inserirci la geometria.

Come posso realizzare un box intorno ad una geometria, ricavarne
altezza e larghezza, ricavare i valori del del foglio in 1:20 e
inserirci il mio poligono?

Guardando sul cook book di pyQgis ci sono vari metodi, che però
prevedono di adattare la geometria alla dimensione del foglio e non
viceversa.

Grazie a tutti per qualsiasi suggerimento.

Ciao

Luca

On 15:36 Wed 20 Jun , Luca Mandolesi wrote:

Per esempio:

se ho una geometria che è racchiusa in un box che misura 1 x 1 metri,
per stamparla in scala 1:20, dovrei caricare un foglio di 5 x 5 cm e
inserirci la geometria.

Come posso realizzare un box intorno ad una geometria, ricavarne
altezza e larghezza, ricavare i valori del del foglio in 1:20 e
inserirci il mio poligono?

Un po' di tempo fa avevo inserito nel wiki uno script di shell che
calcola le dimensioni di una mappa in metri e in pixel, note le coordinate
dei vertici e la risoluzione di un raster (la dimensione del lato di un
pixel quadrato). Non so se può essere utile.
http://wiki.gfoss.it/index.php/Dimensione_di_una_mappa_dalle_coordinate

Ciao,
  Marco

Ciao Marco,
grazie per la dritta. Studianto un po' il plugin easyPrint sono
riuscito a stampare qualcosa in 1:20...

Ora però non capisco perchè, quando vado a caricare la singola
geometria tramite pyQgis e ho già caricato un layer di base tramite il
carica layer nativo di QGis connesso al medesimo DB, ottengo un too
many clients connection...nonostante il mio db abbia come opzione -1
nei limiti di connessione...

La funzione per aprire la connessione sta dentro ad una mia classe che
viene chiamata a sua volta da una interfaccia tramite un import...è
come se facendo l'import, la funzione faccia la connessione anche se
non chiamata, e non solamente nel momento in cui voglio caricare il
layer.

Se invece non ho alcun layer caricato da postgis dentro Qgis, posso
fare un ciclo for e caricare tutte le geometrie che voglio. Peccato
però che alla fine del processo, se provo a caricare un altro layer
ottengo lo stesso problema.

Non capisco lo sbaglio e come scrivere correttamente una funzione di
connessione via pyQgis, senza interferire con il carica layer nativo
di Qgis.

Ciao

Luca

2012/6/25 Marco Curreli <marcocurreli@tiscali.it>:

On 15:36 Wed 20 Jun , Luca Mandolesi wrote:

Per esempio:

se ho una geometria che è racchiusa in un box che misura 1 x 1 metri,
per stamparla in scala 1:20, dovrei caricare un foglio di 5 x 5 cm e
inserirci la geometria.

Come posso realizzare un box intorno ad una geometria, ricavarne
altezza e larghezza, ricavare i valori del del foglio in 1:20 e
inserirci il mio poligono?

Un po' di tempo fa avevo inserito nel wiki uno script di shell che
calcola le dimensioni di una mappa in metri e in pixel, note le coordinate
dei vertici e la risoluzione di un raster (la dimensione del lato di un
pixel quadrato). Non so se può essere utile.
http://wiki.gfoss.it/index.php/Dimensione_di_una_mappa_dalle_coordinate

Ciao,
Marco

_______________________________________________
Gfoss@lists.gfoss.it
http://lists.gfoss.it/cgi-bin/mailman/listinfo/gfoss
Questa e' una lista di discussione pubblica aperta a tutti.
Non inviate messaggi commerciali.
I messaggi di questa lista non rispecchiano necessariamente
le posizioni dell'Associazione GFOSS.it.
594 iscritti all'11.6.2012

Puoi condividere la parte di codice con cui fai la connessione?

giovanni

Inviato da dispositivo mobile

Il giorno 25/giu/2012 22.31, “Luca Mandolesi” <mandoluca@gmail.com> ha scritto:

Ciao Marco,
grazie per la dritta. Studianto un po’ il plugin easyPrint sono
riuscito a stampare qualcosa in 1:20…

Ora però non capisco perchè, quando vado a caricare la singola
geometria tramite pyQgis e ho già caricato un layer di base tramite il
carica layer nativo di QGis connesso al medesimo DB, ottengo un too
many clients connection…nonostante il mio db abbia come opzione -1
nei limiti di connessione…

La funzione per aprire la connessione sta dentro ad una mia classe che
viene chiamata a sua volta da una interfaccia tramite un import…è
come se facendo l’import, la funzione faccia la connessione anche se
non chiamata, e non solamente nel momento in cui voglio caricare il
layer.

Se invece non ho alcun layer caricato da postgis dentro Qgis, posso
fare un ciclo for e caricare tutte le geometrie che voglio. Peccato
però che alla fine del processo, se provo a caricare un altro layer
ottengo lo stesso problema.

Non capisco lo sbaglio e come scrivere correttamente una funzione di
connessione via pyQgis, senza interferire con il carica layer nativo
di Qgis.

Ciao

Luca

2012/6/25 Marco Curreli <marcocurreli@tiscali.it>:

On 15:36 Wed 20 Jun , Luca Mandolesi wrote:

Per esempio:

se ho una geometria che è racchiusa in un box che misura 1 x 1 metri,
per stamparla in scala 1:20, dovrei caricare un foglio di 5 x 5 cm e
inserirci la geometria.

Come posso realizzare un box intorno ad una geometria, ricavarne
altezza e larghezza, ricavare i valori del del foglio in 1:20 e
inserirci il mio poligono?

Un po’ di tempo fa avevo inserito nel wiki uno script di shell che
calcola le dimensioni di una mappa in metri e in pixel, note le coordinate
dei vertici e la risoluzione di un raster (la dimensione del lato di un
pixel quadrato). Non so se può essere utile.
http://wiki.gfoss.it/index.php/Dimensione_di_una_mappa_dalle_coordinate

Ciao,
Marco


Gfoss@lists.gfoss.it
http://lists.gfoss.it/cgi-bin/mailman/listinfo/gfoss
Questa e’ una lista di discussione pubblica aperta a tutti.
Non inviate messaggi commerciali.
I messaggi di questa lista non rispecchiano necessariamente
le posizioni dell’Associazione GFOSS.it.
594 iscritti all’11.6.2012


Gfoss@lists.gfoss.it
http://lists.gfoss.it/cgi-bin/mailman/listinfo/gfoss
Questa e’ una lista di discussione pubblica aperta a tutti.
Non inviate messaggi commerciali.
I messaggi di questa lista non rispecchiano necessariamente
le posizioni dell’Associazione GFOSS.it.
594 iscritti all’11.6.2012

Allora, scusate il paciugo del work in progress.

Diciamo che nel mio mainapp faccio

from pyarchinit_print_utility import Print_utility

...
...

#collego la funzione al bottone
       def on_pushButton_pdf_exp_pressed(self):
    PU = Print_utility(self.iface, self.DATA_LIST)
    PU.first_batch_try()

Poi ho il file incriminato:

"""
/***************************************************************************
testerDialog
                 A QGIS plugin
test print
               -------------------
    begin : 2012-06-20
    copyright : (C) 2012 by luca
    email : pyarchinit@gmail.com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
import os

from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import PyQt4.QtGui

from qgis.core import *
from qgis.gui import *

#from ui_tester import Ui_tester
# create the dialog for zoom to point
class Print_utility:
  if os.name == 'posix':
    HOME = os.environ['HOME']
  elif os.name == 'nt':
    HOME = os.environ['HOMEPATH']
  FILEPATH = os.path.dirname(__file__)
  LAYER_STYLE_PATH = ('%s%s%s%s') % (FILEPATH, os.sep, 'styles', os.sep)
  SRS = 3004
  
  layerUS = ""
  layerQuote = ""
  mapHeight = ""
  mapWidth = ""
  USLayerId = ""
  tav_num = ""
  us = ""
  uri = ""
  
  def __init__(self, iface, data):
    self.iface = iface
    self.data = data
    #self.area = area
    #self.us = us
    self.canvas = self.iface.mapCanvas()
    # set host name, port, database name, username and password

  """
  def on_pushButton_runTest_pressed(self):
    self.first_batch_try()
    """
  def first_batch_try(self):
    #f = open("/test_print_2.txt", "w")
    #f.write(str(self.sito))
    #f.close()
    for i in range(len(self.data)):
      test = self.charge_layer_postgis(self.data[i].sito,
self.data[i].area, self.data[i].us)
      self.us = self.data[i].us
      if test != 0:
        self.test_bbox()
        tav_num= i+1
        self.print_map(tav_num)
      else:
        pass
      """
      for i in self.data:
        self.charge_layer_postgis(i.sito,i.area,i.us)
        self.test_bbox()
        self.print_map(i)
      """
  def converter_1_20(self, n):
    n *= 100
    res = n / 20
    return res

  def test_bbox(self):
    self.layerUS.select( ) # recuperi tutte le geometrie senza attributi
    featPoly = QgsFeature() # crei una feature vuota per il poligono

    dizionario_id_contains = {}
    lista_quote =

    self.layerUS.nextFeature( featPoly ) # cicli sulle feature
recuperate, featPoly conterra la feature poligonale attuale
    bbox = featPoly.geometry().boundingBox() # recupera i punti nel bbox
del poligono

    self.height = self.converter_1_20(float(bbox.height())) * 0.5 #la
misura da cm e' portata in mm
    self.width = self.converter_1_20(float(bbox.width())) * 0.5 #la
misura da cm e' portata in mm
    
    #f = open("/test_paper_size_5.txt", "w")
    #f.write(str(self.width))
    #f.close()

  def getMapExtentFromMapCanvas(self, mapWidth, mapHeight, scale):
    #code from easyPrint plugin
    print "in methode: " + str(scale)

    xmin = self.canvas.extent().xMinimum()
    xmax = self.canvas.extent().xMaximum()
    ymin = self.canvas.extent().yMinimum()
    ymax = self.canvas.extent().yMaximum()
    xcenter = xmin + (xmax - xmin) / 2
    ycenter = ymin + (ymax - ymin) / 2

    mapWidth = mapWidth * scale / 1000 #misura in punti
    mapHeight = mapHeight * scale / 1000 #misura in punti
    
    f = open("/test_paper_size_3.txt", "w")
    f.write(str(mapWidth))
    f.close()

    minx = xcenter - mapWidth / 2
    miny = ycenter - mapHeight / 2
    maxx = xcenter + mapWidth / 2
    maxy = ycenter + mapHeight / 2

    return QgsRectangle(minx, miny, maxx, maxy)

  def print_map(self, tav_num):
    self.tav_num = tav_num

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

    #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 #angolo 0, o in alto a sx
    width, height = self.width*5, self.height*5 #da un valore alla
larghezza e altezza del foglio aumentato di 5 per dare un margine
    dpi = 100 #viene settata la risoluzione di stampa
    
    c.setPaperSize(width, height) #setta le dimensioni della pagina
    
    f = open("/test_paper_size_1.txt", "w")
    f.write(str(width))
    f.close()
    
    composerMap = QgsComposerMap(c, x, y, width, height) #crea un
mapComposer passandogli la classere Composition che a sua volta ha
incapsulato con la classe mapRenderer il canvas corrente
    
    rect = self.getMapExtentFromMapCanvas(c.paperWidth(),
c.paperHeight(), 20.0) #ricava la mappa in scala da inserire nel
compositore passando le dimensioni di pagina in mm e ricavandoli in
punti
    
    f = open("/test_paper_size_2.txt", "w")
    f.write(str(c.paperWidth()))
    f.close()
    
    composerMap.setNewExtent(rect) #setta l'estensione della mappa

    c.addItem(composerMap) #aggiunge la mappa alla composizione c

    #aggiunge la scale bar
    item = QgsComposerScaleBar(c)
    item.setStyle('Numeric') # optionally modify the style
    item.setComposerMap(composerMap)
    item.applyDefaultSize()
    c.addItem(item)

    #width = 1189
    #height = 841

    #c.setPaperSize(width, height)
    c.setPrintResolution(dpi) #setta la risoluzione di stampa

    #Output to a raster image
    #The following code fragment shows how to render a composition to a
raster image:
    
    f = open("/test_paper_size_4.txt", "w")
    f.write(str(dpi))
    f.close()
    
    dpmm = dpi / 25.4 #ricava il valore dei punti per mm
    width_point = float(dpmm * c.paperWidth())
    height_point = float(dpmm * c.paperHeight())

    # create output image and initialize it
    image = QImage(QSize(width_point, height_point), 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()) #viene
settata l'area sorgente con le misure in mm della carta
    targetArea = QRectF(0, 0, width_point, height_point) #viene settata
l'area in cui inserire la mappa con le misure in punti per mm
    c.render(imagePainter, targetArea, sourceArea)
    imagePainter.end()
    tav_name = ("/pyarchinit_print_tester_folder/Tavola_%d_us_%d.png") %
(self.tav_num+1, self.us)
    image.save(str(tav_name), "png")
      
    #QgsMapLayerRegistry.instance().removeMapLayer(layer_id)

    #Output to PDF
    #The following code fragment renders a composition to a PDF file:
    """
    printer = QPrinter()
    printer.setOutputFormat(QPrinter.PdfFormat)
    printer.setOutputFileName("/out.pdf")
    printer.setPaperSize(QSizeF(self.mapWidth, self.mapHeight),
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()
    """
    QgsMapLayerRegistry.instance().removeMapLayer(self.USLayerId)

  def open_connection(self):
    self.uri = QgsDataSourceURI()
    self.uri.setConnection('127.0.0.1','5432', 'mioDB', 'postgres', 'miapass')

  def charge_layer_postgis(self, sito, area, us):
    self.open_connection()
    
    srs = QgsCoordinateReferenceSystem(3004,
QgsCoordinateReferenceSystem.PostgisCrsId)

    gidstr = ("scavo_s = '%s' and area_s = '%s' and us_s = '%d'") %
(sito, area, us)
    
    #f = open("/test_print.txt", "w")
    #f.write(str(gidstr))
    #f.close()
    
    self.uri.setDataSource("public", "pyarchinit_us_view", "the_geom", gidstr)
    
    self.layerUS = QgsVectorLayer(self.uri.uri(), "US", "postgres")

    if self.layerUS.isValid() == True:
      self.layerUS.setCrs(srs)
      self.USLayerId = self.layerUS.getLayerID()
      #self.mapLayerRegistry.append(USLayerId)
      style_path = ('%s%s') % (self.LAYER_STYLE_PATH, 'us_caratterizzazioni.qml')
      self.layerUS.loadNamedStyle(style_path)
      self.iface.mapCanvas().setExtent(self.layerUS.extent())
      QgsMapLayerRegistry.instance().addMapLayer( self.layerUS, True)
    else:
      return 0
      #QMessageBox.warning(self, "Messaggio", "Geometria inesistente",
QMessageBox.Ok)

    """
    gidstr = "sito = 'test'"
    uri.setDataSource("public", "pyarchinit_punti_rif", "the_geom", gidstr)
    self.layerGriglia = QgsVectorLayer(uri.uri(), "Griglia a 50 cm", "postgres")

    if self.layerGriglia.isValid() == True:
      self.layerGriglia.setCrs(srs)
      layerGrigliaId = self.layerGriglia.getLayerID()
      #self.mapLayerRegistry.append(USLayerId)
      #style_path = ('%s%s') % (self.LAYER_STYLE_PATH, 'stile_griglia.qml')
      #self.layerGriglia.loadNamedStyle(style_path)
      #self.iface.mapCanvas().setExtent(self.layerUS.extent())
      QgsMapLayerRegistry.instance().addMapLayer( self.layerGriglia, True)
    else:
      print "layerGriglia US is not valid!!!"

    uri.setDataSource("public", "pyarchinit_uscaratterizzazioni_view",
"the_geom", gidstr)
    layerCar = QgsVectorLayer(uri.uri(), "Unita' Stratigrafiche", "postgres")

    if layerCar.isValid() == True:
      layerCar.setCrs(srs)
      CARLayerId = layerCar.getLayerID()
      self.mapLayerRegistry.append(CARLayerId)
      #style_path = ('%s%s') % (self.LAYER_STYLE_PATH, 'us_caratterizzazioni.qml')
      # self.layerUS.loadNamedStyle(style_path)
      QgsMapLayerRegistry.instance().addMapLayer(layerCar, True)
    else:
      print "Layer Caratterizzazioni is not valid!!!"

    gidstr = "gid = 2257 or gid = 2849 or gid = 2443 or gid = 2370 or
gid = 2297 or gid = 2852 or gid = 2299 or gid = 2225 or gid =
2226 or gid = 2448 or gid = 2862 or gid = 2863 or gid = 2717 or gid =
2718 or gid = 2427 or gid = 2429 or gid = 2245 or gid = 2652 or
gid = 2285 or gid = 2287 or gid = 2288 or gid = 2289 or gid = 2844 or
gid = 2290 or gid = 2475 or gid = 2845 or gid = 2328"

    uri.setDataSource("public", "pyarchinit_quote", "the_geom", gidstr)
    self.layerQuote = QgsVectorLayer(uri.uri(), "Quote", "postgres")

    if self.layerQuote.isValid() == True:
      self.layerQuote.setCrs(srs)
      QuoteLayerId = self.layerQuote.getLayerID()
      #self.mapLayerRegistry.append(QuoteLayerId)
      #style_path = ('%s%s') % (self.LAYER_STYLE_PATH, 'us_caratterizzazioni.qml')
      # self.layerUS.loadNamedStyle(style_path)
      QgsMapLayerRegistry.instance().addMapLayer(self.layerQuote, True)
    else:
      print "Layer Quote is not valid!!!"

    #Print section

    # create image
    """