如何绘制非单调坐标下的colormap?conformal mapping可视化问题
问题背景
我正在开展一项保角变换项目,需将初始z平面(z=x+iy,x/y平面)定义的电位,映射到新w平面(w=u+iv,u/v平面)后绘制。使用colormap/contourf可视化时,z平面效果正常,但映射后坐标不再是矩形/单调递增网格,导致colormap失效。线条映射正常,说明代码逻辑无误,仅contour/colormap函数输入方式不当。
尝试contourf、pcolormesh均存在问题,使用pcolormesh时出现警告:
C:###\conf_map.py:103: UserWarning: The input coordinates to pcolormesh
are interpreted as cell centers, but are not monotonically increasing
or decreasing. This may lead to incorrectly calculated cell edges,
in which case, please supply explicit cell edges to pcolormesh.
ax[1][0].pcolormesh(np.real(w),np.imag(w),Z, shading='auto')
核心代码如下:
from matplotlib import pyplot as plt import numpy as np xdomain = [-np.pi,np.pi] ydomain = [0,3] udomain = [-4,4] vdomain = [-4,4] gridsize = 20 # 电位函数 def pot(z): return np.imag(z) # 从z到w的保角变换 def g(z): return np.sin(z) # 生成z平面的网格 x = np.linspace(xdomain[0]/2,xdomain[1]/2,gridsize) y = np.linspace(ydomain[0],ydomain[1],gridsize) w = g(x+1j*y) z = np.array([pot(i+1j*j) for j in y for i in x]) Z = z.reshape(gridsize,gridsize) fig, ax = plt.subplots(2,2) ax[0][0].contourf(x,y, Z) ax[1][0].contourf(np.real(w),np.imag(w),Z) ax[0][0].set_xlim(xdomain) ax[0][0].set_ylim(ydomain) ax[0][0].set_title('z-plane') ax[1][0].set_xlim(udomain) ax[1][0].set_ylim(vdomain) ax[1][0].set_title('w-plane')
可行解决方案
1. 直接使用tricontourf处理非结构化网格
Matplotlib的tricontourf专为非矩形、非单调网格设计,会自动对输入坐标做三角剖分,再基于三角网格填充颜色,完美适配保角变换后的非规则数据。
修改w平面的绘制代码:
# 展平变换后的坐标和电位值 u = np.real(w).flatten() v = np.imag(w).flatten() Z_flat = Z.flatten() # 用tricontourf绘制 ax[1][0].tricontourf(u, v, Z_flat, levels=20, cmap='viridis')
此方法无需调整网格,直接使用变换后的坐标与电位值即可,无警告且颜色填充准确匹配变换区域。
2. 重新采样到w平面的规则网格
若需要w平面的矩形网格可视化,可先在w平面生成规则u/v网格,通过逆变换映射回z平面得到电位值,再用常规函数绘制。
示例代码(以g(z)=sin(z)的逆变换z=arcsin(w)为例):
# 生成w平面的规则网格 u = np.linspace(udomain[0], udomain[1], gridsize*2) v = np.linspace(vdomain[0], vdomain[1], gridsize*2) U, V = np.meshgrid(u, v) W = U + 1j*V # 逆变换:从w映射回z(取主值分支) Z_w = np.arcsin(W) # 计算对应电位值 Pot_w = np.imag(Z_w) # 用contourf绘制规则网格 ax[1][0].contourf(U, V, Pot_w, levels=20, cmap='viridis')
该方法得到规则网格,适合需要矩形布局的场景,但需实现保角变换的逆函数。
3. 手动实现三角剖分与颜色填充(进阶)
若需高度自定义效果,可借助scipy.spatial.Delaunay手动做三角剖分,逐个三角形填充颜色:
from scipy.spatial import Delaunay # 展平坐标与电位值 u = np.real(w).flatten() v = np.imag(w).flatten() points = np.column_stack((u, v)) Z_flat = Z.flatten() # 执行三角剖分 tri = Delaunay(points) # 遍历每个三角形并填充颜色 for simplex in tri.simplices: pts = points[simplex] z_vals = Z_flat[simplex] # 取三角形电位平均值作为填充色(也可使用插值) avg_z = np.mean(z_vals) # 映射颜色并绘制 ax[1][0].fill(pts[:,0], pts[:,1], color=plt.cm.viridis(avg_z/ydomain[1]))
此方法灵活性最高,但需自行处理颜色映射与剖分细节,适合定制化需求。
内容的提问来源于stack exchange,提问作者Noud Hofker

