How to divide a rectangle in specific number of rows and columns?
If you work a lot with geometric objects you might consider using Shapely library. It has some useful functionality that we could use in order to construct a grid of smaller rectangles from the given rectangle.
First, constructing a Polygon
from your list of tuples:
from shapely.geometry import LineString, MultiPolygon, Polygon
from shapely.ops import split
rec = [(0, 0), (0, 330), (200, 330), (200, 0)]
nx, ny = 2, 4 # number of columns and rows
polygon = Polygon(rec)
This is your polygon:
Next, constructing a list of lines that we will use to split that polygon:
minx, miny, maxx, maxy = polygon.bounds
dx = (maxx - minx) / nx # width of a small part
dy = (maxy - miny) / ny # height of a small part
horizontal_splitters = [LineString([(minx, miny + i*dy), (maxx, miny + i*dy)]) for i in range(ny)]
vertical_splitters = [LineString([(minx + i*dx, miny), (minx + i*dx, maxy)]) for i in range(nx)]
splitters = horizontal_splitters + vertical_splitters
Applying each line to split the polygon:
result = polygon
for splitter in splitters:
result = MultiPolygon(split(result, splitter))
This is how your resulting collection of rectangles will look like:
If you want a list of coordinates back, you can get them like this:
parts = [list(part.exterior.coords) for part in result.geoms]
print(parts)
# [[(0.0, 0.0), (0.0, 82.5), (100.0, 82.5), (100.0, 0.0), (0.0, 0.0)],
# [(100.0, 82.5), (200.0, 82.5), (200.0, 0.0), (100.0, 0.0), (100.0, 82.5)],
# [(0.0, 82.5), (0.0, 165.0), (100.0, 165.0), (100.0, 82.5), (0.0, 82.5)],
# [(100.0, 165.0), (200.0, 165.0), (200.0, 82.5), (100.0, 82.5), (100.0, 165.0)],
# [(0.0, 165.0), (0.0, 247.5), (100.0, 247.5), (100.0, 165.0), (0.0, 165.0)],
# [(100.0, 247.5), (200.0, 247.5), (200.0, 165.0), (100.0, 165.0), (100.0, 247.5)],
# [(0.0, 247.5), (0.0, 330.0), (100.0, 330.0), (100.0, 247.5), (0.0, 247.5)],
# [(100.0, 330.0), (200.0, 330.0), (200.0, 247.5), (100.0, 247.5), (100.0, 330.0)]]
If you use the numpy
library, the problem is greatly simplified using the linspace
function which generates equally-spaced points.
import numpy as np
h = 330
n_rows = 4
w = 200
n_cols = 2
offset_x = w / n_cols
offset_y = h / n_rows
rectangles = []
for x in np.linspace(0, w, n_cols+1).tolist()[:-1]:
for y in np.linspace(0, h, n_rows+1).tolist()[:-1]:
x1 = int(round(x))
x2 = int(round(x + offset_x))
y1 = int(round(y))
y2 = int(round(y + offset_y))
rectangles.append([(x1, y1), (x1, y2), (x2, y2), (x2, y1)])
print(rectangles)