300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > python 画彩虹_python – 在matplotlib中 我如何绘制多色线 如彩虹

python 画彩虹_python – 在matplotlib中 我如何绘制多色线 如彩虹

时间:2023-10-14 19:28:08

相关推荐

python 画彩虹_python – 在matplotlib中 我如何绘制多色线 如彩虹

绘制平行线不是一件容易的事.使用简单的均匀偏移当然不会显示所需的结果.这显示在下面的左图中.

这种简单的偏移可以在matplotlib中产生,如

transformation tutorial所示.

方法1

更好的解决方案可能是使用右侧勾勒出的想法.为了计算第n个点的偏移,我们可以使用法线向量到第n-1和第n个点之间的直线,并沿着该法向量使用相同的距离来计算偏移点.

这种方法的优点是我们在原始行中的点数与在偏移行中的点数相同.缺点是它不完全准确,如图所示.

此方法在下面的代码中的函数偏移量中实现.

为了使这对matplotlib图有用,我们需要考虑线宽应该独立于数据单元.线宽通常以点为单位给出,并且偏移最好以相同的单位给出,例如,可以满足问题的要求(“宽度为3的两条平行线”).

因此,我们的想法是使用ax.transData.transform将坐标从数据转换为显示坐标.点o的偏移也可以转换为相同的单位:使用dpi和标准的ppi = 72,显示坐标的偏移量为o * dpi / ppi.在应用了显示坐标中的偏移之后,逆变换(ax.transData.inverted().变换)允许反向变换.

现在还有另一个问题:如何确保偏移量保持不变,与图形的缩放和大小无关?

每次调整大小调整事件的大小时,可以通过重新计算偏移来解决最后一点.

以下是此方法产生的彩虹曲线的外观.

这是生成图像的代码.

import numpy as np

import matplotlib.pyplot as plt

dpi = 100

def offset(x,y, o):

""" Offset coordinates given by array x,y by o """

X = np.c_[x,y].T

m = np.array([[0,-1],[1,0]])

R = np.zeros_like(X)

S = X[:,2:]-X[:,:-2]

R[:,1:-1] = np.dot(m, S)

R[:,0] = np.dot(m, X[:,1]-X[:,0])

R[:,-1] = np.dot(m, X[:,-1]-X[:,-2])

On = R/np.sqrt(R[0,:]**2+R[1,:]**2)*o

Out = On+X

return Out[0,:], Out[1,:]

def offset_curve(ax, x,y, o):

""" Offset array x,y in data coordinates

by o in points """

trans = ax.transData.transform

inv = ax.transData.inverted().transform

X = np.c_[x,y]

Xt = trans(X)

xto, yto = offset(Xt[:,0],Xt[:,1],o*dpi/72. )

Xto = np.c_[xto, yto]

Xo = inv(Xto)

return Xo[:,0], Xo[:,1]

# some single points

y = np.array([1,2,2,3,3,0])

x = np.arange(len(y))

#or try a sinus

x = np.linspace(0,9)

y=np.sin(x)*x/3.

fig, ax=plt.subplots(figsize=(4,2.5), dpi=dpi)

cols = ["#fff40b", "#00e103", "#ff9921", "#3a00ef", "#ff2121", "#af00e7"]

lw = 2.

lines = []

for i in range(len(cols)):

l, = plt.plot(x,y, lw=lw, color=cols[i])

lines.append(l)

def plot_rainbow(event=None):

xr = range(6); yr = range(6);

xr[0],yr[0] = offset_curve(ax, x,y, lw/2.)

xr[1],yr[1] = offset_curve(ax, x,y, -lw/2.)

xr[2],yr[2] = offset_curve(ax, xr[0],yr[0], lw)

xr[3],yr[3] = offset_curve(ax, xr[1],yr[1], -lw)

xr[4],yr[4] = offset_curve(ax, xr[2],yr[2], lw)

xr[5],yr[5] = offset_curve(ax, xr[3],yr[3], -lw)

