【问题标题】:Visualization of 2D rod-shaped particles in pythonpython中二维棒状粒子的可视化
【发布时间】:2017-06-10 12:44:56
【问题描述】:

我有 2D 的棒状粒子,它由长度(l)和宽度(d)的中间矩形部分组成,两者都有两个半圆形帽直径的末端(d)。所有粒子的直径(d) 保持不变,长度(l) 变化。我想在 python 中可视化它。 matplotlib 可以使用自定义标记吗? 由于模拟中大约有 5K 个粒子,我希望它更快。

我一直在使用 gnuplot,将棒绘制为矢量,这让我了解了粒子,但不是实际大小。

【问题讨论】:

  • 您想要粒子的大小在绝对数据坐标中还是仅相对于彼此?
  • 我有绝对数据坐标,但是有一个可以缩放的最小尺寸。

标签: python matplotlib gnuplot visualization


【解决方案1】:

您可能想看看this post,它使用了this answer 的想法。

杆是带有球形帽的线 (solid_capstyle="round")。

线宽通常以点为单位,然后根据数据单位和当前数据变换计算得出。

为了添加许多这样的行,可以更改上述帖子中的代码以创建很多行。不幸的是,LineCollection 会加快速度,但不允许更改 capstyle。

这是一个例子:

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
import numpy as np

class Rods():
    def __init__(self, x,y,l,w=1, angle=0, **kwargs):
        self.ax = kwargs.pop("ax", plt.gca())
        self.color=kwargs.pop("color", "lightblue")
        self.lw = 1
        self.ax.figure.canvas.draw()
        self.ppd=72./self.ax.figure.dpi
        self.trans = self.ax.transData.transform
        self.lines = []
        self.set_data(x,y,l,w, angle)

        self.cid=self.ax.figure.canvas.mpl_connect('resize_event',self._resize)
        self.cid1=self.ax.figure.canvas.mpl_connect("motion_notify_event",self._resize)
        self.cid2=self.ax.figure.canvas.mpl_connect('button_release_event',self._resize)

    def set_data(self, x,y,l,w=1, angle=0, color=None):
        if color: self.color=color
        self.lw_data = w
        m = np.array([[np.cos(angle), -np.sin(angle)],[np.sin(angle), np.cos(angle)]])
        xy1 = np.dot(m, np.c_[np.zeros_like(x),-l/2.*np.ones_like(x)].T).T
        xy2 = np.dot(m, np.c_[np.zeros_like(x), l/2.*np.ones_like(x)].T).T

        x = np.c_[xy1[:,0] + x,xy2[:,0] + x]
        y = np.c_[xy1[:,1] + y,xy2[:,1] + y]

        if self.lines:
            for line in self.lines: line.remove()
        for i in range(len(x)):
            line = Line2D(x[i,:], y[i,:], 
                           solid_capstyle="round", color=self.color)
            self.lines.append(line)

        for line in self.lines:
            self.ax.add_artist(line)
        self._resize()

    def _resize(self, event=None):
        lw =  ((self.trans((1,self.lw_data))-self.trans((0,0)))*self.ppd)[1]
        if lw != self.lw:
            for line in self.lines:
                line.set_linewidth(lw)
            self.ax.figure.canvas.draw_idle()
            self.lw = lw


fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.axis([0,6,0,6])

x = np.array([1,2,3,4])
y = np.array([2,3,5,5])
l = np.array([2,3,5,4])*0.2

r = Rods(x,y,l,w=0.1, angle=45, color="crimson")
r = Rods(y[::-1],x[::-1],l,w=0.4, angle=90, color="purple")

plt.show()

【讨论】:

  • 应该这样做。谢谢。
猜你喜欢
  • 2021-12-12
  • 2022-11-05
  • 2011-10-30
  • 2018-11-16
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
  • 2021-02-09
  • 1970-01-01
相关资源
最近更新 更多