def get_polygon(self, dangle=np.radians(1)): """ Get the wedge as a polygon. :param dphi: Approximate phi increment of the circle part (deg) :return xy: wedge as a polygon (Nx2 array) """ # end points and angles of arc points = intersect(self.horizontal_line, self.circle) if self.diagonal_line.isabove(points[0]): point1 = points[0] else: point1 = points[1] angle1 = np.arctan2(point1[1] - self.circle.yc, point1[0] - self.circle.xc) points = intersect(self.diagonal_line, self.circle) if self.horizontal_line.isbelow(points[0]): point2 = points[0] else: point2 = points[1] angle2 = np.arctan2(point2[1] - self.circle.yc, point2[0] - self.circle.xc) # arc xy = self.circle.get_polygon(angle1, angle2, dangle) # prepend origin origin = intersect(self.horizontal_line, self.diagonal_line) xy = np.insert(xy, 0, origin[0], axis=0) return xy
def intersect(self, object, tol=0.001): """ Intersect the wedge with a line or circle. :param object: Line or circle to be intersected. :param tol: absolute tolerance for containing points or removing duplicate points. :return [(x, y), ...]: List of intersection points. """ # intersect the lines and the circle defining the wedge with the line points = list(intersect(self.horizontal_line, object)) points += list(intersect(self.diagonal_line, object)) points += list(intersect(self.circle, object)) # collect points outside the wedge delete_points = set() for point in points: if not self.contains(point): delete_points.add(point) # collect duplicate points points = list(set(points)) for point1 in points: for point2 in points: if point1 is point2: break x1, y1 = point1 x2, y2 = point2 if abs(x1 - x2) < tol and abs(y1 - y2) < tol: delete_points.add(point1) # remove points for delete_point in delete_points: points.remove(delete_point) # order according to increasing distance from origin def radius(point): return np.hypot(*point) points.sort(key=radius) return points
def connect(self, player, dest_pos): if player.pos not in self.lighthouses: raise MoveError("Player must be located at the origin lighthouse") if dest_pos not in self.lighthouses: raise MoveError("Destination must be an existing lighthouse") orig = self.lighthouses[player.pos] dest = self.lighthouses[dest_pos] if orig.owner != player.num or dest.owner != player.num: raise MoveError("Both lighthouses must be player-owned") if dest.pos not in player.keys: raise MoveError("Player does not have the destination key") if orig is dest: raise MoveError("Cannot connect lighthouse to itself") assert orig.energy and dest.energy pair = frozenset((orig.pos, dest.pos)) if pair in self.conns: raise MoveError("Connection already exists") x0, x1 = sorted((orig.pos[0], dest.pos[0])) y0, y1 = sorted((orig.pos[1], dest.pos[1])) for lh in self.lighthouses: if ( x0 <= lh[0] <= x1 and y0 <= lh[1] <= y1 and lh not in (orig.pos, dest.pos) and geom.colinear(orig.pos, dest.pos, lh) ): raise MoveError("Connection cannot intersect a lighthouse") new_tris = set() for c in self.conns: if geom.intersect(tuple(c), (orig.pos, dest.pos)): raise MoveError("Connection cannot intersect another connection") if orig.pos in c: third = (l for l in c if l != orig.pos).next() if frozenset((third, dest.pos)) in self.conns: new_tris.add((orig.pos, dest.pos, third)) player.keys.remove(dest.pos) self.conns.add(pair) for i in new_tris: self.tris[i] = [j for j in geom.render(i) if self.island[j]]
def connect(self, player, dest_pos): if player.pos not in self.lighthouses: raise MoveError("Player must be located at the origin lighthouse") if dest_pos not in self.lighthouses: raise MoveError("Destination must be an existing lighthouse") orig = self.lighthouses[player.pos] dest = self.lighthouses[dest_pos] if orig.owner != player.num or dest.owner != player.num: raise MoveError("Both lighthouses must be player-owned") if dest.pos not in player.keys: raise MoveError("Player does not have the destination key") if orig is dest: raise MoveError("Cannot connect lighthouse to itself") assert orig.energy and dest.energy pair = frozenset((orig.pos, dest.pos)) if pair in self.conns: raise MoveError("Connection already exists") x0, x1 = sorted((orig.pos[0], dest.pos[0])) y0, y1 = sorted((orig.pos[1], dest.pos[1])) for lh in self.lighthouses: if (x0 <= lh[0] <= x1 and y0 <= lh[1] <= y1 and lh not in (orig.pos, dest.pos) and geom.colinear(orig.pos, dest.pos, lh)): raise MoveError("Connection cannot intersect a lighthouse") new_tris = set() for c in self.conns: if geom.intersect(tuple(c), (orig.pos, dest.pos)): raise MoveError( "Connection cannot intersect another connection") if orig.pos in c: third = (l for l in c if l != orig.pos).next() if frozenset((third, dest.pos)) in self.conns: new_tris.add((orig.pos, dest.pos, third)) player.keys.remove(dest.pos) self.conns.add(pair) for i in new_tris: self.tris[i] = [j for j in geom.render(i) if self.island[j]]
wedge = Wedge() print(wedge.circle.xc, wedge.circle.yc, wedge.circle.r) print(wedge.get_polygon()) wedge = Wedge((1, 1, 2), (1, 0, 1)) print(wedge.circle.xc, wedge.circle.yc, wedge.circle.r) print(wedge.get_polygon()) exit() line1 = Line(1, 4, 6) line2 = Line(-5, 2, -8) circle1 = Circle(-1, 2, 5) circle2 = Circle(-2, 0, 4) solutions = intersect(line1, line2) for solution in solutions: x, y = solution print('x={}, y={}'.format(x, y)) assert isclose(x, 2) assert isclose(y, 1) solutions = intersect(circle1, line1) for solution in solutions: x, y = solution print('x={}, y={}'.format(x, y)) assert isclose((x - circle1.xc)**2 + (y - circle1.yc)**2, circle1.r**2) assert isclose(line1.a * x + line1.b * y, line1.c) solutions = intersect(line2, circle1) for solution in solutions:
def test_intersect(self): assert intersect(self.ab, self.cd) assert not intersect(self.ab, self.ef)