实验三:空间数据可视化
实验目的
掌握空间数据可视化的原理和方法。
实验内容
在3D空间中绘制以下图形:
1、螺旋曲线(半径为5,每旋转一周z坐标增加π)
2、二元正态分布曲面
3、球面(半径为5)
实验过程
螺旋线
from pyecharts import options as opts
from pyecharts.charts import Line3D
import math
def create_spiral(accuracy):
'''
生成螺旋曲线的数据点,返回规格化的数据
accuracy:螺旋曲线上的点的数量,数量越多,点之间的距离越小
'''
data = []
for t in range(0, accuracy):
theta = t / accuracy * 10 * 2 * math.pi # 角度范围从0到2π
x = 5 * math.cos(theta) # x坐标
y = 5 * math.sin(theta) # y坐标
z = t / accuracy * 10 * math.pi # z坐标,每旋转一周z坐标增加π
data.append([x, y, z])
return data
if __name__ == "__main__":
data = create_spiral(100000)
# 绘图
line3d = (
Line3D()
.add(
"3D螺旋线",
data,
xaxis3d_opts=opts.Axis3DOpts(type_="value"),
yaxis3d_opts=opts.Axis3DOpts(type_="value"),
zaxis3d_opts=opts.Axis3DOpts(type_="value"),
grid3d_opts=opts.Grid3DOpts(width=100, height=100, depth=100),
)
.set_global_opts(
title_opts=opts.TitleOpts(title="3D螺旋曲线图"), # 标题
visualmap_opts=opts.VisualMapOpts(
dimension=2,
max_=3.15 * 10, # z坐标最大值
min_=0, # z坐标最小值
range_color=["green","blue","yellow","orange", "red"],
)
)
)
# 保存为HTML文件
line3d.render("exp2/mission-1/spiral.html")
二维正态分布
from pyecharts import options as opts
from pyecharts.charts import Surface3D
import numpy as np
from scipy.stats import multivariate_normal
def generate_normal_distribution_data(mean, cov, x_range, y_range, num_points):
'''
生成二维正态分布的数据,返回包含三个数组的元组 (X, Y, Z)
mean:均值
cov:方差
x_range:x的取值范围
y_range:y的取值范围
num_points:数据点的数量
'''
x = np.linspace(x_range[0], x_range[1], num_points)
y = np.linspace(y_range[0], y_range[1], num_points)
X, Y = np.meshgrid(x, y)
pos = np.dstack((X, Y)) # 表示三维空间中的每个点
rv = multivariate_normal(mean, cov)
Z = rv.pdf(pos) # # 计算每个点的概率密度
return X, Y, Z
if __name__ == "__main__":
# 数据
mean = [0, 0]
cov = [[1, 0.5], [0.5, 1]]
x_range = (-5, 5)
y_range = (-5, 5)
num_points = 400
X, Y, Z = generate_normal_distribution_data(mean, cov, x_range, y_range, num_points)
# 创建Surface3D图表
surface = (
Surface3D()
.add(
"二维正态分布",
[list(x) for x in zip(X.ravel(), Y.ravel(), Z.ravel())],
shading="color",
grid3d_opts=opts.Grid3DOpts(width=100, height=100),
)
.set_global_opts(
title_opts=opts.TitleOpts("二维正态分布曲面图"),
visualmap_opts=opts.VisualMapOpts(
dimension=2,
max_=Z.max(),
min_=Z.min(),
range_color=["green", "blue", "yellow", "orange", "red"],
)
)
.set_series_opts(
label_opts=opts.LabelOpts(is_show=False),
linestyle_opts=opts.LineStyleOpts(width=0.5),
)
)
# 保存为HTML文件
surface.render("exp2/mission-2/main.html")
球
import math
import numpy as np
from pyecharts import options as opts
from pyecharts.charts import Scatter3D
def create_data(radius, points_num):
'''
生成球面数据点,返回一个二维列表,包含x, y, z三个列表
radius:半径
points_num:数据点的数量
'''
phi = np.linspace(0, 2 * np.pi, points_num) #
theta = np.linspace(0, np.pi, points_num)
phi, theta = np.meshgrid(phi, theta)
x = radius * np.sin(theta) * np.cos(phi)
y = radius * np.sin(theta) * np.sin(phi)
z = radius * np.cos(theta)
return [x, y, z]
if __name__ == "__main__":
radius = 5
points_num = 100
x, y, z = create_data(radius, points_num)
# 创建3D散点图
scatter3d = (
Scatter3D()
.add(
"球",
[list(z) for z in zip(x.reshape(-1), y.reshape(-1), z.reshape(-1))],
grid3d_opts=opts.Grid3DOpts(width=100, height=100, depth=100),
)
.set_global_opts(
title_opts=opts.TitleOpts("球"),
visualmap_opts=opts.VisualMapOpts(
max_=radius, # 球面半径
range_color=["blue", "yellow","orange","red"],
)
)
)
# 保存为HTML文件
scatter3d.render("exp2/mission-3/main.html")
实验结果