169 lines
4.4 KiB
Python
Executable File
169 lines
4.4 KiB
Python
Executable File
#/usr/bin/python
|
|
import random
|
|
import math
|
|
import time
|
|
import matplotlib.pyplot as plt
|
|
|
|
fig = plt.figure()
|
|
|
|
def plotShit(points, centroids=None):
|
|
"""splits dimensions for matplotlib, scatterplots it"""
|
|
if dim >= 2:
|
|
x = [point[0] for point in points]
|
|
y = [point[1] for point in points]
|
|
if centroids:
|
|
xc = [point[0] for point in centroids]
|
|
yc = [point[1] for point in centroids]
|
|
if dim >= 3:
|
|
threedplot = fig.add_subplot(projection='3d')
|
|
z = [point[2] for point in points]
|
|
threedplot.scatter(x, y, z)
|
|
if centroids:
|
|
zc = [point[1] for point in centroids]
|
|
threedplot.scatter(xc, yc, zc, s=190.0)
|
|
else:
|
|
plot = fig.add_subplot()
|
|
plot.scatter(x, y)
|
|
if centroids:
|
|
plot.scatter(xc, yc)
|
|
plt.show()
|
|
|
|
def printPixels(pixels):
|
|
print(chr(27) + "[2J") #Clear
|
|
print('┌' + '─'*len(pixels[0])+'┐', flush=False)
|
|
for row in pixels:
|
|
print('│', end='', flush=False)
|
|
for cell in row:
|
|
print((' ' if cell == 0 else f'\033[{31+cell}m{cell}\033[0m'), end='', flush=False)
|
|
print('│')
|
|
print('└' + '─'*len(pixels[0])+'┘', flush=False)
|
|
|
|
|
|
n = 2000 # initial points
|
|
dim = 2 # in 2 of 3 dimensies. Alleen zinnig voor 2, maar werkt ook voor 3
|
|
k = 4 # aantal clusters/kamers
|
|
domains = [(0,1000)]*dim
|
|
|
|
points = [tuple(round(random.uniform(lb, ub),2) for lb, ub in domains) for _ in range(n)]
|
|
centroids = random.sample(points, k)
|
|
epochs = 0
|
|
while epochs < 5:
|
|
dists = [tuple(math.dist(p, c) for c in centroids) for p in points]
|
|
point_cluster_index = list(map(lambda x: x.index(min(x)), dists))
|
|
points_per_cluster = [[p for i, p in enumerate(points) if point_cluster_index[i] == j] for j in range(k)]
|
|
centroids = [tuple(sum(col) / float(len(col)) for col in zip(*points_per_cluster[i])) for i in range(k)]
|
|
epochs += 1
|
|
#print(points)
|
|
#print(centroids)
|
|
#print(dists)
|
|
#print(point_cluster_index)
|
|
#print(points_per_cluster)
|
|
#print("---")
|
|
|
|
#plotShit(points, centroids)
|
|
|
|
width= 320
|
|
height = 48
|
|
#pixels=[[0]*width]*height #kut python
|
|
pixels=[[0]*width for _ in range(height)] # aanspreken als pixels[y][x] (rows columns, verwarrend).
|
|
|
|
# map cluster centers to pixels:
|
|
cluster_pixels = [(int(c[0]/domains[0][1]*width), int(c[1]/domains[1][1]*height))for c in centroids]
|
|
for i, c in enumerate(cluster_pixels):
|
|
pixels[c[1]][c[0]] = i+1
|
|
|
|
epochs = 0
|
|
while epochs < width*height/200:
|
|
for i, c in enumerate(cluster_pixels):
|
|
for y, row in enumerate(pixels):
|
|
for x, cell in enumerate(row):
|
|
if cell == i+1:
|
|
nx = x-random.randrange(-1,2) # randrange heeft non-inclusive upperbound. leuk.
|
|
ny = y-random.randrange(-1,2)
|
|
if nx >= 0 and ny >= 0 and nx < width and ny < height and pixels[ny][nx] == 0:
|
|
pixels[ny][nx] = i+1
|
|
epochs += 1
|
|
printPixels(pixels)
|
|
|
|
def checknb(x,y,v):
|
|
if x > 0:
|
|
if pixels[y][x-1] not in [v, 0]:
|
|
return True
|
|
if y > 0:
|
|
if pixels[y-1][x-1] not in [v, 0]:
|
|
return True
|
|
if x > 0:
|
|
if pixels[y-1][x-1] not in [v, 0]:
|
|
return True
|
|
if x < width-1:
|
|
if pixels[y][x+1] not in [v, 0]:
|
|
return True
|
|
if y < height-1:
|
|
if pixels[y+1][x] not in [v, 0]:
|
|
return True
|
|
if x < width-1:
|
|
if pixels[y+1][x+1] not in [v, 0]:
|
|
return True
|
|
return False
|
|
|
|
# Edging the caves
|
|
nb = 1
|
|
while nb > 0:
|
|
nb = 0
|
|
for y, row in enumerate(pixels):
|
|
for x, cell in enumerate(row):
|
|
if cell != 0:
|
|
if checknb(x,y,cell):
|
|
nb += 1
|
|
pixels[y][x] = 0
|
|
printPixels(pixels)
|
|
#centroid distances
|
|
c_dists = [[math.dist(p, c) for c in centroids] for p in centroids]
|
|
edges = []
|
|
print(centroids)
|
|
for i, cdist in enumerate(c_dists):
|
|
f = [x if x > 0 else 99999999 for x in cdist]
|
|
m = min(f)
|
|
one = f.index(m)
|
|
f[one] = 9999999
|
|
print(f"Centroid {i+1} is closest to centroid {one+1}")
|
|
m = min(f)
|
|
two = f.index(m)
|
|
edges.append((one, two))
|
|
print(f"Centroid {i+1} is second closest to centroid {two+1}")
|
|
print(cluster_pixels)
|
|
|
|
def draw(x0, y0, x1, y1):
|
|
dx = x1 - x0
|
|
dy = y1 - y0
|
|
D = 2*dy - dx
|
|
y = y0
|
|
|
|
#for x from x0 to x1
|
|
for x in range(x0-1, x1+1):
|
|
if pixels[y][x] <= 0:
|
|
pixels[y][x] = 9
|
|
#plot(x, y)
|
|
if D > 0:
|
|
y = y + 1
|
|
D = D - 2*dx
|
|
D = D + 2*dy
|
|
|
|
print(edges)
|
|
# draw edges:
|
|
for i, edge in enumerate(edges):
|
|
print(f"drawing edges for cluster {i+1}. To {edge[0]+1} and {edge[1]+1}")
|
|
draw(
|
|
cluster_pixels[edge[0]][0],
|
|
cluster_pixels[edge[0]][1],
|
|
cluster_pixels[i][0],
|
|
cluster_pixels[i][1])
|
|
draw(
|
|
cluster_pixels[edge[1]][0],
|
|
cluster_pixels[edge[1]][1],
|
|
cluster_pixels[i][0],
|
|
cluster_pixels[i][1])
|
|
printPixels(pixels)
|
|
|
|
#cluster_pixels = [(int(c[0]/domains[0][1]*width), int(c[1]/domains[1][1]*height))for c in centroids]
|