Python 在矩形matplotlib内绘制线宽

Python 在矩形matplotlib内绘制线宽,python,matplotlib,Python,Matplotlib,在matplotlib中使用面片绘制矩形时遇到问题。将linewidth提供给patches.Rectangle时,将在矩形的外侧绘制边框。下面是一个例子: import matplotlib.pyplot as plt import matplotlib.patches as patches fig, ax = plt.subplots(1) rect = patches.Rectangle((1, 1), 1, 1, facecolor = 'blue') rect2 = patches.R

在matplotlib中使用面片绘制矩形时遇到问题。将
linewidth
提供给patches.Rectangle时,将在矩形的外侧绘制边框。下面是一个例子:

import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig, ax = plt.subplots(1)
rect = patches.Rectangle((1, 1), 1, 1, facecolor = 'blue')
rect2 = patches.Rectangle((1, 2.1), 1, 1, facecolor = 'none', edgecolor = 'black', linewidth = 6)
ax.add_patch(rect)
ax.add_patch(rect2)

ax.set_xlim([0, 3.5])
ax.set_ylim([0, 3.5])
结果如下:

请注意,边框是在框的外部绘制的,因此框+边框现在超过了蓝色框的大小。我希望在框内绘制边框,这样无论线宽如何,边框的大小始终与蓝色框相同

