使用 Python 实现随机中点位移法生成逼真的裂隙面

使用 Python 实现随机中点位移法生成逼真的裂隙面

  • 一、随机中点位移法简介
    • 1. 什么是随机中点位移法?
    • 2. 应用领域
  • 二、 Python 代码实现
    • 1. 导入必要的库
    • 2. 函数定义:随机中点位移法核心逻辑
    • 3. 设置随机数种子
    • 4. 初始化二维裂隙面
    • 5. 初始化网格的四个顶点
    • 6. 初始化步长
    • 7. 开始迭代生成裂隙面
    • 8. 钻石步( Diamond Step )
    • 9. 方形步( Square Step )
    • 10. 更新步长和粗糙度
    • 11. 返回最终结果
    • 12. 调用函数并可视化结果
  • 三、完整代码
  • 四、结果展示与分析
  • 五、扩展与应用
    • 1. 三维裂隙面生成
    • 2. 工程领域应用
    • 3. 性能优化

裂隙面在地质学、岩石力学、计算机图形学等领域有着广泛的应用。它们的随机性和分形特性使得模拟真实裂隙面成为一项重要的研究课题。本文将通过 Python ,结合经典的 随机中点位移法( Random Midpoint Displacement , RMD ),逐步创建一个二维的随机裂隙面,并详细解析每一步代码的实现过程。

先看下效果图:
在这里插入图片描述


一、随机中点位移法简介

1. 什么是随机中点位移法?

随机中点位移法是一种简单且高效的分形生成算法。它的基本思想是从一个大尺度开始,通过不断细化网格,并在每次细化时为中间点添加随机扰动,从而生成具有大尺度结构和小尺度细节的表面。

这一方法的特点是:

  • 高效性:算法复杂度较低,适合生成大规模的表面。
  • 随机性:通过随机扰动,模拟自然界中裂隙、地形等不规则表面的特性。
  • 分形特性:生成的结果具有分形维数,能很好地模拟自然界的粗糙表面。

2. 应用领域

  • 地质学:生成裂隙面,用于研究地下水流动、岩石的强度和稳定性。
  • 计算机图形学:生成自然地貌(如山脉、地形)或粗糙材质。
  • 工程应用:模拟裂隙网络,分析裂隙对渗透率的影响。

二、 Python 代码实现

让我们直接进入代码部分,并通过逐行详解,帮助你全面掌握随机中点位移法的实现。


1. 导入必要的库

import numpy as np
import matplotlib.pyplot as plt
  • numpy :用于处理多维数组和数学计算。我们将借助它来创建二维数组并进行随机数生成。
  • matplotlib.pyplot :用于可视化生成的裂隙面。这是 Python 中非常强大的绘图库。

2. 函数定义:随机中点位移法核心逻辑

def midpoint_displacement_2d(size, roughness, seed=None):"""使用随机中点位移法生成二维粗糙裂隙面。参数:- size: 裂隙面的网格尺寸(必须是2的幂次方+1,例如65, 129, 257等)。- roughness: 粗糙度参数,控制表面的起伏程度。- seed: 随机数种子,用于生成可重复的结果。返回值:- surface: 生成的二维裂隙面。"""

函数说明

  • size :二维数组的大小,必须为 2^n + 1 (如 129 , 257 等)。这种结构使网格能够在每次迭代中被整齐地细分。
  • roughness :粗糙度参数,控制生成裂隙面的起伏程度。值越大,表面越粗糙;值越小,表面越平滑。
  • seed :随机数种子,用于确保生成的结果是可重复的。指定种子后,每次运行都会生成相同的裂隙面。

3. 设置随机数种子

    if seed is not None:np.random.seed(seed)

解释

  • 如果用户提供了 seed 值,那么我们使用 np.random.seed(seed) 设置随机数生成器的种子。
  • 这样可以确保生成的随机数序列是固定的,从而保证结果的可重复性。

4. 初始化二维裂隙面

    surface = np.zeros((size, size))
  • np.zeros((size, size)) :创建一个大小为 (size, size) 的二维数组,初始值全为 0
  • 这个数组将表示裂隙面的高度值,每一个元素对应网格的一个节点。

5. 初始化网格的四个顶点

    surface[0, 0] = np.random.uniform(-1, 1)surface[0, -1] = np.random.uniform(-1, 1)surface[-1, 0] = np.random.uniform(-1, 1)surface[-1, -1] = np.random.uniform(-1, 1)

解释

  • 随机为二维数组的四个角点赋值,值范围为 [-1, 1]
  • 这四个顶点值将作为整个裂隙面生成的初始条件。

6. 初始化步长

    step_size = size - 1

