def shorten_border_for_crosswalk(input_border, street_name, lanes, crosswalk_width=10, destination='from_intersection', exclude_links=True, exclude_parallel=True): """ Remove the portion of the input border overlapping with any crosswalk crossing the input border. Scan all lanes with street names other than the street the input border belongs to, and identify crosswalks related to each lane. :param input_border: list of coordinates :param street_name: string :param lanes: list of dictionaries :param crosswalk_width: float :param destination: string :param exclude_links: True if exclude links, False otherwise :return: list of coordinates """ border = copy.deepcopy(input_border) if destination == 'from_intersection': multi_string_index = -1 else: multi_string_index = 0 for l in lanes: if l['name'] == 'no_name' or l['name'] == street_name: continue if exclude_links and 'link' in l['name']: continue if 'median' in l: border_type = 'median' else: border_type = 'left_border' bearing_delta = abs( get_angle_between_bearings( get_compass(l[border_type][-2], l[border_type][-1]), get_compass(input_border[0], input_border[-1]))) if bearing_delta > 90.0: bearing_delta = (180.0 - bearing_delta) % 180.0 if bearing_delta < 30.0: if exclude_parallel: logger.debug( "Processing %s, excluding %s for shortening: almost parallel %r" % (street_name, l['name'], bearing_delta)) continue lb, rb = add_space_for_crosswalk(l, crosswalk_width=crosswalk_width) coord = lb + rb[::-1] polygon = geom.Polygon(coord) temp = cut_border_by_polygon(border, polygon, multi_string_index) if temp is not None: border = temp border = drop_small_edges(border) return border
def construct_turn_arc_with_initial_angle(origin_border, destination_border, initial_angle=15.0, number_of_points=12, turn_direction=-1.0): intersection_point, vector1, vector2 = get_turn_angle( origin_border, destination_border) if intersection_point is None: return None from_origin_to_intersection = great_circle_vec_check_for_nan( intersection_point[1], intersection_point[0], vector1[1][1], vector1[1][0]) from_destination_to_intersection = great_circle_vec_check_for_nan( intersection_point[1], intersection_point[0], vector2[1][1], vector2[1][0]) bearing1 = get_compass(vector1[1], vector1[0]) bearing2 = get_compass(vector2[0], vector2[1]) angle = ((turn_direction * (bearing2 - bearing1) + 360) % 360) sin1 = math.sin(to_rad(180.0 - angle)) l_dest = from_destination_to_intersection z = l_dest * sin1 / (sin1 + math.sin(to_rad(initial_angle))) l_origin = z * math.cos(to_rad(initial_angle)) + (l_dest - z) * math.cos( to_rad(180.0 - angle)) if from_origin_to_intersection > l_origin: # Drive along the origin vector past the intersection last_origin_point = extend_vector(vector1, length=l_origin, backward=False, relative=False)[1] else: # Start turning immediately last_origin_point = vector1[1] azimuth = (get_compass(intersection_point, last_origin_point) - initial_angle + 360) % 360 point = nv_frame.GeoPoint(latitude=last_origin_point[1], longitude=last_origin_point[0], degrees=True) result, _azimuthb = point.geo_point(distance=100.0, azimuth=azimuth, degrees=True) first_orin_point = (result.longitude_deg, result.latitude_deg) angled_origin_border = [first_orin_point, last_origin_point] return construct_turn_arc(angled_origin_border, destination_border, number_of_points=number_of_points, turn_direction=turn_direction)
def get_simulated_crosswalk(street_data, streets, width=1.8): """ Construct a simulated crosswalk :param street_data: street dictionary :param streets: list of dictionaries :param width: float, crosswalk width in meters :return: crosswalk dictionary """ right_border = shorten_border_for_crosswalk(street_data['right_border'], street_data['name'], streets, crosswalk_width=2, destination='to_intersection', exclude_parallel=False) left_border = shorten_border_for_crosswalk(street_data['left_border'], street_data['name'], streets, crosswalk_width=2, destination='to_intersection', exclude_parallel=False) right_border2 = shorten_border_for_crosswalk(street_data['right_border'], street_data['name'], streets, crosswalk_width=2 + width, destination='to_intersection', exclude_parallel=False) left_border2 = shorten_border_for_crosswalk(street_data['left_border'], street_data['name'], streets, crosswalk_width=2 + width, destination='to_intersection', exclude_parallel=False) crosswalk = { 'lane_id': '1C', 'name': street_data['name'], 'simulated': 'yes', 'right_border': [right_border[-1], left_border[-1]], 'left_border': [right_border2[-1], left_border2[-1]], 'median': shift_vector([right_border[-1], left_border[-1]], -width / 2.0), 'path_id': 0, 'path': [], 'lane_type': 'crosswalk', 'direction': 'undefined', 'nodes': [], 'nodes_coordinates': [], 'width': width, 'type': 'footway' } bearing = get_compass(crosswalk['right_border'][0], crosswalk['right_border'][-1]) crosswalk['bearing'] = bearing crosswalk['compass'] = get_compass_rhumb(bearing), crosswalk['length'] = get_border_length(crosswalk['median']) logger.debug('Created crosswalk for street %s %s' % (street_data['name'], street_data['compass'])) return crosswalk
def get_sector(point, block): """ Get visibility sector from a point to a blocking object :param point: point coordinates :param block: guideway dictionary :return: max and min azimuths and points where sector boundaries crosses the block """ max_azimuth = -1.0 min_azimuth = 361.0 for x in block['reduced_left_border'] + block['reduced_right_border']: azimuth = get_compass(point, x) if azimuth < min_azimuth: min_point = x min_azimuth = azimuth elif azimuth == min_azimuth: if get_distance_between_points( point, x) < get_distance_between_points(point, min_point): min_point = x min_azimuth = azimuth if azimuth > max_azimuth: max_point = x max_azimuth = azimuth elif azimuth == max_azimuth: if get_distance_between_points( point, x) < get_distance_between_points(point, max_point): max_point = x max_azimuth = azimuth return min_azimuth, max_azimuth, min_point, max_point
def construct_u_turn_arc(origin_border, destination_border, number_of_points=12): """ Construct a turn arc with the destination border :param origin_border: list of coordinates :param destination_border: list of coordinates :param number_of_points: integer :return: list of coordinates """ bearing1 = get_compass(origin_border[-2], origin_border[-1]) bearing2 = get_compass(destination_border[0], destination_border[1]) angle = abs(get_angle_between_bearings(bearing1, bearing2)) radius, landing_border = get_u_turn_radius_and_landing_border(origin_border, destination_border) if radius > 50: logger.debug('U-turn bearings %r, %r, angle %r' % (bearing1, bearing2, angle)) logger.warning('Radius is too large %r, landing border %r' % (radius, landing_border)) ob = cut_line_by_relative_distance(destination_border, 0.95) radius, landing_border = get_u_turn_radius_and_landing_border(ob, destination_border) logger.debug('Retry bearings %r, %r, angle %r' % (bearing1, bearing2, angle)) logger.debug('Adjusted radius %r, landing border %r' % (radius, landing_border)) else: ob = origin_border shift = [2.0 * radius * (math.sin(to_rad(angle / 2.0 * i / float(number_of_points)))) ** 2 for i in range(0, number_of_points + 1) ] vec = [ob[-1], extend_vector(ob[-2:], length=30.0, backward=False, relative=True)[-1]] vector = [extend_vector(vec, length=radius * (math.sin(to_rad(angle * i / float(number_of_points)))), backward=False )[1] for i in range(0, number_of_points + 1) ] arc = [shift_by_bearing_and_distance(vector[i], shift[i], ob[-2:], bearing_delta=-90.0) for i in range(0, number_of_points + 1) ] return arc[:-1] + landing_border
def get_simulated_crosswalk(street_data, streets, width=1.8): """ Construct a simulated crosswalk :param street_data: street dictionary :param streets: list of dictionaries :param width: float, crosswalk width in meters :return: crosswalk dictionary """ if is_highway(street_data): return None logger.debug("Simulated crosswalk for %s" % street_data['name']) right_border = shorten_border_for_crosswalk(street_data['right_border'], street_data['name'], streets, crosswalk_width=3, destination='to_intersection', exclude_parallel=True, max_reduction=130.0 ) left_border = shorten_border_for_crosswalk(street_data['left_border'], street_data['name'], streets, crosswalk_width=3, destination='to_intersection', exclude_parallel=True, max_reduction=130.0 ) right_border2 = shorten_border_for_crosswalk(street_data['right_border'], street_data['name'], streets, crosswalk_width=3 + width, destination='to_intersection', exclude_parallel=True, max_reduction=130.0 ) left_border2 = shorten_border_for_crosswalk(street_data['left_border'], street_data['name'], streets, crosswalk_width=3 + width, destination='to_intersection', exclude_parallel=False, max_reduction=130.0 ) vector = [right_border[-1], right_border2[-1]] resized_vector = extend_vector(vector, length=width, backward=False) vector2 = [get_closest_point(p, street_data['left_border']) for p in resized_vector] # logger.debug("Vector %r" % vector) # logger.debug("Resize %r" % resized_vector) # logger.debug("Vecto2 %r" % vector2) r_b = [right_border[-1], left_border[-1]] r_l = [shift_by_bearing_and_distance(r_b[0], width, [right_border[-1], right_border[-2]], bearing_delta=0.0), shift_by_bearing_and_distance(r_b[-1], width, [left_border[-1], left_border[-2]], bearing_delta=0.0)] crosswalk = { 'lane_id': '1C', 'name': street_data['name'], 'simulated': 'yes', # 'right_border': [vector[0], vector2[0]], # 'left_border': [resized_vector[1], vector2[1]], 'right_border': r_b, # [right_border[-1], left_border[-1]], 'left_border': r_l, # [right_border2[-1], left_border2[-1]], 'median': shift_vector([right_border[-1], left_border[-1]], -width / 2.0), 'path_id': 0, 'path': [], 'lane_type': 'crosswalk', 'direction': 'undefined', 'nodes': [], 'nodes_coordinates': [], 'width': width, 'type': 'footway' } bearing = get_compass(crosswalk['right_border'][0], crosswalk['right_border'][-1]) crosswalk['bearing'] = bearing crosswalk['compass'] = get_compass_rhumb(bearing), crosswalk['length'] = get_border_length(crosswalk['median']) if crosswalk['length'] > 50.0: return None if "id" in street_data: crosswalk["street_id"] = street_data["id"] logger.debug( 'Created crosswalk for street %s %s' % (street_data['name'], street_data['compass'])) return crosswalk
def construct_turn_arc(origin_border, destination_border, number_of_points=12, turn_direction=-1.0, lane=None): """ Construct a turn arc :param origin_border: list of coordinates :param destination_border: list of coordinates :param number_of_points: integer :param turn_direction: -1 if left turn otherwise 1 :return: list of coordinates """ intersection_point, vector1, vector2 = get_turn_angle( origin_border, destination_border) if intersection_point is None: logger.debug('Origin %r' % origin_border) logger.debug('Destin %r' % destination_border) logger.debug('Cannot find intersection point') return None from_origin_to_intersection = great_circle_vec_check_for_nan( intersection_point[1], intersection_point[0], vector1[1][1], vector1[1][0]) from_destination_to_intersection = great_circle_vec_check_for_nan( intersection_point[1], intersection_point[0], vector2[1][1], vector2[1][0]) #logger.debug("Vectors 1 %r" % vector1) #logger.debug("Vectors 2 %r" % vector2) if lane is not None: lane["left_vector"] = vector1 lane["right_vector"] = vector2 # logger.debug("Intersection point %r" % intersection_point) bearing1 = get_compass(vector1[1], vector1[0]) bearing2 = get_compass(vector2[0], tuple(vector2[1])) angle = ((turn_direction * (bearing2 - bearing1) + 360) % 360) if from_origin_to_intersection < from_destination_to_intersection: distance_to_starting_point = from_origin_to_intersection dist_delta = 0.0 else: distance_to_starting_point = from_destination_to_intersection dist_delta = from_origin_to_intersection - from_destination_to_intersection radius = distance_to_starting_point / math.tan(to_rad(angle / 2.0)) if radius < 0.0: logger.error("Negative radius %r" % radius) logger.debug("from_origin_to_intersection %r" % from_origin_to_intersection) logger.debug("from_destination_to_intersection %r" % from_destination_to_intersection) return None else: logger.debug("Radius %r" % radius) shift = [ turn_direction * 2.0 * radius * (math.sin(to_rad(angle / 2.0 * i / float(number_of_points))))**2 for i in range(0, number_of_points + 1) ] vec = [origin_border[-1], intersection_point] vector = [ extend_vector(vec, length=dist_delta + radius * (math.sin(to_rad(angle * i / float(number_of_points)))), backward=False)[1] for i in range(0, number_of_points + 1) ] return [ shift_by_bearing_and_distance(vector[i], shift[i], vec, bearing_delta=turn_direction * 90.0) for i in range(0, number_of_points + 1) ]