4

I want to create a grid with a python script in PyQgis. I have the layer from which I want to take the extent.

it seems that there is different formula : The one from QGIS doc : https://docs.qgis.org/2.6/en/docs/user_manual/processing_algs/qgis/vector_creation_tools/creategrid.html

processing.runalg('qgis:creategrid', type, width, height, hspacing, vspacing, centerx, centery, crs, output)

The one I found on different forums with a string for extent : processing.runalg('qgis:creategrid', type, extent, hspacing, vspacing, crs, output)

I tried both and I always got :problem answer

I tried it from my script and from the console.

Here is my code if it can help :

#!/usr/bin/env Python
from glob import glob
from os import path
import numpy as np
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from qgis.core import *
from qgis.utils import iface
import processing


class Grid:
def __init__(self, iface,crs):
    """Initialize using the qgis.utils.iface
    object passed from the console.

    """
    self.iface = iface
    self.crs=crs

def new_grid(self,cellsizex,cellsizey,extent,centerx,centery,grid_out):
    processing.runalg('qgis:creategrid', type=1, extent=extent, hspacing=cellsizex, vspacing=cellsizey, crs=self.crs, output=grid_out)


class Extent:
def __init__(self, iface):
    """Initialize using the qgis.utils.iface
    object passed from the console.

    """
    self.iface = iface

def main(self):

    pabs= "K:\Histo_Europe_All" #path absolu
    path=pabs+"\0_Quadrillage\extent_eu.shp"
    name_l="extent_eu"

    layer=QgsVectorLayer(path,name_l, "ogr")

    extent = QgsVectorLayer( path, '', 'ogr' ).extent()

    cellsize = 1000
    centerx = (extent.xMinimum() + extent.xMaximum()) / 2
    centery = (extent.yMinimum() + extent.yMaximum()) / 20

    #first method
    width = (extent.xMaximum() - extent.xMinimum())
    height = (extent.yMaximum() - extent.yMinimum())/10

    #second method
    extent2 = str(extent.xMinimum())+ ',' + str(extent.xMaximum())+ ',' +str(ymin)+ ',' +str(extent.yMaximum())  

    cellsizex = 0,002775
    cellsizey = 0,002775
    ymin=extent.yMinimum()+ 0,8 * (extent.yMaximum() - extent.yMinimum())



    grid=pabs+"\1_Grids\Grid0.shp"
    g=Grid(self.iface,layer.crs().authid())
    g.new_grid(cellsizex,cellsizey,extent2,centerx,centery,grid)

Don't mind the missing spaces at the beginning of the classes, they do exist in my code.

I edit my question based on comments. I also gave up the extent as QGIS advise width and height. My code is now the following :

class Grid:
def __init__(self, iface,crs):
    """Initialize using the qgis.utils.iface
    object passed from the console.

    """
    self.iface = iface
    self.crs=crs

def new_grid(self,cellsizex,cellsizey,width,height,centerx,centery,grid_out):
    #processing.runalg("qgis:creategrid", cellsizex, cellsizey, width, height, centerx, centery, 1, layer.crs().authid(), grid_out)
    #processing.runalg('qgis:creategrid', width, height, cellsizex, cellsizey, centerx, centery,"EPSG:4326", grid_out)
    #processing.runalg('qgis:creategrid', type=1, extent=extent, hspacing=cellsizex, vspacing=cellsizey, crs=self.crs, output=grid_out)
    processing.runalg('qgis:creategrid', 1, width,height, cellsizex, cellsizey, self.crs, output=grid_out)

class Extent:
def __init__(self, iface):
    """Initialize using the qgis.utils.iface
    object passed from the console.

    """
    self.iface = iface

