2

I have been using this tutorial to try to make a dot density map using python within QGIS, and my code shamelessly draws from the linked tutorial:

import random
src = "~/maps/SAMS_areas.shp"
tractLyr = QgsVectorLayer(src, "SAMS", "our")
popLyr =  QgsVectorLayer('Point?crs=epsg:3006', "counts" , "memory")
i = tractLyr.fieldNameIndex('counts')
features = tractLyr.getFeatures()
vpr = popLyr.dataProvider()
for feature in features:
  pop = feature.attributes()[i]
  density = pop
  found = 0
  dots = []
  g = feature.geometry()
  minx =  g.boundingBox().xMinimum()
  miny =  g.boundingBox().yMinimum()
  maxx =  g.boundingBox().xMaximum()
  maxy =  g.boundingBox().yMaximum()
  while found < density:
    x = random.uniform(minx,maxx)
    y = random.uniform(miny,maxy)
    pnt = QgsPoint(x,y)
    if g.contains(pnt):
      dots.append(pnt)
      found += 1
  geom = QgsGeometry.fromMultiPoint(dots)
  f = QgsFeature()
  f.setGeometry(geom)
  dotFeatures.append(f)
vpr.addFeatures(dotFeatures)
popLyr.updateExtents()
QgsMapLayerRegistry.instance().addMapLayers([popLyr,tractLyr])

I keep getting an error saying that none type object has no attribute bounding box, and I checked this other question where it is suggested that maybe the cause of such error is the format of the variables. I can confirm that my variables for counts are integers (I use a .csvt file and all). This error appears also if I try to use the dialogue box on the GUI. I wonder if this is because my shapefile has features that are represented by multiple polygons. I ended up with this setup because wanted to spread the dots only within the residential areas of each district/feature, what led to some districts being split in several polygons.

Kenji
  • 377
  • 5
  • 12

1 Answers1

2

I modified your script to:

import random
src = "/home/zeito/pyqgis_data/polygon8.shp"
tractLyr = QgsVectorLayer(src, "SAMS", "ogr")
popLyr =  QgsVectorLayer('Point?crs=epsg:32612', "counts" , "memory")
i = tractLyr.fieldNameIndex('counts')
features = tractLyr.getFeatures()
vpr = popLyr.dataProvider()
dotFeatures = []
for feature in features:
  pop = feature.attributes()[i]
  density = pop
  found = 0
  dots = []
  g = feature.geometry()
  minx =  g.boundingBox().xMinimum()
  miny =  g.boundingBox().yMinimum()
  maxx =  g.boundingBox().xMaximum()
  maxy =  g.boundingBox().yMaximum()
  while found < density:
    x = random.uniform(minx,maxx)
    y = random.uniform(miny,maxy)
    pnt = QgsPoint(x,y)
    if g.contains(pnt):
      dots.append(pnt)
      found += 1
  geom = QgsGeometry.fromMultiPoint(dots)
  f = QgsFeature()
  f.setGeometry(geom)
  dotFeatures.append(f)
vpr.addFeatures(dotFeatures)
popLyr.updateExtents()
QgsMapLayerRegistry.instance().addMapLayers([popLyr,tractLyr])

for adapting to my test shapefile (polygon8.shp) and its projection (where it was also created the field 'counts'). Basically, your errors are in:

.
.
.
src = "/home/zeito/pyqgis_data/polygon8.shp" #it needs an absolute path
tractLyr = QgsVectorLayer(src, "SAMS", "ogr") #driver is 'ogr', not 'our'
.
.
.
dotFeatures = []  #not defined
.
.
.

After running the script at the Python Console of QGIS I got:

enter image description here

It works for generating the memory layer.

xunilk
  • 29,891
  • 4
  • 41
  • 80
  • It did solve the script problem, and you may also add that I had forgotten to define the dotFeatures list as well. Now I get a script that runs, but I get the spinning ball of death, which is a different problem. – Kenji Mar 04 '16 at 10:08
  • Yes, it was also detected by me but I forgot to include it. Thanks for pointed out this omision. – xunilk Mar 04 '16 at 10:15