Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何为Matplotlib';s填充函数?_Python_Matplotlib_Polygon_Fill - Fatal编程技术网

Python 如何为Matplotlib';s填充函数?

Python 如何为Matplotlib';s填充函数?,python,matplotlib,polygon,fill,Python,Matplotlib,Polygon,Fill,多边形由两个列表表示。列表xs按降序包含x坐标。对于每个x值,listregions中的对应元素是一个切片列表。每个切片表示属于多边形内部的y范围。对于每个x值,切片按递增顺序排序 我想使用Matplotlib的fill函数绘制填充多边形。该函数需要对点进行排序,以便从一点到另一点描述多边形的轮廓。如何对数据集中的点进行排序以获得正确的多边形 下面是我拥有的数据类型的一个示例 xs = range(10, 0, -1) regions = [[slice(0, 3)], [

多边形由两个列表表示。列表
xs
按降序包含x坐标。对于每个x值,list
regions
中的对应元素是一个切片列表。每个切片表示属于多边形内部的y范围。对于每个x值,切片按递增顺序排序

我想使用Matplotlib的
fill
函数绘制填充多边形。该函数需要对点进行排序,以便从一点到另一点描述多边形的轮廓。如何对数据集中的点进行排序以获得正确的多边形

下面是我拥有的数据类型的一个示例

xs = range(10, 0, -1)
regions = [[slice(0, 3)],
           [slice(0, 4), slice(5.2, 5.8)],
           [slice(1, 5), slice(5.4, 5.8)],
           [slice(1.3, 6)],
           [slice(1.8, 6)],
           [slice(1.9, 3), slice(3.1, 6.1)],
           [slice(2, 2.9), slice(3.2, 5), slice(6, 6.2)],
           [slice(2.1, 2.7), slice(3.4, 5.1), slice(5.9, 6.3)],
           [slice(3.5, 5.2), slice(5.7, 6.4)],
           [slice(3.8, 5.3), slice(5.8, 6.1)]]
点的正确排序方法如下所示

xx = [10, 9, 8, 7, 6, 5, 4, 3, 3, 4, 5, 5, 4, 3, 2, 1,
   1, 2, 3, 4, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8,
   9, 9, 8, 8, 9, 10]
yy = [0, 0, 1, 1.3, 1.8, 1.9, 2, 2.1, 2.7, 2.9, 3, 3.1,
      3.2, 3.4, 3.5, 3.8, 5.3, 5.2, 5.1, 5, 6, 5.9, 5.7,
      5.8, 6.1, 6.4, 6.3, 6.2, 6.3, 6, 6, 5.8, 5.8, 5.2,
      5.4, 5, 4, 3]
这个数字应该是这样的

到目前为止,我已经尝试定义转折点,即轮廓改变方向的x值。这可以通过将
numpy.diff
应用于包含每个x值的切片数的数组来实现。如果差值不为零,则该x值是一个转折点。这或许可以用来找出下一点。困难在于找出下一个切片以及是使用切片的开始还是结束

类似,但在我的例子中,多边形的形状要复杂得多。另一方面,我有关于多边形内部的信息

编辑

我刚刚意识到,上述问题并不总是有唯一的解决方案。例如,上面示例中的点集也支持该解决方案

xx = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 5,
       4, 3, 3, 4, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8,
       9, 9, 8, 8, 9, 10]
yy = [0, 0, 1, 1.3, 1.8, 1.9, 2, 2.1, 3.5, 3.8, 5.3, 5.2,
      2.7, 2.9, 3, 3.1, 3.2, 3.4, 5.1, 5, 6, 5.9, 5.7,
      5.8, 6.1, 6.4, 6.3, 6.2, 6.1, 6, 6, 5.8, 5.8, 5.2,
      5.4, 5, 4, 3]


我正在寻找的解决方案是最小化每条边坡度的绝对值(除了垂直线段)。在上面的示例中,这对应于第一个解决方案。

这里是执行此任务的函数。它是一个生成器,用于生成找到的所有多边形(如果有多个连接的多边形)

首先,必须将区域重写为元组:

regions = [[(sl.start, sl.stop) for sl in sllist] for sllist in regions]
通过调用生成器(在循环中或其他方式)完成排序。该函数以(x,y)点列表的形式生成多边形。获取单独的
xx
yy
列表很容易:

for polygon in order_points(xs, regions):
    xx, yy = zip(*polygon)
函数本身被详细注释

