8

I have a layer with many buildings as points on a map. One of the attributes of each building is "download_speed".

I want to put a square grid (100 x 100 meters) on top of the map. The squares should behave as follows:

  1. The square should only be visible if there is at least one building in the square.

  2. The square should be red if none of the buildings in the square have a "download_speed" above 10 (Mbit/s).

  3. The square should be gray if some of the buildings in the square have a "download_speed" above 10 (Mbit/s)

  4. The square should be black if all of the buildings in the square have a "download_speed" above 10 (Mbit/s)

I'm a complete newbie on QGIS (and GIS-software generally), but an experienced user of Python in data science.

The end result should look somewhat like the picture below:

enter image description here

5
  • Welcome to GIS SE! I have two questions for you: 1) are you able to create the grid on your own? I don't see any criteria for its creation (about the extent, for example). 2) Do you want to maintain the cells which don't store any information (i.e. where there's no building within them)? Or maybe you only want to not displaying them when rendering the colors?
    – mgri
    Commented Apr 1, 2017 at 12:41
  • I know how to create a vectorgrid with Qgis, but maybe the way to go is make the squares with PyQgis or some other way? I dont have to maintain the squares without buildings. Commented Apr 1, 2017 at 15:02
  • Please, see my answer and let me know if it fits your needs.
    – mgri
    Commented Apr 1, 2017 at 18:33
  • 1
    Thanks a lot @mgri. This was exactly what I was looking for :-) Commented Apr 1, 2017 at 19:01
  • oh, well! I'm glad it was helpful!
    – mgri
    Commented Apr 1, 2017 at 23:17

1 Answer 1

5

Some time ago I wrote a post for creating a vector grid of polygons:

How to generate a vector grid of polygons in QGIS using Python

which inspired me for proposing a solution.

My approach recurs to a custom script from the Processing Toolbox (please, refer to the above post if you don't know how to do it).

As input parameters, it requires:

  • the point vector layer;
  • the extent of the grid;
  • the horizontal spacing, i.e. the horizontal side length for the features in the grid;
  • the vertical spacing, i.e. the vertical side length for the features in the grid.

Assuming that the download speeds are stored in the "download_speed" field, you may use this code:

##Point_layer=vector point
##Grid_extent=extent
##Horizontal_spacing=number 10
##Vertical_spacing=number 10

from qgis.core import *
from qgis.PyQt.QtCore import QVariant
from PyQt4.QtGui import QColor

layer = processing.getObject(Point_layer)
crs = layer.crs().toWkt()

extent = Grid_extent.split(',')
(xmin, xmax, ymin, ymax) = (float(extent[0]), float(extent[1]), float(extent[2]), float(extent[3]))
hspacing = Horizontal_spacing
vspacing = Vertical_spacing

# Create the grid layer
vector_grid = QgsVectorLayer('Polygon?crs='+ crs, 'vector_grid' , 'memory')
prov = vector_grid.dataProvider()

all_features = {}
index = QgsSpatialIndex() # Spatial index
for ft in layer.getFeatures():
    index.insertFeature(ft)
    all_features[ft.id()] = ft

# Add ids and coordinates fields
fields = QgsFields()
fields.append(QgsField('ID', QVariant.Int, '', 10, 0))
fields.append(QgsField('XMIN', QVariant.Double, '', 24, 6))
fields.append(QgsField('XMAX', QVariant.Double, '', 24, 6))
fields.append(QgsField('YMIN', QVariant.Double, '', 24, 6))
fields.append(QgsField('YMAX', QVariant.Double, '', 24, 6))
fields.append(QgsField('Color', QVariant.String, '', 10))
prov.addAttributes(fields)

# Generate the features for the vector grid
id = 0
y = ymax
while y >= ymin:
    x = xmin
    while x <= xmax:
        point1 = QgsPoint(x, y)
        point2 = QgsPoint(x + hspacing, y)
        point3 = QgsPoint(x + hspacing, y - vspacing)
        point4 = QgsPoint(x, y - vspacing)
        vertices = [point1, point2, point3, point4] # Vertices of the polygon for the current id
        inAttr = [id, x, x + hspacing, y - vspacing, y]
        tmp_geom = QgsGeometry().fromPolygon([vertices])
        idsList = index.intersects(tmp_geom.boundingBox())
        if idsList:
            tmp_list = [all_features[id]['download_speed'] for id in idsList]
            if max(tmp_list) <= 10:
                inAttr.append('Red')
            elif min(tmp_list) > 10:
                inAttr.append('Black')
            else:
                inAttr.append('Grey')
            feat = QgsFeature()
            feat.setGeometry(tmp_geom) # Set geometry for the current id
            feat.setAttributes(inAttr) # Set attributes for the current id
            prov.addFeatures([feat])
            id += 1
        x = x + hspacing
    y = y - vspacing

# Update fields for the vector grid
vector_grid.updateFields()

# define the lookup: value -> (color, label)
speeds_colors = {'Red': ('#e31a1c', 'Red'), 'Black': ('#000000', 'Black'), 'Grey': ('#82807f', 'Grey'),}

# create a category for each item in speeds_colors
categories = []
for speed_color, (color, label) in speeds_colors.items():
    symbol = QgsSymbolV2.defaultSymbol(vector_grid.geometryType())
    symbol.setColor(QColor(color))
    category = QgsRendererCategoryV2(speed_color, symbol, label)
    categories.append(category)
print categories
# create the renderer and assign it to the layer
expression = 'Color' # field name
renderer = QgsCategorizedSymbolRendererV2(expression, categories) # categorized symbol renderer
vector_grid.setRendererV2(renderer) # assign the renderer to the layer
vector_grid.triggerRepaint()

# Add the layer to the Layers panel
QgsMapLayerRegistry.instance().addMapLayer(vector_grid)

As an experienced Python user, you should be able to easily understand the above code and adapt it to your specific needs (otherwise, let me know if you need any explanation). One more thing: I didn't deeply test the conditionals for the assignment of colors, but it should be an easy task for you.

Testing the code on these random points:

enter image description here

I obtain this result:

enter image description here

which seems to be what you are looking for.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.