윤영준 윤영준 2023-06-14
separated voronoi based algorithm that was used for text placement and size optimizer. However, since this same algorithm can be used for other applications like finding the optimal placement of say, any facilities, this function is separated.
@0b5797eec663176ee0b49bcfe56e0fd52331aad0
 
algorithms/voronoi.py (added)
+++ algorithms/voronoi.py
@@ -0,0 +1,62 @@
+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
+    """
+    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(파일 끝에 줄바꿈 문자 없음)
choropleth.py
--- choropleth.py
+++ choropleth.py
@@ -5,10 +5,7 @@
 import plotly.express as px
 import plotly.graph_objects as go
 import cv2
-from itertools import compress
-from geopandas import points_from_xy
-from scipy.spatial import Voronoi, voronoi_plot_2d
-from scipy.spatial.distance import cdist
+from algorithms.voronoi import get_lecc
 # import matplotlib.pyplot as plt  # debugging
 
 sep = os.path.sep
@@ -18,68 +15,12 @@
     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 plotly_fig2array(fig, scale):
     # convert Plotly fig to  an array
     fig_bytes = fig.to_image(format="png", width=2000, height=800, scale=scale)
     buf = io.BytesIO(fig_bytes)
     img = Image.open(buf)
     return np.asarray(img)
-
-
-def beautify_text_placement(shp):
-    """
-    Function to optimize text placement and size using Voronoi diagram.
-
-    Arguments:
-    shp -- shape object
-    """
-    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
-
 
 def choropleth_chart(shp, df, title, save_dir, colorscheme="BuGn", show_legend=True, unit='',
                      adaptive_legend_font_size=False, geo_annot_scale = 1500,
@@ -115,7 +56,7 @@
     lecc = None
     lecc_dist = None
     if adaptive_legend_font_size:
-        lecc, lecc_dist = beautify_text_placement(shp)
+        lecc, lecc_dist = get_lecc(shp)
 
     # draw the choropleth
     fig = px.choropleth(
Add a comment
List