You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非凸曲线笛卡尔网格上的流线绘制问题求助

我之前做非凸域流场流线可视化时也遇到过一模一样的问题,给你分享几个亲测好用的解决方案:

一、高效将速度场插值到笛卡尔网格

matplotlib的streamplot确实只支持结构化网格输入,不用手动折腾,用scipy.interpolate里的工具就能快速搞定:

推荐用griddata函数,它可以直接把非结构化的点数据插值到指定的笛卡尔网格上,示例代码如下:

import numpy as np
from scipy.interpolate import griddata
import matplotlib.pyplot as plt

# 假设你的原始非凸域上的速度场数据
x_original = np.random.rand(1000) * 10  # 原始点x坐标
y_original = np.random.rand(1000) * 10  # 原始点y坐标
u_original = np.sin(x_original) + np.cos(y_original)  # 原始u速度
v_original = np.cos(x_original) - np.sin(y_original)  # 原始v速度

# 生成你需要的笛卡尔网格
xi = np.linspace(0, 10, 100)
yi = np.linspace(0, 10, 100)
XX, YY = np.meshgrid(xi, yi)

# 插值速度场到网格上,method可选'nearest'/'linear'/'cubic',按需选择
u_grid = griddata((x_original, y_original), u_original, (XX, YY), method='cubic')
v_grid = griddata((x_original, y_original), v_original, (XX, YY), method='cubic')

这个方法比手动处理高效太多,而且插值精度可控。

二、优雅处理非凸域的插值问题

你之前用虚拟nan单元的方法确实繁琐,这里有两个更优的思路:

1. 先筛选域内网格点再插值

首先用matplotlib.path.Path定义你的非凸域边界,然后筛选出笛卡尔网格中属于域内的点,只对这些点做插值,自动忽略域外点:

from matplotlib.path import Path

# 定义非凸域的边界点(比如一个带凹口的多边形)
non_convex_boundary = np.array([
    [0, 0], [10, 0], [10, 10], [5, 7], [0, 10], [0, 0]
])
path = Path(non_convex_boundary)

# 将网格点转化为二维点数组
grid_points = np.vstack([XX.ravel(), YY.ravel()]).T
# 判断每个网格点是否在域内
inside = path.contains_points(grid_points)

# 只对域内点插值,域外点自动设为nan
u_grid = np.full(XX.shape, np.nan)
v_grid = np.full(YY.shape, np.nan)

# 插值域内点
u_grid[inside.reshape(XX.shape)] = griddata(
    (x_original, y_original), u_original, 
    (XX[inside.reshape(XX.shape)], YY[inside.reshape(XX.shape)]),
    method='cubic'
)
v_grid[inside.reshape(XX.shape)] = griddata(
    (x_original, y_original), v_original, 
    (XX[inside.reshape(XX.shape)], YY[inside.reshape(XX.shape)]),
    method='cubic'
)

这样就不用手动添加虚拟单元,直接通过边界路径筛选域内点,逻辑清晰且高效。

2. 使用支持掩码的插值器

如果你的原始数据是离散点,还可以用scipy.interpolate.CloughTocher2DInterpolator(一种高精度的二维插值器),结合掩码来处理非凸域:

from scipy.interpolate import CloughTocher2DInterpolator

# 创建插值器
interp_u = CloughTocher2DInterpolator((x_original, y_original), u_original)
interp_v = CloughTocher2DInterpolator((x_original, y_original), v_original)

# 先对所有网格点插值,再用路径掩码把域外点设为nan
u_grid = interp_u(XX, YY)
v_grid = interp_v(XX, YY)
u_grid[~inside.reshape(XX.shape)] = np.nan
v_grid[~inside.reshape(XX.shape)] = np.nan

这种方法插值精度更高,适合对结果要求较高的场景。

最后绘制流线

处理完网格速度场后,直接用streamplot绘制即可,它会自动忽略nan值的区域:

plt.streamplot(XX, YY, u_grid, v_grid, color='blue')
plt.plot(non_convex_boundary[:,0], non_convex_boundary[:,1], 'k-')  # 绘制非凸域边界
plt.show()

内容的提问来源于stack exchange,提问作者pums974

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:42:33