def main(self):

    pabs= "K:/Histo_Europe_All" #path absolu
    path=pabs+"/0_Quadrillage/extent_eu.shp"
    name_l="extent_eu"

    layer=QgsVectorLayer(path,name_l, "ogr")

    extent = QgsVectorLayer( path, '', 'ogr' ).extent()

    cellsize = 1000
    centerx = (extent.xMinimum() + extent.xMaximum()) / 2
    centery = (extent.yMinimum() + extent.yMaximum()) / 20
    width = (extent.xMaximum() - extent.xMinimum())
    height = (extent.yMaximum() - extent.yMinimum())/10
    print(width)
    print(height)

    cellsizex = 0.002775
    cellsizey = 0.002775
    ymin=extent.yMinimum()+ 0.8 * (extent.yMaximum() - extent.yMinimum())
    extent2 = str(extent.xMinimum())+ ',' + str(extent.xMaximum())+ ',' +str(ymin)+ ',' +str(extent.yMaximum())  

    grid=pabs+"/1_Grids/Grid0.shp"
    g=Grid(self.iface,layer.crs().authid())
    g.new_grid(cellsizex,cellsizey,width,height,centerx,centery,grid)

Now it answers : Error: Wrong parameter value: 40.967325 (width)

PolyGeo
  • 65,136
  • 29
  • 109
  • 338
J.Delannoy
  • 505
  • 2
  • 18
  • I think self.crs=self.layer.crs.authid() should instead be self.crs=self.layer.crs().authid() – Joseph Jun 27 '17 at 12:07
  • Is it ok in my edited post? – J.Delannoy Jun 27 '17 at 12:10
  • Any particular reason why you are using two different classes instead of putting those functions into one? – Joseph Jun 28 '17 at 09:51
  • It's just because I don't know how to call another method from the a method whcih is in the same class. So if I put everything together I don't know how to call new_grid() from main(). – J.Delannoy Jun 28 '17 at 10:34
  • 1
    Edited my post with a slightly more concise version. Seems to work fine for me so hopefully for you too :) – Joseph Jun 28 '17 at 10:49
  • This version if much more simple, thank you. But I still get : Error: Wrong parameter value: My python version perhaps ? I am using 2.18.9 – J.Delannoy Jun 28 '17 at 10:57
  • I tried with another computher which has the same version and it does not work neither. Could you give me your version so as I tried with it ? – J.Delannoy Jun 28 '17 at 11:00
  • And could you give me the kind of value you get for the extent because I'm surprised to see that mine are still really high. It does not seem correct – J.Delannoy Jun 28 '17 at 11:04
  • I am using QGIS 2.18.2 for Win7 64-bit. The processing plugin version is 2.12.99. It seems either a required parameter is missing or an empty value is being fed to the algorithm. You can do a simple check like printing each parameter and see if the values are correct. What CRS is your layer in? You have to be careful if your CRS uses meters or degrees as units. – Joseph Jun 28 '17 at 11:05
  • So, first problem my layer extent is false so I changed it by writting it directly for the moment. Second problem : i discovered that "crs" field is empty while it should be 4326, so in degrees. – J.Delannoy Jun 28 '17 at 11:12
  • Got it !!! Between yesterday and today I changed the name of a directory .... So it didn't find the shapefile of course ... – J.Delannoy Jun 28 '17 at 11:15
  • Nice one! Hopefully that will solve the issue =) – Joseph Jun 28 '17 at 11:25
  • 1
    Yes it works now !!! Thank you very much for your help. If ever someone else is interested : with this version of QGIS I can't use centerx and centery some I made calcuatation so as to the extent of my grid is different to the one of my layer. For example : ymin=ymin+(ymax-ymin)/2 – J.Delannoy Jun 28 '17 at 11:26
  • Most welcome, glad you got it working and thanks for including the tip :) – Joseph Jun 28 '17 at 11:30

1 Answers1

2

