def split_line_by_nearest_points(gdf_line, gdf_points, tolerance, crs): """ Split the union of lines with the union of points resulting :param GeoDataFrame gdf_line: GeoDataFrame with multiple rows of connecting line segments :param GeoDataFrame gdf_points: geodataframe with multiple rows of single points :returns: ``gdf_segments`` (GeoDataFrame of segments) :rtype: GeoDataFrame https://github.com/ojdo/python-tools/blob/master/shapelytools.py#L144 """ # union all geometries line = gdf_line.geometry.unary_union line._crs = crs snap_points = gdf_points.geometry.unary_union snap_points._crs = crs # snap and split coords on line # returns GeometryCollection # snap_points = snap(coords, line, tolerance) # snap_points._crs = crs split_line = split(line, snap(snap_points, line, tolerance)) split_line._crs = crs segments = [feature for feature in split_line if feature.length > 0.01] gdf_segments = gdf(geometry=segments, crs=crs) # gdf_segments.columns = ['index', 'geometry'] return gdf_segments
def one_linestring_per_intersection(lines, crs): """ Move line endpoints to intersections of line segments. Given a list of touching or possibly intersecting LineStrings, return a list LineStrings that have their endpoints at all crossings and intersecting points and ONLY there. Args: a list of LineStrings or a MultiLineString Returns: a list of LineStrings """ lines_merged = linemerge(lines) # intersecting multiline with its bounding box somehow triggers a first intersection try: bounding_box = box(*lines_merged.bounds) lines_merged = lines_merged.intersection(bounding_box) except: #if the bounding_box fails, then revert to lines merge. print('bounding box method did not work, falling to a more simple method, no need to worry') # merge the result lines_merged = linemerge(lines_merged) lines = [line for line in lines_merged] df = gdf(geometry=lines, crs=crs) return df
def compute_intersections(lines, crs): import itertools inters = [] for line1, line2 in itertools.combinations(lines, 2): if line1.intersects(line2): inter = line1.intersection(line2) if "Point" == inter.type: inters.append(inter) elif "MultiPoint" == inter.type: inters.extend([pt for pt in inter]) elif "MultiLineString" == inter.type: multiLine = [line for line in inter] first_coords = multiLine[0].coords[0] last_coords = multiLine[len(multiLine) - 1].coords[1] inters.append(Point(first_coords[0], first_coords[1])) inters.append(Point(last_coords[0], last_coords[1])) elif "GeometryCollection" == inter.type: for geom in inter: if "Point" == geom.type: inters.append(geom) elif "MultiPoint" == geom.type: inters.extend([pt for pt in geom]) elif "MultiLineString" == geom.type: multiLine = [line for line in geom] first_coords = multiLine[0].coords[0] last_coords = multiLine[len(multiLine) - 1].coords[1] inters.append(Point(first_coords[0], first_coords[1])) inters.append(Point(last_coords[0], last_coords[1])) geometry = inters df = gdf(geometry=geometry, crs=crs) return df
def frm_to_lgaFrm(frm, key = 'LGA'): lgas = load.load_lgas() indices = frm.index.names frm = frm.copy() frm = frm.reset_index() frm['geometry'] = frm[key].apply(lambda x: lgas.loc[x]['geometry']) frm = frm.set_index(indices) frm = gdf(frm) return frm
def computer_end_points(lines, crs): all_points = [] for line in lines: for i in [0, -1]: # start and end point all_points.append(line.coords[i]) unique_points = set(all_points) endpts = [Point(p) for p in unique_points] df = gdf(geometry=endpts, crs=crs) return df
def simplify_liness_accurracy(lines, decimals, crs): new_lines = [] for line in lines: points_of_line = [] for point in line.coords: x = round(point[0], decimals) y = round(point[1], decimals) points_of_line.append((x, y)) new_lines.append(LineString(points_of_line)) df = gdf(geometry=new_lines, crs=crs) return df
def simplify_points_accurracy(buiding_centroids, decimals, crs): new_points = [] names = [] for point, name in zip(buiding_centroids.geometry, buiding_centroids.Name): x = round(point.x, decimals) y = round(point.y, decimals) new_points.append(Point(x, y)) names.append(name) df = gdf(geometry=new_points, crs=crs) df["Name"] = names return df
def erase_no_surrounding_areas(all_surroundings, zone, area_with_buffer): """ Remove buildings inside zone and outside of buffer from Surroundings GeoDataFrame :param geopandas.GeoDataFrame all_surroundings: Surroundings GeoDataFrame :param geopandas.GeoDataFrame zone: Zone GeoDataFrame :param geopandas.GeoDataFrame area_with_buffer: Buffer area GeoDataFrame :return: GeoDataFrame with surrounding buildings """ buffer_polygon = area_with_buffer.to_crs(zone.crs).geometry.values[0] zone_area = gdf(geometry=[zone.geometry.unary_union], crs=zone.crs) within_buffer = all_surroundings.geometry.intersects(buffer_polygon) surroundings = all_surroundings[within_buffer] rep_points = gdf(geometry=surroundings.geometry.representative_point(), crs=all_surroundings.crs) not_in_zone = spatial_join(rep_points, zone_area, how='left')['index_right'].isna() return surroundings[not_in_zone].copy()
def calc_surrounding_area(zone_gdf, buffer_m): """ Adds buffer to zone to get surroundings area :param geopandas.GeoDataFrame zone_gdf: Zone GeoDataFrame :param float buffer_m: Buffer to add to zone building geometries :return: Surrounding area GeoDataFrame """ surrounding_area = gdf( geometry=[zone_gdf.geometry.buffer(buffer_m).unary_union], crs=zone_gdf.crs) return surrounding_area
def create_terminals(buiding_centroids, crs, street_network): # get list of nearest points near_points = near_analysis(buiding_centroids, street_network, crs) # extend to the buiding centroids all_points = near_points.append(buiding_centroids) all_points.crs = crs # Aggregate these points with the GroupBy lines_to_buildings = all_points.groupby(['Name'])['geometry'].apply(lambda x: LineString(x.tolist())) lines_to_buildings = gdf(lines_to_buildings, geometry='geometry', crs=crs) lines_to_buildings = lines_to_buildings.append(street_network).reset_index(drop=True) lines_to_buildings.crs = crs return lines_to_buildings
def snappy_endings(lines, max_distance, crs): """Snap endpoints of lines together if they are at most max_length apart. Args: lines: a list of LineStrings or a MultiLineString max_distance: maximum distance two endpoints may be joined together """ # initialize snapped lines with list of original lines # snapping points is a MultiPoint object of all vertices snapped_lines = [line for line in lines] snapping_points = vertices_from_lines(snapped_lines) # isolated endpoints are going to snap to the closest vertex isolated_endpoints = find_isolated_endpoints(snapped_lines) # only move isolated endpoints, one by one for endpoint in isolated_endpoints: # find all vertices within a radius of max_distance as possible target = nearest_neighbor_within(snapping_points, endpoint, max_distance) # do nothing if no target point to snap to is found if not target: continue # find the LineString to modify within snapped_lines and update it for i, snapped_line in enumerate(snapped_lines): if endpoint.touches(snapped_line): snapped_lines[i] = bend_towards(snapped_line, where=endpoint, to=target) break # also update the corresponding snapping_points for i, snapping_point in enumerate(snapping_points): if endpoint.equals(snapping_point): snapping_points[i] = target break # post-processing: remove any resulting lines of length 0 snapped_lines = [s for s in snapped_lines if s.length > 0] df = gdf(geometry=snapped_lines, crs=crs) return df
def near_analysis(buiding_centroids, street_network, crs): near_point = [] building_name = [] for point, name in zip(buiding_centroids.geometry, buiding_centroids.Name): point._crs = crs distance = 10e10 for line in street_network.geometry: line._crs = crs nearest_point_candidate = line.interpolate(line.project(point)) distance_candidate = point.distance(nearest_point_candidate) if distance_candidate < distance: distance = distance_candidate nearest_point = nearest_point_candidate building_name.append(name) near_point.append(nearest_point) geometry = near_point df = gdf(geometry=geometry, crs=crs) df["Name"] = building_name return df
def df_buffer_extent(inDf, inEpsg, meterTolerance, geomCol="geometry", mantainOriginalGeom=None): """ For all geometries, calculate the boundary given by the sum between the feature extent and the Tolerance variable """ from shapely.geometry import Polygon from geopandas import GeoDataFrame as gdf from gasp.g.ext import featext_to_dfcols inDf = featext_to_dfcols(inDf, geomCol) inDf['minx'] = inDf.minx - meterTolerance inDf['miny'] = inDf.miny - meterTolerance inDf['maxx'] = inDf.maxx + meterTolerance inDf['maxy'] = inDf.maxy + meterTolerance # Produce new geometries geoms = [ Polygon([[ext[0], ext[3]], [ext[1], ext[3]], [ext[1], ext[2]], [ext[0], ext[2]], [ext[0], ext[3]]]) for ext in zip(inDf.minx, inDf.maxx, inDf.miny, inDf.maxy) ] # Delete uncessary columns dropCols = ['minx', 'miny', 'maxx', 'maxy'] if mantainOriginalGeom: inDf.rename(columns={geomCol: 'old_geom'}, inplace=True) else: dropCols.append(geomCol) inDf.drop(dropCols, axis=1, inplace=True) resDf = gdf(inDf, crs={'init': 'epsg:{}'.format(inEpsg)}, geometry=geoms) return resDf
aust_recovery_cv = narrow_recovery_df.set_index(narrow_recovery_df['Country/Region']).\ loc['Australia',] # charts fig, (ax1, ax2, ax3) = plt.subplots(nrows=3, sharex=True, sharey=False) aust_conf_cv.groupby('date')['confirmed'].sum().plot(ax=ax1, title="Confirmed") aust_death_cv.groupby('date')['death'].sum().plot(ax=ax2, title="Deaths") aust_recovery_cv.groupby('date')['recovery'].sum().plot(ax=ax3, title="Recovery") #choose most recent date end_date = datetime.strftime(narrow_conf_df.date.max(),"%m/%d/%Y") date_conf_df = narrow_conf_df.loc[narrow_conf_df['date']==end_date,] # # Datad=Frame as GeoDataFrame points_list = [Point(x, y) for x, y in zip(date_conf_df.Long, date_conf_df.Lat)] points = gdf(date_conf_df, geometry=points_list) points.crs = {'init' :'epsg:4326'} points = points.to_crs({'init': 'epsg:4283'}) # join points data to australia by location m_layer = geopandas.sjoin(aust, points, how="inner", op='intersects') #make the map m_layer.plot(column='confirmed', cmap='Blues', linewidth=0.8, edgecolor='0.8', label="confirmed") vmin = m_layer['confirmed'].min() vmax = m_layer['confirmed'].max() sm = plt.cm.ScalarMappable(cmap='Blues', norm=plt.Normalize(vmin=vmin, vmax=vmax)) # Chlorepleth :
def connect_building_to_grid(building_points, input_streets_shp): # Import data lines = gdf.from_file(input_streets_shp) # Create DF for points on line points_on_line = building_points[["Name", "geometry"]].copy() lines = lines[["geometry"]].copy() lines["FID"] = range(lines.shape[0]) # points_on_line['Node Type'] = None for idx, point in points_on_line.iterrows(): points_on_line.loc[idx, 'Building'] = point['Name'] # points_on_line.loc[idx, 'Name'] = point['Name'] + ' Coupling Point' # Prepare DF for nearest point on line building_points['min_dist_to_lines'] = 0 building_points['nearest_line'] = None for idx, point in building_points.iterrows(): distances = lines.distance(point.geometry) nearest_line_idx = distances.idxmin() building_points.loc[idx, 'nearest_line'] = nearest_line_idx building_points.loc[idx, 'min_dist_to_lines'] = lines.distance( point.geometry).min() # find point on nearest line project_distances = lines.project(point.geometry) project_distance_nearest_line = lines.interpolate( project_distances[nearest_line_idx]) points_on_line.loc[ idx, 'geometry'] = project_distance_nearest_line[nearest_line_idx] # Determine Intersections of lines for idx, line in lines.iterrows(): line.geometry = line.geometry.buffer(0.0001) line_intersections = lines.intersection(line.geometry) for index, intersection in line_intersections.iteritems(): if intersection.geom_type == 'LineString' and index != idx: centroid_buffered = line_intersections[index].centroid.buffer( 0.1) # middle of Linestrings if not points_on_line.intersects(centroid_buffered).any(): index_points_on_line = points_on_line.shape[ 0] # current number of rows in points_on_line points_on_line.loc[ index_points_on_line, 'geometry'] = line_intersections[index].centroid points_on_line.loc[index_points_on_line, 'Building'] = None # Name Points for idx, point in points_on_line.iterrows(): points_on_line.loc[idx, 'Name'] = 'Node' + str(idx) points_on_line.loc[idx, 'Node_int'] = int(idx) # Split Linestrings at points_on_line tranches_list = [] for idx, line in lines.iterrows(): line_buffered = line.copy() line_buffered.geometry = line.geometry.buffer(0.0001) line_point_intersections = points_on_line.intersection( line_buffered.geometry) filtered_points = line_point_intersections[ line_point_intersections.is_empty == False] start_point = Point(line.values[0].xy[0][0], line.values[0].xy[1][0]) distance = filtered_points.distance(start_point) filtered_points = gdf(data=filtered_points) filtered_points['distance'] = distance filtered_points.sort_values(by='distance', inplace=True) # Create new Lines for idx1 in range(0, len(filtered_points) - 1): start = filtered_points.iloc[idx1][0] end = filtered_points.iloc[idx1 + 1][0] newline = LineString([start, end]) tranches_list.append(newline) tranches = gdf(data=tranches_list, crs=points_on_line.crs) tranches.columns = ['geometry'] tranches['Name'] = None tranches['Startnode'] = None tranches['Endnode'] = None tranches['Startnode_int'] = None tranches['Endnode_int'] = None tranches['Length'] = 0 for idx, tranch in tranches.iterrows(): # print (idx) # print (tranch) tranches.loc[idx, 'Name'] = 'tranch' + str(idx) tranches.loc[idx, 'Length'] = tranch.values[0].length # print (tranch.values[0].boundary) startnode = tranch.values[0].boundary[0] endnode = tranch.values[0].boundary[1] start_intersection = points_on_line.intersection(startnode.buffer(0.1)) end_intersection = points_on_line.intersection(endnode.buffer(0.1)) start_intersection_filtered = start_intersection[ start_intersection.is_empty == False] end_intersection_filtered = end_intersection[end_intersection.is_empty == False] startnode_index = start_intersection_filtered.index.values[0] endnode_index = end_intersection_filtered.index.values[0] tranches.loc[idx, 'Startnode'] = 'Node' + str( start_intersection_filtered.index.values[0]) tranches.loc[idx, 'Endnode'] = 'Node' + str(endnode_index) tranches.loc[idx, 'Startnode_int'] = int( start_intersection_filtered.index.values[0]) tranches.loc[idx, 'Endnode_int'] = int(endnode_index) # UTM to LAT, LON # building_nodes = building_nodes.to_crs("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs") # streets = streets.to_crs("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs") return points_on_line, tranches
df_prcp['date'] = [datetime.datetime.strptime(d, "%Y-%m-%dT%H:%M:%S") for d in dates_prcp] df_prcp['prcp'] = [p for p in prcp] df_prcp['attributes'] = [p for p in attributes] df_prcp['station_id'] = [p for p in station] # Get lat/long of stations station_list = pd.read_csv(ghcnd_station_inventory) stations = df_prcp.merge(station_list, on='station_id', how='left') # Save precip data precip_path = data_path / 'precip' / 'station_data' / img precip_path_shp = precip_path / 'shp' try: precip_path_shp.mkdir(parents=True) except FileExistsError: pass stations.to_csv(precip_path / '{}'.format(img + '_precip.csv', index=False)) # Sum daily measurements and save as shapefile stations = gdf(stations, geometry=geopandas.points_from_xy(stations.long, stations.lat)) stations = stations.groupby(['station_id', 'name', 'elevation', 'lat', 'long']).sum().reset_index() stations = gdf(stations, geometry=geopandas.points_from_xy(stations.long, stations.lat)) stations.crs = 'EPSG:4269' stations = stations.to_crs('EPSG:4326') stations.to_file(str(precip_path_shp / '{}'.format(img + '_precip.shp')))