Created
November 20, 2023 10:55
-
-
Save BenedictWilkins/5d43bf17dbe5ef452e219a61a5352447 to your computer and use it in GitHub Desktop.
Implementation of hatching for an axis aligned rectangle.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def line_intersection(line1, line2): | |
""" | |
Find the intersection of two lines. | |
Each line is defined by a pair of points (x1, y1) and (x2, y2). | |
""" | |
x1, y1, x2, y2 = line1 | |
x3, y3, x4, y4 = line2 | |
denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4) | |
if denominator == 0: | |
return None # Lines are parallel | |
px = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / denominator | |
py = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / denominator | |
return px, py | |
def clip_line_to_rect(x_start, y_start, x_end, y_end, xmin, xmax, ymin, ymax): | |
""" | |
Clip a line to the boundaries of a rectangle. | |
""" | |
rect_lines = [ | |
(xmin, ymin, xmin, ymax), # Left edge | |
(xmin, ymax, xmax, ymax), # Top edge | |
(xmax, ymax, xmax, ymin), # Right edge | |
(xmax, ymin, xmin, ymin) # Bottom edge | |
] | |
clipped_line = [] | |
for rect_line in rect_lines: | |
intersection = line_intersection((x_start, y_start, x_end, y_end), rect_line) | |
if intersection and xmin <= intersection[0] <= xmax and ymin <= intersection[1] <= ymax: | |
clipped_line.append(intersection) | |
if len(clipped_line) < 2: | |
return None # Line does not intersect the rectangle | |
return clipped_line[0], clipped_line[1] | |
def custom_hatch(ax, xmin, xmax, ymin, ymax, color='black', angle=45, density=20): | |
""" | |
Add custom hatched region to an axis. | |
Parameters: | |
ax (matplotlib.axes.Axes): The axis to add the hatched region. | |
xmin, xmax (float): The x-axis limits of the hatched region. | |
ymin, ymax (float): The y-axis limits of the hatched region. | |
color (str): Color of the hatch lines. | |
angle (float): Angle of the hatch lines in degrees. | |
density (int): Number of hatch lines. | |
""" | |
# Convert angle to radians | |
angle_rad = np.radians(angle) | |
# Define the width and height of the rectangle | |
width = xmax - xmin | |
height = ymax - ymin | |
# Calculate the maximum distance required for the lines to cover the rectangle | |
diag_len = np.sqrt(width**2 + height**2) | |
# Calculate the step size based on the density and diagonal length | |
step = diag_len / density | |
# Calculate the starting points for the lines | |
x_starts = np.linspace(xmin - diag_len, xmax + diag_len, density + 1) | |
y_starts = ymin + (x_starts - xmin) * np.tan(angle_rad) | |
# Calculate the ending points for the lines | |
x_ends = x_starts + height / np.sin(angle_rad) | |
y_ends = y_starts - width / np.cos(angle_rad) | |
# Draw each line, clipping it to the rectangle | |
for x_start, y_start, x_end, y_end in zip(x_starts, y_starts, x_ends, y_ends): | |
clipped_line = clip_line_to_rect(x_start, y_start, x_end, y_end, xmin, xmax, ymin, ymax) | |
if clipped_line: | |
line_xs, line_ys = zip(*clipped_line) | |
ax.add_line(plt.Line2D(line_xs, line_ys, linewidth=1, color=color, alpha=0.5, solid_capstyle='butt')) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment