def convex_polygon_area(polygon):
    """Compute the area of a convex polygon (on the XY plane).

    Parameters
    ----------
    polygon : sequence
        The XY coordinates of the vertices/corners of the polygon.
        The vertices are assumed to be in order.
        The polygon is assumed to be closed:
        the first and last vertex in the sequence should not be the same.

    Returns
    -------
    float
        The area of the polygon.

    """

    poly_len = len(polygon)

    if poly_len < 3:
        sys.exit("The polygon is not valid")
    elif poly_len == 3:
        v1 = np.subtract(polygon[1], polygon[0])
        v2 = np.subtract(polygon[2], polygon[0])
        poly_area = abs(cross_vectors_xy(v2, v1)[2] / 2)
    else:
        x_products = []
        # check if the polygon is convex TODO: revew
        for p in range(poly_len):
            AB = np.subtract(polygon[p - 1], polygon[p - 2])
            BC = np.subtract(polygon[p], polygon[p - 1])
            x_products.append(cross_vectors_xy(AB, BC))
        if not (all(i[2] > 0.0
                    for i in x_products) or all(i[2] < 0.0
                                                for i in x_products)):
            sys.exit("the polygon is not convex.")
        # compute internal areas
        int_areas = []
        for p in range(poly_len - 2):
            v1 = np.subtract(polygon[p + 1], polygon[0])
            v2 = np.subtract(polygon[p + 2], polygon[0])
            int_areas.append(abs(cross_vectors_xy(v2, v1)[2] / 2))
        #compute toal area
        poly_area = sum(int_areas)

    return poly_area
def polygon_area_xy(polygon):
    from compas.geometry import cross_vectors_xy
    area_running_sum = 0.0
    for index in range(len(polygon)):
        p0 = polygon[index]
        p1 = polygon[(index + 1) % len(polygon)]
        #print(cross_vectors_xy(p0,p1)[2])
        area_running_sum += cross_vectors_xy(p0, p1)[2]
    return area_running_sum / 2.0
Пример #3
0
def convex_hull_xy(points):
    """Computes the convex hull of a set of 2D points.

    Input: an iterable sequence of (x, y) pairs representing the points.
    Output: a list of vertices of the convex hull in counter-clockwise order,
      starting from the vertex with the lexicographically smallest coordinates.
    Implements Andrew's monotone chain algorithm. O(n log n) complexity.
    """

    # Sort the points lexicographically (tuples are compared lexicographically).
    # Remove duplicates to detect the case we have just one unique point.
    points = sorted(set(points))

    # Boring case: no points or a single point, possibly repeated multiple times.
    if len(points) <= 1:
        return points

    # # 2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product.
    # # Returns a positive value, if OAB makes a counter-clockwise turn,
    # # negative for clockwise turn, and zero if the points are collinear.
    # def cross(o, a, b):
    #     return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])

    # Build lower hull
    lower = []
    for p in points:
        while len(lower) >= 2 and cross_vectors_xy(lower[-2], lower[-1],
                                                   p) <= 0:
            lower.pop()
        lower.append(p)

    # Build upper hull
    upper = []
    for p in reversed(points):
        while len(upper) >= 2 and cross_vectors_xy(upper[-2], upper[-1],
                                                   p) <= 0:
            upper.pop()
        upper.append(p)

    # Concatenation of the lower and upper hulls gives the convex hull.
    # Last point of each list is omitted because it is repeated at the beginning of the other list.
    return lower[:-1] + upper[:-1]
Пример #4
0
 def cross(o, a, b):
     u = subtract_vectors(a, o)
     v = subtract_vectors(b, o)
     return cross_vectors_xy(u, v)[2]