解释

  • 设置初始步长为 size - 1
  • 步长是指当前迭代中,用于分割网格的大小。在每次迭代中,步长会减半,从而逐步细化网格。

7. 开始迭代生成裂隙面

    while step_size > 1:half_step = step_size // 2

解释

  • 使用 while 循环,直到步长小于或等于 1
  • 在每次循环中,计算半步长 half_step = step_size // 2 ,用于在网格的中点和边界点之间插值。

8. 钻石步( Diamond Step )

        for x in range(0, size - 1, step_size):for y in range(0, size - 1, step_size):avg = (surface[x, y]+ surface[x + step_size, y]+ surface[x, y + step_size]+ surface[x + step_size, y + step_size]) / 4surface[x + half_step, y + half_step] = avg + np.random.uniform(-1, 1) * roughness

说明

  • 目标:为每个网格单元的中心点生成一个新值。
  • avg :计算当前网格四个顶点的平均值。
  • np.random.uniform(-1, 1) * roughness :添加一个随机扰动,其幅度由 roughness 控制。
  • 更新后的值存储在网格的中心点位置 surface[x + half_step, y + half_step]

9. 方形步( Square Step )

        for x in range(0, size - 1, half_step):for y in range((x + half_step) % step_size, size - 1, step_size):avg = 0count = 0if x - half_step >= 0:avg += surface[x - half_step, y]count += 1if x + half_step < size:avg += surface[x + half_step, y]count += 1if y - half_step >= 0:avg += surface[x, y - half_step]count += 1if y + half_step < size:avg += surface[x, y + half_step]count += 1surface[x, y] = avg / count + np.random.uniform(-1, 1) * roughness

说明

  • 目标:为网格的每条边界点生成一个新值。
  • 通过计算边界点相邻的点的平均值,并添加随机扰动,为边界点赋值。

10. 更新步长和粗糙度

        step_size //= 2roughness /= 2

说明

  • 每次迭代后,步长减半,逐步细化网格。
  • 同时,降低随机扰动幅度(粗糙度),使得细节更平滑。

11. 返回最终结果

    return surface

说明

  • 返回生成的裂隙面(二维数组)。

12. 调用函数并可视化结果

size = 129
roughness = 1.0
seed = 42
surface = midpoint_displacement_2d(size, roughness, seed)plt.figure(figsize=(10, 8))
plt.imshow(surface, cmap='terrain', origin='upper')
plt.colorbar(label="Height")
plt.title("Random Midpoint Displacement Surface")
plt.xlabel("X-axis")
plt.ylabel("Y-axis")
plt.show()

说明

  • 参数:
    - size=129 :网格大小为 129 × 129
    - roughness=1.0 :初始粗糙度。
    - seed=42 :随机种子,用于生成可复现的结果。
  • 使用 matplotlib 绘制结果:
    - imshow :展示二维裂隙面。
    - cmap='terrain' :用地形色彩映射模拟裂隙表面。

三、完整代码

import numpy as np
import matplotlib.pyplot as pltdef midpoint_displacement_2d(size, roughness, seed=None):"""使用随机中点位移法生成二维粗糙裂隙面。参数:- size: 裂隙面的网格尺寸(必须是2的幂次方+1,例如65, 129, 257等)。- roughness: 粗糙度参数,控制表面的起伏程度。- seed: 随机数种子,用于生成可重复的结果。返回值:- surface: 生成的二维裂隙面。"""if seed is not None:np.random.seed(seed)# 初始化一个二维数组,并将四个顶点随机赋值surface = np.zeros((size, size))surface[0, 0] = np.random.uniform(-1, 1)surface[0, -1] = np.random.uniform(-1, 1)surface[-1, 0] = np.random.uniform(-1, 1)surface[-1, -1] = np.random.uniform(-1, 1)step_size = size - 1  # 初始步长while step_size > 1:half_step = step_size // 2# 钻石步:计算中点值for x in range(0, size - 1, step_size):for y in range(0, size - 1, step_size):avg = (surface[x, y]+ surface[x + step_size, y]+ surface[x, y + step_size]+ surface[x + step_size, y + step_size]) / 4surface[x + half_step, y + half_step] = avg + np.random.uniform(-1, 1) * roughness# 方形步:计算边点值for x in range(0, size - 1, half_step):for y in range((x + half_step) % step_size, size - 1, step_size):avg = 0count = 0if x - half_step >= 0:avg += surface[x - half_step, y]count += 1if x + half_step < size:avg += surface[x + half_step, y]count += 1if y - half_step >= 0:avg += surface[x, y - half_step]count += 1if y + half_step < size:avg += surface[x, y + half_step]count += 1surface[x, y] = avg / count + np.random.uniform(-1, 1) * roughness# 缩小步长,并降低粗糙度比例step_size //= 2roughness /= 2return surface# 参数设置
size = 129  # 网格尺寸(2^n + 1,例如65, 129, 257)
roughness = 1.0  # 粗糙度系数
seed = 42  # 随机种子(可选)# 生成裂隙面
surface = midpoint_displacement_2d(size, roughness, seed)# 绘制裂隙面
plt.figure(figsize=(10, 8))
plt.imshow(surface, cmap='terrain', origin='upper')
plt.colorbar(label="Height")
plt.title("Random Midpoint Displacement Surface")
plt.xlabel("X-axis")
plt.ylabel("Y-axis")
plt.show()

