def strip_endpoints(filename): """ If we are using an osm node file, strip out endpoints and write out to inters.shp """ nodes = fiona.open(filename) intersections = [(Point(n['geometry']['coordinates']), n['properties']) for n in nodes if not n['properties']['dead_end']] util.write_shp(nodes.schema, os.path.join(MAP_FP, 'inters.shp'), intersections, 0, 1, crs=nodes.crs)
def get_signals(): nodes = util.read_shp( os.path.join(MAP_FP, 'all_nodes', 'nodes', 'nodes.shp')) signals = [ node for node in nodes if node[1]['highway'] == 'traffic_signals' ] schema = { 'geometry': 'Point', 'properties': { 'highway': 'str', 'osmid': 'str', 'ref': 'str' } } util.write_shp(schema, os.path.join(MAP_FP, 'osm_signals.shp'), signals, 0, 1, crs=fiona.crs.from_epsg(3857))
def create_segments(roads_shp_path, print_buffers=False): inters_shp_path_raw = os.path.join(MAP_FP, 'inters.shp') inters_shp_path = os.path.join(MAP_FP, 'inters_3857.shp') inters = reproject_and_read(inters_shp_path_raw, inters_shp_path) # Read in boston segments + mass DOT join roads = [(shape(road['geometry']), road['properties']) for road in fiona.open(roads_shp_path)] print "read in {} road segments".format(len(roads)) # unique id did not get included in shapefile, need to add it for adjacency for i, road in enumerate(roads): road[1]['orig_id'] = int(str(99) + str(i)) # Initial buffer = 20 meters int_buffers = get_intersection_buffers(inters, 20) if print_buffers: # create new schema that has only an 'id' property of type string buff_schema = { 'geometry': 'Polygon', 'properties': {}, } # write out shapefile that has intersection buffers util.write_shp(buff_schema, os.path.join(MAP_FP, 'int_buffers.shp'), [(x, {}) for x in int_buffers], 0, 1) non_int_lines, inter_segments = find_non_ints(roads, int_buffers) # Planarize intersection segments # Turns the list of LineStrings into a MultiLineString union_inter = [({ 'id': idx }, unary_union(l)) for idx, l in inter_segments['lines'].items()] print "extracted {} intersection segments".format(len(union_inter)) # Intersections shapefile inter_schema = { 'geometry': 'LineString', 'properties': { 'id': 'int' }, } util.write_shp(inter_schema, os.path.join(MAP_FP, 'inters_segments.shp'), union_inter, 1, 0) # The inters_segments shapefile above only gives an id property # Store the other properties from inters_segments as json file with open(os.path.join(DATA_FP, 'inters_data.json'), 'w') as f: json.dump(inter_segments['data'], f) # add non_inter id format = 00+i non_int_w_ids = [] i = 0 for l in non_int_lines: prop = copy.deepcopy(l[1]) prop['id'] = '00' + str(i) prop['inter'] = 0 non_int_w_ids.append(tuple([l[0], prop])) i += 1 print "extracted {} non-intersection segments".format(len(non_int_w_ids)) # Non-intersection shapefile road_properties = {k: 'str' for k, v in non_int_w_ids[0][1].items()} road_schema = {'geometry': 'LineString', 'properties': road_properties} util.write_shp(road_schema, os.path.join(MAP_FP, 'non_inters_segments.shp'), non_int_w_ids, 0, 1) # Create shapefile that combines intersections and non-intersections while # preserving their newly created IDs # need to make the schema consistent between the two # for now, just keep the ids for the non-intersection segments # to keep things simple non_int_no_prop = [] for i in non_int_w_ids: id = i[1]['id'] # reverse the order of the tuple # while we're at it to make it # consistent with union_inter non_int_no_prop.append(({'id': id}, i[0])) # concatenate the two datasets inter_and_non_int = union_inter + non_int_no_prop # create new schema that has only an 'id' property of type string all_schema = { 'geometry': 'LineString', 'properties': { 'id': 'str' }, } # write out shapefile that has intersection and non-intersection segments # along with their new IDs util.write_shp(all_schema, os.path.join(MAP_FP, 'inter_and_non_int.shp'), inter_and_non_int, 1, 0) return inter_segments['data']
new_buffered.append((b, new_line[0], new_line[1])) new_index.insert(idx, b.bounds) non_ints_with_candidates = get_candidates(new_buffered, new_index, orig_map_non_inter) print "Adding features: " + ','.join(feats) get_mapping(non_ints_with_candidates, feats) # Write the non-intersections segments back out with the new features schema = { 'geometry': 'LineString', 'properties': {k: 'str' for k in orig_map_non_inter[0][1].keys()} } util.write_shp(schema, os.path.join(MAP_FP, 'non_inters_segments.shp'), orig_map_non_inter, 0, 1) # Now do intersections orig_map_inter = util.read_shp( os.path.join(MAP_FP, 'inters_segments_orig.shp')) new_map_inter = util.read_shp( os.path.join(MAP_FP, args.map2dir, 'inters_segments.shp')) orig_buffered_inter = [] orig_index_inter = rtree.index.Index() new_buffered_inter = [] new_index_inter = rtree.index.Index() for idx, new_line in enumerate(new_map_inter): b = new_line[0].buffer(10)
# Planarize intersection segments union_inter = [({ 'id': idx }, unary_union(l)) for idx, l in inter_segments['lines'].items()] print "extracted {} intersection segments".format(len(union_inter)) # Intersections shapefile inter_schema = { 'geometry': 'LineString', 'properties': { 'id': 'int' }, } write_shp(inter_schema, MAP_FP + '/inters_segments.shp', union_inter, 1, 0) # Output inters_segments properties as json with open(DATA_FP + '/inters_data.json', 'w') as f: json.dump(inter_segments['data'], f) # add non_inter id format = 00+i non_int_w_ids = [] i = 0 for l in non_int_lines: prop = copy.deepcopy(l[1]) prop['id'] = '00' + str(i) non_int_w_ids.append(tuple([l[0], prop])) i += 1 print "extracted {} non-intersection segments".format(len(non_int_w_ids))
orig=pyproj.Proj(init='epsg:4326'))) print "Read in data from {} concerns".format(len(concern)) combined_seg, segments_index = util.read_segments() # Find nearest crashes - 30 tolerance print "snapping crashes to segments" util.find_nearest(crash, combined_seg, segments_index, 30) # Find nearest concerns - 20 tolerance print "snapping concerns to segments" util.find_nearest(concern, combined_seg, segments_index, 20) # Write concerns concern_schema = make_schema('Point', concern[0]['properties']) print "output concerns shp to ", MAP_FP util.write_shp(concern_schema, MAP_FP + '/concern_joined.shp', concern, 'point', 'properties') print "output concerns data to ", PROCESSED_DATA_FP with open(PROCESSED_DATA_FP + '/concern_joined.json', 'w') as f: json.dump([c['properties'] for c in concern], f) # Write crash crash_schema = make_schema('Point', crash[0]['properties']) print "output crash shp to ", MAP_FP util.write_shp(crash_schema, MAP_FP + '/crash_joined.shp', crash, 'point', 'properties') print "output crash data to ", PROCESSED_DATA_FP with open(PROCESSED_DATA_FP + '/crash_joined.json', 'w') as f: json.dump([c['properties'] for c in crash], f)
def reproject_and_clean_feats(orig_file, result_file, DOC_FP): """ Reads in osm_ways file, cleans up the features, and reprojects results into 3857 projection Additionally writes a key which shows the correspondence between highway type as a string and the resulting int feature Features: width lanes hwy_type osm_speed signal Args: orig_file: Filename for original file result_file: Filename for resulting file in 3857 projection DOC_FP: directory to write highway keys file to Returns: None, writes to file """ way_results = fiona.open(orig_file) # Convert the map from above to 3857 reprojected_way_lines = [ tuple(x.values()) for x in util.reproject_records(way_results) ] highway_keys = {} for way_line in reprojected_way_lines: # All features need to be ints, so convert them here # Use speed limit if given in osm speed = way_line[1]['maxspeed'] if speed: s = re.search('[0-9]+', speed) if s: speed = s.group(0) if not speed: speed = 0 # round width width = 0 if ['width'] in way_line[1].keys(): width = way_line[1]['width'] if not width or ';' in width or '[' in width: width = 0 else: width = round(float(width)) lanes = way_line[1]['lanes'] if lanes: lanes = max([int(x) for x in re.findall('\d', lanes)]) else: lanes = 0 # Need to have an int highway field if way_line[1]['highway'] not in highway_keys.keys(): highway_keys[way_line[1]['highway']] = len(highway_keys) # Use oneway oneway = 0 if way_line[1]['oneway'] == 'True': oneway = 1 way_line[1].update({ 'width': width, 'lanes': int(lanes), 'hwy_type': highway_keys[way_line[1]['highway']], 'osm_speed': speed, 'signal': 0, 'oneway': oneway }) schema = way_results.schema # Add values to schema if they don't exist, so new map won't break schema['properties'].update({ # Add highway type key and osm_speed to the schema 'width': 'int', 'lanes': 'int', 'hwy_type': 'int', 'osm_speed': 'int', 'signal': 'int', 'oneway': 'int', }) util.write_shp(schema, result_file, reprojected_way_lines, 0, 1, crs=fiona.crs.from_epsg(3857)) # Write highway keys to docs if needed for reference if not os.path.exists(DOC_FP): os.makedirs(DOC_FP) with open(os.path.join(DOC_FP, 'highway_keys.csv'), 'wb') as f: w = csv.writer(f) w.writerow(['type', 'value']) for item in highway_keys.iteritems(): w.writerow(item)