2017-06-10 64 views
0

2D棒状磨粒的我在2D杆喜欢颗粒,有在两端的两个半圆形帽,其由长度()和宽度(d)的中间矩形部分的直径(d)。所有颗粒的直径()保持恒定并且长度(l)变化。我想用python来想象它。 matplotlib可以自定义标记吗? 由于在模拟中大约有5K个粒子,我希望它速度很快。可视化在python

我一直在使用gnuplot,绘制杆作为向量,它给了我一个粒子的想法,但不是实际的大小。

+0

你想拥有绝对数据颗粒的大小坐标或只是相对于对方? – ImportanceOfBeingErnest

+0

我有绝对的数据坐标,但是有一个我可以缩放的最小尺寸。 –

回答

1

你可能想看看this post,它使用的想法从this answer

杆将是一个带球冠的线(solid_capstyle="round")。

enter image description here

线宽,其在点通常给出然后从数据单位来计算和当前数据变换。

为了添加很多这样的行,可以从上述文章中更改代码以创建大量行。不幸的是,一个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() 

enter image description here

+0

这应该做到这一点。谢谢。 –