def centroid_corner(geom): '''all these characters working with corners could be merged and cleaned ''' from shapely.geometry import Point if geom is None: return (None, None) distances = [] # set empty list of distances centroid = geom.centroid # define centroid points = list(geom.exterior.coords) # get points of a shape stop = len(points) - 1 # define where to stop for i in np.arange( len(points) ): # for every point, calculate angle and add 1 if True angle if i == 0: continue elif i == stop: a = np.asarray(points[i - 1]) b = np.asarray(points[i]) c = np.asarray(points[1]) p = Point(points[i]) if _true_angle(a, b, c) is True: distance = centroid.distance( p ) # calculate distance point - centroid distances.append(distance) # add distance to the list else: continue else: a = np.asarray(points[i - 1]) b = np.asarray(points[i]) c = np.asarray(points[i + 1]) p = Point(points[i]) if _true_angle(a, b, c) is True: distance = centroid.distance(p) distances.append(distance) else: continue if not distances: # circular buildings from momepy.dimension import _longest_axis if geom.has_z: coords = [ (coo[0], coo[1]) for coo in geom.convex_hull.exterior.coords ] else: coords = geom.convex_hull.exterior.coords return (_longest_axis(coords) / 2, 0) return (np.mean(distances), np.std(distances))
def __init__(self, gdf): self.gdf = gdf # define empty list for results results_list = [] results_list_sd = [] # calculate angle between points, return true or false if real corner def true_angle(a, b, c): ba = a - b bc = c - b cosine_angle = np.dot( ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc)) angle = np.arccos(cosine_angle) if np.degrees(angle) <= 170: return True if np.degrees(angle) >= 190: return True return False # iterating over rows one by one for index, row in tqdm(gdf.iterrows(), total=gdf.shape[0]): distances = [] # set empty list of distances centroid = row["geometry"].centroid # define centroid points = list( row["geometry"].exterior.coords) # get points of a shape stop = len(points) - 1 # define where to stop for i in np.arange( len(points) ): # for every point, calculate angle and add 1 if True angle if i == 0: continue elif i == stop: a = np.asarray(points[i - 1]) b = np.asarray(points[i]) c = np.asarray(points[1]) p = Point(points[i]) if true_angle(a, b, c) is True: distance = centroid.distance( p) # calculate distance point - centroid distances.append(distance) # add distance to the list else: continue else: a = np.asarray(points[i - 1]) b = np.asarray(points[i]) c = np.asarray(points[i + 1]) p = Point(points[i]) if true_angle(a, b, c) is True: distance = centroid.distance(p) distances.append(distance) else: continue if not distances: # circular buildings from momepy.dimension import _longest_axis results_list.append( _longest_axis(row["geometry"].convex_hull.exterior.coords) / 2) results_list_sd.append(0) else: results_list.append(np.mean(distances)) # calculate mean results_list_sd.append(np.std(distances)) # calculate st.dev self.mean = pd.Series(results_list, index=gdf.index) self.std = pd.Series(results_list_sd, index=gdf.index)
def centroid_corners(objects): """ Calculates mean distance centroid - corners and st. deviation. .. math:: \\overline{x}=\\frac{1}{n}\\left(\\sum_{i=1}^{n} dist_{i}\\right);\\space \\mathrm{SD}=\\sqrt{\\frac{\\sum|x-\\overline{x}|^{2}}{n}} Parameters ---------- objects : GeoDataFrame GeoDataFrame containing objects Returns ------- means, st_devs : tuple means : Series Series containing mean distance values. st_devs : Series Series containing standard deviation values. References ---------- Schirmer PM and Axhausen KW (2015) A multiscale classification of urban morphology. Journal of Transport and Land Use 9(1): 101–130. + Cimburova (ADD) Examples -------- >>> means, deviations = momepy.centroid_corners(buildings_df) Calculating distance centroid - corner... 100%|██████████| 144/144 [00:00<00:00, 846.58it/s] Distances centroid - corner calculated. >>> buildings_df['ccd_means'] = means >>> buildings_df['ccd_stdev'] = deviations >>> buildings_df['ccd_means'][0] 15.961531913184833 >>> buildings_df['ccd_stdev'][0] 3.0810634305400177 """ # define empty list for results results_list = [] results_list_sd = [] print('Calculating distance centroid - corner...') # calculate angle between points, return true or false if real corner def true_angle(a, b, c): ba = a - b bc = c - b cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc)) angle = np.arccos(cosine_angle) if np.degrees(angle) <= 170: return True elif np.degrees(angle) >= 190: return True return False # iterating over rows one by one for index, row in tqdm(objects.iterrows(), total=objects.shape[0]): distances = [] # set empty list of distances centroid = row['geometry'].centroid # define centroid points = list(row['geometry'].exterior.coords) # get points of a shape stop = len(points) - 1 # define where to stop for i in np.arange( len(points) ): # for every point, calculate angle and add 1 if True angle if i == 0: continue elif i == stop: a = np.asarray(points[i - 1]) b = np.asarray(points[i]) c = np.asarray(points[1]) p = Point(points[i]) if true_angle(a, b, c) is True: distance = centroid.distance( p) # calculate distance point - centroid distances.append(distance) # add distance to the list else: continue else: a = np.asarray(points[i - 1]) b = np.asarray(points[i]) c = np.asarray(points[i + 1]) p = Point(points[i]) if true_angle(a, b, c) is True: distance = centroid.distance(p) distances.append(distance) else: continue if not distances: from momepy.dimension import _longest_axis results_list.append( _longest_axis(row['geometry'].convex_hull.exterior.coords) / 2) results_list_sd.append(0) else: results_list.append(np.mean(distances)) # calculate mean results_list_sd.append(np.std(distances)) # calculate st.dev means = pd.Series(results_list) st_devs = pd.Series(results_list_sd) print('Distances centroid - corner calculated.') return means, st_devs