我在2D中有棒状颗粒,由长度中间的矩形部分( l )和宽度( d )组成,两者都有两个半圆形的帽子直径末端( d )。所有粒子的直径( d )保持不变,长度( l )会发生变化。我想在python中可视化它。 matplotlib可以使用自定义标记吗? 由于模拟中有大约5K的粒子,我希望它很快。
我一直在使用gnuplot,将棒绘制为矢量,让我了解粒子,但不是实际尺寸。
答案 0 :(得分: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()