我尝试过两种不同的方法,但都不令人满意:

  • 将线宽从绝对单位转换为数据单位,然后计算一个较小的框,该框可以使用与另一个框匹配的法线边框绘制
  • 探索中的一些
    offsetbox
    功能,尽管我没有走多远,因为我不知道如何正确指定
    pad

  • 任何帮助都将不胜感激

    最简单的方法是设置一个剪辑矩形,隐藏矩形外的所有内容。因为您已经有了一个矩形,所以可以使用它来剪裁自己

    当边界以边界线为中心绘制时,将剪掉一半。这可以通过将宽度设置为所需宽度的两倍来解决

    请注意,为了按需要进行剪裁,矩形已经需要转换为轴坐标。因此,首先将矩形面片添加到ax,然后才使用设置剪裁

    还请注意,对于默认参数,矩形的内部和薄边框使用相同的颜色。将线宽设置为零可确保不会在矩形外绘制

    类似地,椭圆只能在内部用线绘制

    下面的代码使用10的厚度和一些额外的红色虚线来说明发生了什么

    import matplotlib.pyplot as plt
    import matplotlib.patches as patches
    
    fig, ax = plt.subplots()
    
    pad = 0.1 # distance between the rectangles
    for i in range(3):
        for j in range(2):
            x = .5 + i * (1 + pad)
            y =  .5 + j * (1 + pad)
            if i == j:
                patch = patches.Rectangle((x, y), 1, 1, facecolor='blue', linewidth=0)
            elif i < 2:
                patch = patches.Rectangle((x, y), 1, 1, facecolor='none', edgecolor='black',
                                         linewidth=10*2 if j == 0 else 10)
            else:
                patch = patches.Ellipse((x+0.5, y+0.5), 1, 1, facecolor='none', edgecolor='black',
                                         linewidth=10*2 if j == 0 else 10)
            ax.add_patch(patch)
            if j == 0:
                patch.set_clip_path(patch)
    
    for i in range(3):
        x = .5 + i * (1 + pad)
        for s in 0,1:
            ax.axvline (x+s, color='crimson', ls=':', lw=1)
    for j in range(2):
        y =  .5 + j * (1 + pad)
        for s in 0,1:
            ax.axhline (y+s, color='crimson', ls=':', lw=1)
    
    ax.set_xlim([0, 4.0])
    ax.set_ylim([0, 3.0])
    ax.set_aspect('equal')
    plt.show()
    
    导入matplotlib.pyplot作为plt
    将matplotlib.patches导入为修补程序
    图,ax=plt.子批次()
    pad=0.1#矩形之间的距离
    对于范围(3)中的i:
    对于范围(2)内的j:
    x=.5+i*(1+pad)
    y=.5+j*(1+pad)
    如果i==j:
    面片=面片。矩形((x,y),1,1,facecolor='blue',线宽=0)
    elif i<2:
    patch=patches.矩形((x,y),1,1,facecolor='none',edgecolor='black',
    如果j==0,线宽=10*2(其他10)
    其他:
    patch=patches.椭圆((x+0.5,y+0.5),1,1,facecolor='none',edgecolor='black',
    如果j==0,线宽=10*2(其他10)
    ax.添加补丁(补丁)
    如果j==0:
    补丁。设置剪辑路径(补丁)
    对于范围(3)中的i:
    x=.5+i*(1+pad)
    对于0,1中的s:
    ax.axvline(x+s,color='crimson',ls=':',lw=1)
    对于范围(2)内的j:
    y=.5+j*(1+pad)
    对于0,1中的s:
    ax.axhline(y+s,color='crimson',ls=':',lw=1)
    ax.set_xlim([0,4.0])
    ax.set_ylim([0,3.0])
    ax.set_方面(“相等”)
    plt.show()
    
    下图显示了在顶部绘制和在底部使用双线宽剪裁的标准方式


    最简单的方法是设置一个剪辑矩形,隐藏矩形外的所有内容。因为您已经有了一个矩形,所以可以使用它来剪裁自己

    当边界以边界线为中心绘制时,将剪掉一半。这可以通过将宽度设置为所需宽度的两倍来解决

    请注意,为了按需要进行剪裁,矩形已经需要转换为轴坐标。因此,首先将矩形面片添加到ax,然后才使用设置剪裁

    还请注意,对于默认参数,矩形的内部和薄边框使用相同的颜色。将线宽设置为零可确保不会在矩形外绘制

    类似地,椭圆只能在内部用线绘制

    下面的代码使用10的厚度和一些额外的红色虚线来说明发生了什么

    import matplotlib.pyplot as plt
    import matplotlib.patches as patches
    
    fig, ax = plt.subplots()
    
    pad = 0.1 # distance between the rectangles
    for i in range(3):
        for j in range(2):
            x = .5 + i * (1 + pad)
            y =  .5 + j * (1 + pad)
            if i == j:
                patch = patches.Rectangle((x, y), 1, 1, facecolor='blue', linewidth=0)
            elif i < 2:
                patch = patches.Rectangle((x, y), 1, 1, facecolor='none', edgecolor='black',
                                         linewidth=10*2 if j == 0 else 10)
            else:
                patch = patches.Ellipse((x+0.5, y+0.5), 1, 1, facecolor='none', edgecolor='black',
                                         linewidth=10*2 if j == 0 else 10)
            ax.add_patch(patch)
            if j == 0:
                patch.set_clip_path(patch)
    
    for i in range(3):
        x = .5 + i * (1 + pad)
        for s in 0,1:
            ax.axvline (x+s, color='crimson', ls=':', lw=1)
    for j in range(2):
        y =  .5 + j * (1 + pad)
        for s in 0,1:
            ax.axhline (y+s, color='crimson', ls=':', lw=1)
    
    ax.set_xlim([0, 4.0])
    ax.set_ylim([0, 3.0])
    ax.set_aspect('equal')
    plt.show()
    
    导入matplotlib.pyplot作为plt
    将matplotlib.patches导入为修补程序
    图,ax=plt.子批次()
    pad=0.1#矩形之间的距离
    对于范围(3)中的i:
    对于范围(2)内的j:
    x=.5+i*(1+pad)
    y=.5+j*(1+pad)
    如果i==j:
    面片=面片。矩形((x,y),1,1,facecolor='blue',线宽=0)
    elif i<2:
    patch=patches.矩形((x,y),1,1,facecolor='none',edgecolor='black',
    如果j==0,线宽=10*2(其他10)
    其他:
    patch=patches.椭圆((x+0.5,y+0.5),1,1,facecolor='none',edgecolor='black',
    如果j==0,线宽=10*2(其他10)
    ax.添加补丁(补丁)
    如果j==0:
    补丁。设置剪辑路径(补丁)
    对于范围(3)中的i:
    x=.5+i*(1+pad)
    对于0,1中的s:
    ax.axvline(x+s,color='crimson',ls=':',lw=1)
    对于范围(2)内的j:
    y=.5+j*(1+pad)
    对于0,1中的s:
    ax.axhline(y+s,color='crimson',ls=':',lw=1)
    ax.set_xlim([0,4.0])
    ax.set_ylim([0,3.0])
    ax.set_方面(“相等”)
    plt.show()
    
    下图显示了在顶部绘制和在底部使用双线宽剪裁的标准方式


    一个不需要额外计算的实用解决方案是在蓝色矩形上添加一个相同宽度的蓝色边框。@JanKuiken这种方法的一个问题是框开始重叠,而如果边框进入内部,框之间的填充将保持不变。一个不需要额外计算的实用解决方案是在蓝色矩形上添加一个相同宽度的蓝色边框。@JanKuiken这种方法的一个问题是框开始重叠,而如果边框进入内部,框之间的填充将保持不变。