I think there's a couple of things you could try:

  • In your new_grid() function, replace the processing line with the following (if you want to assign variables such as type=1 etc. then you should use a dictionary as described in this post:

    processing.runalg('qgis:creategrid', 1, extent, cellsizex, cellsizey, self.crs, output=grid_out)
    
  • When defining a path for your output, either include the raw string (r) or use a single forward slash to escape:

    grid=pabs+"/1_Grids/Grid0.shp"
    

Edit:

Made some changes to your code which might help (unfortunately, I can't test it at the moment):

class Grid:
def __init__(self, iface):
    """Initialize using the qgis.utils.iface
    object passed from the console.
    """
    self.iface = iface

def new_grid(self,cellsizex,cellsizey,layer_extent,crs,grid_out):
    processing.runalg('qgis:creategrid', 1, layer_extent, cellsizex, cellsizey, crs, grid_out)

class Extent:
def __init__(self, iface):
    """Initialize using the qgis.utils.iface
    object passed from the console.
    """
    self.iface = iface

def main(self):
    pabs= "K:/Histo_Europe_All" #path absolu
    path=pabs+"/0_Quadrillage/extent_eu.shp"
    name_l="extent_eu"

    layer=QgsVectorLayer(path,name_l, "ogr")
    crs=layer.crs().authid()

    extent = layer.extent()
    xmin = extent.xMinimum()
    xmax = extent.xMaximum()
    ymin = extent.yMinimum()
    ymax = extent.yMaximum()

    cellsizex = 0.002775
    cellsizey = 0.002775

    grid=pabs+"/1_Grids/Grid0.shp"
    g=Grid(self.iface)
    g.new_grid(cellsizex,cellsizey,"%f,%f,%f,%f"% (xmin,xmax,ymin,ymax),crs,grid)

Edit 2:

Combined both classes into one, did a quick test and works fine for me so hopefully it will for you too.

class Grid:
    def __init__(self, iface):
        """Initialize using the qgis.utils.iface
        object passed from the console.
        """
        self.iface = iface

    def main(self):
        pabs = "K:/Histo_Europe_All" #path absolu
        path = pabs+"/0_Quadrillage/extent_eu.shp"
        grid = pabs+"/1_Grids/Grid0.shp"
        name_l = "extent_eu"

        layer = QgsVectorLayer(path,name_l, "ogr")
        crs = layer.crs().authid()
        extent = layer.extent()
        xmin = extent.xMinimum()
        xmax = extent.xMaximum()
        ymin = extent.yMinimum()
        ymax = extent.yMaximum()

        cellsizex = 0.002775
        cellsizey = 0.002775

        processing.runalg('qgis:creategrid', 1, "%f,%f,%f,%f"% (xmin,xmax,ymin,ymax), cellsizex, cellsizey, crs, grid)

Then use self.main() to call the function.

Joseph
  • 75,746
  • 7
  • 171
  • 282
  • I should have said that i also tried this way, sorry. I just tried the dictionary thing because I was wondering if the problem came from the fact that I included center parameters. So I retried with your proposition, I still get the same error. – J.Delannoy Jun 27 '17 at 11:36
  • @J.Delannoy - No problem! Did you also use decimal points instead of commas in your cellsizes? (i.e. 0,002775 to 0.002775) – Joseph Jun 27 '17 at 11:37
  • Yes I tried it too, it does not change the error message though. – J.Delannoy Jun 27 '17 at 11:42
  • As I put exactly the sames parameters it asks in its error message, that must be a problem of type, no ? My parameters are numbers except the extent, the crs and the output which are strings. – J.Delannoy Jun 27 '17 at 11:50
  • @J.Delannoy - Try using self.crs=crs.authid() – Joseph Jun 27 '17 at 11:53
  • I think that is what I do as I write : g=Grid(self.iface,layer.crs().authid()) But as I am perhaps wrong I tried to use it directely from the class Grid and it says me : AttributeError: 'builtin_function_or_method' object has no attribute 'authid' – J.Delannoy Jun 27 '17 at 12:00
  • I don't understand why I should replace the comma as self.iface is for the iface parameters. Do I missed something ? – J.Delannoy Jun 27 '17 at 12:08
  • @J.Delannoy - Edited my post and made some changes to the code you used. Perhaps you can test it? – Joseph Jun 27 '17 at 12:26
  • Thank you for your help. I tried it and got : Error: Wrong parameter value: With nothing at the end – J.Delannoy Jun 27 '17 at 12:45
  • And if I try with width and height I go back to my first problem : wrong number of parameters. So I guess it wants an extent even if the doc says to give width and height. Perhaps it is a change between the qgis version. I have 2.18.9 and the doc is for 2.6 – J.Delannoy Jun 27 '17 at 12:50
  • If I print the layer extent it gaves me really high numbers : 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 for xmin – J.Delannoy Jun 27 '17 at 12:53