kopia lustrzana https://github.com/villares/sketch-a-day
				
				
				
			
		
			
				
	
	
		
			116 wiersze
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			116 wiersze
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
#*- 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)
 |