0

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.

enter image description here

1
  • No actually. That problem talks about selecting uniform samples from existing grid points. In this question I need to add new N number of grid points uniformly.
    – TK7372
    Commented Jul 27, 2022 at 12:41

1 Answer 1

2

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')

enter image description here

5
  • 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).
    – TK7372
    Commented Jul 28, 2022 at 4:46
  • Seems buffer(-10) is causing it.
    – TK7372
    Commented Jul 28, 2022 at 4:54
  • Are your coordinate system in degrees? Reproject it to a crs in meters
    – Bera
    Commented 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.
    – TK7372
    Commented 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.
    – Bera
    Commented Jul 28, 2022 at 10:53

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