matplotlib -> Python 导入Excel三维坐标数据 生成三维曲面地形图(体) 5-5、线条平滑曲面且可通过面观察柱体变化(五)

环境和包:

环境
python:python-3.12.0-amd64
包:
matplotlib 3.8.2
pandas     2.1.4
openpyxl   3.1.2
scipy      1.12.0

示例一代码: 

import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.ticker as ticker
import pandas as pd
from scipy.interpolate import griddata
from matplotlib.colors import ListedColormap


def map_rate(X: list, to_min: float, to_max: float) -> list:
    """区间映射
    Attribute:
    - X: 需要映射的列表
    - to_min: 要映射到的最小值
    - to_max: 要映射到的最大值
    """
    x_min = min(X)
    x_max = max(X)
    return list([int(round(to_min + ((to_max - to_min) / (x_max - x_min)) * (i - x_min), 1)) for i in X])


# rainbow色带
def rainbow(x):
    # rainbow色带
    data = [(255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0)]
    co = map_rate(x, 0, 175)
    return np.array(list(data[i] for i in co))


# 求中点
def midpoints(x):
    sl = ()
    for i in range(x.ndim):
        x = (x[sl + np.index_exp[:-1]] + x[sl + np.index_exp[1:]]) / 2.0
        sl += np.index_exp[:]
    return x


# 归一化函数
def normalize(data):
    mx = np.max(data) * np.ones(data.shape)
    mn = np.min(data) * np.ones(data.shape)
    return (data - mn) / (mx - mn)


# 定义应力与半径的关系
def Mises(r):
    return np.round(r * 2, 2)  # 计算von mises应力,并保留小数点后两位


# 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['kaiti']
plt.rcParams["axes.unicode_minus"] = False  # 解决图像中的"-"负号的乱码问题


# 创建自定义颜色调色板
def create_custom_colormap(name, colors):
    colors = np.array(colors)
    cmap = plt.get_cmap(name)
    cmap.set_over(colors[-1])
    cmap.set_under(colors[0])
    cmap.set_bad(colors[0])
    return cmap


# 定义一些颜色
# colors = ['red', 'blue', 'green', 'yellow', 'purple']
colors = ['red', 'orange', 'yellow', 'green', 'blue']
# 创建自定义颜色映射对象
my_colormap = create_custom_colormap('turbo_r', colors)
# 读取Excel文件
df = pd.read_excel('update-2.xlsx')
# df = pd.read_excel('煤仓模拟参数222.xlsx')
# print('数量:',df)
# 提取x、y、z数据
x = df['x'].values
y = df['y'].values
z = df['z'].values

# 定义圆柱的参数
R = 3800  # 圆柱的半径
H = 5000  # 圆柱的高
# 网格点数量
nr = 19j  # 沿半径分几层
ntheta = 25j  # >=4
nh = 9j
# 转换坐标系,并求中点
r, theta, z2 = np.mgrid[0:R:nr, 0:np.pi * 2:ntheta, 0:H:nh]
x2 = r * np.cos(theta)
y2 = r * np.sin(theta)

rc, thetac, zc = midpoints(r), midpoints(theta), midpoints(z2)

# 填充网格
a, b, c = rc.shape
rr = list(rc[:, 0, 0])
sphere = np.zeros((a, b, c)) == 0

# 设置颜色
hsv = np.zeros(sphere.shape + (3,))
r_color1 = rainbow(rr)
r_color2 = normalize(r_color1)
rgb_r = r_color2[:, 0]
rgb_g = r_color2[:, 1]
rgb_b = r_color2[:, 2]
for i in range(a):
    hsv[i, ..., 0] = rgb_r[i] * np.ones((b, c))
    hsv[i, ..., 1] = rgb_g[i] * np.ones((b, c))
    hsv[i, ..., 2] = rgb_b[i] * np.ones((b, c))

# 求应力
mises_r = np.linspace(0, R, a)
mises = Mises(mises_r)
# 画图
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')


# 使用griddata函数进行插值,这里使用最近邻插值法,你也可以选择其他的插值方法
# 插值后的数据用于绘制平滑曲面地形图
grid_x, grid_y = np.mgrid[min(x):max(x):1000j, min(y):max(y):1000j]
grid_z = griddata((x, y), z, (grid_x, grid_y), method='linear')
# 使用平滑曲面插值后的数据绘制地形图
# 绘制地形图(camp:coolwarm,viridis,plasma,inferno,magma,cividis,rainbow)
cmap = ListedColormap(['blue', 'green', 'yellow', 'orange', 'Red'])
ax.contourf(grid_x, grid_y, grid_z, levels=300, cmap=my_colormap)




ax.voxels(x2, y2, z2, sphere,
          facecolors=hsv,
          edgecolors=np.clip(2 * hsv - 0.5, 0, 1),
          linewidth=0.5)


ax.grid(True)


# 设置x轴的刻度间隔
ax.set_xticks(np.arange(-4000, 4000, 1000))  # 从-7500到7500,步长为2500

# 设置y轴的刻度间隔
ax.set_yticks(np.arange(-4000, 4000, 1000))  # 从-7500到7500,步长为2500

# 设置z轴的刻度间隔
ax.set_zticks(np.arange(0, 8000, 1000))  # 从10000到31000,步长为2500
plt.show()

示例二代码: 

import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.ticker as ticker
import pandas as pd
from scipy.interpolate import griddata
from matplotlib.colors import ListedColormap