四、结果展示与分析

运行上述代码后,你将看到一个二维裂隙面,具有随机的高低起伏,形似真实的自然裂隙。裂隙面的粗糙度参数和网格分辨率可以根据需要调整,以满足不同的应用场景。

在这里插入图片描述


五、扩展与应用

1. 三维裂隙面生成

将此方法扩展到三维数组,可以生成更加复杂的三维裂隙网络。

2. 工程领域应用

模拟裂隙对流体流动的影响,分析裂隙面在接触力学中的作用。

3. 性能优化

使用并行计算或 GPU 加速,可以快速生成高分辨率的裂隙面。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/64883.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

活动预告 | Microsoft Power Platform 在线技术公开课:实现业务流程自动化

课程介绍 参加“Microsoft Power Platform 在线技术公开课&#xff1a;实现业务流程自动化”活动&#xff0c;了解如何更高效地开展业务。参加我们举办的本次免费培训活动&#xff0c;了解如何借助 Microsoft AI Builder 和 Power Automate 优化工作流。结合使用这些工具可以帮…

LLM(十二)| DeepSeek-V3 技术报告深度解读——开源模型的巅峰之作

近年来&#xff0c;大型语言模型&#xff08;LLMs&#xff09;的发展突飞猛进&#xff0c;逐步缩小了与通用人工智能&#xff08;AGI&#xff09;的差距。DeepSeek-AI 团队最新发布的 DeepSeek-V3&#xff0c;作为一款强大的混合专家模型&#xff08;Mixture-of-Experts, MoE&a…

el-pagination 为什么只能展示 10 条数据(element-ui@2.15.13)

好的&#xff0c;我来帮你分析前端为什么只能展示 10 条数据&#xff0c;以及如何解决这个问题。 问题分析&#xff1a; pageSize 的值&#xff1a; 你的 el-pagination 组件中&#xff0c;pageSize 的值被设置为 10&#xff1a;<el-pagination:current-page"current…

TCP网络编程(一)—— 服务器端模式和客户端模式

这篇文章将会编写基本的服务器网络程序&#xff0c;主要讲解服务器端和客户端代码的原理&#xff0c;至于网络名词很具体的概念&#xff0c;例如什么是TCP协议&#xff0c;不会过多涉及。 首先介绍一下TCP网络编程的两种模式&#xff1a;服务器端和客户端模式&#xff1a; 首先…

在K8S中,如何部署kubesphere?

在Kubernetes集群中&#xff0c;对于一些基础能力较弱的群体来说K8S控制面板操作存在一定的难度&#xff0c;此时kubesphere可以有效的解决这类难题。以下是部署kubesphere的操作步骤&#xff1a; 操作部署&#xff1a; 1. 部署nfs共享存储目录 yum -y install nfs-server e…

树莓派之旅-第一天 系统的烧录和设置

自言自语&#xff1a; 在此记录一下树莓派的玩法。以后有钱了买点来玩啊草 系统的安装烧录 系统下载 树莓派官网&#xff1a;https://www.raspberrypi.com/ 首页点击SoftWare进入OS下载页面 这里是安装工具&#xff1a;安装工具负责将系统镜像安装到sd卡中 点击下载符合自己…

商用车自动驾驶,迎来大规模量产「临界点」?

商用车自动驾驶&#xff0c;正迎来新的行业拐点。 今年初&#xff0c;交通部公开发布AEB系统运营车辆标配征求意见稿&#xff0c;首次将法规限制条件全面放开&#xff0c;有望推动商用车AEB全面标配&#xff0c;为开放场景的商用车智能驾驶市场加了一把火。 另外&#xff0c;…

人工智能及深度学习的一些题目

1、一个含有2个隐藏层的多层感知机&#xff08;MLP&#xff09;&#xff0c;神经元个数都为20&#xff0c;输入和输出节点分别由8和5个节点&#xff0c;这个网络有多少权重值&#xff1f; 答&#xff1a;在MLP中&#xff0c;权重是连接神经元的参数&#xff0c;每个连接都有一…

Solon 加入 GitCode:助力国产 Java 应用开发新飞跃

