在许多情况下,我发现将方轴放在图形上很方便,这样我就可以轻松地以transAxes
单位进行工作,而不必担心图形的纵横比。然而,我遇到的一个问题是,当你画一条线时,线宽lw/2
从路径的任一方向延伸点。这是正常的、预期的行为,当然,但它会导致问题,如果我试图将某些东西刻录到某些轴上(并使用边界框中的所有空间),线条将夹在轴的边缘. 我可以设置clip_on=False
,但这只会使我试图在轴上内切的图形超出轴的边界。我的问题是 - 我如何在“线宽”规格(以点为单位)和transAxes
单位,以便我可以补偿形状的额外长度/宽度?
我已经制定了一个简单的 MWE 来证明我的意思:
"""
MWE demonstrating the cliping of linewidths that are inscribed in axes.
"""
from __future__ import division
from matplotlib.pyplot import figure, show, savefig
from matplotlib.pyplot import Circle
from matplotlib.lines import Line2D
# Make a figure
(fig_w, fig_h) = (7.5, 2.5)
cdpi = 150
fig_aspect = fig_h/fig_w
fig = figure(1, figsize=(fig_w, fig_h), dpi=cdpi)
# Helper functions to center the circles
get_w_from_h = lambda h: h*fig_aspect
get_b_from_h = lambda h: (1-h)/2
get_l_centered = lambda left, span, w: left+(span-w)/2
# Left circle 1 - The line at the center shows that lw is the same number of pixels no matter
# what transform you use.
l_h = 0.25
l_w = get_w_from_h(l_h); l_b = get_b_from_h(l_h)
l_l = get_l_centered(0, 1/3, l_w)
l_box = [l_l, l_b, l_w, l_h]
lcax = fig.add_axes(l_box)
lclw = 2.0
lcirc = Circle((0.5, 0.5), 0.5, lw=lclw, color='#FF3932', fill=False, transform=lcax.transAxes)
lline = Line2D([-0.5, 1.5], [0.5, 0.5], lw=lclw*4, color='#FF3932',
dashes=[5,1e-14,1e-14, 5], clip_on=False, transform=lcax.transAxes)
lcax.add_patch(lcirc)
lcax.add_line(lline)
lcax.axis('off')
# Left Circle 2
l_h2 = 0.75
l_w2 = get_w_from_h(l_h2); l_b2 = get_b_from_h(l_h2)
l_l2 = get_l_centered(0, 1/3, l_w2)
l_box2 = [l_l2, l_b2, l_w2, l_h2]
lcax2 = fig.add_axes(l_box2)
lcirc2 = Circle((0.5, 0.5), 0.5, lw=lclw, color='#b20500', fill=False, transform=lcax2.transAxes)
lline2 = Line2D([0.1, 0.9], [0.5, 0.5], lw=lclw*4, color='#b20500',
dashes=[1e-14,5,5, 1e-14], transform=lcax2.transAxes)
lcax2.add_patch(lcirc2)
lcax2.add_line(lline2)
lcax2.axis('off')
# Middle circle
m_h = 0.9
m_w = get_w_from_h(m_h); m_b = get_b_from_h(m_h)
m_l = get_l_centered(1/3, 1/3, m_w)
m_box = [m_l, m_b, m_w, m_h]
mcax = fig.add_axes(m_box)
mclw = 4.0
mcirc = Circle((0.5, 0.5), 0.5, lw=mclw, color='b', fill=False,
clip_on=False,
transform=mcax.transAxes)
mcax.add_patch(mcirc)
mcax.axis('off')
# Right circle 1
r_h = 0.75
r_w = get_w_from_h(r_h); r_b = get_b_from_h(r_h)
r_l = get_l_centered(2/3, 1/3, r_w)
r_box = [r_l, r_b, r_w, r_h]
rcax = fig.add_axes(r_box, zorder=1)
rclw = 2.0
rcirc = Circle((0.5, 0.5), 0.5, lw=rclw, edgecolor='k', facecolor='#4E4E4E',
fill=True, transform=rcax.transAxes)
rcax.add_patch(rcirc)
rcax.axis('off')
# Right circle 2
r_h2 = 0.5
r_w2 = get_w_from_h(r_h2); r_b2 = get_b_from_h(r_h2)
r_l2 = get_l_centered(2/3, 1/3, r_w2)
r_box2 = [r_l2, r_b2, r_w2, r_h2]
rcax2 = fig.add_axes(r_box2, zorder=2)
rcirc2 = Circle((0.5, 0.5), 0.5, lw=rclw, edgecolor='none', facecolor='#BBBBBB',
fill=True, transform=rcax2.transAxes)
rcax2.add_patch(rcirc2)
rcax2.axis('off')
savefig('ClippingMWE.png', transparent=True, dpi=cdpi)
Run Code Online (Sandbox Code Playgroud)
这会生成这个数字:
根据左侧圆圈中的比较,无论线宽放置在哪个轴上(这是有道理的),它似乎始终是相同的像素数。中心圆圈是我希望圆圈全部看起来的样子(没有剪裁),但当然圆圈实际上比我想要的略宽。右侧的圆圈显示剪切框相对于线的作用位置。显然,在轴上刻出实心圆是没有问题的。
虽然我也有兴趣知道是否有一个标志或我可以设置的东西来在路径的某一侧画线(例如在路径的内侧而不是在路径的中心画线),我主要感兴趣的是如何从转换lw
到transAxes
单位,因为我想计算的空间,我需要适应一个给定大小的字体数量时具有基本相同的问题。