不用Matplotlib库 使用python实现一个matlab中的contourc算法
时间: 2024-03-11 10:47:51 浏览: 27
`contourc` 函数是 Matlab 中的一个绘制等高线的函数,并且其算法比较复杂,不过我们可以从其基本思路出发,自己实现一个类似的算法。
以下是一个 Python 实现的 `contourc` 函数,可以用于计算二维数组的等值线数据:
```python
import numpy as np
def contourc(Z, levels=None, extent=None):
"""
计算等值线数据
:param Z: 二维数组,待计算的数据
:param levels: 列表,指定等值线的值
:param extent: 元组,指定数据的范围
:return: 等值线数据,格式为 [(x1, y1), (x2, y2), ..., (xn, yn), -1, (x1, y1), (x2, y2), ..., (xm, ym), -1, ...]
"""
# 定义一些常量
MAX_NUM_LINES = 2000 # 最大等值线数量
MAX_NUM_POINTS = 1000 # 最大等值线点数
TINY = 1e-10 # 微小值,用于判断是否为0
# 将数据转换为 numpy 数组,方便计算
Z = np.asarray(Z)
# 获取数据的范围
if extent is None:
xmin, xmax = 0, Z.shape[1] - 1
ymin, ymax = 0, Z.shape[0] - 1
else:
xmin, xmax, ymin, ymax = extent
# 等值线的值
if levels is None:
levels = np.linspace(Z.min(), Z.max(), num=10)
# 初始化等值线数据
lines = []
num_lines = 0
# 计算每个等值线的数据
for level in levels:
# 初始化数据
line = np.zeros((MAX_NUM_POINTS, 2)) # 等值线上的点
num_points = 0 # 等值线上的点的数量
mask = np.zeros(Z.shape, dtype=bool) # 标记已经经过的点
# 找到等值线的起点
for i in range(xmin, xmax):
for j in range(ymin, ymax):
if not mask[j, i] and abs(Z[j, i] - level) < TINY:
# 找到等值线的起点
x, y = i, j
line[num_points] = [x, y]
num_points += 1
mask[y, x] = True
break
else:
continue
break
# 如果没有起点,则跳过该等值线
if num_points == 0:
continue
# 计算等值线上的点
while True:
if num_points >= MAX_NUM_POINTS:
# 等值线上的点太多,跳过该等值线
break
# 找到相邻的等值点
neighbors = []
x, y = line[num_points - 1]
if x > xmin and not mask[y, x - 1] and abs(Z[y, x - 1] - level) < TINY:
neighbors.append((x - 1, y))
if x < xmax - 1 and not mask[y, x + 1] and abs(Z[y, x + 1] - level) < TINY:
neighbors.append((x + 1, y))
if y > ymin and not mask[y - 1, x] and abs(Z[y - 1, x] - level) < TINY:
neighbors.append((x, y - 1))
if y < ymax - 1 and not mask[y + 1, x] and abs(Z[y + 1, x] - level) < TINY:
neighbors.append((x, y + 1))
# 如果没有相邻的等值点,则结束该等值线
if len(neighbors) == 0:
break
# 找到距离起点最近的等值点
min_dist = float('inf')
for neighbor in neighbors:
dist = (neighbor[0] - line[0, 0]) ** 2 + (neighbor[1] - line[0, 1]) ** 2
if dist < min_dist:
x, y = neighbor
min_dist = dist
# 将等值点加入等值线
line[num_points] = [x, y]
num_points += 1
mask[y, x] = True
# 如果等值线回到了起点,则结束该等值线
if num_points > 2 and line[num_points - 1, 0] == line[0, 0] and line[num_points - 1, 1] == line[0, 1]:
break
# 如果等值线上的点太少,则跳过该等值线
if num_points < 2:
continue
# 将等值线加入结果
lines.append(line[:num_points])
num_lines += 1
# 如果等值线数量太多,则结束计算
if num_lines >= MAX_NUM_LINES:
break
# 将等值线数据转换为指定格式
contour_data = []
for line in lines:
for point in line:
contour_data.append(tuple(point))
contour_data.append(-1)
return contour_data
```
该函数的输入为一个二维数组 `Z`,其输出为等值线的数据,格式为 `[(x1, y1), (x2, y2), ..., (xn, yn), -1, (x1, y1), (x2, y2), ..., (xm, ym), -1, ...]`,其中 `-1` 表示等值线的结束。
以下是一个示例程序,可以用于绘制等值线图:
```python
import matplotlib.pyplot as plt
# 定义数据
x = y = np.linspace(-2, 2, 101)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X ** 2 + Y ** 2))
# 计算等值线数据
contour_data = contourc(Z)
# 绘制等值线图
plt.figure()
for i in range(len(contour_data)):
if contour_data[i] == -1:
continue
x, y = contour_data[i]
plt.scatter(x, y, color='r')
plt.show()
```
该程序中,使用 `contourc` 函数计算等值线数据,并使用 Matplotlib 绘制等值线图。
相关推荐
![docx](https://img-home.csdnimg.cn/images/20210720083331.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)