def calc_stop_line(self, ref_point, crossing, kerb_lines): stop_line = list() vec = crossing.polyline[-1] - crossing.polyline[0] p3 = ref_point p4 = p3 + vec for kerb_line in kerb_lines: for i in range(len(kerb_line.polyline) - 1): p1 = kerb_line.polyline[i] p2 = kerb_line.polyline[i + 1] p = intersection_point(p1, p2, p3, p4) if is_between(p, p1, p2): stop_line.append(p) break if len(stop_line) < 2: raise RuntimeError("stop-line has only %d point" % len(stop_len)) if len(stop_line) == 2: return stop_line stop_line.sort(key=lambda point: point.x) if is_between(ref_point, stop_line[0], stop_line[1]): return (stop_line[0], stop_line[1]) return (stop_line[1], stop_line[2])
def extend_to_meet(self, position): road_item = None w = 2 h = 2 for graphics_item in self.scene().items(position.x() - w / 2.0, position.y() - h / 2.0, w, h): if graphics_item == self: continue if not graphics_item.is_selectable: continue road_item = graphics_item.road_item if hasattr(road_item, "polyline"): break if not road_item: return self.restricted_to_straight_line(position) line = self.chains[0].line() p1 = Point(line.x1(), line.y1()) p2 = Point(line.x2(), line.y2()) polyline = road_item.polyline for i in range(len(polyline) - 1): p3 = polyline[i] p4 = polyline[i + 1] p = intersection_point(p1, p2, p3, p4) if is_between(p, p3, p4): return QtCore.QPointF(p.x, p.y) return self.restricted_to_straight_line(position)
def get_reference_point(self, lane_marking, crossing): polyline = self.get_polyline(lane_marking, crossing) p1 = polyline[-1] p2 = polyline[-2] p3 = crossing.polyline[0] p4 = crossing.polyline[-1] p = intersection_point(p1, p2, p3, p4) vec = p2 - p p = p + (2.5 / abs(vec)) * vec return p
def extend_to_meet(self, graphics_item): if len(self.polyline) < 2: return False polyline = graphics_item.road_item.polyline p = polyline[0] if polyline[0].distance(self.polyline[0]) < polyline[0].distance( self.polyline[-1]): p3 = self.polyline[0] p4 = self.polyline[1] for i in range(len(polyline) - 1): p1 = polyline[i] p2 = polyline[i + 1] p = intersection_point(p1, p2, p3, p4) if is_between(p, p1, p2): angle = angle_between_2_lines(p1, p, p4) if angle > 30 and angle < 150: if p3.distance(p) < 3: self.draw_line(self.polyline[0], p) self.polyline[0] = p return True else: p3 = self.polyline[-1] p4 = self.polyline[-2] for i in range(len(polyline) - 1): p1 = polyline[i] p2 = polyline[i + 1] p = intersection_point(p1, p2, p3, p4) if is_between(p, p1, p2): angle = angle_between_2_lines(p1, p, p4) if angle > 30 and angle < 150: if p3.distance(p) < 3: self.draw_line(self.polyline[-1], p) self.polyline[-1] = p return True return False
def order_lane_edges(self, lane_edges, stop_line): p1 = stop_line.polyline[0] p2 = stop_line.polyline[-1] for lane_edge in lane_edges: if p1.distance(lane_edge.polyline[0]) < p1.distance( lane_edge.polyline[-1]): # The lane-edge's first point is closer to the closer to the stop-line than its # last point. Reverse its polyline so that it points towards the stop-line. lane_edge.polyline.reverse() lane_edge.stop_line = stop_line p3 = lane_edge.polyline[-1] p4 = lane_edge.polyline[-2] # Extends the lane-edge so that it touches the stop-line. lane_edge.polyline[-1] = intersection_point(p1, p2, p3, p4) # Re-arrange the order of the lane-edges, although at this point we do not know if the # ordering is from left to right or vice versa. stop_line.lane_edges.sort( key=lambda lane_edge: lane_edge.polyline[-1].x) # Make sure that the order of the lane-edges is from right to left when looking at the # stop-line while standing before the lane-edges' last points. Also make sure that the # stop-line's polyline moves from right to left. if p1.distance(lane_edges[0].polyline[-1]) < p1.distance( lane_edges[-1].polyline[-1]): # The stop-line's first point is closer to lane_edges[0] than to the last lane_edge. p2 = stop_line.polyline[1] vec1 = p2 - p1 p4 = lane_edges[0].polyline[-1] p3 = lane_edges[0].polyline[-2] vec2 = p4 - p3 if cross_product(vec1, vec2) > 0: lane_edges.reverse() stop_line.polyline.reverse() else: p2 = stop_line.polyline[1] vec1 = p2 - p1 p4 = lane_edges[-1].polyline[-1] p3 = lane_edges[-1].polyline[-2] vec2 = p4 - p3 if cross_product(vec1, vec2) < 0: lane_edges.reverse() else: stop_line.polyline.reverse() # Extends the stop-line so that the stop-line touches the first and last lane-edges. stop_line.polyline[0] = lane_edges[0].polyline[-1] stop_line.polyline[-1] = lane_edges[-1].polyline[-1]
def create_missing_stop_line(self, path): crossings, lane_markings, kerb_lines = self.items_in_selection_region( path) if len(kerb_lines) < 2: show_error_message( "The selection region must include at least 2 kerb-lines.") return important_marking_types = ("B", "C", "A", "L", "S", "S1", "A1") for lane_marking in lane_markings: if lane_marking.marking_type in important_marking_types: break else: msg = "The selection region must contain at least one lane-marking of the types: " msg = msg + "'%s'" % important_marking_types[0] for type in important_marking_types[1:]: msg = msg + ", '%s'" % type show_error_message(msg) return crossing = crossings[0] ref_point = self.get_reference_point(lane_marking, crossing) stop_line = self.calc_stop_line(ref_point, crossing, kerb_lines) for lane_marking in lane_markings: polyline = self.get_polyline(lane_marking, crossing) p1 = polyline[-1] p2 = polyline[-2] p = intersection_point(p1, p2, stop_line[0], stop_line[-1]) if is_between(p, stop_line[0], stop_line[-1]) and is_between( p, p1, p2): polyline[-1] = p self.adjust_lane_marking(lane_marking, polyline) lane_marking = self.main_window.digital_map.add_lane_marking( "M", "discard", stop_line) self.main_window.scene.draw_lane_marking(lane_marking) self.load_lane_marking(lane_marking)
def get_crossing_at_start_of_lane_edges(self, lane_edges, crossings): distances = list() for i, crossing in enumerate(crossings): d = 0.0 n = 0 p = crossing.polyline[0] for lane_edge in lane_edges: d = d + p.distance(lane_edge.polyline[0]) n = n + 1 p = crossing.polyline[-1] for lane_edge in lane_edges: d = d + p.distance(lane_edge.polyline[0]) n = n + 1 distances.append(d / n) the_crossing = None big_number = 999999 for i, d in enumerate(distances): if big_number > d: big_number = d the_crossing = crossings[i] p1 = the_crossing.polyline[0] p2 = the_crossing.polyline[-1] for lane_edge in lane_edges: discard, distance = nearest_point(p1, lane_edge.polyline[0], p2) if distance < 3.0: lane_edge.crossing = the_crossing p3 = lane_edge.polyline[0] p4 = lane_edge.polyline[1] lane_edge.polyline[0] = intersection_point(p1, p2, p3, p4) if p2.distance(lane_edges[0].polyline[0]) < p2.distance( lane_edges[-1].polyline[0]): the_crossing.polyline.reverse() the_crossing.polyline[-1] = lane_edges[-1].polyline[0] the_crossing.lane_edges = lane_edges
def extend_stop_lines_to_kerb(self, stop_lines): for stop_line in stop_lines: kerb_lines = list() p1 = stop_line.polyline[0] p2 = stop_line.polyline[-1] # There should be only 2 kerb-lines, but if there is a road-divider, which is usually # only one meter wide, then the following search may be too wide and return the other # side of the road-divider, thus adding a third kerb-line. for road_item in self.tracing_paper.road_items_around_line( p1, p2, 2, 0.1): if isinstance(road_item, Kerb_line): kerb_lines.append(road_item) if len(kerb_lines) < 2: continue if len(kerb_lines) > 3: print "found a stop-line (%s, %s) that cuts more than 3 kerb-lines" % ( p1, p2) continue stop_line_polyline = list() for p in stop_line.polyline: stop_line_polyline.append(p) polyline = list() for kerb_line in kerb_lines: for i in range(len(kerb_line.polyline) - 1): p3 = kerb_line.polyline[i] p4 = kerb_line.polyline[i + 1] p = intersection_point(p3, p4, p1, p2) if is_between(p, p3, p4): # A long kerb-line may be folded like the letter 'U'. Just like a # horizontal line may intersect 'U' at 2 places, the stop-line may also # intersect the kerb-line at 2 places. We ignore the intersection that # is too far away from the stop-line. if p.distance(p1) < 2 or p.distance(p2) < 2: polyline.append(p) # The 'U'-shaped kerb-line may represent the road-divider, which is # usually one meter wide, enough room for someone to stand on. It is # possible that the latter part of the kerb-line is nearer to the # stop-line (we don't know which side of the 'U'-shaped kerb-line is # the stop-line. Therefore, we cannot break out of the for-loop; we # have to check the other "stem" of the 'U'. re_arrange_co_linear_points(polyline) if polyline[0].distance(p1) > polyline[0].distance(p2): # The first point is closer to the last point of the stop-line. We reverse the # polyline so that it is in the same direction as the stop-line's polyline. polyline.reverse() if len(polyline) < 2: continue if len(polyline) == 2: stop_line_polyline[0] = polyline[0] stop_line_polyline[-1] = polyline[-1] elif len(polyline) == 3: if polyline[1].distance(p1) < polyline[1].distance(p2): # The middle point is closer to the stop-line's first point. stop_line_polyline[0] = polyline[1] stop_line_polyline[-1] = polyline[2] else: stop_line_polyline[0] = polyline[0] stop_line_polyline[-1] = polyline[1] else: print "found a stop-line (%s, %s) that cuts at more than 3 places" % ( p1, p2) continue stop_line.polyline = stop_line_polyline point = stop_line_polyline[0] path = QtGui.QPainterPath(QtCore.QPointF(point.x, point.y)) for point in stop_line_polyline: path.lineTo(point.x, point.y) stop_line.visual_item.setPath(path)