Search code examples
pythonmatplotlib

Coloring certain locations in a pattern in Python


I am generating a pattern with a square and coloring red and green at different locations. I would like to color the white spaces between different squares yellow and print the coordinates of these yellow squares. I have shown the output below including the full code. I would be grateful if somebody can help.

import matplotlib.pyplot as plt

# Define the grid size and the number of squares
grid_size = 4
square_size = 1  # Size of each square
gap = 0.1        # Gap between squares

# Create a new figure
plt.figure(figsize=(6, 6), dpi=80)

# Lists to store the coordinates of the rectangles
green_rectangles = []
red_rectangles = []

# Add yellow rectangles to fill the gaps before drawing the squares
for row in range(grid_size):
    for col in range(grid_size):
        # Calculate the coordinates for the bottom-left corner of the gap
        x = col * (square_size + gap)
        y = row * (square_size + gap)
        
        # Create a yellow rectangle for the gap
        if row < grid_size - 1:
            plt.Rectangle((x, y + square_size), square_size, gap, edgecolor='none', facecolor='yellow')
        if col < grid_size - 1:
            plt.Rectangle((x + square_size, y), gap, square_size + gap, edgecolor='none', facecolor='yellow')

# Loop through rows and columns to draw the squares
for row in range(grid_size):
    for col in range(grid_size):
        # Calculate the coordinates for the bottom-left corner of the square
        x = col * (square_size + gap)
        y = row * (square_size + gap)
        
        # Create a square using plt.Rectangle
        rectangle = plt.Rectangle((x, y), square_size, square_size, edgecolor='black', facecolor='black')
        plt.gca().add_patch(rectangle)

# Add green rectangles to fill the vertical gaps
for row in range(grid_size):
    for col in range(grid_size - 1):  # Exclude the last column
        x = (col + 1) * (square_size + gap) - gap
        y = row * (square_size + gap)
        green_rectangle = plt.Rectangle((x, y), gap, square_size, edgecolor='none', facecolor='green')
        plt.gca().add_patch(green_rectangle)
        green_rectangles.append((x, y))

# Add red rectangles to fill the horizontal gaps
for row in range(grid_size - 1):  # Exclude the last row
    for col in range(grid_size):
        x = col * (square_size + gap)
        y = (row + 1) * (square_size + gap) - gap
        red_rectangle = plt.Rectangle((x, y), square_size, gap, edgecolor='none', facecolor='red')
        plt.gca().add_patch(red_rectangle)
        red_rectangles.append((x, y))

# Print the coordinates of the red and green rectangles
print("Green rectangles:")
for coord in green_rectangles:
    print(coord)

print("\nRed rectangles:")
for coord in red_rectangles:
    print(coord)

# Set the aspect of the plot to be equal, so squares appear as squares
plt.gca().set_aspect('equal')

# Set limits to accommodate the gaps
plt.xlim(0, grid_size * (square_size + gap))
plt.ylim(0, grid_size * (square_size + gap))

# Remove axis values
plt.gca().set_xticks([])
plt.gca().set_yticks([])

# Add grid lines for better visualization
plt.grid(True, which='both', linestyle='--', linewidth=0.5)

# Show the plot
plt.show()

enter image description here


Solution

  • With , you can get the intersection of each "gridlines-like" combination :

    from shapely import box
    import matplotlib.pyplot as plt
    from shapely.plotting import plot_polygon
    
    bl = (0, 0)      # grid's bottom-left
    grid_size = 4    # grid's initial size
    square_size = 1  # sub-squares size 
    gap = 0.1        # distance between ss
    
    steps = [
        square_size + (square_size + gap) * i # round ?
        for i in range(grid_size // square_size - 1)
    ]
    extent = grid_size + gap * (grid_size - 1) # round ?
    square = box(bl[0], bl[1], bl[0] + extent, bl[1] + extent)
    
    g_rects = [box(x, 0, x + gap, extent) for x in steps]
    r_rects = [box(0, y, extent, y + gap) for y in steps]
    y_rects = [r.intersection(g) for r in r_rects for g in g_rects]
    
    fig, ax = plt.subplots(figsize=(6, 6), subplot_kw={"aspect": "equal"})
    
    styles = {"alpha": 1, "add_points": False}
    
    for lst, c in zip([g_rects, r_rects, y_rects], "gry"):
        for r in lst:
            plot_polygon(r, color=c, zorder=2, **styles, ax=ax)
    else:
        plot_polygon(square, color="k", **styles, ax=ax)
    

    NB: The coords can be obainted with map(lambda p: list(p.exterior.coords), y_rects)

    enter image description here