sketch-a-day/2020/sketch_2020_08_18a/grid.py

116 wiersze
3.2 KiB
Python
Czysty Wina Historia

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#*- coding: utf-8 -*-
from __future__ import division, print_function
from random import sample, choice
class Grid():
def __init__(self, graph, width, height, margin=None, mode=0):
"""
mode 0: heavy center
mode 1: heavy perifery
"""
margin = margin or width / 40
cols, rows = dim_grid(len(graph))
w, h = (width - margin * 2) / cols, (height - margin * 2) / rows
points = []
for i in range(cols * rows):
c = i % cols
r = i // rows
x = margin + w * 0.5 + c * w # - 14 * (r % 2) + 7
y = margin + h * 0.5 + r * h # - 14 * (c % 2) + 7
z = 0
points.append([x, y, z])
points = sorted(
points, key=lambda p: dist(p[0], p[1], width / 2, height / 2))
if mode == 0:
v_list = reversed(
sorted(graph.vertices(), key=graph.vertex_degree))
elif mode == 1:
v_list = sorted(graph.vertices(), key=graph.vertex_degree)
else:
v_list = graph.vertices()
print("random mode")
Grid.w, Grid.h = w, h
self.graph = graph
self.grid = {v: p for v, p in zip(v_list, points)}
recalculate_sizes_from_v_deg(self.graph, self)
def __getitem__(self, k):
return self.grid[k]
def __setitem__(self, k, v):
self.grid[k] = v
def __len__(self):
return len(self.grid)
def keys(self):
return self.grid.keys()
def values(self):
return self.grid.values()
def __iter__(self):
return iter(self.grid)
def swap(self, num=2):
grid = self.grid
graph = self.graph
fail = 0
n = m = edge_distances(graph, grid)
while m <= n and fail < len(graph) ** 2:
new_grid = dict(grid)
if num == 2:
a, b = sample(graph.vertices(), 2)
new_grid[a], new_grid[b] = new_grid[b], new_grid[a]
else:
ks = sample(graph.vertices(), num)
vs = [grid[k] for k in sample(ks, num)]
for k, v in zip(ks, vs):
new_grid[k] = v
n = edge_distances(graph, new_grid)
if m > n:
t = "{:.2%} at: {} tries of {}v shuffle/swap" \
.format((n - m) / m, fail + 1, num)
print("\n" + t, end="")
recalculate_sizes_from_v_deg(graph, new_grid)
self.grid = new_grid
else:
fail += 1
print(".", end='')
def dim_grid(n):
a = int(sqrt(n))
b = n // a
if a * b < n:
b += 1
print(u'{}: {} × {} ({})'.format(n, a, b, a * b))
return a, b
def edge_distances(graph, grid):
total = 0
for edge in graph.edges():
if len(edge) == 2:
a, b = edge
d = PVector.dist(PVector(*grid[a]),
PVector(*grid[b]))
total += d
return total
def recalculate_sizes_from_v_deg(graph, grid):
u = Grid.w / 10
for k in grid.keys():
grid[k][2] = u * graph.vertex_degree(k)
return u
def v_dist(a, b):
xa, ya, _ = a
xb, yb, _ = b
return dist(xa, ya, xb, yb)