I have a shapefile of a region. I want to put N number of grid points on that shapefile and create a new layer(shapefile) with all grid points as we do in QGIS. But instead I want to do it in Python. I am new to GIS so I don't have much idea about libraries.
1 Answer
From each polygons area, calculate a spacing, list coordinates in x and y direction, create points from them, check if they are inside and count them:
import numpy as np
import geopandas as gpd
from shapely.geometry import Point
df = gpd.read_file(r'/home/bera/Desktop/GIStest/5_ok_my.shp')
def grid(row, pointcount):
"""A function to create a point grid inside polygons"""
finished = 0
maxiter = 10 #You might need to raise this.
iterations = 0
while finished != 1 or iterations<maxiter: #Until there are n points inside the polygon or maxiter is reached
iterations+=1
xmin, ymin, xmax, ymax = row.geometry.bounds #Find polygon bounds
#Find suitable spacing. The -10 buffer is to prevent points at polygon border.
spacing=(((row.geometry.buffer(-10).area/pointcount)**0.5)*0.99)*(1.3-np.random.random()*0.6)
nspacingx=np.ceil((xmax-xmin)/spacing) #Number of points in x
nspacingy=np.ceil((ymax-ymin)/spacing) #and y
randomstart=[xmin-spacing*np.random.random(),ymin-spacing*np.random.random()] #A random start coordinate
xlist=[randomstart[0]+(x*spacing) for x in range(int(nspacingx)+1)] #Create a list of x coordinates
ylist=[randomstart[1]+(y*spacing) for y in range(int(nspacingy)+1)] #And y
#Using meshgrid, list all points combinations [Point(x1,y1), Point(x1,y2), ... and check if they are inside the polygon
points = [Point(coords) for coords in np.array(np.meshgrid(xlist, ylist)).T.reshape(-1, 2).tolist() if Point(coords).intersects(row.geometry)]
#points_inside = [p.intersects(row.geometry) for p in points]
if len(points)==pointcount:
#print(sum(points))
return points
finished=1
df['gridlist'] = df.apply(grid, args=(10,), axis=1) #Apply the function with 10 m spacing
df = df.explode('gridlist') #Explode so each point in gridlist become a row
df['geometry'] = df['gridlist']
df = df.drop('gridlist', axis=1)
df.to_file(r'/home/bera/Desktop/GIStest/5_ok_my_grid.shp')
-
Thanks @BERA. For some reason my spacing is being calculated as 0. at spacing=(((row.geometry.buffer(-10).area/pointcount)**0.5)*0.99)*(1.3-np.random.random()*0.6).– TK7372Commented Jul 28, 2022 at 4:46
-
-
Are your coordinate system in degrees? Reproject it to a crs in meters– BeraCommented Jul 28, 2022 at 7:38
-
May I know which crs are you using? Mine is EPSG:4326. I changed it EPSG:3857 it worked. But points in some polygons are still on border.– TK7372Commented Jul 28, 2022 at 10:37
-
3006. 3857 should work. Yes I also got points on the border but I didnt have time to fix it.– BeraCommented Jul 28, 2022 at 10:53