python代码实现了多种风格地图(`wildcluster`、`street`、`market`、`random`)的生成以及可视化功能

时间:2024-10-30 08:40:35

代码实现了多种风格地图(wildclusterstreetmarketrandom)的生成以及可视化功能。地图生成过程包括初始化地图、设置起点和终点、添加特定元素(如种子点、道路、建筑、货架、障碍物等),并确保起点和终点之间可达,最后通过matplotlib库将生成的地图可视化。

import numpy as np
import random
import matplotlib.pyplot as plt
from collections import deque
import math
from scipy.spatial import distance
from shapely.geometry import LineString

# wildcluster 风格地图生成
# 检查从起点出发可达的区域,并将无法到达的区域设置为障碍物(使用广度优先搜索 BFS)
def mark_or_check_reachability(map_array, start, end, mark_unreachable=False):
    h, w = map_array.shape
    visited = np.zeros((h, w), dtype=bool)
    queue = deque([start])
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]

    while queue:
        x, y = queue.popleft()
        if (x, y) == end:
            if not mark_unreachable:
                return True
        if visited[y, x]:
            continue
        visited[y, x] = True
        for dx, dy in directions:
            nx, ny = x + dx, y + dy
            if 0 <= nx < w and 0 <= ny < h and not visited[ny, nx] and map_array[ny, nx] != 0:
                queue.append((nx, ny))

    if mark_unreachable:
        # 将无法到达的区域设置为障碍物
        for y in range(h):
            for x in range(w):
                if not visited[y, x] and map_array[y, x] == 255:
                    map_array[y, x] = 0
        # 检查终点是否可达
        if not visited[end[1], end[0]]:
            return None
        return map_array
    else:
        return False

def generate_wildcluster_map(w, h, density):
    density_config = {
   
        'sparse': (0.01, 0.4),
        'normal': (0.02, 0.5),
        'dense': (0.03, 0.6)
    }
    seed_ratio, p = density_config[density]
    n_seeds = int(w * h * seed_ratio)

    attempts = 0
    while attempts < 50:
        # 初始化地图,全为255(表示空地)
        basemap = np.full((h, w), 255, dtype=np.uint8)

        # 随机生成起点和终点
        end_point = (random.randint(0, w-1), random.randint(0, 2))
        start_point = (random.randint(0, w-1), random.randint(h-3, h-1))
        basemap[end_point[1], end_point[0]] = 200  # 终点蓝色
        basemap[start_point[1], start_point[0]] = 100  # 起点绿色

        # 生成种子点
        seeds = set()
        while len(seeds) < n_seeds:
            sx, sy = random.randint(0, w-1), random.randint(0, h-1)
            if (abs(sx - start_point[0]) > 5 or abs(sy - start_point[1]) > 5) and \
               (abs(sx - end_point[0]) > 5 or abs(sy - end_point[1]) > 5):
                seeds.add((sx, sy))

        # 扩展种子点
        for sx, sy in seeds:
            basemap[sy, sx] = 0
            expansion_radius = random.randint(1, 3)
            for dx in range(-expansion_radius, expansion_radius + 1):
                for dy in range(-expansion_radius, expansion_radius + 1):
                    nx, ny = sx + dx, sy + dy
                    if 0 <= nx < w and 0 <= ny < h and random.random() > p and basemap[ny, nx] == 255:
                        basemap[ny, nx] = 0

        # 将从起点出发无法到达的区域填成障碍物
        basemap = mark_or_check_reachability(basemap, start_point, end_point, mark_unreachable=True)

        # 如果地图有效则返回
        if basemap is not None:
            return basemap, start_point, end_point

        attempts += 1

    raise RuntimeError(