在当今数字化快速发展的时代&#xff0c;Java 应用开发框架不断演进&#xff0c;开发者们始终在寻找更快、更小、更简单的解决方案。近期&#xff0c;Solon 正式加入 GitCode&#xff0c;为广大 Java 开发者带来全新的开发体验&#xff0c;尤其是在国产应用开发进程中&#xff…

VScode 只能运行c,运行不了c++的解决问题

原文链接&#xff1a;Vscode只能运行c&#xff0c;运行不了c的解决方法 VScode 只能运行c&#xff0c;运行不了c&#xff0c;怎么回事呢&#xff0c;解决问题&#xff1a; 在tasks.json中加上“"-lstdc"”&#xff0c; 这样之后 要重启VScode&#xff0c;点击链接…

SpringCloud系列教程:微服务的未来 (五)枚举处理器、JSON处理器、分页插件实现

在现代 Java 开发中&#xff0c;我们常常需要处理各种通用的功能和需求&#xff0c;诸如枚举的处理、JSON 数据处理&#xff0c;以及分页查询等。这些功能虽然看似简单&#xff0c;但在实际开发中往往涉及到许多细节和优化。为了提高开发效率、减少重复代码的编写&#xff0c;我…

游戏引擎学习第69天

回顾碰撞响应时我们停留的位置 从昨天的讨论开始&#xff0c;我们正准备处理碰撞响应的复杂性。具体来说&#xff0c;我们讨论的是&#xff0c;当两个实体在屏幕上发生碰撞时&#xff0c;如何回应这种情况。碰撞本身并不复杂&#xff0c;但要处理其后的反应和规则则更具挑战性…

MAC环境安装(卸载)软件

MAC环境安装&#xff08;卸载&#xff09;软件 jdknode安装node&#xff0c;并实现不同版本的切换背景 卸载node从node官网下载pkg安装的node卸载用 homebrew 安装的node如果你感觉删的不够干净&#xff0c;可以再细分删除验证删除结果 jdk 1.下载jdk 先去官网下载自己需要的版…

本地LLM部署--llama.cpp

–图源GitHub项目主页 概述 llama.cpp是以一个开源项目&#xff08;GitHub主页&#xff1a;llamma.cpp&#xff09;&#xff0c;也是本地化部署LLM模型的方式之一&#xff0c;除了自身能够作为工具直接运行模型文件&#xff0c;也能够被其他软件或框架进行调用进行集成。 其…

uniapp中使用ruoyiPlus中的加密使用(crypto-js)

package.json中添加 "crypto-js": "^4.2.0", "jsencrypt": "^3.3.2",但是vue2中使用 import CryptoJS from cryptojs; 这一步就会报错 参照 参照这里&#xff1a;vue2使用CryptoJS实现信息加解密 根目录下的js文档中新增一个AESwork.…

go项目使用gentool生成model的gen.go问题

Gen Tool 是一个没有依赖关系的二进制文件&#xff0c;可以用来从数据库生成结构。 使用方法&#xff1a; go install gorm.io/gen/tools/gentoollatest在项目根目录,执行连接的数据库中指定某几张表结构生成数据库model层 gentool -dsn "root:123456tcp(localhost:330…

路由基本配置实验

路由器用于实现不同类型网络之间的互联。 路由器转发ip分组的基础是路由表。 路由表中的路由项分为直连路由项、静态路由项和动态路由项。 通过配置路由器接口的ip地址和子网掩码自动生成直连路由项。 通过手工配置创建静态路由项。 热备份路由器协议允许将由多个路由器组…

产品原型设计

&#x1f923;&#x1f923;目录&#x1f923;&#x1f923; 一、Axure原型设计&#xff08;Axure RP 9 &#xff09;1.1 软件下载安装1.2 产品原型展示1.3 产品原型下载1.4 视频课程推荐 二、磨刀原型设计2.1 软件下载安装2.2 产品原型展示2.3 产品原型下载2.4 视频课程推荐 什…

Android反编译

安卓反编译要用到三个工具&#xff0c; 工具1&#xff1a;apktool反编译出来资源文件和源码 工具2&#xff1a;d2j-dex2jar生成classes_dex2jar.jar文件工具3&#xff1a;jd-gui.exe 打开classes_dex2jar.jar文件查看java代码一、 反编译得到资源文件&#xff08;工具1&#xf…

计算机网络 (17)点对点协议PPP

一、PPP协议的基本概念 PPP协议最初设计是为两个对等节点之间的IP流量传输提供一种封装协议&#xff0c;它替代了原来非标准的第二层协议&#xff08;如SLIP&#xff09;。在TCP/IP协议集中&#xff0c;PPP是一种用来同步调制连接的数据链路层协议&#xff08;OSI模式中的第二层…