def map_rate(X: list, to_min: float, to_max: float) -> list:
    """区间映射
    Attribute:
    - X: 需要映射的列表
    - to_min: 要映射到的最小值
    - to_max: 要映射到的最大值
    """
    x_min = min(X)
    x_max = max(X)
    return list([int(round(to_min + ((to_max - to_min) / (x_max - x_min)) * (i - x_min), 1)) for i in X])


# rainbow色带
def rainbow(x):
    # rainbow色带
    data = [(255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0),
            (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0)]
    co = map_rate(x, 0, 175)
    return np.array(list(data[i] for i in co))


# 求中点
def midpoints(x):
    sl = ()
    for i in range(x.ndim):
        x = (x[sl + np.index_exp[:-1]] + x[sl + np.index_exp[1:]]) / 2.0
        sl += np.index_exp[:]
    return x


# 归一化函数
def normalize(data):
    mx = np.max(data) * np.ones(data.shape)
    mn = np.min(data) * np.ones(data.shape)
    return (data - mn) / (mx - mn)


# 定义应力与半径的关系
def Mises(r):
    return np.round(r * 2, 2)  # 计算von mises应力,并保留小数点后两位


# 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['kaiti']
plt.rcParams["axes.unicode_minus"] = False  # 解决图像中的"-"负号的乱码问题


# 创建自定义颜色调色板
def create_custom_colormap(name, colors):
    colors = np.array(colors)
    cmap = plt.get_cmap(name)
    cmap.set_over(colors[-1])
    cmap.set_under(colors[0])
    cmap.set_bad(colors[0])
    return cmap


# 定义一些颜色
# colors = ['red', 'blue', 'green', 'yellow', 'purple']
colors = ['red', 'orange', 'yellow', 'green', 'blue']
# 创建自定义颜色映射对象
my_colormap = create_custom_colormap('turbo_r', colors)
# 读取Excel文件
df = pd.read_excel('update-2.xlsx')
# df = pd.read_excel('煤仓模拟参数222.xlsx')
# print('数量:',df)
# 提取x、y、z数据
x = df['x'].values
y = df['y'].values
z = df['z'].values

# 定义圆柱的参数
R = 3800  # 圆柱的半径
H = 5000  # 圆柱的高
# 网格点数量
nr = 19j  # 沿半径分几层
ntheta = 25j  # >=4
nh = 9j
# 转换坐标系,并求中点
r, theta, z2 = np.mgrid[0:R:nr, 0:np.pi * 2:ntheta, 0:H:nh]
x2 = r * np.cos(theta)
y2 = r * np.sin(theta)

rc, thetac, zc = midpoints(r), midpoints(theta), midpoints(z2)

# 填充网格
a, b, c = rc.shape
rr = list(rc[:, 0, 0])
sphere = np.zeros((a, b, c)) == 0

# 设置颜色
hsv = np.zeros(sphere.shape + (3,))
r_color1 = rainbow(rr)
r_color2 = normalize(r_color1)
rgb_r = r_color2[:, 0]
rgb_g = r_color2[:, 1]
rgb_b = r_color2[:, 2]
for i in range(a):
    hsv[i, ..., 0] = rgb_r[i] * np.ones((b, c))
    hsv[i, ..., 1] = rgb_g[i] * np.ones((b, c))
    hsv[i, ..., 2] = rgb_b[i] * np.ones((b, c))

# 求应力
mises_r = np.linspace(0, R, a)
mises = Mises(mises_r)
# 画图
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# 使用griddata函数进行插值,这里使用最近邻插值法,你也可以选择其他的插值方法
# 插值后的数据用于绘制平滑曲面地形图
grid_x, grid_y = np.mgrid[min(x):max(x):1000j, min(y):max(y):1000j]
grid_z = griddata((x, y), z, (grid_x, grid_y), method='linear')
# 使用平滑曲面插值后的数据绘制地形图
# 绘制地形图(camp:coolwarm,viridis,plasma,inferno,magma,cividis,rainbow)
cmap = ListedColormap(['blue', 'green', 'yellow', 'orange', 'Red'])
ax.contourf(grid_x, grid_y, grid_z, levels=300, cmap=my_colormap)

ax.voxels(x2, y2, z2, sphere,
          facecolors=hsv,
          edgecolors=np.clip(2 * hsv - 0.5, 0, 1),
          linewidth=0.5)

# 实心圆柱上面在套一个白色泉
# 先根据极坐标方式生成数据
u2 = np.linspace(0, 2 * np.pi, 50)  # 把圆分按角度为50等分
h2 = np.linspace(0, 10000 - 200, 20)  # 把高度9000均分为20份
x2 = np.outer(np.sin(u2), np.ones(len(h2)) * 3800)  # x值重复20次
y2 = np.outer(np.cos(u2), np.ones(len(h2)) * 3800)  # y值重复20次
z2 = np.outer(np.ones(len(u2)), h2)  # x,y 对应的高度

# Plot the surface
ax.plot_surface(x2, y2, z2, cmap=plt.get_cmap('autumn'), alpha=0.15)
ax.grid(True)

# 设置x轴的刻度间隔
ax.set_xticks(np.arange(-4000, 4000, 1000))  # 从-7500到7500,步长为2500

# 设置y轴的刻度间隔
ax.set_yticks(np.arange(-4000, 4000, 1000))  # 从-7500到7500,步长为2500

# 设置z轴的刻度间隔
ax.set_zticks(np.arange(0, 8000, 1000))  # 从10000到31000,步长为2500
plt.show()
效果图 

资源下载(分享-->资源分享):

我的网盘>编程案例>python>资源文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fyhs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值