【问题标题】:Fill polygon with custom hatch with matplotlib使用 matplotlib 用自定义填充填充多边形
【发布时间】:2018-01-29 19:40:48
【问题描述】:

我想用线填充填充一堆多边形。线条必须相对于 x 轴具有特定角度。我发现 matplotlib 已经支持一些孵化类,并且可以定义一个自定义类(如How to fill a polygon with a custom hatch in matplotlib?)。我试图生成一个自定义舱口,但是当我将它附加到舱口列表时,init 函数不知道角度。我尝试了以下课程:

class AngularHatch(HatchPatternBase):
    def __init__(self, hatch, density, angle):
        self.num_lines = int((hatch.count('{'))*density*3)
        self.num_vertices = self.num_lines * 2
        self.R = np.array([[np.cos(angle), -np.sin(angle)],
                       [np.sin(angle), np.cos(angle)]])

    def set_vertices_and_codes(self, vertices, codes):
        steps, stepsize = np.linspace(0.0, 1.0, self.num_lines, False,
                                  retstep=True)
        steps += stepsize / 2.
        vertices[0::2, 0] = 0
        vertices[0::2, 1] = steps
        vertices[1::2, 0] = 1
        vertices[1::2, 1] = steps
        for i, v in enumerate(vertices):
            vertices[i] = self.R.dot(v)
    codes[0::2] = Path.MOVETO
    codes[1::2] = Path.LINETO

然后我将这个类添加到孵化的可用类列表中。但是,这不会生成正确的行,因为代码是从 Horizo​​ntalHatch 源代码here 修改的,我认为这会在单位正方形中生成行。此外,我需要为要渲染的每个多边形生成一个特定角度的补丁。 ¿ 有关如何为每个多边形的此类提供正确角度的任何想法?

【问题讨论】:

    标签: python python-3.x numpy matplotlib polygon


    【解决方案1】:

    以下内容不能解决此问题。它只是解决了部分问题,并显示了该方法在哪一点失败。我目前确信 matplotlib 无法使用任意角度进行孵化,因为单元格的大小是固定的。

    为了克服设置角度的问题,可以定义一种自定义格式来获取角度信息。例如。 "{angle}{factor}",这样"{45}{2}" 将产生一个角度为 45°、密度因子为 2 的阴影。

    然后我不完全理解计算顶点的尝试。要复制内置影线的行为,可以直接旋转它们。

    问题在于,这种方式的线影线仅适用于 45° 的角度。这是因为晶胞边缘的线条没有很好地对齐。请参阅以下内容:

    import numpy as np
    import matplotlib.hatch
    import matplotlib.path
    import matplotlib.pyplot as plt
    from matplotlib.patches import Ellipse, Rectangle
    
    class AngularHatch(matplotlib.hatch.HatchPatternBase):
        def __init__(self, hatch, density):
            self.num_lines=0
            self.num_vertices=0
            if hatch[0] == "{":
                h = hatch.strip("{}").split("}{")
                angle = np.deg2rad(float(h[0])-45)
                d = float(h[1])
                self.num_lines = int(density*d)
                self.num_vertices = (self.num_lines + 1) * 2
                self.R = np.array([[np.cos(angle), -np.sin(angle)],
                                    [np.sin(angle), np.cos(angle)]])
    
        def set_vertices_and_codes(self, vertices, codes):
    
            steps = np.linspace(-0.5, 0.5, self.num_lines + 1, True)
    
            vertices[0::2, 0] = 0.0 + steps
            vertices[0::2, 1] = 0.0 - steps
            vertices[1::2, 0] = 1.0 + steps
            vertices[1::2, 1] = 1.0 - steps
            codes[0::2] = matplotlib.path.Path.MOVETO
            codes[1::2] = matplotlib.path.Path.LINETO
            vertices[:,:] = np.dot((vertices-0.5),self.R)+0.5
    
    
    
    matplotlib.hatch._hatch_types.append(AngularHatch)
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    
    ellipse = ax.add_patch(Rectangle((0.1, 0.1), 0.4, 0.8, fill=False))
    ellipse.set_hatch('{45}{1}')
    ellipse.set_color('red')
    ellipse = ax.add_patch(Rectangle((0.55, 0.1), 0.4, 0.8, fill=False))
    ellipse.set_hatch('{22}{1}')
    ellipse.set_color('blue')
    plt.show()
    

    【讨论】:

    • 我会尽快修改答案,我给了 +1,因为这是一个有用的答案,但我不能单独使用 matplotlib 来做到这一点,我结束了使用 Shapely 和他们的 multilinestring 类。实际上,我认为问题及其答案来自另一个 stackexchange 网站。
    猜你喜欢
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 2014-01-01
    相关资源
    最近更新 更多