如何有效地绘制带有三角形的二维矢量场?

问题描述 投票:0回答:1

免责声明:我在plotly github上添加了一个功能请求,以获取与我正在寻找的功能类似的功能。

我写了一段代码,使用plotly绘制向量场,类似于3D中的锥体图,以下是代码片段:

import numpy as np
import plotly.graph_objects as go
import plotly.colors as pc


def plot_vector_field(x,y,u,v):
    
    # Function to get colors for the triangles
    def get_colors(values, colorscale='Viridis'):
                        colorscale = pc.get_colorscale(colorscale)
                        unique_magnitudes = np.unique(values)
                        color_map = {val: pc.sample_colorscale(colorscale, val)[0] for val in unique_magnitudes}
                        return np.vectorize(color_map.get)(values)

    # Function to plot the triangles
    def plot_triangle(fig, position,direction,size,color):
                        x = [position[0]+direction[0]*size/2, 
                                position[0]-direction[0]*size/3 + direction[1]*size/4, 
                                position[0]-direction[0]*size/3 - direction[1]*size/4]
                        y = [position[1]+direction[1]*size/2, 
                                position[1]-direction[1]*size/3 - direction[0]*size/4, 
                                position[1]-direction[1]*size/3 + direction[0]*size/4]

                        fig.add_trace(go.Scatter(
                                                x=x,
                                                y=y,
                                                fill='toself',
                                                mode='lines', 
                                                line=dict(color='rgba(0,0,0,0)'),
                                                fillcolor=color,
                                                showlegend=False,
                                                name=''
                                            ))
        
    # Calculate the magnitude of the vectors
    magnitude = np.sqrt(u**2 + v**2)
    magnitude_normalized = magnitude/np.max(magnitude)

    # Get the colors for the triangles
    colors = get_colors(magnitude_normalized, colorscale='viridis')

    # Get the direction of the vectors
    angle = np.arctan2(v, u)
    direction = np.array([np.cos(angle), np.sin(angle)]).T

    # Create the figure
    fig = go.Figure()

    # For each point in the grid, plot a triangle
    for i in range(len(x)):
        plot_triangle(fig, 
                    position=[x[i],y[i]], 
                    direction=direction[i], 
                    size=0.8*magnitude_normalized[i], 
                    color=colors[i])

    
    # Add a trace for the colorbar
    colorbar_trace = go.Scatter(
                        x=[None],
                        y=[None],
                        mode='markers',
                        marker=dict(
                            colorscale='Viridis',
                            cmin=0,
                            cmax=np.max(magnitude),
                            colorbar=dict(
                                title=''
                            )
                        ),
                        showlegend=False
                    )
    fig.add_trace(colorbar_trace)

    return fig


x = np.linspace(-2, 2, 10)
y = np.linspace(-2, 2, 10)
X, Y = np.meshgrid(x, y)
u = -1 - X**2 + Y
v = 1 + X - Y**2

fig = plot_vector_field(X.flatten(), Y.flatten(), u.flatten(), v.flatten())
fig.show()

产生这个数字: Triangle plot

问题是,当我扩大点数时,该函数的性能很差,因为它将每个三角形绘制为不同的轨迹。

有更好的方法吗?

我已经研究过在一条轨迹中绘制所有三角形,但发现很难使填充和颜色按预期工作。

vector plotly
1个回答
0
投票

我实际上自己找到了方法,通过使用分散函数来代替。这是一个可以实现这一目的的功能脚本:

import plotly.graph_objects as go
import numpy as np

x = np.linspace(-2, 2, 10)
y = np.linspace(-2, 2, 10)
X, Y = np.meshgrid(x, y)
u = -1 - X**2 + Y
v = 1 + X - Y**2


# Calculate the magnitude of the vectors
magnitude = np.sqrt(u**2 + v**2)
magnitude_normalized = magnitude/np.max(magnitude)

# Get the direction of the vectors
angle = np.arctan2(v, u)
direction = np.array([np.cos(angle), np.sin(angle)]).T

fig = go.Figure(data = go.Scatter(
x=X.flatten(),
y=Y.flatten(),
mode='markers',
marker=dict(symbol='arrow', angle=angle.flatten()*180/np.pi, size=50*magnitude_normalized.flatten(), color=magnitude_normalized.flatten())
)
)

fig.show()
© www.soinside.com 2019 - 2024. All rights reserved.