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
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]
def cross(o, a, b): u = subtract_vectors(a, o) v = subtract_vectors(b, o) return cross_vectors_xy(u, v)[2]