{"id":"49yK3AvGT7","url":"https://pastebin.ca/49yK3AvGT7","raw_url":"https://raw.anybin.ca/49yK3AvGT7","visibility":"public","access":"public","created_at":1789453805839,"expires_at":1790058605839,"fetch_limit":null,"fetches_used":0,"reads_remaining":null,"size_bytes":4586,"syntax_hint":"python","title":null,"filename":null,"change_note":null,"cipher":null,"cipher_meta":null,"parent_id":null,"root_id":"49yK3AvGT7","version":1,"owner_id":null,"recipient_id":null,"body":"# -*- coding: utf-8 -*-\n\"\"\"从一条山脊到一整片大陆.ipynb\n\nAutomatically generated by Colab.\n\nOriginal file is located at\n    https://colab.research.google.com/drive/1Huc6gsj8JWXMhVpzBvpS9RDTmPrmqp5f\n\"\"\"\n\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom matplotlib.colors import LinearSegmentedColormap\nfrom mpl_toolkits.mplot3d import Axes3D\n\n\ndef diamond_square(iterations=8,\n                   initial_displacement=1.0,\n                   decay=0.55,\n                   seed=7):\n    \"\"\"\n    用钻石—正方形算法生成二维山地。\n\n    iterations:\n        迭代次数。最终网格大小为 (2^iterations + 1) × (2^iterations + 1)\n\n    initial_displacement:\n        第一次迭代时的随机偏移幅度\n\n    decay:\n        每轮迭代后，随机偏移缩小的比例\n\n    seed:\n        随机种子。相同种子会生成相同的山脉\n    \"\"\"\n\n    rng = np.random.default_rng(seed)\n\n    size = 2 ** iterations + 1\n    terrain = np.zeros((size, size))\n\n    # 给平面的四个角设置初始高度\n    terrain[0, 0] = rng.uniform(-0.2, 0.2)\n    terrain[0, -1] = rng.uniform(-0.2, 0.2)\n    terrain[-1, 0] = rng.uniform(-0.2, 0.2)\n    terrain[-1, -1] = rng.uniform(-0.2, 0.2)\n\n    step = size - 1\n    displacement = initial_displacement\n\n    while step > 1:\n        half = step // 2\n\n        # -------------------------\n        # 第一步：正方形步骤\n        # -------------------------\n        # 找到每个正方形的中心点，\n        # 取四个角高度的平均值，再加入随机偏移\n        for y in range(half, size - 1, step):\n            for x in range(half, size - 1, step):\n                top_left = terrain[y - half, x - half]\n                top_right = terrain[y - half, x + half]\n                bottom_left = terrain[y + half, x - half]\n                bottom_right = terrain[y + half, x + half]\n\n                average = (\n                    top_left\n                    + top_right\n                    + bottom_left\n                    + bottom_right\n                ) / 4\n\n                terrain[y, x] = average + rng.uniform(\n                    -displacement,\n                    displacement\n                )\n\n        # -------------------------\n        # 第二步：钻石步骤\n        # -------------------------\n        # 找到每个菱形的中心点，\n        # 取周围已有点的平均值，再加入随机偏移\n        for y in range(0, size, half):\n            start_x = half if (y // half) % 2 == 0 else 0\n\n            for x in range(start_x, size, step):\n                neighbors = []\n\n                if y - half >= 0:\n                    neighbors.append(terrain[y - half, x])\n                if y + half < size:\n                    neighbors.append(terrain[y + half, x])\n                if x - half >= 0:\n                    neighbors.append(terrain[y, x - half])\n                if x + half < size:\n                    neighbors.append(terrain[y, x + half])\n\n                average = np.mean(neighbors)\n\n                terrain[y, x] = average + rng.uniform(\n                    -displacement,\n                    displacement\n                )\n\n        # 网格尺度缩小\n        step //= 2\n\n        # 随着尺度变小，随机偏移也逐渐减小\n        displacement *= decay\n\n    # 把高度归一化到 0～1\n    terrain -= terrain.min()\n    terrain /= terrain.max()\n\n    return terrain\n\n\n# 生成二维山地\nterrain = diamond_square(\n    iterations=8,\n    initial_displacement=1.0,\n    decay=0.55,\n    seed=7\n)\n\n\n# 自定义地形颜色：\n# 深蓝—浅蓝—绿色—棕色—白色\nterrain_colors = LinearSegmentedColormap.from_list(\n    \"terrain_colors\",\n    [\n        (0.00, \"#264653\"),\n        (0.18, \"#4f8a8b\"),\n        (0.32, \"#84a98c\"),\n        (0.55, \"#52734d\"),\n        (0.72, \"#8b6f47\"),\n        (0.88, \"#b8a88a\"),\n        (1.00, \"#f5f5f5\")\n    ]\n)\n\n\n# 建立平面坐标\nsize = terrain.shape[0]\nx = np.linspace(0, 1, size)\ny = np.linspace(0, 1, size)\nX, Y = np.meshgrid(x, y)\n\n\n# 为了让山峰更加明显，对高度稍作非线性处理\nZ = terrain ** 1.35\n\n\n# 绘制三维山脉\nfig = plt.figure(figsize=(14, 9))\nax = fig.add_subplot(111, projection=\"3d\")\n\nsurface = ax.plot_surface(\n    X,\n    Y,\n    Z,\n    cmap=terrain_colors,\n    linewidth=0,\n    antialiased=True,\n    rcount=180,\n    ccount=180\n)\n\nax.view_init(elev=42, azim=-125)\n\n# 调整纵向比例，使山脉更有立体感\nax.set_box_aspect((1, 1, 0.38))\n\nax.set_axis_off()\nax.set_title(\n    \"Diamond-Square Fractal Mountain\",\n    fontsize=18,\n    pad=10\n)\n\nplt.tight_layout()\nplt.show()\n\n"}