for i in range(6):

lines[i].set_data(xr[i], yr[i])

plot_rainbow()

fig.canvas.mpl_connect("resize_event", plot_rainbow)

fig.canvas.mpl_connect("button_release_event", plot_rainbow)

plt.savefig(__file__+".png", dpi=dpi)

plt.show()

方法2

为避免重叠线,必须使用更复杂的解决方案.

可以首先将每个垂直于它所属的两个线段的点偏移(下图中的绿点).然后计算通过这些偏移点的直线并找到它们的交点.

特定情况是两个后续线段的斜率相等.必须注意这一点(下面的代码中的eps).

from __future__ import division

import numpy as np

import matplotlib.pyplot as plt

dpi = 100

def intersect(p1, p2, q1, q2, eps=1.e-10):

""" given two lines, first through points pn, second through qn,

find the intersection """

x1 = p1[0]; y1 = p1[1]; x2 = p2[0]; y2 = p2[1]

x3 = q1[0]; y3 = q1[1]; x4 = q2[0]; y4 = q2[1]

nomX = ((x1*y2-y1*x2)*(x3-x4)- (x1-x2)*(x3*y4-y3*x4))

denom = float( (x1-x2)*(y3-y4) - (y1-y2)*(x3-x4) )

nomY = (x1*y2-y1*x2)*(y3-y4) - (y1-y2)*(x3*y4-y3*x4)

if np.abs(denom) < eps:

#print "intersection undefined", p1

return np.array( p1 )

else:

return np.array( [ nomX/denom , nomY/denom ])

def offset(x,y, o, eps=1.e-10):

""" Offset coordinates given by array x,y by o """

X = np.c_[x,y].T

m = np.array([[0,-1],[1,0]])

S = X[:,1:]-X[:,:-1]

R = np.dot(m, S)

norm = np.sqrt(R[0,:]**2+R[1,:]**2) / o

On = R/norm

Outa = On+X[:,1:]

Outb = On+X[:,:-1]

G = np.zeros_like(X)

for i in xrange(0, len(X[0,:])-2):

p = intersect(Outa[:,i], Outb[:,i], Outa[:,i+1], Outb[:,i+1], eps=eps)

G[:,i+1] = p

G[:,0] = Outb[:,0]

G[:,-1] = Outa[:,-1]

return G[0,:], G[1,:]

def offset_curve(ax, x,y, o, eps=1.e-10):

""" Offset array x,y in data coordinates

by o in points """

trans = ax.transData.transform

inv = ax.transData.inverted().transform

X = np.c_[x,y]

Xt = trans(X)

xto, yto = offset(Xt[:,0],Xt[:,1],o*dpi/72., eps=eps )

Xto = np.c_[xto, yto]

Xo = inv(Xto)

return Xo[:,0], Xo[:,1]

# some single points

y = np.array([1,1,2,0,3,2,1.,4,3]) *1.e9

x = np.arange(len(y))

x[3]=x[4]

#or try a sinus

#x = np.linspace(0,9)

#y=np.sin(x)*x/3.

fig, ax=plt.subplots(figsize=(4,2.5), dpi=dpi)

cols = ["r", "b"]

lw = 11.

lines = []

for i in range(len(cols)):

l, = plt.plot(x,y, lw=lw, color=cols[i], solid_joinstyle="miter")

lines.append(l)

def plot_rainbow(event=None):

xr = range(2); yr = range(2);

xr[0],yr[0] = offset_curve(ax, x,y, lw/2.)

xr[1],yr[1] = offset_curve(ax, x,y, -lw/2.)

for i in range(2):

lines[i].set_data(xr[i], yr[i])

plot_rainbow()

fig.canvas.mpl_connect("resize_event", plot_rainbow)

fig.canvas.mpl_connect("button_release_event", plot_rainbow)

plt.show()

请注意,只要线条之间的偏移小于线条上后续点之间的距离,此方法就可以正常工作.否则方法1可能更适合.

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。