
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
... | ... | @@ -0,0 +1,62 @@ |
1 | +import numpy as np | |
2 | +from itertools import compress | |
3 | +from geopandas import points_from_xy | |
4 | +from scipy.spatial import Voronoi, voronoi_plot_2d | |
5 | +from scipy.spatial.distance import cdist | |
6 | + | |
7 | +def extract(lst, i): | |
8 | + return [item[i] for item in lst] | |
9 | + | |
10 | +def extract_coord(lst): | |
11 | + return [item.coords[:] for item in lst] | |
12 | + | |
13 | + | |
14 | +def coord_lister(geom): | |
15 | + coords = list(geom.exterior.coords) | |
16 | + return (coords) | |
17 | + | |
18 | +# def vor_ver(furthest_pnt, i): | |
19 | +# return furthest_pnt[i].vertices | |
20 | + | |
21 | +def get_lecc(shp): | |
22 | + """ | |
23 | + This functions finds largest enclosed circle center from shape file. | |
24 | + It is used for optimizing text placement and size using Voronoi diagram in this project | |
25 | + Arguments: | |
26 | + shp -- shape object | |
27 | + """ | |
28 | + num_area = len(shp) | |
29 | + polygons_coord = shp.geometry.apply(coord_lister) | |
30 | + furthest_pnt = [None] * num_area | |
31 | + voronoi_ori = [None] * num_area | |
32 | + for i, points in enumerate(polygons_coord): | |
33 | + voronoi_ori[i] = Voronoi(points, furthest_site=False) | |
34 | + furthest_pnt[i] = voronoi_ori[i].vertices | |
35 | + | |
36 | + voronoi_nodes = [None] * num_area | |
37 | + leccc = [None] * num_area | |
38 | + # get voronoi nodes that is inside the polygon. | |
39 | + for i in range(num_area): | |
40 | + voronoi_nodes[i] = points_from_xy(extract(furthest_pnt[i], 0), extract(furthest_pnt[i], 1)) | |
41 | + voronoi_nodes_if_inside = shp.geometry[i].contains(voronoi_nodes[i]) | |
42 | + voronoi_nodes[i] = list(compress(voronoi_nodes[i], voronoi_nodes_if_inside)) | |
43 | + leccc[i] = [item for sublist in extract_coord(voronoi_nodes[i]) for item in sublist] | |
44 | + | |
45 | + dist = [None] * num_area | |
46 | + for i, points in enumerate(polygons_coord): | |
47 | + # explaining this mess : I need to get the LEC from candidate I got before, but the thing is, | |
48 | + # cdist from scipy only accepts exact dimension with array like object, | |
49 | + # which means I need to explicitly set the shape of ndarray, convert list of points into ndarray | |
50 | + dist[i] = cdist(np.array([list(item) for item in points]), np.array([list(item) for item in leccc[i]])) | |
51 | + | |
52 | + lecc = [None] * num_area | |
53 | + lecc_dist = [None] * num_area | |
54 | + for i in range(num_area): | |
55 | + voronoi_nodes_dist = [None] * (dist[i].shape[1]) | |
56 | + for j in range(dist[i].shape[1]): | |
57 | + voronoi_nodes_dist[j] = min(dist[i][:, j]) | |
58 | + lecc_ind = np.argmax(voronoi_nodes_dist) | |
59 | + lecc[i] = leccc[i][lecc_ind] | |
60 | + lecc_dist[i] = np.max(voronoi_nodes_dist) | |
61 | + | |
62 | + return lecc, lecc_dist(파일 끝에 줄바꿈 문자 없음) |
--- choropleth.py
+++ choropleth.py
... | ... | @@ -5,10 +5,7 @@ |
5 | 5 |
import plotly.express as px |
6 | 6 |
import plotly.graph_objects as go |
7 | 7 |
import cv2 |
8 |
-from itertools import compress |
|
9 |
-from geopandas import points_from_xy |
|
10 |
-from scipy.spatial import Voronoi, voronoi_plot_2d |
|
11 |
-from scipy.spatial.distance import cdist |
|
8 |
+from algorithms.voronoi import get_lecc |
|
12 | 9 |
# import matplotlib.pyplot as plt # debugging |
13 | 10 |
|
14 | 11 |
sep = os.path.sep |
... | ... | @@ -18,68 +15,12 @@ |
18 | 15 |
return [item[i] for item in lst] |
19 | 16 |
|
20 | 17 |
|
21 |
-def extract_coord(lst): |
|
22 |
- return [item.coords[:] for item in lst] |
|
23 |
- |
|
24 |
- |
|
25 |
-def coord_lister(geom): |
|
26 |
- coords = list(geom.exterior.coords) |
|
27 |
- return (coords) |
|
28 |
- |
|
29 |
-# def vor_ver(furthest_pnt, i): |
|
30 |
-# return furthest_pnt[i].vertices |
|
31 |
- |
|
32 | 18 |
def plotly_fig2array(fig, scale): |
33 | 19 |
# convert Plotly fig to an array |
34 | 20 |
fig_bytes = fig.to_image(format="png", width=2000, height=800, scale=scale) |
35 | 21 |
buf = io.BytesIO(fig_bytes) |
36 | 22 |
img = Image.open(buf) |
37 | 23 |
return np.asarray(img) |
38 |
- |
|
39 |
- |
|
40 |
-def beautify_text_placement(shp): |
|
41 |
- """ |
|
42 |
- Function to optimize text placement and size using Voronoi diagram. |
|
43 |
- |
|
44 |
- Arguments: |
|
45 |
- shp -- shape object |
|
46 |
- """ |
|
47 |
- num_area = len(shp) |
|
48 |
- polygons_coord = shp.geometry.apply(coord_lister) |
|
49 |
- furthest_pnt = [None] * num_area |
|
50 |
- voronoi_ori = [None] * num_area |
|
51 |
- for i, points in enumerate(polygons_coord): |
|
52 |
- voronoi_ori[i] = Voronoi(points, furthest_site=False) |
|
53 |
- furthest_pnt[i] = voronoi_ori[i].vertices |
|
54 |
- |
|
55 |
- voronoi_nodes = [None] * num_area |
|
56 |
- leccc = [None] * num_area |
|
57 |
- # get voronoi nodes that is inside the polygon. |
|
58 |
- for i in range(num_area): |
|
59 |
- voronoi_nodes[i] = points_from_xy(extract(furthest_pnt[i], 0), extract(furthest_pnt[i], 1)) |
|
60 |
- voronoi_nodes_if_inside = shp.geometry[i].contains(voronoi_nodes[i]) |
|
61 |
- voronoi_nodes[i] = list(compress(voronoi_nodes[i], voronoi_nodes_if_inside)) |
|
62 |
- leccc[i] = [item for sublist in extract_coord(voronoi_nodes[i]) for item in sublist] |
|
63 |
- |
|
64 |
- dist = [None] * num_area |
|
65 |
- for i, points in enumerate(polygons_coord): |
|
66 |
- # explaining this mess : I need to get the LEC from candidate I got before, but the thing is, |
|
67 |
- # cdist from scipy only accepts exact dimension with array like object, |
|
68 |
- # which means I need to explicitly set the shape of ndarray, convert list of points into ndarray |
|
69 |
- dist[i] = cdist(np.array([list(item) for item in points]), np.array([list(item) for item in leccc[i]])) |
|
70 |
- |
|
71 |
- lecc = [None] * num_area |
|
72 |
- lecc_dist = [None] * num_area |
|
73 |
- for i in range(num_area): |
|
74 |
- voronoi_nodes_dist = [None] * (dist[i].shape[1]) |
|
75 |
- for j in range(dist[i].shape[1]): |
|
76 |
- voronoi_nodes_dist[j] = min(dist[i][:, j]) |
|
77 |
- lecc_ind = np.argmax(voronoi_nodes_dist) |
|
78 |
- lecc[i] = leccc[i][lecc_ind] |
|
79 |
- lecc_dist[i] = np.max(voronoi_nodes_dist) |
|
80 |
- |
|
81 |
- return lecc, lecc_dist |
|
82 |
- |
|
83 | 24 |
|
84 | 25 |
def choropleth_chart(shp, df, title, save_dir, colorscheme="BuGn", show_legend=True, unit='', |
85 | 26 |
adaptive_legend_font_size=False, geo_annot_scale = 1500, |
... | ... | @@ -115,7 +56,7 @@ |
115 | 56 |
lecc = None |
116 | 57 |
lecc_dist = None |
117 | 58 |
if adaptive_legend_font_size: |
118 |
- lecc, lecc_dist = beautify_text_placement(shp) |
|
59 |
+ lecc, lecc_dist = get_lecc(shp) |
|
119 | 60 |
|
120 | 61 |
# draw the choropleth |
121 | 62 |
fig = px.choropleth( |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?