def find_intersect(self, other: 'Segment') -> Optional[Intersection]: """ Gets the Intersection between this and another road if they intersect or if this road can be extended to intersect with it :param other: Another Segment to check for an intersection with :return: An Intersection tuple with the point and the factors for each road """ r = vectors.sub(self.end, self.start) s = vectors.sub(other.end, other.start) t_numerator = vectors.cross_product( vectors.sub(other.start, self.start), s) u_numerator = vectors.cross_product( vectors.sub(other.start, self.start), r) denominator = vectors.cross_product(r, s) if denominator == 0: return None this_factor = t_numerator / denominator other_factor = u_numerator / denominator if 0 < other_factor < 1: return Intersection( (self.start[0] + (this_factor * r[0]), self.start[1] + (this_factor * r[1])), this_factor, other_factor) return None
def offset_point(point, rotate_function, offset_length, predecessor, successor): pre_offset_vector = None suc_offset_vector = None if predecessor: pre_direction = vectors.unit(vectors.sub(point, predecessor)) pre_offset_vector = vectors.mult(rotate_function(pre_direction), offset_length) if successor: suc_direction = vectors.unit(vectors.sub(successor, point)) suc_offset_vector = vectors.mult(rotate_function(suc_direction), offset_length) if predecessor and successor: return intersection((vectors.add(predecessor, pre_offset_vector), vectors.add(point, pre_offset_vector)), (vectors.add(point, suc_offset_vector), vectors.add(successor, suc_offset_vector))) elif predecessor: return vectors.add(point, pre_offset_vector) elif successor: return vectors.add(point, suc_offset_vector) else: raise Exception( 'at least one of predecessor and successor have to be set')
def angle_between_ccw(road1: Segment, road2: Segment) -> float: """ Gets the angle between road1 and road2 in a counterclockwise direction """ if road1.start == road2.start: vect1 = vectors.sub(road1.end, road1.start) vect2 = vectors.sub(road2.end, road1.start) elif road1.start == road2.end: vect1 = vectors.sub(road1.end, road1.start) vect2 = vectors.sub(road2.start, road1.start) elif road1.end == road2.start: vect1 = vectors.sub(road1.start, road1.end) vect2 = vectors.sub(road2.end, road1.end) elif road1.end == road2.end: vect1 = vectors.sub(road1.start, road1.end) vect2 = vectors.sub(road2.start, road1.end) dot = vectors.dot(vect1, vect2) det = vectors.determinant(vect1, vect2) deg = math.degrees(math.atan2(det, dot)) if -180 <= deg <= 0: deg += 360 return deg
def closest_analogies( left2: str, left1: str, right2: str, words: List[Word] ) -> List[Tuple[float, Word]]: word_left1 = find_word(left1, words) word_left2 = find_word(left2, words) word_right2 = find_word(right2, words) if (not word_left1) or (not word_left2) or (not word_right2): return [] vector = v.add( v.sub(word_left1.vector, word_left2.vector), word_right2.vector) closest = most_similar(vector, words)[:10] def is_redundant(word: str) -> bool: """ Sometimes the two left vectors are so close the answer is e.g. "shirt-clothing is like phone-phones". Skip 'phones' and get the next suggestion, which might be more interesting. """ word_lower = word.lower() return ( left1.lower() in word_lower or left2.lower() in word_lower or right2.lower() in word_lower) closest_filtered = [(dist, w) for (dist, w) in closest if not is_redundant(w.text)] return closest_filtered
def point_at(self, factor: float) -> Tuple[float, float]: """ Gets the point along the road (length * factor) away from the start :param factor: Fraction of the way down the road, between 0 and 1 :return: The point along the road """ end_vector = vectors.sub(self.end, self.start) return self.start[0] + (factor * end_vector[0]), self.start[1] + ( factor * end_vector[1])
def _zoom_change(self, step, center): new_level = self._zoom_at(self._zoom_increment + step) old_world = screen_to_world(center, self.pan, self.zoom) new_world = screen_to_world(center, self.pan, new_level) world_pan = vectors.sub(new_world, old_world) self.zoom = new_level self.pan = vectors.add(self.pan, world_to_screen(world_pan, (0, 0), new_level)) self._zoom_increment += step return
def from_seg(segment: roads.Segment) -> Set[Tuple[int, int]]: """ Gets the sectors the segment is in or within snapping distance of """ start_sector = containing_sector(segment.start) end_sector = containing_sector(segment.end) aux_secs = set() if start_sector[0] != end_sector[0] and start_sector[1] != end_sector[1]: diff = vectors.sub(start_sector, end_sector) aux_secs.add((end_sector[0] + diff[0], end_sector[1])) aux_secs.add((end_sector[0], end_sector[1] + diff[1])) start_secs = from_point(segment.start, config.MIN_DIST_EDGE_CONTAINED) end_secs = from_point(segment.end, config.MIN_DIST_EDGE_CONTAINED) return start_secs.union(end_secs).union(aux_secs)
def closest_analogies(left2: str, left1: str, right2: str, words: List[Word]) -> List[Tuple[float, Word]]: word_left1 = find_word(words, left1) word_left2 = find_word(words, left2) word_right2 = find_word(words, right2) vector = v.add(v.sub(word_left1.vector, word_left2.vector), word_right2.vector) closest = sorted_by_similarity(words, vector)[:10] def is_redundant(word: str) -> bool: #Sometimes the two left vectors are so close the answer is e.g. #"shirt-clothing is like phone-phones". Skip 'phones' and get the next #suggestion, which might be more interesting. return (left1.lower() in word.lower() or left2.lower() in word.lower() or right2.lower() in word.lower()) return [(dist, w) for (dist, w) in closest if not is_redundant(w.text)]
def update(self): #self.rect.y -= 1 target_vector = v.sub(self.target, self.pos) move_vector = [c * self.speed for c in v.normalize(target_vector)] self.x, self.y = v.add(self.pos, move_vector) self.rect.x = self.x self.rect.y = self.y for wall in walls: if self.rect.colliderect(wall.rect): if self.rect.x > 0: # Moving right; Hit the left side of the wall self.rect.right = wall.rect.left if self.rect.x < 0: # Moving left; Hit the right side of the wall self.rect.left = wall.rect.right if self.rect.y > 0: # Moving down; Hit the top side of the wall self.rect.bottom = wall.rect.top if self.rect.y < 0: # Moving up; Hit the bottom side of the wall self.rect.top = wall.rect.bottom
def main(): pygame.init() drawing.init() screen_data = drawing.ScreenData( pygame.display.set_mode(config.SCREEN_RES, pygame.RESIZABLE), (0, 0)) input_data = InputData() path_data = pathing.PathData() selection = None lots = [] city = generation.generate() city_labels = [] for road in city.roads: city_labels.append((str(road.global_id), road.point_at(0.5))) prev_time = pygame.time.get_ticks() running = True while running: if pygame.time.get_ticks() - prev_time < 16: continue input_data.pos = pygame.mouse.get_pos() input_data.pressed = pygame.mouse.get_pressed() prev_time = pygame.time.get_ticks() for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.VIDEORESIZE: screen_data.screen = pygame.display.set_mode( event.dict["size"], pygame.RESIZABLE) config.SCREEN_RES = event.dict["size"] elif event.type == pygame.KEYDOWN: if event.key == pygame.K_g: debug.SHOW_ROAD_ORDER = False city_labels = [] selection = None path_data = pathing.PathData() city = generation.generate() for road in city.roads: city_labels.append( (str(road.global_id), road.point_at(0.5))) if event.key == pygame.K_b: lots = build_gen.gen_lots(city) # Pathing elif event.key == pygame.K_z: path_data.start = road_near_point(input_data.pos, screen_data, city) elif event.key == pygame.K_x: path_data.end = road_near_point(input_data.pos, screen_data, city) elif event.key == pygame.K_c: pathing.astar(path_data, city.roads) elif event.key == pygame.K_v: pathing.dijkstra(path_data, city.roads) # Debug Views else: handle_keys_debug(event.key) elif event.type == pygame.MOUSEBUTTONDOWN: # Zooming if event.button == 4: screen_data.zoom_in(input_data.pos) elif event.button == 5: screen_data.zoom_out(input_data.pos) # Dragging & Selection if input_data.prev_pressed[0]: if input_data.pressed[0]: # Continue drag screen_data.pan = vectors.add( screen_data.pan, vectors.sub(input_data.pos, input_data.drag_prev_pos)) input_data.drag_prev_pos = input_data.pos else: if input_data.pos == input_data.drag_start: # Select road selection = selection_from_road( road_near_point(input_data.drag_start, screen_data, city)) # Clear out drag information input_data.drag_start = None input_data.drag_prev_pos = (0, 0) else: if input_data.pressed[0]: # Drag started input_data.drag_start = input_data.pos input_data.drag_prev_pos = input_data.pos # Drawing screen_data.screen.fill((0, 0, 0)) if debug.SHOW_HEATMAP: drawing.draw_heatmap(50, city, screen_data) if debug.SHOW_SECTORS: drawing.draw_sectors(screen_data) color = (125, 255, 50) for poly in lots: temp = [] for point in poly: temp.append( drawing.world_to_screen(point, screen_data.pan, screen_data.zoom)) pygame.draw.polygon(screen_data.screen, color, temp) color = (color[0], color[1] - 11, color[2] + 7) if color[1] < 0: color = (color[0], 255, color[2]) if color[2] > 255: color = (color[0], color[1], 0) # Draw roads if debug.SHOW_ISOLATE_SECTOR and selection is not None: for sector in sectors.from_seg(selection.road): drawing.draw_all_roads(city.sectors[sector], screen_data) elif debug.SHOW_MOUSE_SECTOR: mouse_sec = sectors.containing_sector( drawing.screen_to_world(input_data.pos, screen_data.pan, screen_data.zoom)) if mouse_sec in city.sectors: drawing.draw_all_roads(city.sectors[mouse_sec], screen_data) else: tl_sect = sectors.containing_sector( drawing.screen_to_world((0, 0), screen_data.pan, screen_data.zoom)) br_sect = sectors.containing_sector( drawing.screen_to_world(config.SCREEN_RES, screen_data.pan, screen_data.zoom)) for x in range(tl_sect[0], br_sect[0] + 1): for y in range(tl_sect[1], br_sect[1] + 1): if (x, y) in city.sectors: drawing.draw_all_roads(city.sectors[(x, y)], screen_data) drawing.draw_roads_selected(selection, screen_data) drawing.draw_roads_path(path_data, screen_data) if debug.SHOW_INFO: debug_labels = debug.labels(screen_data, input_data, path_data, selection, city) for x in range(len(debug_labels[0])): label_pos = (10, 10 + x * 15) drawing.draw_label_screen((debug_labels[0][x], label_pos), screen_data, 1) for x in range(len(debug_labels[1])): label_pos = (config.SCREEN_RES[0] - 10, 10 + x * 15) drawing.draw_label_screen((debug_labels[1][x], label_pos), screen_data, -1) if debug.SHOW_ROAD_ORDER: for label in city_labels: drawing.draw_label_world(label, screen_data, 1) pygame.display.flip()