finish task_gen

This commit is contained in:
2025-09-05 11:10:42 +08:00
parent da022d4f83
commit 4e51158215
17 changed files with 82 additions and 50 deletions

View File

@@ -0,0 +1,186 @@
import math
import random
import matplotlib.patches as patches
import matplotlib.pyplot as plt
import numpy as np
from shapely.geometry import Point, Polygon
def rotate_point(px, py, cx, cy, angle):
radians = math.radians(angle)
cos_a = math.cos(radians)
sin_a = math.sin(radians)
# cos_a = math.cos(angle)
# sin_a = math.sin(angle)
temp_x = px - cx
temp_y = py - cy
rotated_x = temp_x * cos_a - temp_y * sin_a
rotated_y = temp_x * sin_a + temp_y * cos_a
return rotated_x + cx, rotated_y + cy
def get_rotated_corners(x, y, width, height, angle):
cx = x
cy = y
corners = [
(x - width / 2, y - height / 2),
(x + width / 2, y - height / 2),
(x - width / 2, y + height / 2),
(x + width / 2, y + height / 2)
]
return [rotate_point(px, py, cx, cy, angle) for px, py in corners]
def is_within_bounds(corners, plane_width, plane_height):
min_x = min(px for px, _ in corners)
max_x = max(px for px, _ in corners)
min_y = min(py for _, py in corners)
max_y = max(py for _, py in corners)
return min_x >= -plane_width / 2 and max_x <= plane_width / 2 and min_y >= -plane_height / 2 and max_y <= plane_height / 2
def is_collision(new_corners, placed_objects):
for _, existing_corners in placed_objects:
if polygons_intersect(new_corners, existing_corners):
return True
return False
def polygons_intersect(p1, p2):
for polygon in [p1, p2]:
for i1 in range(len(polygon)):
i2 = (i1 + 1) % len(polygon)
projection_axis = (-(polygon[i2][1] - polygon[i1][1]), polygon[i2][0] - polygon[i1][0])
min_p1, max_p1 = project_polygon(projection_axis, p1)
min_p2, max_p2 = project_polygon(projection_axis, p2)
if max_p1 < min_p2 or max_p2 < min_p1:
return False
return True
def project_polygon(axis, polygon):
min_proj = max_proj = (polygon[0][0] * axis[0] + polygon[0][1] * axis[1])
for (x, y) in polygon[1:]:
projection = x * axis[0] + y * axis[1]
min_proj = min(min_proj, projection)
max_proj = max(max_proj, projection)
return min_proj, max_proj
def generate_object_sizes(num_objects, size_options):
sizes = []
max_size = max(size_options, key=lambda s: s[0] * s[1])
max_count = 0
for _ in range(num_objects):
if max_count < 3:
size = random.choice(size_options)
if size == max_size:
max_count += 1
else:
size = random.choice([s for s in size_options if s != max_size])
sizes.append(size)
sizes.sort(key=lambda s: s[0] * s[1], reverse=True)
return sizes
def calculate_distance(corners1, corners2):
center1 = np.mean(corners1, axis=0)
center2 = np.mean(corners2, axis=0)
return np.linalg.norm(center1 - center2)
def place_objects(num_objects, plane_width, plane_height, obj_sizes):
placed_objects = []
attempts = 0
max_attempts = num_objects * 100
while len(placed_objects) < num_objects and attempts < max_attempts:
width, height = obj_sizes[len(placed_objects)]
valid_position = False
best_position = None
max_distance = -1
for _ in range(200):
x = random.uniform(-plane_width / 2 + width / 2, plane_width / 2 - width / 2)
y = random.uniform(-plane_height / 2 + height / 2, plane_height / 2 - height / 2)
angle = random.choice(range(0, 360, 15))
new_corners = get_rotated_corners(x, y, width, height, angle)
if is_within_bounds(new_corners, plane_width, plane_height) and not is_collision(new_corners,
placed_objects):
if not placed_objects:
best_position = (x, y, width, height, angle)
valid_position = True
break
min_distance = min(calculate_distance(new_corners, obj[1]) for obj in placed_objects)
if min_distance > max_distance:
max_distance = min_distance
best_position = (x, y, width, height, angle)
valid_position = True
if valid_position:
placed_objects.append((best_position, get_rotated_corners(*best_position)))
attempts = 0
else:
attempts += 1
return [obj[0] for obj in placed_objects]
color_list = [
'blue', 'green', 'orange', 'purple', 'red', 'yellow', 'pink',
'cyan', 'magenta', 'lime', 'teal', 'lavender', 'brown', 'beige',
'maroon', 'navy', 'olive', 'coral', 'turquoise', 'silver', 'gold'
]
def visualize_objects(objects, plane_width, plane_height, filename):
fig, ax = plt.subplots()
ax.set_xlim(-plane_width / 2, plane_width / 2)
ax.set_ylim(-plane_height / 2, plane_height / 2)
ax.set_aspect('equal')
for i, (x, y, width, height, angle) in enumerate(objects):
cx = x
cy = y
color = color_list[i % len(color_list)] # 从颜色列表中选择颜色
rect = patches.Rectangle((x - width / 2, y - height / 2), width, height, edgecolor='r', facecolor=color,
alpha=0.5)
t = plt.matplotlib.transforms.Affine2D().rotate_deg_around(cx, cy, angle) + ax.transData
rect.set_transform(t)
ax.add_patch(rect)
plt.grid(True)
plt.savefig(filename, bbox_inches='tight')
# plt.show()
def create_grid(plane_width, plane_height, grid_size):
grid_points = []
for x in np.arange(-plane_width / 2, plane_width / 2, grid_size):
for y in np.arange(-plane_height / 2, plane_height / 2, grid_size):
grid_points.append((x, y))
return grid_points
def filter_occupied_grids(grid_points, placed_objects):
available_points = grid_points.copy()
for obj in placed_objects:
obj_poly = Polygon(obj[1]) # 获取已放置物体的多边形
available_points = [
point for point in available_points
if not obj_poly.contains(Point(point))
]
return available_points