10

I am using QGIS to map a number of radio antennas (for mobile network). Once I have the layer of the sites (done), I would like to assign to each site a coverage area (envelope). I could achieve that using the "fixed distance buffer" function of fTools

However, I couldn't make the envelope have a Hexagon shape.

When I specify the number of segments: 1: I obtain a square 2: I obtain an octagon ...

How can I get a Hexagon?

1

2 Answers 2

14

As @MappaGnosis commented, you could write a script for this. Here's one called polygonbuffer which takes three arguments: The output file name, the radius of your buffer, and the number of corners of the polygons.

Open a Python console in QGIS, paste the script and press enter to define the function, then call using something like polygonbuffer("polygons.shp",50,6) to get hexagons with a radius of 50 map units:

import numpy as np
def polygonbuffer(outputFilename, bufferLength, polygonSides=6):
 layer = qgis.utils.iface.activeLayer()
 provider = layer.dataProvider()
 fields = provider.fields()
 writer = QgsVectorFileWriter(outputFilename, "CP1250", fields, QGis.WKBPolygon, provider.crs(), "ESRI Shapefile")
 inFeat = QgsFeature()
 outFeat = QgsFeature()
 inGeom = QgsGeometry()
 provider.select( provider.attributeIndexes() )
 while provider.nextFeature(inFeat):
  point = inFeat.geometry().asPoint()
  inGeom = inFeat.geometry()
  outFeat.setGeometry(QgsGeometry.fromPolygon(
   [[QgsPoint(point[0]+np.sin(angle)*bufferLength, point[1]+np.cos(angle)*bufferLength)
     for angle in np.linspace(0,2*np.pi,polygonSides, endpoint=False)]]))
  outFeat.setAttributeMap( inFeat.attributeMap() )
  writer.addFeature( outFeat )
 del writer
 newlayer = QgsVectorLayer(outputFilename, "Polygons", "ogr")
 QgsMapLayerRegistry.instance().addMapLayer(newlayer)
4

Here is @Jake's script adapted to PyQGIS 3 and some extras:

# Settings:
inputlayer = iface.activeLayer()
polygonSides = 6
bufferLength = 100 # in CRS units

# No changes needed below #
import numpy as np
if inputlayer.wkbType() != QgsWkbTypes.Point: # Only execute script if selected layer is of type point
    print("Error: Selected layer is not of type Point! - Script wont work with other geometry types or MultiPoints!")
else: # run script
    if polygonSides == 6: # set name of new layer to Hexagons if 6 sides were chosen
        layername = "Hexagons"
    else: # else set layername to generic "polygons"
        layername = "Polygons"
    newlayer = QgsVectorLayer("Polygon", layername, "memory") # Create the new outputlayer
    newlayer.setCrs(inputlayer.crs()) # Set new layers CRS to inputlayers crs
    with edit(newlayer): # edit new layer
        newlayer.dataProvider().addAttributes(inputlayer.fields()) # copy fields from input layer to new layer
        for feat in inputlayer.getFeatures(): # iterate over inputlayer
            point = feat.geometry().asPoint() # get geometry of inputpoint
            geom = [QgsPointXY(point[0]+np.sin(angle)*bufferLength, point[1]+np.cos(angle)*bufferLength)
             for angle in np.linspace(0,2*np.pi,polygonSides, endpoint=False)] # create the vertices of hexagon polygon
            outFeat = QgsFeature() # create new feature
            outFeat.setAttributes(feat.attributes()) # copy attributes of inputfeature to outputfeature
            outFeat.setGeometry(QgsGeometry.fromPolygonXY([geom])) # set new features geometry from vertices-pointlist
            newlayer.dataProvider().addFeature(outFeat) # add the feature
            newlayer.updateFeature(outFeat) # and update it
    QgsProject.instance().addMapLayer(newlayer) # add new layer to canvas

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.