I use this code to ~randomly place a grid of sample plots for forest inventory: <!-- language: lang-py --> import numpy as np from itertools import product polylayer = iface.activeLayer() #Highlight polygon layer in layer tree npoints = 8 pointlayer = QgsVectorLayer('Point?crs=epsg:3006', 'point' , 'memory') #Change prov = pointlayer.dataProvider() for poly in polylayer.getFeatures(): geom = poly.geometry() bbox = poly.geometry().boundingBox() xmin, xmax, ymin, ymax = bbox.xMinimum(),bbox.xMaximum(),bbox.yMinimum(),bbox.yMaximum() success = 0 while success == 0: featlist = [] spacing = ((geom.area()/npoints)**0.5)*np.random.uniform(0.7,1.3) #Adjust random range nspacesx = np.ceil((xmax-xmin)/spacing) nspacesy = np.ceil((ymax-ymin)/spacing) randomstart = [xmin-spacing*np.random.random(),ymin-spacing*np.random.random()] xlist=[randomstart[0]+(x*spacing) for x in range(int(nspacesx)+1)] ylist=[randomstart[1]+(y*spacing) for y in range(int(nspacesy)+1)] for x,y in product(xlist,ylist): feat = QgsFeature() feat.setGeometry(QgsPoint(x,y)) featlist.append(feat) points_inside = [1 if f.geometry().intersects(geom.buffer(-5,10)) else 0 for f in featlist] #I use negative buffer to prevent points to end up near polygon edge. You need to adjust -5 m or remove the buffering. #print(sum(points_inside)) if sum(points_inside)==npoints: featlist = [p for p,i in zip(featlist, points_inside) if i==1] prov.addFeatures(featlist) success = 1 QgsProject.instance().addMapLayer(pointlayer) [![enter image description here][1]][1] [1]: https://i.sstatic.net/lG7lK.png