Module src.app.tools.clipped_voronoi
This class was borrowed from a StackOverflow post. COPYRIGHT by Flabetvibes (https://stackoverflow.com/users/2225883/flabetvibes) Source: https://stackoverflow.com/questions/28665491/getting-a-bounded-polygon-coordinates-from-voronoi-cells
Source code
'''
This class was borrowed from a StackOverflow post.
COPYRIGHT by Flabetvibes (https://stackoverflow.com/users/2225883/flabetvibes)
Source: https://stackoverflow.com/questions/28665491/getting-a-bounded-polygon-coordinates-from-voronoi-cells
'''
import matplotlib.pyplot as pl
import numpy as np
import scipy as sp
import scipy.spatial
import sys
eps = sys.float_info.epsilon
def cvt(points, bounding_box, num_iterations):
centroids, vor = voronoi(points, bounding_box)
for i in range(num_iterations - 1):
centroids, vor = voronoi(centroids, [0, 1, 0, 1])
return centroids, vor
def in_box(points, bounding_box):
return np.logical_and(np.logical_and(bounding_box[0] <= points[:, 0],
points[:, 0] <= bounding_box[1]),
np.logical_and(bounding_box[2] <= points[:, 1],
points[:, 1] <= bounding_box[3]))
def voronoi(in_points, bounding_box):
# Select in_points inside the bounding box
i = in_box(in_points, bounding_box)
# Mirror points
points_center = in_points[i, :]
points_left = np.copy(points_center)
points_left[:, 0] = bounding_box[0] - (points_left[:, 0] - bounding_box[0])
points_right = np.copy(points_center)
points_right[:, 0] = bounding_box[1] + (bounding_box[1] - points_right[:, 0])
points_down = np.copy(points_center)
points_down[:, 1] = bounding_box[2] - (points_down[:, 1] - bounding_box[2])
points_up = np.copy(points_center)
points_up[:, 1] = bounding_box[3] + (bounding_box[3] - points_up[:, 1])
points = np.append(points_center,
np.append(np.append(points_left,
points_right,
axis=0),
np.append(points_down,
points_up,
axis=0),
axis=0),
axis=0)
# Compute Voronoi
vor = sp.spatial.Voronoi(points)
# Filter regions
regions = []
for region in vor.regions:
flag = True
for index in region:
if index == -1:
flag = False
break
else:
x = vor.vertices[index, 0]
y = vor.vertices[index, 1]
if not(bounding_box[0] - eps <= x and x <= bounding_box[1] + eps and
bounding_box[2] - eps <= y and y <= bounding_box[3] + eps):
flag = False
break
if region != [] and flag:
regions.append(region)
vor.filtered_points = points_center
vor.filtered_regions = regions
centroids = []
for region in vor.filtered_regions:
vertices = vor.vertices[region + [region[0]], :]
centroid = centroid_region(vertices)
centroids.append(centroid[0, :])
centroids = np.array(centroids)
return centroids, vor
def centroid_region(vertices):
# Polygon's signed area
A = 0
# Centroid's x
C_x = 0
# Centroid's y
C_y = 0
for i in range(0, len(vertices) - 1):
s = (vertices[i, 0] * vertices[i + 1, 1] - vertices[i + 1, 0] * vertices[i, 1])
A = A + s
C_x = C_x + (vertices[i, 0] + vertices[i + 1, 0]) * s
C_y = C_y + (vertices[i, 1] + vertices[i + 1, 1]) * s
A = 0.5 * A
C_x = (1.0 / (6.0 * A)) * C_x
C_y = (1.0 / (6.0 * A)) * C_y
return np.array([[C_x, C_y]])
Functions
def centroid_region(vertices)
-
Source code
def centroid_region(vertices): # Polygon's signed area A = 0 # Centroid's x C_x = 0 # Centroid's y C_y = 0 for i in range(0, len(vertices) - 1): s = (vertices[i, 0] * vertices[i + 1, 1] - vertices[i + 1, 0] * vertices[i, 1]) A = A + s C_x = C_x + (vertices[i, 0] + vertices[i + 1, 0]) * s C_y = C_y + (vertices[i, 1] + vertices[i + 1, 1]) * s A = 0.5 * A C_x = (1.0 / (6.0 * A)) * C_x C_y = (1.0 / (6.0 * A)) * C_y return np.array([[C_x, C_y]])
def cvt(points, bounding_box, num_iterations)
-
Source code
def cvt(points, bounding_box, num_iterations): centroids, vor = voronoi(points, bounding_box) for i in range(num_iterations - 1): centroids, vor = voronoi(centroids, [0, 1, 0, 1]) return centroids, vor
def in_box(points, bounding_box)
-
Source code
def in_box(points, bounding_box): return np.logical_and(np.logical_and(bounding_box[0] <= points[:, 0], points[:, 0] <= bounding_box[1]), np.logical_and(bounding_box[2] <= points[:, 1], points[:, 1] <= bounding_box[3]))
def voronoi(in_points, bounding_box)
-
Source code
def voronoi(in_points, bounding_box): # Select in_points inside the bounding box i = in_box(in_points, bounding_box) # Mirror points points_center = in_points[i, :] points_left = np.copy(points_center) points_left[:, 0] = bounding_box[0] - (points_left[:, 0] - bounding_box[0]) points_right = np.copy(points_center) points_right[:, 0] = bounding_box[1] + (bounding_box[1] - points_right[:, 0]) points_down = np.copy(points_center) points_down[:, 1] = bounding_box[2] - (points_down[:, 1] - bounding_box[2]) points_up = np.copy(points_center) points_up[:, 1] = bounding_box[3] + (bounding_box[3] - points_up[:, 1]) points = np.append(points_center, np.append(np.append(points_left, points_right, axis=0), np.append(points_down, points_up, axis=0), axis=0), axis=0) # Compute Voronoi vor = sp.spatial.Voronoi(points) # Filter regions regions = [] for region in vor.regions: flag = True for index in region: if index == -1: flag = False break else: x = vor.vertices[index, 0] y = vor.vertices[index, 1] if not(bounding_box[0] - eps <= x and x <= bounding_box[1] + eps and bounding_box[2] - eps <= y and y <= bounding_box[3] + eps): flag = False break if region != [] and flag: regions.append(region) vor.filtered_points = points_center vor.filtered_regions = regions centroids = [] for region in vor.filtered_regions: vertices = vor.vertices[region + [region[0]], :] centroid = centroid_region(vertices) centroids.append(centroid[0, :]) centroids = np.array(centroids) return centroids, vor