def order_points(x, regions):
    """Given two lists of the same length, one of x values and one of regions,
    determine how to order the points so that they describe a polygon that
    contains the interior of all regions.

    This function is a generator that yields disjoint polygons.

    Parameters
    ==========

    x: list
       x values at which the regions are defined

    regions: list of lists of tuples
       Each list contains information for one x value.  The sublist contains
       so-called regions that are described by tuples corresponding to the
       bottom and the top of the region.  The y values between the bottom and
       the top of each region are in the interior of a polygon.

       Each list of tuples should be sorted by increasing y value.

    Yields
    ======

    polygon: list of tuples
       Ordered list of (x, y) coordinated of the points on the polygon.

    """
    # Make sure the x values are in ascending order.
    xvals, yregions = zip(*sorted(zip(x, regions)))

    # Direction is -1 when going toward low x, 1 when going toward high x.
    direction = 1
    # Indicate whether the inside of the polygon is below, 0, or above, 1, the
    # current point.
    inside = 1

    # List all possible combinations of x index, region index.
    tovisit = [(pos, rpos) for pos in range(len(xvals))
                            for rpos in range(len(yregions[pos]))]
    pos, rpos = tovisit.pop(0)
    ycur = yregions[pos][rpos][0]

    # Keep track of already visited points.
    visited = set()
    # Keep track of current polygon.
    polygon = []
    while True:
        # Keep track of ordered points.
        xcur = xvals[pos]
        polygon.append((xcur, ycur))
        visited.add((xcur, ycur))

        # Find the minimum vertical distance between the current position and
        # the following points: points at the next (as specified by direction)
        # x value, and points at the current x value

        # For points at the next x, if the polygon is currently above, inside =
        # 1, the points considered are at the bottom of a region, i.e., at
        # index 0 of the tuple.
        next_pos = pos + direction
        if next_pos < 0 or next_pos >= len(xvals):
            next_pos = pos
        distance = -1
        for ri, region in enumerate(yregions[pos]):
            if (xcur, region[inside]) not in visited:
                d = abs(ycur - region[inside])
                if d < distance or distance == -1:
                    distance = d
                    move = ('vertical', (pos, ri, inside))

        # For points at the same x, if the polygon is currently above, the
        # points considered are at the top of a region, i.e., at index 1 of the
        # tuple.
        for ri, region in enumerate(yregions[next_pos]):
            polypos = (not inside)
            if (xvals[next_pos], region[polypos]) not in visited:
                d = abs(ycur - region[polypos])
                if d < distance or distance == -1:
                    distance = d
                    move = ('next', (next_pos, ri, polypos))

        # If no suitable next point is found, the polygon is complete. Yield
        # the polygon and try to find a separate polygon.
        if distance < 0:
            yield polygon
            polygon = []
            direction = 10  # dummy value to detect if no next point is found
            while tovisit:
                pos, slpos = tovisit.pop(0)
                ycur = yregions[pos][slpos][0]
                if (xvals[pos], ycur) not in visited:
                    direction = 1
                    inside = 1
                    break
            if direction == 10:
                break
            continue

        # Make the move.
        if move[0] == 'vertical':
            # Vertical move changes the direction (unless it is the very first
            # move) and toggles inside/outside.
            if len(polygon) > 1:
                direction *= -1
            inside = int(not inside)
        pos, rpos, end = move[1]
        ycur = yregions[pos][rpos][end]
def order_点(x,区域):
“”“给定两个长度相同的列表,一个是x值列表,另一个是区域列表,
确定如何对点进行排序,以便它们描述
包含所有区域的内部。
此函数是生成不相交多边形的生成器。
参数
==========
x:列表
定义区域的x值
区域:元组列表的列表
每个列表包含一个x值的信息。子列表包含
所谓的区域,由对应于
区域的底部和顶部。底部和顶部之间的y值
每个区域的顶部位于多边形的内部。
每个元组列表都应该通过增加y值进行排序。
产量
======
多边形:元组列表
多边形上点(x,y)坐标的有序列表。
"""
#确保x值按升序排列。
xVAL,yregions=zip(*已排序(zip(x,区域)))
#当走向低x时方向为-1,当走向高x时方向为1。
方向=1
#指示多边形的内部是低于0还是高于1
#当前点。
内部=1
#列出x索引、区域索引的所有可能组合。
tovisit=[(销售点,RPO)适用于范围内的销售点(len(xVAL))
对于范围内的RPO(len(yregions[pos]))]
pos,RPO=tovisit.pop(0)
ycur=Y地区[pos][RPO][0]
#跟踪已访问的点。
访问=设置()
#跟踪当前多边形。
多边形=[]
尽管如此:
#跟踪已排序的点。
xcur=xvals[pos]
polygon.append((xcur,ycur))
已访问。添加((xcur,ycur))
#找到当前位置与目标之间的最小垂直距离
#以下点:下一个点(按方向指定)
#x值,并指向当前x值
#对于位于下一个x的点,如果多边形当前位于上方,则位于内部=
#1,所考虑的点位于区域底部,即
#元组的索引0。
下一个位置=位置+方向
如果next_pos<0或next_pos>=len(xVAL):
下一个位置=位置
距离=-1
对于ri,枚举中的区域(Y区域[pos]):
如果(xcur,区域[内部])未访问:
d=绝对值(ycur-区域[内部])
如果d<距离或距离==-1:
距离=d
移动=(‘垂直’,(位置、ri、内部))
#对于同一x上的点,如果多边形当前位于上方,则
#所考虑的点位于区域顶部,即位于区域的索引1处
#元组。
对于ri,枚举中的区域(Y区域[下一个位置]):
polypos=(不在内部)
如果(xVAL[next_pos],区域[polypos])未访问:
d=绝对值(ycur-区域[polypos])
如果d<距离或距离==-1:
距离=d
move=('next',(next_pos,ri,polypos))
#如果未找到合适的下一点,则多边形已完成。产量
#单击多边形并尝试查找单独的多边形。
如果距离小于0:
屈服多边形
多边形=[]
方向=10#虚拟值,用于检测是否未找到下一个点
访问期间:
pos,slpos=tovisit.pop(0)
ycur=yregions[pos][slpos][0]
如果(xVAL[pos],ycur)未访问:
方向=1
内部=1
打破
如果方向==10: