import numpy as np from itertools import compress from geopandas import points_from_xy from scipy.spatial import Voronoi, voronoi_plot_2d from scipy.spatial.distance import cdist def extract(lst, i): return [item[i] for item in lst] def extract_coord(lst): return [item.coords[:] for item in lst] def coord_lister(geom): coords = list(geom.exterior.coords) return (coords) # def vor_ver(furthest_pnt, i): # return furthest_pnt[i].vertices def get_lecc(shp): """ This functions finds largest enclosed circle center from shape file. It is used for optimizing text placement and size using Voronoi diagram in this project Arguments: shp -- shape object returns - lecc : which is largest enclosed circle lecc_dist : which is radius of largest enclosed circle """ num_area = len(shp) polygons_coord = shp.geometry.apply(coord_lister) furthest_pnt = [None] * num_area voronoi_ori = [None] * num_area for i, points in enumerate(polygons_coord): voronoi_ori[i] = Voronoi(points, furthest_site=False) furthest_pnt[i] = voronoi_ori[i].vertices voronoi_nodes = [None] * num_area leccc = [None] * num_area # get voronoi nodes that is inside the polygon. for i in range(num_area): voronoi_nodes[i] = points_from_xy(extract(furthest_pnt[i], 0), extract(furthest_pnt[i], 1)) voronoi_nodes_if_inside = shp.geometry[i].contains(voronoi_nodes[i]) voronoi_nodes[i] = list(compress(voronoi_nodes[i], voronoi_nodes_if_inside)) leccc[i] = [item for sublist in extract_coord(voronoi_nodes[i]) for item in sublist] dist = [None] * num_area for i, points in enumerate(polygons_coord): # explaining this mess : I need to get the LEC from candidate I got before, but the thing is, # cdist from scipy only accepts exact dimension with array like object, # which means I need to explicitly set the shape of ndarray, convert list of points into ndarray dist[i] = cdist(np.array([list(item) for item in points]), np.array([list(item) for item in leccc[i]])) lecc = [None] * num_area lecc_dist = [None] * num_area for i in range(num_area): voronoi_nodes_dist = [None] * (dist[i].shape[1]) for j in range(dist[i].shape[1]): voronoi_nodes_dist[j] = min(dist[i][:, j]) lecc_ind = np.argmax(voronoi_nodes_dist) lecc[i] = leccc[i][lecc_ind] lecc_dist[i] = np.max(voronoi_nodes_dist) return lecc, lecc_dist