def compute_fundamental_triangle(tessellation_configuration): """Compute the vertices of the hyperbolic triangle with the following properties: - Vertex A lies at the origin. - Vertex C lies on the x-axis. - Vertex B is chosen so that angle CAB is pi / p, and (hyperbolic) angle ABC is pi / q. Derivation: The desired point is B = (b_x, b_y). This point is on the line L: y = tan(pi / p) x and on an unknown circle C perpendicular to the unit circle with center G = (g_x, 0). If A = (0, 0) and D = (d_x, 0) is the intersection of the line [AG] with C, then we need (hyperbolic) angle ABD to be pi / q. This is the same as requiring that the tangent line to C at B forms an angle of pi / q with the line between A and (cos(pi / q), sin(pi / q)), which has slope tan(pi / p + pi / q). The slope of a tangent line to circle C at point B is given by y'(B) = -(b_x - g_x) / b_y Setting y'(B) = tan(pi / p + pi / q) and writing b_y in terms of b_x gives tan(pi / p + pi / q) tan(pi / p) = (g_x - b_x) / b_x Or, letting Z = tan(pi / p + pi / q) tan(pi / p), b_x(Z + 1) = g_x. Next, we use the fact that C and the unit circle are orthogonal to get a relationship between their radii (pythagorean theorem): 1^2 + r^2 = g_x^2, where r^2 = (b_x - g_x)^2 + tan(pi / p)^2 b_x^2 substituting in g = b_x (Z + 1) and solving for b_x, b_x = sqrt(1 / (1 + 2Z - (tan(pi / p))^2)) We can then solve for b_y, g, and d_x trivially. """ p = tessellation_configuration.numPolygonSides q = tessellation_configuration.numPolygonsPerVertex tan_p = math.tan(math.pi / p) Z = math.tan(math.pi / p + math.pi / q) * tan_p b_x = math.sqrt(1 / (1 + 2 * Z - tan_p**2)) b_y = b_x * tan_p g_x = b_x * (Z + 1) d_x = g_x - math.sqrt(b_y**2 + (b_x - g_x)**2) A = Point(0, 0) B = Point(b_x, b_y) D = Point(d_x, 0) return [A, B, D]
def draw_rectangle(self, rectangle, color="black", linewidth=0.5): c1 = self.point_to_coordinates(rectangle.p1) c2 = self.point_to_coordinates(Point(rectangle.p1.x, rectangle.p2.y)) c3 = self.point_to_coordinates(rectangle.p2) c4 = self.point_to_coordinates(Point(rectangle.p2.x, rectangle.p1.y)) path = "{0}--{1}--{2}--{3}--cycle".format(c1, c2, c3, c4) self.draw_path(path, color=color, linewidth=linewidth)
def test_cross(self): np.testing.assert_array_equal( self.pnts.cross(self.pnts).data, np.array(np.vectorize( lambda *args: tuple(cross_product(Point(*args), Point(*args))) )(*self.points.T)).T )
def split_on_lines(regions, frame): rois = [] for region in regions: roi = Rectangle.from_bbox(region.bbox) fragment = Rectangle.from_bbox(region.bbox).sample_from_image(frame) lines = lines_y(fragment) if not len(lines): rois.append(roi) continue distances = [] line_midpoints = list(map(lambda line: Point((line[0] + line[2]) // 2, (line[1] + line[3]) // 2), lines)) center = Point(roi.w // 2, roi.h // 2) dist_from_center = lambda point: Point.point_distance(center, point) distances = list(map(dist_from_center, line_midpoints)) _, central_line_midpoint = min(zip(distances, line_midpoints), key= lambda pair: pair[0]) mid_x = central_line_midpoint.x left_w = mid_x right_w = roi.w - mid_x if (left_w / right_w > 0.5 and left_w / right_w < 2): left = Rectangle(roi.x, roi.y, left_w, roi.h) right = Rectangle(roi.x + left_w, roi.y, right_w, roi.h) rois.extend([left, right]) else: rois.append(roi) return rois
def test_brightness_radius(self): s0 = stars.Star(Point(1, 0, 0), 'A', 1, 'and', None) s1 = stars.Star(Point(1, 0, 0), 'A', 3, 'and', None) s2 = stars.Star(Point(1, 0, 0), 'A', 3, 'and', None) sky = stars.StarrySky(Point(1, 0, 0), Point(0, 1, 0), [s0, s1, s2]) st = sky.get_stars() self.assertFalse(st[0].r == st[1].r)
def test_brightness(self): s0 = stars.Star(Point(1, 0, 0), 'A', 1, 'and', None) s1 = stars.Star(Point(1, 0, 0), 'A', 3, 'and', None) s2 = stars.Star(Point(1, 0, 0), 'A', 3, 'and', None) sky = stars.StarrySky(Point(1, 0, 0), Point(0, 1, 0), [s0, s1, s2]) st = sky.get_stars() self.assertTrue(st[0].m == 1)
def test_scale(self): sky = stars.StarrySky(Point(1, 0, 0), Point(0, 1, 0), []) sky.resize(Point(100, 100)) s0 = stars.Star(Point(0, 0, 0), 'A', 1, 'and', None) sky.scale(s0) self.assertAlmostEqual(s0.x, 50) self.assertAlmostEqual(s0.y, 50)
def __get_point_distances(self, mytank, obstacle): d1 = get_distance(Point(obstacle[0]), mytank) d2 = get_distance(Point(obstacle[1]), mytank) d3 = get_distance(Point(obstacle[2]), mytank) d4 = get_distance(Point(obstacle[3]), mytank) return [d1, d2, d3, d4]
def drawDebug(frame, detections, polygon: Polygon): # Рисуем полигон for i in range(polygon.vertexCount): x1 = polygon.vertices[i].x y1 = polygon.vertices[i].y x2 = polygon.vertices[(i + 1) % polygon.vertexCount].x y2 = polygon.vertices[(i + 1) % polygon.vertexCount].y cv2.line(frame, (x1, y1), (x2, y2), (0, 0, 255), 1) if len(detections) == 0: return frame # Рисуем обнаружения for x, y, w, h in detections: rectCentre = Point(x + w / 2, y + h / 2) rectColor = (0, 255, 0) #green distanceToPoly = polygon.distance(rectCentre) if distanceToPoly < SHADE_DISTANCE: rectColor = Point.lerp(rectColor, (255, 0, 0), 1 - distanceToPoly / SHADE_DISTANCE) cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.putText(frame, str(distanceToPoly), (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, rectColor, 2) return frame
def read(file_nm, no_strips): """Reads a file with on the first uncommented line a bbox (4 numbers separated by a space) and subsequently 0 or more lines with points (2 numbers separated by a space) into a Strip Structure. If no valid box is found in the input file, it returns None. Otherwise a StripStructure with 0 or more points is returned. Returns - None or a StripStructure instance """ with open(file_nm, 'r') as f: lines = [line for line in f.readlines() if not line.startswith('#')] bbox, *pts = [[float(c) for c in line.split(' ')] for line in lines] if len(bbox) == 4: extent = Rectangle( Point(bbox[0], bbox[1]), Point(bbox[2], bbox[3]) ) structure = StripStructure(extent, no_strips) for pt in pts: if len(pt) == 2: structure.append_point(Point(pt[0], pt[1])) return structure
def __init__(self, x, y, robot, obstacles, start, goal, cspace, display_tree=False): '''Defines a motion planning problem. Args: x: float. the width of the map's area y: float. the height of the map's area robot: a robot.Robot instance obstacles: list of geometry.Objects self.robot can't move through start: tuple of floats: starting configuration of self.robot goal: tuple of floats: goal configuration of self.robot cspace: robot.Configuration space of self.robot display_tree: bool. if True, draw the generated plan trees ''' self.x = x self.y = y self.robot = robot self.obstacles = obstacles self.start = start self.goal = goal self.region = AABB(Point(0, 0), Point(x, y)) self.cspace = cspace self.display_tree = display_tree assert self.valid_configuration(self.start) assert self.valid_configuration(self.goal)
def test_find_path_astar_same_place(self): world_map = [ '..', '..', ] path = find_path_astar(world_map, Point(1, 0), Point(1, 0), '#') assert path == [Point(1, 0)]
def testHit(self): sphere = Sphere() ray1 = Ray(origin=Point(0, 0, 2), dir=-VEC_Z) intersection1 = sphere.ray_intersection(ray1) assert intersection1 assert HitRecord( world_point=Point(0.0, 0.0, 1.0), normal=Normal(0.0, 0.0, 1.0), surface_point=Vec2d(0.0, 0.0), t=1.0, ray=ray1, material=sphere.material, ).is_close(intersection1) ray2 = Ray(origin=Point(3, 0, 0), dir=-VEC_X) intersection2 = sphere.ray_intersection(ray2) assert intersection2 assert HitRecord( world_point=Point(1.0, 0.0, 0.0), normal=Normal(1.0, 0.0, 0.0), surface_point=Vec2d(0.0, 0.5), t=2.0, ray=ray2, material=sphere.material, ).is_close(intersection2) assert not sphere.ray_intersection( Ray(origin=Point(0, 10, 2), dir=-VEC_Z))
def test_vec_point_multiplication(self): m = Transformation( m=[ [1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 9.0, 8.0, 7.0], [0.0, 0.0, 0.0, 1.0], ], invm=[ [-3.75, 2.75, -1, 0], [5.75, -4.75, 2.0, 1.0], [-2.25, 2.25, -1.0, -2.0], [0.0, 0.0, 0.0, 1.0], ], ) assert m.is_consistent() expected_v = Vec(14.0, 38.0, 51.0) assert expected_v.is_close(m * Vec(1.0, 2.0, 3.0)) expected_p = Point(18.0, 46.0, 58.0) assert expected_p.is_close(m * Point(1.0, 2.0, 3.0)) expected_n = Normal(-8.75, 7.75, -3.0) assert expected_n.is_close(m * Normal(3.0, 2.0, 4.0))
def test_is_close(self): ray1 = Ray(origin=Point(1.0, 2.0, 3.0), dir=Vec(5.0, 4.0, -1.0)) ray2 = Ray(origin=Point(1.0, 2.0, 3.0), dir=Vec(5.0, 4.0, -1.0)) ray3 = Ray(origin=Point(5.0, 1.0, 4.0), dir=Vec(3.0, 9.0, 4.0)) assert ray1.is_close(ray2) assert not ray1.is_close(ray3)
def test_distance_to_3_4_from_origin_should_be_5(self): my_point = Point (0 , 0) another_point = Point (3 , 4) self.assertEqual(5, my_point.distance_to(another_point)) self.assertEqual(5, another_point.distance_to(my_point))
def test_intersection_1(): l1 = Line() # X axis l2 = Line(direction_vector=Vector([0, 1, 0]), point=Point(0, 1, 0)) # Y-axis l3 = Line(direction_vector=Vector([-1, 1, 0]), point=Point(3, 0, 0)) assert l1.intersection(l2) == Point(0, 0, 0) assert l3.intersection(l2) == Point(0, 3, 0)
def test_equality_false(self): # given the two points with different coordinates point1 = Point(5, 0) point2 = Point(5, 5) # then they are not equal self.assertNotEqual(point1, point2)
def test_equality_true(self): # given the two points with the same coordinates point1 = Point(5, 0) point2 = Point(5, 0) # then they are equal self.assertEqual(point1, point2)
def fit_points(points: Points): xy = np.polyfit(points.x, points.y, 1) xz = np.polyfit(points.x, points.z, 1) x0 = min(points.x) x1 = max(points.x) return Line(Point(x0, x0 * xy[0] + xy[1], x0 * xz[0] + xz[1]), Point(x1, x1 * xy[0] + xy[1], x1 * xz[0] + xz[1]))
def add_cutout(self, kind, corner_1, corner_2, bb_inner='sw', name=None, rotate=0, flipxy=False): import copy c1 = copy.copy(corner_1) c2 = copy.copy(corner_2) # Change signs so positive relative movements go into the side if 'n' in bb_inner: c1.y = -corner_1.y c2.y = -corner_2.y if 'e' in bb_inner: c1.x = -corner_1.x c2.x = -corner_2.x if flipxy: c1 = Point(c1.y, c1.x) c2 = Point(c2.y, c2.x) bb = self.inner_bounding_box[bb_inner] c1 = c1.relative_to(bb) c2 = c2.relative_to(bb) c1.rotate(rotate, bb) c2.rotate(rotate, bb) self.cutouts.append((kind, name, c1, c2))
def __init__(self, extent, no_strips): """Constructor. Inits a StripStructure instance with the correct number of Strip instances and makes sure that the domain is correctly divided over the strips. """ self.strips = [] # Extend this method, # so that the right number of strip objects (with the correct extent) # are appended to the strips list # assuming that the extent is a rectangle instance # should have no_strips no of strips as rectangle instances, need to divide the extent into multiple rects ll = extent.ll ur = extent.ur del_x = extent.width() strip_leng = del_x / no_strips new_ll_x = ll.x new_ur_x = ll.x + strip_leng for _ in range(no_strips): s = Strip(Rectangle(Point(new_ll_x, ll.y), Point(new_ur_x, ur.y))) new_ll_x += strip_leng new_ur_x += strip_leng #append a strip rect instance to strips list self.strips.append(s)
def __init__(self, a: Point = Point(0, 0, 0), b: Point = Point(1, 0, 0)): if not all(isinstance(p, Point) for p in (a, b)): raise TypeError("args a and b must be of type Point") if a == b: raise ValueError("points a and b are same!") self.a = a self.b = b
def test_distance_to_3_4_from_origin_should_be_5(self): origin = Point(0, 0) other_point = Point(3, 4) self.assertEqual(5, origin.distance_to(other_point)) self.assertEqual(5, other_point.distance_to(origin))
def last_changes(final_list_of_segments, final_list_of_circles): new_segments = [] for Seg in final_list_of_segments: P1 = Seg.point_1 P2 = Seg.point_2 EPSSS = 10 p1x = P1.x p1y = P1.y p2x = P2.x p2y = P2.y P1_new = Point(p1x, p1y) P2_new = Point(p2x, p2y) k1 = False k2 = False for circle in final_list_of_circles: radius_ = circle.radius center_ = circle.center distt1 = Point.distance_between(P1, center_) if abs(distt1 - radius_) < EPSSS: P1_new = circle.project_point_seg(Seg, P1) k1 = True distt2 = Point.distance_between(P2, center_) if abs(distt2 - radius_) < EPSSS: P2_new = circle.project_point_seg(Seg, P2) k2 = True if k1 and k2: break new_segments.append(Segment(P1_new, P2_new)) return new_segments
def concave_triangle(n: int, width: float, height: float, inner_height: float = None, round: int = 4) -> Union[Polygon, TriangulatedPolygon]: """A concave triangle with one point at the top and many points on the bottom.""" if n < 4: raise ValueError('Number of vertices MUST be at least 4.') if height <= 0 or width <= 0: raise ValueError('Height and width MUST be positive.') if inner_height is None: inner_height = 0.1 * height elif inner_height >= height: raise ValueError('Inner height MUST be less than height.') points = deque([Point(0, height).round(round)]) half_n = n // 2 center_point = half_n * 2 == n width /= 2 for i in range(half_n): if i + 1 == half_n and center_point: points.append(Point(0, inner_height).round(round)) continue x = i * width / half_n x_exp = i / half_n * log(100) points.append( Point(-width + x, inner_height * (1 - exp(-x_exp))).round(round)) points.appendleft( Point(width - x, inner_height * (1 - exp(-x_exp))).round(round)) return points
def testTransformation(self): plane = Plane(transformation=rotation_y(angle_deg=90.0)) ray1 = Ray(origin=Point(1, 0, 0), dir=-VEC_X) intersection1 = plane.ray_intersection(ray1) assert intersection1 assert HitRecord( world_point=Point(0.0, 0.0, 0.0), normal=Normal(1.0, 0.0, 0.0), surface_point=Vec2d(0.0, 0.0), t=1.0, ray=ray1, material=plane.material, ).is_close(intersection1) ray2 = Ray(origin=Point(0, 0, 1), dir=VEC_Z) intersection2 = plane.ray_intersection(ray2) assert not intersection2 ray3 = Ray(origin=Point(0, 0, 1), dir=VEC_X) intersection3 = plane.ray_intersection(ray3) assert not intersection3 ray4 = Ray(origin=Point(0, 0, 1), dir=VEC_Y) intersection4 = plane.ray_intersection(ray4) assert not intersection4
def ribbon(scale, seq, enu2ned): left = Point(0, -scale / 2, 0) right = Point(0, scale / 2, 0) # transform origin and wingtips to world frame curPose = seq.get_state_from_index(0).transform ctr = seq.get_state_from_index(0).pos curLeft = curPose.point(left) curRight = curPose.point(right) # init vertex and face lists x = [ctr.x, curLeft.x, curRight.x] y = [ctr.y, curLeft.y, curRight.y] z = [ctr.z, curLeft.z, curRight.z] faces = [] facecolors = [] ctrIndex = 0 for i in range(1, seq.data.shape[0]): # transform origin and wingtips to world frame nextPose = seq.get_state_from_index(i).transform nextctr = seq.get_state_from_index(i).pos nextLeft = nextPose.point(left) nextRight = nextPose.point(right) # update vertex and face lists x.extend([nextctr.x, nextLeft.x, nextRight.x]) y.extend([nextctr.y, nextLeft.y, nextRight.y]) z.extend([nextctr.z, nextLeft.z, nextRight.z]) [roll, pitch, wca, wca_axis] = maneuverRPY(0, seq.get_state_from_index(i), enu2ned) # [roll, pitch, wca, wca_axis] = maneuverRPY(0, enu2ned.quat(seq.get_state_from_index(i))) facecolor = rollColor(roll) # clockwise winding direction faces.append([ctrIndex, ctrIndex + 1, ctrIndex + 4]) facecolors.append(facecolor) faces.append([ctrIndex, ctrIndex + 5, ctrIndex + 2]) facecolors.append(facecolor) faces.append([ctrIndex, ctrIndex + 4, ctrIndex + 5]) facecolors.append(facecolor) ctrIndex += 3 I, J, K = np.array(faces).T return [ go.Mesh3d(name='ribbon', x=x, y=y, z=z, i=I, j=J, k=K, intensitymode="cell", facecolor=facecolors, showlegend=True, hoverinfo="none") ]
def arm_command(self, path_name, distance='0'): if path_name in predefined_paths: intervals = self.robot.execute_predefined_arm_path(path_name) else: try: distance = int(distance) except ValueError: raise CommandError("Distance must be integer, got '" + distance + "'") if path_name == 'east': delta = Point(distance, 0) elif path_name == 'west': delta = Point(-distance, 0) elif path_name == 'north': delta = Point(0, distance) elif path_name == 'south': delta = Point(0, -distance) else: raise CommandError("Unknown arm path '" + path_name + "'") if distance == 0: raise CommandError('Must specify nonzero distance') intervals = self.robot.execute_arm_path(delta) path_length = intervals.shape[0] left_bytes = ''.join([tohex(i, 8) for i in intervals[:, 0]]) right_bytes = ''.join([tohex(i, 8) for i in intervals[:, 1]]) encoded_path = tohex(path_length, 8) + left_bytes + right_bytes return 'A' + encoded_path
def tiptrace(seq, span, enu2ned): def rpyd(i): [roll, pitch, wca, wca_axis] = maneuverRPY(0, seq.get_state_from_index(i), enu2ned) # return enu2ned.quat(seq.get_state_from_index(i).att).to_euler() * 180/np.pi return Point(roll, -pitch, wca) * 180 / np.pi text = [ "t:{:.1f}, roll: {:.1f}, pitch: {:.1f}, wca: {:.1f}".format( seq.data.index[i], rpyd(i).x, rpyd(i).y, rpyd(i).z) for i in range(seq.data.shape[0]) ] def make_offset_trace(pos, name, colour, text): return trace3d(*seq.body_to_world(pos).data.T, name=name, colour=colour, text=text, width=1) return [ make_offset_trace(Point(0, span / 2, 0), "starboard", "green", text), make_offset_trace(Point(0, -span / 2, 0), "port", "red", text) ]
def ur5(): I = Interface() I.connect() MOVABLE_ARM_JOINTS = [1, 2, 3, 4, 5, 6] ROBOT_URDF_PATH = '../models/ur5_description/urdf/ur5.urdf' END_EFFECTOR_LINK = 'end_effector_link' TABLE = '../models/table/table.urdf' CUBE_URDF = '../models/cube/%s_cube.urdf' # ------------------------UR5--------------------------# x_offset = 0.33 y_offset = 0.15 robot = I.load_model(ROBOT_URDF_PATH) redBlock1 = I.load_model(CUBE_URDF % 'red', Pose(Point(0.3 + x_offset, -0.1 + y_offset, 0.265)), fixed_base=False) redBlock2 = I.load_model(CUBE_URDF % 'red', Pose( Point(0.35 + x_offset, 0.05 + y_offset, 0.265)), fixed_base=False) table = I.load_model(TABLE, Pose(Point(0.35 + x_offset, 0.0 + y_offset, 0.05), Euler(0.0, 0.0, 1.57)), fixed_base=False, scaling=0.3) # ------------------------Jaco---------------------------# velocities = Csv('UR5_velocities.csv', [ 'joints_1', 'joints_2', 'joints_3', 'joints_4', 'joints_5', 'joints_6', 'joints_11', 'joints_13', 'joints_15', 'joints_16', 'joints_17', 'joints_18' ], mode='r').read() torques = Csv('UR5_torques.csv', [ 'joints_1', 'joints_2', 'joints_3', 'joints_4', 'joints_5', 'joints_6', 'joints_11', 'joints_13', 'joints_15', 'joints_16', 'joints_17', 'joints_18' ], mode='r').read() action = Csv('UR5_action.csv', ['action'], mode='r').read() for joint, values in velocities.items(): velocities[joint] = map(float, values) velocities = np.vstack(velocities.values()) for joint, values in torques.items(): torques[joint] = map(float, values) torques = np.vstack(torques.values()) I.replay(robot, [velocities.T, torques.T, action.values()[0]]) # time.sleep(5.0) I.disconnect()
def _point_or_random(self, options): if 'point' in options: point = Point(options['point'][0], options['point'][1], self._config['dim']) else: point = Point.random(self._config['dim']) return point
def randomPoint(size = (1000, 800), border = 0): if not border: return Point(random.randrange(size[0]), random.randrange(size[1])) else: s0 = size[0] - 2 * border s1 = size[1] - 2 * border p = Point(random.randrange(s0), random.randrange(s1)) return p.transform(Point(border, border))
def make_img(fractal): size = Point(200,200) bbox = BoundingBox(Point(0,0), size) im = Image.new("RGB", size.tuple(), "white") draw = ImageDraw.Draw(im) fractal.draw(draw, bbox) return im
def __init__(self, location, cat='', name='', rating=[], age_groups=[], feature=[], description='', outdoor=True): Point.__init__(self, location.x, location.y) self.geo = (self.x, self.y) # redundant, but may be useful for Kuba self.name = name self.type = cat Rating.__init__(self, rating) self.age_groups = age_groups Feature.__init__(self, feature) Description.__init__(self, description, outdoor)
def make_zoomed_img(fractal, amt, foci_idx=0): zoom = fractal.zoom_change ** amt size = Point(200,200) focus = fractal.foci[foci_idx] cam_center = Point(focus.x * size.x, focus.y * size.y) def transform(p): return ((p-cam_center)*zoom)+cam_center bbox = BoundingBox(transform(Point(0,0)), transform(size)) im = Image.new("RGB", size.tuple(), "white") draw = ImageDraw.Draw(im) fractal.draw(draw, bbox) return im
def isObstacle(self, x, y): """ True if there's an obstacle in (x, y), false otherwise """ point = Point(x, y) isObst = False id = 0 while not isObst and id<len(self.shapes): if self.shapes[id] != self.rect: isObst = point.containedIn(self.shapes[id]) id += 1 return isObst
def test_intersection(): plane = Plane(0.0, 0.0, 1.0, -0.9) a = Point(0.5, 0.5, -0.9) b = Point(0.0, 0.0, 0.0) assert plane.intersection(a, b) == Point(-0.5, -0.5, 0.9) points = [Point(0.5, 0.0, 0.0), Point(0.5, 1.0, 0.0), Point(0.5, 1.0, 1.0), Point(0.5, 0.1, 1.0)] polygon = Polygon(points, Point(0.5, 0.5, 0.5)) source = Point(0.5, 0.5, 0.5) mirror = source.mirror_with(Plane.from_normal_and_point(Vector(1.0, 0.0, 0.0), Point(1.0, 0.5, 0.5))) intersection = polygon.plane().intersection(mirror, Point(1.0, 0.0, 0.0)) assert intersection == Point(0.5, -0.5, -0.5)
def __init__(self, pos, revolvable=True, angle=None): self.coord = Point(pos) self.target_coord = Point(0, 0) if angle is None: angle = randint(0, 360) self.vector = Vector(angle, 0) self.course = self.vector.angle self.shot = False self._revolvable = revolvable self.load_value = 0 self._distance_cache = {} self._events = Queue() self._selected = False self._state = 'stopped' self._need_moving = False # container - это список обьектов игры по типам, # инициализируется в Scene if self.container is None: raise Exception("You must create robopycode.engine.Scene" " instance at first!") self.container.append(self) GameObject._objects_count += 1 self.id = GameObject._objects_count self.debug('born %s', self) self._heartbeat_tics = 5
class ToolbarOption(pygame.sprite.Sprite): def __init__(self, top, name, data, font_manager): pygame.sprite.Sprite.__init__(self) self.selected = False self.name = name self.data = data self.position = Point(constants.HORIZONTAL_TILES + editor_constants.RIGHT_BAR_ITEM_SPACING, top) self.size = editor_constants.RIGHT_BAR_ITEM_RATIO self.font_manager = font_manager self.update_graphics() def toggle_select(self): self.selected = not self.selected self.update_graphics() def update_graphics(self): size = int(round(self.size * constants.TILE_SIZE)) self.image = pygame.Surface([size, size]) self.image.fill(self.data.color) if self.selected: rect = pygame.Rect(self.image.get_rect()) pygame.draw.rect(self.image, pygame.Color(0, 0, 0), rect, 1) text = self.font_manager.render(self.data.label, 20, pygame.color.Color(0, 0, 0)) dest = Point(self.image.get_width() / 2 - text.get_width() / 2, self.image.get_height() / 2 - text.get_height() / 2) self.image.blit(text, dest) self.rect = self.image.get_rect(topleft=self.position.scale(constants.TILE_SIZE))
def snapToGrid(self, point): snap_point = Point(point.x, point.y) width = self.surface.get_width() center = width / 2 half = self.grid_size / 2 offset = map(lambda x: x - center, range(center % self.grid_size, width, self.grid_size)) possible_x = range(point.x - half, point.x + half) possible_y = range(point.y - half, point.y + half) for x in possible_x: if x in offset: snap_point.x = x break for y in possible_y: if y in offset: snap_point.y = y break return snap_point
class Tile(pygame.sprite.Sprite): def __init__(self, tile_type, x, y): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface([constants.TILE_SIZE, constants.TILE_SIZE], flags=pygame.SRCALPHA) if tile_type == "W": self.image.fill(constants.TILE_WALL_COLOR) self.solid = True elif tile_type == "G": self.image.fill(constants.TILE_GROUND_COLOR) self.solid = False self.type = tile_type self.rect = self.image.get_rect() self.rect.x = constants.TILE_SIZE * x self.rect.y = constants.TILE_SIZE * y self.position = Point(x + 0.5, y + 0.5) self.exposed_sides = {TILE_RIGHT: True, TILE_LEFT: True, TILE_TOP: True, TILE_BOTTOM: True} self.sides = None def set_accessible(self, direction, value): self.exposed_sides[direction] = value def get_sides(self): if self.sides is None: tile_top_left = self.position.translate(Vector(-0.5, -0.5)) tile_top_right = self.position.translate(Vector(0.5, -0.5)) tile_bottom_right = self.position.translate(Vector(0.5, 0.5)) tile_bottom_left = self.position.translate(Vector(-0.5, 0.5)) self.sides = [] tile_left = Line(tile_bottom_left, tile_top_left) if self.exposed_sides[TILE_LEFT]: self.sides.append(tile_left) tile_right = Line(tile_top_right, tile_bottom_right) if self.exposed_sides[TILE_RIGHT]: self.sides.append(tile_right) tile_top = Line(tile_top_left, tile_top_right) if self.exposed_sides[TILE_TOP]: self.sides.append(tile_top) tile_bottom = Line(tile_bottom_right, tile_bottom_left) if self.exposed_sides[TILE_BOTTOM]: self.sides.append(tile_bottom) return self.sides
def _scale(self, point, rel, reverse, ratio): width = float(self.shape.bounds.width) height = float(self.shape.bounds.height) if ratio: old_r = self.grabbed_stamp.scale[1] / self.grabbed_stamp.scale[0] if old_r != ratio: self.grabbed_stamp.scale = (self.grabbed_stamp.scale[0], ratio * self.grabbed_stamp.scale[0]) print 'ratio:', self.grabbed_stamp.scale[1] / self.grabbed_stamp.scale[0] if reverse: anchor = Point(width/2 * self.grabbed_stamp.scale[0], height/2 * self.grabbed_stamp.scale[1]) else: anchor = Point(-width/2 * self.grabbed_stamp.scale[0], -height/2 * self.grabbed_stamp.scale[1]) anchor = Point.rotate(anchor, self.grabbed_stamp.angle) anchor.x += self.grabbed_stamp.pos.x anchor.y += self.grabbed_stamp.pos.y rel = Point(point.x - anchor.x, point.y - anchor.y) rel = Point.rotate(rel, -self.grabbed_stamp.angle) if ratio != None: a = self.grabbed_stamp.scale[0] > 0 b = rel.x < rel.y c = reverse # No, this is not pretty. But I didn't like the alternative much # either. This reassigns either the x or y value such that # rel.y / rel.x = ratio, while also indirectly keeding the anchor # 'within' rel. This creates the expeceted behavior while resizing # and keeping the ratio, even when mirrored and flipped. if ((a and b and c) or (a and not b and not c) or (not a and b and not c) or (not a and not b and c)): rel.y = ratio * rel.x elif ((a and b and not c) or (a and not b and c) or (not a and b and c) or (not a and not b and not c)): rel.x = 1 / ratio * rel.y dx = rel.x dy = rel.y if reverse: dx = -dx dy = -dy old_scale_x = self.grabbed_stamp.scale[0] old_scale_y = self.grabbed_stamp.scale[1] old_dx = width - old_scale_x * width old_dy = height - old_scale_y * height new_dx = old_dx + dx new_dy = old_dy + dy new_scale_x = (width - new_dx) / width new_scale_y = (height - new_dy) / height if abs(new_scale_x) > 0.1 and abs(new_scale_y) > 0.1: self.grabbed_stamp.scale = (new_scale_x, new_scale_y) if reverse: dx = -dx dy = -dy p = Point.rotate(Point(dx, dy), self.grabbed_stamp.angle) self.grabbed_stamp.pos.x += p.x / 2.0 self.grabbed_stamp.pos.y += p.y / 2.0
def create_image(color): #the grid cell size is 25*25, but we want a little bleed over #for the black outline width = 26 height =26 margin = 4 im = Image.new("RGB", (width, height)) draw = ImageDraw.Draw(im) #each corner of the square, starting in the upper-left and moving clockwise a = Point(0,0) b = Point(width-1, 0) c = Point(width-1, height) d = Point(0, height) #bounds of the interior square inner_left = margin inner_right = width-margin-1 inner_top = margin inner_bottom = height-margin #points of the interior square e = Point(inner_left, inner_top) f = Point(inner_right, inner_top) g = Point(inner_right, inner_bottom) h = Point(inner_left, inner_bottom) #left and right bevels draw.rectangle([a.tuple(), c.tuple()], fill=mid_color(color,black,0.1)) #interior square draw.rectangle([e.tuple(), g.tuple()], fill=color) #upper bevel draw.polygon([p.tuple() for p in [a,b,f,e]], fill=mid_color(color, white, 0.5)) #lower bevel draw.polygon([p.tuple() for p in [h,g,c,d]], fill=mid_color(color, black, 0.5)) #outline draw.rectangle([a.tuple(), (c-Point(0,1)).tuple()], outline=black, fill=None) return im
class VerticalToolbar(pygame.sprite.Sprite): def __init__(self, editor_level, font_manager): pygame.sprite.Sprite.__init__(self) self.editor_level = editor_level self.selected = None self.position = Point(constants.HORIZONTAL_TILES, 0) self.width = editor_constants.RIGHT_BAR_RATIO self.height = constants.VERTICAL_TILES self.options = Group() self.hotkeys = {} top = editor_constants.RIGHT_BAR_ITEM_SPACING for (name, data) in editor_constants.ENTITY_DATA: option = ToolbarOption(top, name, data, font_manager) if self.selected is None: self.select(option) self.options.add(option) top += editor_constants.RIGHT_BAR_ITEM_RATIO + editor_constants.RIGHT_BAR_ITEM_SPACING self.hotkeys[data.hotkey] = option self.update_graphics() def hotkey(self, hotkey): if hotkey in self.hotkeys: self.select(self.hotkeys[hotkey]) def select(self, option): if self.selected is not None: self.selected.toggle_select() self.selected = option self.selected.toggle_select() self.editor_level.entity_to_create = option.name def left_click(self, position, pressed): for option in self.options: rect = pygame.Rect(option.position.scale(constants.TILE_SIZE), (constants.TILE_SIZE * option.size, constants.TILE_SIZE * option.size)) if rect.collidepoint(position.scale(constants.TILE_SIZE)): self.select(option) def update_graphics(self): width = int(round(self.width * constants.TILE_SIZE)) height = int(round(self.height * constants.TILE_SIZE)) self.image = pygame.Surface([width, height]) self.image.fill(editor_constants.TOOLBAR_COLOR) self.rect = self.image.get_rect(topleft=self.position.scale(constants.TILE_SIZE)) def draw(self, screen): self.options.draw(screen)
class Room(Rect): """ This class represents a room in our dungeon - it has four walls and four corners. """ def __init__(self, center, width, height): start_x = int(center.x - (width / 2)) start_y = int(center.y - (height / 2)) start = Point(start_x, start_y) self.center = center super().__init__(start, width, height) end_x = self.start.x + width end_y = self.start.y + height self.end = Point(end_x, end_y) self.populate() _, self.top_right, self.bottom_left, _ = self.get_vertices() self.north = Wall("North", self.start, self.top_right) self.south = Wall("South", self.bottom_left, self.end) self.east = Wall("East", self.top_right, self.end) self.west = Wall("West", self.start, self.bottom_left) self.walls = [self.north, self.south, self.east, self.west] # need a copy that we won't change self._walls = [wall for wall in self.walls] def populate(self): """ This fills our internal list with the points between our start point and end point """ x_values = range(self.start.x, self.end.x) y_values = range(self.start.y, self.end.y) # range() isn't inclusive, so we'll need to add the end # point after we're done self.points = [Point(x, y).to_tuple() for x in x_values for y in y_values] self.points.append(self.end.to_tuple()) def within(self, point): """ Queries whether a point is inside the room. """ return point.to_tuple() in self.points def blacklist_wall(self, wall): """ Removes a wall from our acting list. """ self.walls.remove(wall)
def __init__(self, top, name, data, font_manager): pygame.sprite.Sprite.__init__(self) self.selected = False self.name = name self.data = data self.position = Point(constants.HORIZONTAL_TILES + editor_constants.RIGHT_BAR_ITEM_SPACING, top) self.size = editor_constants.RIGHT_BAR_ITEM_RATIO self.font_manager = font_manager self.update_graphics()
def __init__(self, tile_type, x, y): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface([constants.TILE_SIZE, constants.TILE_SIZE], flags=pygame.SRCALPHA) if tile_type == "W": self.image.fill(constants.TILE_WALL_COLOR) self.solid = True elif tile_type == "G": self.image.fill(constants.TILE_GROUND_COLOR) self.solid = False self.type = tile_type self.rect = self.image.get_rect() self.rect.x = constants.TILE_SIZE * x self.rect.y = constants.TILE_SIZE * y self.position = Point(x + 0.5, y + 0.5) self.exposed_sides = {TILE_RIGHT: True, TILE_LEFT: True, TILE_TOP: True, TILE_BOTTOM: True} self.sides = None
class Polyomino: def __init__(self): self.delta = Point(0,0) self.orientation = 0 self.points = [[],[],[],[]] self.name = "" def __iter__(self): for point in self.points[self.orientation]: yield point + self.delta def rotate_right(self): self.orientation = (self.orientation+1)%4 def rotate_left(self): self.orientation = (self.orientation-1)%4 def move(self, delta): self.delta += delta def move_to(self, target): """moves such that the top left corner of the Polyomino's hitbox is at target.""" left = min(p.x for p in self) top = min(p.y for p in self) dx = target.x - left dy = target.y - top self.move(Point(dx,dy)) def reset(self): self.delta = Point(0,0) self.orientation = 0 def copy(self): ret = Polyomino() ret.delta = self.delta.copy() ret.orientation = self.orientation ret.name = self.name for i in range(4): ret.points[i] = map(Point.copy, self.points[i]) return ret def __eq__(self, other): if not isinstance(other, Polyomino): return False return set(self) == set(other) def __ne__(self, other): return not self == other def __repr__(self): return "Polyomino({})".format(", ".join(map(str, self)))
def __init__(self, editor_level, font_manager): pygame.sprite.Sprite.__init__(self) self.editor_level = editor_level self.selected = None self.position = Point(constants.HORIZONTAL_TILES, 0) self.width = editor_constants.RIGHT_BAR_RATIO self.height = constants.VERTICAL_TILES self.options = Group() self.hotkeys = {} top = editor_constants.RIGHT_BAR_ITEM_SPACING for (name, data) in editor_constants.ENTITY_DATA: option = ToolbarOption(top, name, data, font_manager) if self.selected is None: self.select(option) self.options.add(option) top += editor_constants.RIGHT_BAR_ITEM_RATIO + editor_constants.RIGHT_BAR_ITEM_SPACING self.hotkeys[data.hotkey] = option self.update_graphics()
def __init__(self, center, width, height): start_x = int(center.x - (width / 2)) start_y = int(center.y - (height / 2)) start = Point(start_x, start_y) self.center = center super().__init__(start, width, height) end_x = self.start.x + width end_y = self.start.y + height self.end = Point(end_x, end_y) self.populate() _, self.top_right, self.bottom_left, _ = self.get_vertices() self.north = Wall("North", self.start, self.top_right) self.south = Wall("South", self.bottom_left, self.end) self.east = Wall("East", self.top_right, self.end) self.west = Wall("West", self.start, self.bottom_left) self.walls = [self.north, self.south, self.east, self.west] # need a copy that we won't change self._walls = [wall for wall in self.walls]
def __init__(self): self.delta = Point(0,0) self.orientation = 0 self.points = [[],[],[],[]] self.name = ""
def test_distance_to_same_point_should_be_zero(self): my_point = Point(5, 7) self.assertEqual(0, my_point.distance_to(my_point))
def localPoint(self, global_point): local_point = Point() local_point.x = global_point.x - self.rect.left - self.rect.width / 2 local_point.y = global_point.y - self.rect.top - self.rect.height / 2 return local_point
def create_image(color, right, down, left, up): #the grid cell size is 25*25, but we want a little bleed over #for the black outline width = 26 height =26 margin = 4 im = Image.new("RGBA", (width, height)) draw = ImageDraw.Draw(im) #each corner of the square, starting in the upper-left and moving clockwise a = Point(0,0) b = Point(width-1, 0) c = Point(width-1, height) - Point(0,1) d = Point(0, height) - Point(0,1) corners = [a,b,c,d] if up: draw.line([a.tuple(), b.tuple()], fill=color) if right: draw.line([b.tuple(), c.tuple()], fill=color) if down: draw.line([c.tuple(), d.tuple()], fill=color) if left: draw.line([d.tuple(), a.tuple()], fill=color) return im
import pygame import sys import time from geometry import Point import random from renderer import Renderer from algorithm import Algorithm random.seed() pygame.init() window = pygame.display.set_mode((800, 600)) rend = Renderer(window) point_list = Point.generate_points(100, -200, 200, -200, 200) algo = Algorithm(point_list) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit(0) algo.next_step() rend.queue_algorithm(algo) rend.draw() time.sleep(2) #pygame.draw.circle
def reset(self): self.delta = Point(0,0) self.orientation = 0
def board_vector(self): pos = Point(self.position.x, self.start.y) board = Vector(pos, pos.transform(self.direction)) return board
def polar_angle_sort(self, min_point): sort_list = copy.deepcopy(self.point_array) sort_list.remove(min_point) sort_list.sort(key = lambda point: Point.calculate_polar_angle(min_point, point)) sort_list.insert(0, min_point) return sort_list
class GameObject(): """ Main game object """ radius = 1 _objects_count = 0 states = ['stopped', 'turning', 'moving'] container = None _animated = True def __init__(self, pos, revolvable=True, angle=None): self.coord = Point(pos) self.target_coord = Point(0, 0) if angle is None: angle = randint(0, 360) self.vector = Vector(angle, 0) self.course = self.vector.angle self.shot = False self._revolvable = revolvable self.load_value = 0 self._distance_cache = {} self._events = Queue() self._selected = False self._state = 'stopped' self._need_moving = False # container - это список обьектов игры по типам, # инициализируется в Scene if self.container is None: raise Exception("You must create robopycode.engine.Scene" " instance at first!") self.container.append(self) GameObject._objects_count += 1 self.id = GameObject._objects_count self.debug('born %s', self) self._heartbeat_tics = 5 def __str__(self): return 'obj(%s, %s %s cour=%.1f %s)' \ % (self.id, self.coord, self.vector, self.course, self._state) def __repr__(self): return str(self) def debug(self, pattern, *args): """ Show debug information if DEBUG mode """ if isinstance(self, Tank): if self._selected: log.debug('%s:%s' % (self.id, pattern), *args) else: log.debug('%s:%s:%s' % (self.__class__.__name__, self.id, pattern), *args) def _need_turning(self): return self._revolvable and int(self.course) != int(self.vector.angle) def turn_to(self, arg1): """ Turn to the subject / in that direction """ if isinstance(arg1, GameObject) or arg1.__class__ == Point: self.vector = Vector(self, arg1, 0) elif arg1.__class__ == int or arg1.__class__ == float: direction = arg1 self.vector = Vector(direction, 0) else: raise Exception("use GameObject.turn_to(GameObject/Point " "or Angle). Your pass %s" % arg1) self._state = 'turning' def move(self, direction, speed=3): """ Ask movement in the direction of <angle>, <speed> """ if speed > tank_speed: speed = tank_speed self.vector = Vector(direction, speed) self.target_coord = self.coord + self.vector * 100 # далеко-далеко... self._need_moving = True if self._need_turning(): self._state = 'turning' else: self._state = 'moving' def move_at(self, target, speed=3): """ Ask movement to the specified point <object/point/coordinats>, <speed> """ if type(target) in (type(()), type([])): target = Point(target) elif target.__class__ == Point: pass elif isinstance(target, GameObject): target = target.coord else: raise Exception("move_at: target %s must be coord " "or point or GameObject!" % target) if speed > tank_speed: speed = tank_speed self.target_coord = target self.vector = Vector(self.coord, self.target_coord, speed) self._need_moving = True if self._need_turning(): self._state = 'turning' else: self._state = 'moving' def stop(self): """ Unconditional stop """ self._state = 'stopped' self._need_moving = False self._events.put(EventStopped()) def _game_step(self): """ Proceed one game step - do turns, movements and boundary check """ self.debug('obj step %s', self) if self._revolvable and self._state == 'turning': delta = self.vector.angle - self.course if abs(delta) < tank_turn_speed: self.course = self.vector.angle if self._need_moving: self._state = 'moving' else: self._state = 'stopped' self._events.put(EventStopped()) else: if -180 < delta < 0 or delta > 180: self.course -= tank_turn_speed else: self.course += tank_turn_speed self.course = normalise_angle(self.course) if self._state == 'moving': self.coord.add(self.vector) if self.coord.near(self.target_coord): self.stop() self._events.put(EventStoppedAtTargetPoint( self.target_coord)) # boundary_check left_ro = self._runout(self.coord.x) if left_ro: self.coord.x += left_ro + 1 self.stop() botm_ro = self._runout(self.coord.y) if botm_ro: self.coord.y += botm_ro + 1 self.stop() righ_ro = self._runout(self.coord.x, field_width) if righ_ro: self.coord.x -= righ_ro + 1 self.stop() top_ro = self._runout(self.coord.y, field_height) if top_ro: self.coord.y -= top_ro + 1 self.stop() self._heartbeat_tics -= 1 if not self._heartbeat_tics: event = EventHearbeat() self._events.put(event) self.hearbeat() self._heartbeat_tics = 5 def _runout(self, coordinate, hight_bound=None): """ proverka vyhoda za granicy igrovogo polja """ if hight_bound: out = coordinate - (hight_bound - self.radius) else: out = self.radius - coordinate if out < 0: out = 0 return out def distance_to(self, obj): """ Calculate distance to <object/point> """ if isinstance(obj, GameObject): # и для порожденных классов return self.coord.distance_to(obj.coord) if obj.__class__ == Point: return self.coord.distance_to(obj) raise Exception("GameObject.distance_to: obj %s " "must be GameObject or Point!" % (obj,)) def near(self, obj, radius=20): """ Is it near to the <object/point>? """ return self.distance_to(obj) <= radius def _proceed_events(self): while not self._events.empty(): event = self._events.get() event.handle(self) def stopped(self): """ Event: stopped """ pass def stopped_at_target(self): """ Event: stopped at target """ pass def hearbeat(self): """ Event: Heartbeat """ pass