2013-04-07 3 views
2

다각형은 두 개의 목록으로 표시됩니다. 목록 xs에는 x 좌표가 내림차순으로 포함됩니다. 각 x 값에 대해 목록 regions의 해당 요소는 조각 목록입니다. 각 슬라이스는 다각형의 내부에 속하는 y 범위를 나타냅니다. 각 x 값에 대해 슬라이스는 오름차순으로 정렬됩니다.Matplotlib의 채우기 기능에 포인트를 주문하는 방법은 무엇입니까?

Matplotlib의 fill 함수를 사용하여 채워진 다각형을 그려야합니다. 이 함수는 포인트를 따라 점을 그리면서 다각형의 윤곽을 설명하도록 점을 정렬해야합니다. 올바른 다각형을 얻기 위해 데이터 세트의 점을 정렬하려면 어떻게해야합니까?

다음은 내가 가지고있는 데이터 종류의 예입니다.

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] 

을 다음과 그림은 지금까지와 같은 Filled polygon

과 같아야로

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)]] 

포인트를 주문하는 올바른 방법은, 내가 전환점, 즉 정의 시도 , x 값은 윤곽이 방향을 변경하는 값입니다. 이 작업은 각 x 값에 대한 조각 수를 포함하는 배열에 적용한 numpy.diff으로 수행 할 수 있습니다. 차이가 0이 아니면 그 x 값은 전환점입니다. 이것은 아마도 다음 지점을 파악하는 데 사용될 수 있습니다. 어려움은 다음 슬라이스와 슬라이스의 시작 또는 끝 사용 여부를 파악하는 것입니다.

This question과 비슷하지만, 제 경우에는 다각형이 훨씬 복잡한 모양을 가지고 있습니다. 반면에, 나는 다각형 안에있는 것에 대한 정보를 가지고 있습니다.

편집

난 그냥 명시된 바와 같이 문제가 항상 유일한 해결책이 없음을 깨달았다. 예를 들어, 실시 예에서의 포인트들의 세트는 상기도

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] 

Alternative Polygon

I 찾던 용액 수직으로부터 (떨어져 각각의 에지의 기울기의 절대 값을 최소화하는 하나의 해결책을 인정 세그먼트). 위의 예에서는 첫 번째 해결 방법에 해당합니다.

답변

0

다음은 작업을 수행하는 기능입니다. 발견 된 모든 다각형을 생성하는 생성기입니다 (연결된 다각형이 둘 이상인 경우).

우선 영역 튜플로 재기록되어야한다 :

regions = [[(sl.start, sl.stop) for sl in sllist] for sllist in regions] 

순서는 (a 루프 또는 기타) 발생기를 호출함으로써 수행된다. 이 함수는 다각형을 (x, y) 점의 목록으로 만듭니다. 별도 xxyy 목록을 얻기 쉽다 :

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] 
관련 문제