# 尝试实现柏林噪声
import numpy as np
import matplotlib.pyplot as plt
import random
# 存储二维坐标梯度向量的数组(x,y)
G2 = [(-0.56, -0.39), (-0.88, 0.04), (0.84, 0.35), (-0.17, -0.62), (0.53, -0.49), (0.07, -0.89), (0.11, -0.38), (0.37, 0.5), (-0.7, -0.43), (-0.75, 0.09), (0.24, 0.23), (-0.59, -0.76), (0.53, 0.57), (0.67, -0.23), (0.18, -0.24), (0.43, 0.94), (0.58, 0.46), (0.32, 0.37), (-0.32, 0.58), (0.32, 0.52), (0.48, 0.75), (-0.9, 0.37), (-0.16, -0.33), (0.04, -0.36), (0.04, 0.68), (-0.75, 0.56), (0.87, 0.5), (0.66, 0.14), (0.94, -0.83), (-0.83, 0.18), (-0.53, 0.86), (0.41, -0.24), (0.64, -0.65), (-0.55, -0.86), (0.36, 0.58), (0.02, 0.55), (-0.27, 0.42), (0.45, -0.52), (-0.53, -0.71), (-0.44, 0.91), (-0.16, 0.18), (-0.21, -0.07), (0.77, 0.53), (-0.06, -0.02), (-0.53, 0.29), (-0.29, 0.35), (-0.63, -0.22), (0.26, -0.43), (0.53, -0.99), (-0.76, 0.25), (0.1, -0.86), (-0.36, -0.71), (-0.62, 0.51), (0.23, -0.69), (0.43, -0.29), (0.06, -0.04), (0.25, 0.75), (-0.0, 0.81), (0.64, 0.82), (-0.96, 0.12), (0.36, 0.42), (0.74, 0.61), (0.24, 0.57), (-0.28, -0.08), (-0.93, 0.45), (-0.83, -0.96), (0.68, 0.43), (0.7, 0.87), (0.12, 0.19), (-0.73, 0.82), (0.51, -0.03), (0.61, -0.33), (-0.47, 0.19), (0.71, -0.61), (0.41, -0.76), (-0.85, -0.2), (-0.65, 0.69), (0.89, 0.17), (-0.26, 0.36), (-0.59, 0.09), (-0.69, -0.15), (0.62, 0.5), (0.79, 0.97), (0.24, 0.6), (0.53, 0.69), (0.48, -0.06), (-0.27, -0.72), (-0.4, 0.29), (-0.01, -0.05), (0.61, -0.92), (0.18, -0.36), (0.76, -0.15), (-0.13, 0.33), (0.17, 0.06), (0.54, -0.79), (-0.78, -0.96), (-0.02, 0.47), (-0.97, 0.38), (0.78, 0.91), (0.58, 0.74), (0.79, 0.93), (-0.94, 0.15), (0.05, 0.15), (0.24, -0.77), (0.5, 0.14), (0.67, -0.98), (0.43, 0.01), (0.67, 0.52), (0.01, 0.1), (0.73, 0.6), (0.48, -0.22), (-0.79, 0.34), (0.98, 0.23), (-0.87, -0.93), (0.41, -0.22), (-0.98, -0.07), (0.68, 0.27), (-0.64, -0.02), (0.43, 0.7), (0.36, 0.2), (0.63, 0.48), (-0.36, -0.09), (-0.6, -0.86), (0.11, -0.16), (0.57, 0.75), (0.77, 0.41), (-0.91, 0.76), (-0.01, 0.71), (-0.8, 0.74), (-0.38, 0.1), (0.12, 0.22), (-0.19, 0.88), (0.44, -0.82), (-0.01, -0.86), (0.13, 0.05), (-0.58, 0.48), (-0.56, 0.34), (0.28, -0.63), (-0.35, -0.44), (0.73, -0.4), (0.82, 0.74), (0.07, 0.93), (-0.52, 0.66), (0.86, -0.85), (-0.86, 0.9), (0.95, -0.88), (-0.09, 0.46), (0.12, -0.72), (0.24, 0.51), (0.87, 0.77), (-0.82, -0.44), (-0.17,
-0.98), (0.34, -0.21), (0.49, 0.15), (-0.85, -0.62), (0.5, -0.78), (-0.36, 0.73), (-0.42, -0.13), (-0.09, -0.65), (0.96, 0.72), (0.76, 0.12), (0.74, -0.65), (0.3, -0.01), (-0.41, 0.52), (-0.75, -0.66), (0.89, -0.39), (-0.82, 0.45), (0.98, 0.63), (0.3, -0.6), (0.83, -0.52), (-0.1, -0.78), (0.84, -0.39), (0.37, 0.38), (-0.53, -0.83), (-0.08, -0.98), (-0.95, 0.44), (-0.54, -0.4), (0.73, -0.13), (0.68, -0.44), (-0.36, -0.7), (-0.84, -0.34), (0.22, 0.54), (0.06, -0.31), (0.66, -0.71), (-0.43, 0.71), (-0.77, -0.99), (-0.54, 0.4), (-0.16, 0.97), (0.93, -0.37), (-0.0, -0.68), (0.29, 0.67), (-0.95, -0.81), (0.67, -0.53), (0.56, 0.16), (-0.26, -0.04), (-0.1, 0.5), (0.21, 0.71), (-0.76, 0.79), (0.06, 0.65), (-0.78, 0.29), (0.03, -0.68), (0.78, 0.76), (-0.75, 0.61), (-0.11, -0.58), (0.57, 0.06), (0.51, -0.2), (0.44, -0.9), (0.21, 0.22), (0.32, -0.52), (-0.38, 0.23), (0.57, 0.27), (-0.32, 0.49), (-0.09, -0.94), (0.13, 0.12), (-0.68, 0.16), (-0.11, -0.28), (-0.93, 0.62), (-0.52, 0.82), (-0.15, -0.97), (-0.83, 0.22), (0.18, 0.25), (0.06, -0.77), (0.53, 0.42), (0.73, -0.19), (-0.68, 0.38), (-0.45, -0.57), (0.75, -0.01), (-0.89, -0.1), (-0.97, 0.55), (0.24, 0.0), (-0.02, 0.65), (0.44, 0.87), (0.91, -0.51), (-0.33, -0.51), (-0.57, 0.05), (0.53, 0.68), (0.06, 0.83), (-0.46, 0.54), (-0.86, 0.46), (0.53, 0.6), (0.56, -0.76), (0.8, 0.95), (0.47, -0.24), (-0.85, -0.98), (-0.26, -0.89), (-1.0, -0.03), (0.04, 0.37), (-0.15, -0.7), (0.0, -0.69), (0.46, 0.57), (-0.47, -0.8), (0.31, 0.32), (-0.04, -0.1), (0.08, 0.82), (-0.48, 0.47), (0.64, -0.9)]*2
# 存储G2下表的数组P2
P2 = [149, 97, 137, 184, 58, 1, 220, 152, 41, 235, 246, 191, 36, 188, 190, 108, 222, 52, 39, 159, 104, 90, 197, 202, 5, 245, 93, 134, 157, 146, 38, 17, 124, 32, 203, 28, 106, 12, 233, 227, 77, 27, 155, 214, 114, 154, 242, 53, 139, 183, 16, 70, 130, 23, 229, 119, 101, 181, 228, 98, 230, 136, 107, 55, 225, 24, 199, 67, 34, 113, 182, 44, 215, 169, 66,
208, 247, 131, 22, 80, 100, 212, 232, 87, 221, 167, 194, 29, 14, 33, 196, 115, 19, 170, 171, 240, 150, 63, 43, 244, 111, 206, 83, 51, 85, 151, 205, 249, 9, 163, 250, 75, 164, 195, 84, 147, 237, 209, 138, 79, 176, 248, 4, 129, 82, 73, 180, 239, 30, 234, 35, 173, 236, 76, 74, 89, 125, 189, 123, 20, 117, 148, 179, 207, 48, 251, 241, 140, 26, 172,
18, 158, 92, 141, 94, 254, 71, 120, 62, 177, 186, 109, 56, 10, 226, 144, 61, 161, 72, 122, 187, 160, 49, 128, 7, 116, 68, 118, 112, 95, 238, 231, 252, 178, 166, 69, 88, 86,
255, 105, 192, 210, 0, 174, 201, 31, 185, 57, 253, 59, 243, 142, 65, 224, 217, 135, 219, 145, 25, 126, 211, 2, 102, 162, 133, 153, 213, 37, 110, 54, 96, 165, 200, 15, 3, 21, 156, 78, 64, 121, 204, 218, 198, 127, 40, 103, 91, 143, 47, 216, 175, 11, 13, 132, 60, 6, 168, 8, 223, 193, 81, 50, 42, 46, 99, 45]
def square(length, width) -> int:
'''定义单位正方形形成网格,x纵坐标为width,y横坐标为length
[A, ,B]
[ ]
[C, ,D]'''
# 存储单位正方形网格的二维数组
square_list = [[0]*length for y in range(width)]
for x in range(width):
for y in range(length):
# 定义梯度向量,存储到单位正方形中
G = G2[P2[x]+y]
square_list[x][y] = G
# 返回填充完毕的单位正方形网格
return square_list # ?我当时加这个干嘛 *2
def dot(width, length):
'''随机生成的输入点'''
return (round(random.uniform(0, width-1), 2), round(random.uniform(0, length-1), 2))
def lerp(a, b, x):
'''线性插值'''
return a + x * (b-a)
def fade(t):
'''fade函数计算u,v进行非线性差值,0<=t<=1'''
return 6 * t**5 - 15 * t**4 + 10 * t**3
def perlin(dots, squares, persistence, cover_num) -> list:
'''计算传入点的影响值,在地形中就是海拔,dot为一个[x,y]数组
persistence为振幅,cover_num为叠加次数
[Ga, ,Gb]
[ ]
[Gc, ,Gd]
'''
persistence = persistence
dots_influence_value = []
for map_num in range(1, cover_num+1):
# TODO 叠加噪声仍然等待解决
frequency = 2**map_num
amplitude = persistence**map_num
for num in range(len(dots)):
# 获取点的xy坐标
x = dots[num][0]
y = dots[num][1]
# 定位点所在的单位正方形
x0 = int(x//1)
y0 = int(y//1)
x1 = int(x0 + 1)
y1 = int(y0 + 1)
# 计算距离向量
distanceA = (x-x0, y-y0)
distanceB = (x-x0, y-y1)
distanceC = (x-x1, y-y0)
distanceD = (x-x1, y-y1)
# 获取四个顶点上的梯度向量
Ga = squares[x0][y0]
Gb = squares[x0][y1]
Gc = squares[x1][y0]
Gd = squares[x1][y1]
# 对各个顶点上的梯度向量和距离向量做数量积运算,就是AB*AC = |AB|*|AC|*cosΘ
# cosΘ = (AB * AC)/(|AB|*|AC|)
# |AB| = (x**2 + y**2)**0.5
#!草了,其实就是点乘运算x1x2+y1y2
#! 计算出四个顶点的影响值
valueA = Ga[0]*distanceA[0]+Ga[1]*distanceA[1]
valueB = Gb[0]*distanceB[0]+Gb[1]*distanceB[1]
valueC = Gc[0]*distanceC[0]+Gc[1]*distanceC[1]
valueD = Gd[0]*distanceD[0]+Gd[1]*distanceD[1]
#! 利用lerp和fade进行双线性插值计算,y为u,x为f)
u = fade(y-y0)
v = fade(x-x0)
# 双线性插值的两个点
#! 是对四个顶点的影响值进行插值
y1 = lerp(valueA, valueB, u)
y2 = lerp(valueC, valueD, u)
# 用v进行最终输入点影响值计算
dots_influence_value.append(lerp(y1, y2, v))
return dots_influence_value
# 设定地图和单位正方形的长和宽
length = 100
width = 50
# TODO持续度(0~1)
persistence = 0.5
squares = square(length, width)
#print('单位正方形:\n',squares)
# 创建点坐标的列表,循环里的是个数
dots = [dot(width, length) for x in range(50)]
'''
dots = []
for x in range(10):
for y in range(10):
dots.append([x,y])
'''
dots_position_x = []
dots_position_y = []
dots_num = len(dots)
# 分离两点坐标放到列表中形成映射
for x in range(dots_num):
dots_position_x.append(dots[x][0])
dots_position_y.append(dots[x][1])
# 整理两点坐标
dots_position_x.sort()
dots_position_y.sort()
dots_position = []
print('dots')
print(dots_position_x)
print(dots_position_y)
# 对两点坐标进行重组
for x in range(dots_num):
for y in range(dots_num):
dots_position.append([dots_position_x[x], dots_position_y[y]])
influence_value_list = perlin(dots_position, squares,persistence,cover_num=3)
#print(influence_value_list)
#将点的影响值转化为二维数组,其xy坐标与position_x,y形成映射
twoD_influence_value_list = []
counts = 0
for x in range(len(dots_position_x)):
temp = []
for y in range(len(dots_position_y)):
temp.append(influence_value_list[counts])
counts += 1
twoD_influence_value_list.append(temp)
print(twoD_influence_value_list)
print(len(twoD_influence_value_list))
#print(dots_position)
#print(influence_value_list)
#?实际出点的数量应该是上述长度**2
plt.contourf(dots_position_y, dots_position_x, twoD_influence_value_list, 10)
plt.show()
#?并没有什么问题,但是不连续性还是有点强,可能是没有噪声叠加的原因