如何使用Shapely沿由(x,y)点集组成的中心线绘制正方形/矩形?
First off, Shapely excels at geometric computations but doesn’t handle rendering on its own—so we’ll pair it with Matplotlib to visualize the final result. Here’s a step-by-step solution tailored to your needs:
Step 1: Import Required Libraries
Start by importing the tools we’ll need for geometry and plotting:
from shapely.geometry import LineString, Polygon import matplotlib.pyplot as plt
Step 2: Define Your Line Coordinates
Convert your list of (x,y) points into a Shapely LineString to represent the original black line:
# Replace this with your actual coordinate list coordinate_list = [(0, 0), (2, 1), (3, 3), (5, 4), (6, 2)] original_line = LineString(coordinate_list)
Step 3: Generate Squares Along the Line
We’ll cover two common scenarios you might want:
Scenario 1: Squares Using Each Line Segment as a Side
This creates squares where every segment of your line acts as one side of the square, oriented perpendicular to the segment’s direction:
def create_square_from_segment(segment): # Extract the two endpoints of the segment point_a = segment.coords[0] point_b = segment.coords[1] # Calculate the vector of the segment dx = point_b[0] - point_a[0] dy = point_b[1] - point_a[1] # Compute the other two vertices (rotated 90° counterclockwise) point_c = (point_b[0] - dy, point_b[1] + dx) point_d = (point_a[0] - dy, point_a[1] + dx) # Return the square as a Shapely Polygon return Polygon([point_a, point_b, point_c, point_d]) # Split the original line into individual segments line_segments = [LineString([coordinate_list[i], coordinate_list[i+1]]) for i in range(len(coordinate_list)-1)] # Generate squares for each segment segment_squares = [create_square_from_segment(seg) for seg in line_segments]
Scenario 2: Fixed-Size Squares Centered Along Each Segment
If you want squares of consistent size (regardless of segment length), use this approach. Squares will be centered on each segment and aligned with its direction:
def create_fixed_size_square(segment, side_length): point_a = segment.coords[0] point_b = segment.coords[1] dx = point_b[0] - point_a[0] dy = point_b[1] - point_a[1] segment_length = segment.length # Unit vectors along and perpendicular to the segment unit_along = (dx / segment_length, dy / segment_length) unit_perpendicular = (-dy / segment_length, dx / segment_length) # CCW direction # Midpoint of the segment mid_x = (point_a[0] + point_b[0]) / 2 mid_y = (point_a[1] + point_b[1]) / 2 half_side = side_length / 2 # Calculate all four corners of the square corner1 = (mid_x + half_side*unit_along[0] + half_side*unit_perpendicular[0], mid_y + half_side*unit_along[1] + half_side*unit_perpendicular[1]) corner2 = (mid_x + half_side*unit_along[0] - half_side*unit_perpendicular[0], mid_y + half_side*unit_along[1] - half_side*unit_perpendicular[1]) corner3 = (mid_x - half_side*unit_along[0] - half_side*unit_perpendicular[0], mid_y - half_side*unit_along[1] - half_side*unit_perpendicular[1]) corner4 = (mid_x - half_side*unit_along[0] + half_side*unit_perpendicular[0], mid_y - half_side*unit_along[1] + half_side*unit_perpendicular[1]) return Polygon([corner1, corner2, corner3, corner4]) # Generate fixed-size squares (adjust side_length as needed) fixed_size_squares = [create_fixed_size_square(seg, side_length=1) for seg in line_segments]
Step 4: Visualize the Result
Use Matplotlib to draw the original black line and red squares:
# Plot the original line x_line, y_line = original_line.xy plt.plot(x_line, y_line, color='black', linewidth=2, label='Original Line') # Plot squares (use segment_squares or fixed_size_squares based on your choice) for square in fixed_size_squares: x_sq, y_sq = square.exterior.xy plt.fill(x_sq, y_sq, color='red', alpha=0.5, label='Red Squares' if fixed_size_squares.index(square)==0 else "") plt.legend() plt.axis('equal') # Ensures squares don't look stretched plt.show()
Quick Tips:
- To rotate squares clockwise instead of counterclockwise, swap the perpendicular vector to
(dy / segment_length, -dx / segment_length). - Adjust the
alphavalue inplt.fill()to make squares more or less transparent. - Shapely’s
Polygonclass ensures your squares are valid geometric shapes, which you can use for further calculations if needed.
内容的提问来源于stack exchange,提问作者Kush

