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

使用Python Sympy绘图时如何为所有零值点绘制红色标识线

需求说明

需要找出目标函数所有取值为0的点位,在生成的3D图像中用醒目的红色线条标注这些零值位置,便于清晰识别。目前未找到Sympy库中可实现类似功能的相关接口,现有实现代码如下:

import inspect
from IPython.display import display, Math

from sympy import *
xi,eta,b,a = symbols("xi,eta,b,a")
Nq = Matrix([[1,xi,eta,xi**2,xi*eta,eta**2,xi**2*eta,xi*eta**2]])
AINV = Matrix([[1,1,1,1,-b,-a,-b,-a],
               [0,0,0,0,0,2*a,0,-2*a],
               [0,0,0,0,-2*b,0,2*b,0],
               [0,0,0,0,0,a,0,a],
               [1,-1,1,-1,0,0,0,0],
               [0,0,0,0,b,0,b,0],
               [-1,-1,1,1,2*b,0,-2*b,0],
               [-1,1,1,-1,0,-2*a,0,2*a]])
N = Nq*AINV
N1 = combsimp(N[0])
N2 = combsimp(N[1])
N3 = combsimp(N[2])
N4 = combsimp(N[3])
N5 = combsimp(N[4])
N6 = combsimp(N[5])
N7 = combsimp(N[6])
N8 = combsimp(N[7])

NN = Matrix([[N1,N2,N3,N4,N5,N6,N7,N8]])
NN

# Jupyter环境运行请取消下一行注释
# %matplotlib notebook

Xi = Matrix([0,12,16,8,4,2,4,7])
Yi = Matrix([4,0,12,7,3,5,7,8])

J1 = diff(NN,xi)*Xi
J2 = diff(NN,xi)*Yi
J3 = diff(NN,eta)*Xi
J4 = diff(NN,eta)*Yi

J = Matrix([[J1,J2],[J3,J4]])
JDet = J.det()
JDetPLOT = JDet.subs(a,1).subs(b,1)
plotting.plot3d(JDetPLOT,(xi,-1,1),(eta,-1,1))
实现方案

Sympy自带的plot3d接口没有直接标注指定等值线的功能,按以下步骤修改即可实现零值线标注:

  • 用数值方法提取零值线:通过lambdify把符号表达式转为支持numpy数组运算的数值函数,在xi、eta的[-1,1]定义域上生成高密度网格,计算所有网格点的函数值后,直接提取z=0的等值线坐标。该方法比符号求解速度更快,不会出现漏根、符号求解失败的问题。
  • 图层叠加绘图:先绘制原函数的半透明3D曲面保证底层数据可见,再单独绘制提取到的零值线,将线条设置为3像素粗的正红色保证醒目,叠加后即可清晰识别零值位置。

修改后的可直接运行代码如下:

import numpy as np
import matplotlib.pyplot as plt
from sympy import *

# 原有符号计算逻辑保留
xi,eta,b,a = symbols("xi,eta,b,a")
Nq = Matrix([[1,xi,eta,xi**2,xi*eta,eta**2,xi**2*eta,xi*eta**2]])
AINV = Matrix([[1,1,1,1,-b,-a,-b,-a],
               [0,0,0,0,0,2*a,0,-2*a],
               [0,0,0,0,-2*b,0,2*b,0],
               [0,0,0,0,0,a,0,a],
               [1,-1,1,-1,0,0,0,0],
               [0,0,0,0,b,0,b,0],
               [-1,-1,1,1,2*b,0,-2*b,0],
               [-1,1,1,-1,0,-2*a,0,2*a]])
N = Nq*AINV
N1 = combsimp(N[0])
N2 = combsimp(N[1])
N3 = combsimp(N[2])
N4 = combsimp(N[3])
N5 = combsimp(N[4])
N6 = combsimp(N[5])
N7 = combsimp(N[6])
N8 = combsimp(N[7])
NN = Matrix([[N1,N2,N3,N4,N5,N6,N7,N8]])

Xi = Matrix([0,12,16,8,4,2,4,7])
Yi = Matrix([4,0,12,7,3,5,7,8])
J1 = diff(NN,xi)*Xi
J2 = diff(NN,xi)*Yi
J3 = diff(NN,eta)*Xi
J4 = diff(NN,eta)*Yi
J = Matrix([[J1,J2],[J3,J4]])
JDet = J.det()
JDetPLOT = JDet.subs(a,1).subs(b,1)

# 转数值函数,生成网格数据
JDet_np = lambdify((xi, eta), JDetPLOT, 'numpy')
xi_arr = np.linspace(-1, 1, 200)
eta_arr = np.linspace(-1, 1, 200)
XI, ETA = np.meshgrid(xi_arr, eta_arr)
Z = JDet_np(XI, ETA)

# 绘制3D图
# Jupyter环境运行请取消下一行注释
# %matplotlib notebook
fig = plt.figure(figsize=(9, 7))
ax = fig.add_subplot(111, projection='3d')
# 绘制半透明原曲面
ax.plot_surface(XI, ETA, Z, cmap='viridis', alpha=0.6)
# 绘制粗红色零值线
ax.contour(XI, ETA, Z, levels=[0], colors='#ff0000', linewidths=3)
ax.set_xlabel(r'$\xi$')
ax.set_ylabel(r'$\eta$')
ax.set_zlabel('Jacobian Determinant')
plt.tight_layout()
plt.show()

如果需要获取零值点的精确坐标,可以对提取到的contour对象的路径数据做解析,即可拿到所有零值线上的离散点坐标。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 06:12:39