def addShapeAsHole(self, name='undefined'): """Adds a hole in the shape of the current shape with the current position""" newhole = Polygon(self.getShapeOriented()) if self.convex_hull: newhole = newhole.convex_hull newhole.shape_nfps = defaultdict() newhole.name = name newhole.position = self.position newhole.angle = self.angle newhole.origin = affinity.rotate(Point(-self.circle_center[0], -self.circle_center[1]), self.angle, origin=(0,0)) newhole.origin = affinity.translate(newhole.origin, self.position[0], self.position[1]) self.hole_shapes.append(newhole)
def find_parallel_street_segments(self): """ This method finds parallel segments and returns a list of pair of way ids :return: A list of pair of parallel way ids """ streets = self.ways.get_list() street_polygons = [] # Threshold for merging - increasing this will merge parallel ways that are further apart. distance_to_sidewalk = 0.00009 for street in streets: start_node_id = street.get_node_ids()[0] end_node_id = street.get_node_ids()[-1] start_node = self.nodes.get(start_node_id) end_node = self.nodes.get(end_node_id) vector = start_node.vector_to(end_node, normalize=True) perpendicular = np.array([vector[1], - vector[0]]) * distance_to_sidewalk p1 = start_node.vector() + perpendicular p2 = end_node.vector() + perpendicular p3 = end_node.vector() - perpendicular p4 = start_node.vector() - perpendicular poly = Polygon([p1, p2, p3, p4]) poly.angle = math.degrees(math.atan2(vector[0], vector[1])) poly.nids = set((start_node_id, end_node_id)) street_polygons.append(poly) # Find pair of polygons that intersect each other. polygon_combinations = combinations(street_polygons, 2) # Create a list for storing parallel pairs parallel_pairs = [] # All possible pairs are stored for debugging purposes for pair_poly in polygon_combinations: # pair_poly[0] and pair_poly[1] are polygons # Add the pair to the list of all possible pairs for debug, but limit size to 50 # Get node id of street being checked # street1 = streets[street_polygons.index(pair_poly[0])] # street2 = streets[street_polygons.index(pair_poly[1])] angle_diff = ((pair_poly[0].angle - pair_poly[1].angle) + 360.) % 180. if pair_poly[0].intersects(pair_poly[1]) and (angle_diff < 10. or angle_diff > 170.): # If the polygon intersects, and they have a kind of similar angle, and they don't share a node, # then they should be merged together. parallel_pairs.append((street_polygons.index(pair_poly[0]), street_polygons.index(pair_poly[1]))) filtered_parallel_pairs = [] # Filter parallel_pairs and store in filtered_parallel_pairs for pair in parallel_pairs: street_pair = (streets[pair[0]], streets[pair[1]]) # street1 = streets[pair[0]] # street2 = streets[pair[1]] shared_nids = set(street_pair[0].nids) & set(street_pair[1].nids) # Find the adjacent nodes for the shared node if len(shared_nids) > 0: # Two paths merges at one node shared_nid = list(shared_nids)[0] shared_node = self.nodes.get(shared_nid) idx1 = street_pair[0].nids.index(shared_nid) idx2 = street_pair[1].nids.index(shared_nid) # Nodes are sorted by longitude (x-axis), so two paths should merge at the left-most node or the # right most node. if idx1 == 0 and idx2 == 0: # The case where shared node is at the left-end adj_nid1 = street_pair[0].nids[1] adj_nid2 = street_pair[1].nids[1] else: # The case where sahred node is at the right-end adj_nid1 = street_pair[0].nids[-2] adj_nid2 = street_pair[1].nids[-2] adj_node1 = self.nodes.get(adj_nid1) adj_node2 = self.nodes.get(adj_nid2) angle_to_node1 = math.degrees(shared_node.angle_to(adj_node1)) angle_to_node2 = math.degrees(shared_node.angle_to(adj_node2)) if abs(abs(angle_to_node1)-abs(angle_to_node2)) > 90: # Paths are connected but they are not parallel lines continue filtered_parallel_pairs.append(pair) return [(streets[pair[0]].id, streets[pair[1]].id) for pair in filtered_parallel_pairs]