使用 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 加速,可以快速生成高分辨率的裂隙面。