2

I'm currently trying to create a series of subplots within a larger plot, but outside of a nesting smaller plot, and am having trouble with it. This is the code I'm working from. I've also added a picture of what I'm trying to get at the bottom.

Learning QGIS=group
input_layer=vector
size=number 15
subplotsize=number 2
subplots=number 4
squares=output vector
minisquares=output vector
from qgis.core import *
from processing.tools.vector import VectorWriter
import random
# get the input layer and its fields
my_layer = processing.getObject(input_layer)
fields = my_layer.dataProvider().fields()
#get the input layer and its fields
my_layer2 = processing.getObject(input_layer)
fields2 = my_layer2.dataProvider().fields()
# create the output vector writer with the same fields
writer = VectorWriter(squares, None, fields, QGis.WKBPolygon, my_layer.crs())
writer2 = VectorWriter(minisquares, None, fields2, QGis. WKBPolygon, my_layer2.crs())
# create output features
feat = QgsFeature()
feat2 = QgsFeature()
sx=subplots
sps=subplotsize/2
for input_feature in my_layer.getFeatures():
    # copy attributes from the input point feature
    attributes = input_feature.attributes()
    feat.setAttributes(attributes)
    # create square polygons
    point = input_feature.geometry().asPoint()
    xmin = point.x() - size/2
    ymin = point.y() - size/2 
    for tx in range(0, sx):
        px=random.uniform(1, 10) - 5 + point.x()
        py=random.uniform(1, 10) - 5 + point.y()
        print px, py 
        square = QgsRectangle(px-sps, py-sps, px+sps, py+sps)
        feat2.setGeometry(QgsGeometry.fromRect(square))
        writer2.addFeature(feat2)
    square = QgsRectangle(xmin,ymin,xmin+size,ymin+size)
    feat.setGeometry(QgsGeometry.fromRect(square))
    writer.addFeature(feat)
del writer

I know this is probably a basic question, but I'm new to coding and all I've managed to do is move around the coordinates of the subplots.

enter image description here

1

I have a working example which uses the python console in QGIS.

Assuming the input plots are circles or regular sided squares.

It takes 5 variables:

  • innerlayer [Inner geometry (nesting smaller plot)]
  • outerlayer [Inner geometry (larger plot)]
  • points [number of seed points/outputs polygons to generate]
  • buf_dist [distance to buffer | radius/width of output polygons]
  • circle [True or False; whether to output circles]

To run, edit the variables and paste the code into the python console in QGIS. Tested for QGIS 2.8.2

import random
from PyQt4.QtCore import QVariant

layer=iface.activeLayer()
innerlayer=QgsVectorLayer('C://temp//InnerShp.shp', 'InnerShp', 'ogr')
outerlayer=QgsVectorLayer('C://temp//OuterShp.shp', 'OuterShp', 'ogr')
crs = layer.crs().toWkt()

points = 15 # set as you want
buf_dist = 100
circle = True

#aad layers to viewer
QgsMapLayerRegistry.instance().addMapLayer(outerlayer)
QgsMapLayerRegistry.instance().addMapLayer(innerlayer)

# Create the output layer
outLayer = QgsVectorLayer('Point?crs='+ crs, 'random_points' , 'memory')
prov = outLayer.dataProvider()
prov.addAttributes([QgsField('ID', QVariant.Int, '', 10, 0)])
outLayer.updateFields()


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



first = True
for feat in outerlayer.getFeatures():
    if first:
        outFeat = QgsFeature()
        outGeom = QgsGeometry(feat.geometry())
        first = False
    else:
        outGeom = outGeom.combine(feat.geometry())

outFeat.setGeometry(outGeom)

first = True
for infeat in innerlayer.getFeatures():
    if first:
        innerFeat = QgsFeature()
        innerGeom = QgsGeometry(infeat.geometry())
        first = False
    else:
        innerGeom = innerGeom.combine(infeat.geometry())

innerFeat.setGeometry(innerGeom)

id = 0
p = 1
while p <= points:
    x_coord = random.uniform(xmin, xmax)
    y_coord = random.uniform(ymin, ymax)
    pt = QgsPoint(x_coord, y_coord)
    tmp_geom = QgsGeometry.fromPoint(pt)
    if tmp_geom.intersects(outFeat.geometry()) and not tmp_geom.intersects(innerFeat.geometry()):
        outGeom = QgsFeature()
        outGeom.setGeometry(tmp_geom)
        outGeom.setAttributes([id])
        prov.addFeatures([outGeom])
        id += 1
        p += 1

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

layer = iface.activeLayer()

feats = [ feat for feat in layer.getFeatures() ]

epsg = layer.crs().postgisSrid()

uri = "Polygon?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

if not circle:
    mem_layer = QgsVectorLayer(uri,
                               'square_buffer',
                               'memory')
    prov = mem_layer.dataProvider()
    for i, feat in enumerate(feats):
        new_feat = QgsFeature()
        new_feat.setAttributes([i])
        tmp_feat = feat.geometry().buffer(buf_dist, -1).boundingBox().asWktPolygon()
        new_feat.setGeometry(QgsGeometry.fromWkt(tmp_feat))
        prov.addFeatures([new_feat])
    QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

if circle:
    mem_layer_circle = QgsVectorLayer(uri,
                               'round_buffer',
                               'memory')
    provcircle = mem_layer_circle.dataProvider()
    for i, feat in enumerate(feats):
        new_feat = QgsFeature()
        new_feat.setAttributes([i])
        tmp_feat = feat.geometry().buffer(buf_dist, 20).asPolygon()
        new_feat.setGeometry(QgsGeometry.fromPolygon(tmp_feat))
        provcircle.addFeatures([new_feat])    
    QgsMapLayerRegistry.instance().addMapLayer(mem_layer_circle)

Example Outputs:

enter image description here

Work adapted from these questions:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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