Create sketch_2020_12_10b_naive_graph.pyde

main
Alexandre B A Villares 2020-12-10 16:59:22 -03:00
rodzic a87a205f95
commit 00a21526ca
1 zmienionych plików z 194 dodań i 0 usunięć

Wyświetl plik

@ -0,0 +1,194 @@
"""
More naive graph drawing
A directed graph from a list of edges
"""
nodes = []
edges = []
NODE_SIZE = 50 # Diâmetro dos nodes
EDGE_SIZE = 100 # Distância sugerida para Edges
BACKGROUND = color(10, 0, 0)
def setup():
size(400, 400)
strokeWeight(3)
graph = [[6, 2], [10, 11], [3, 6], [9, 2], # [2, 9],
[11, 9], [3, 8], [5, 11], [1, 4], [7, 3]]
proposed_nodes = set()
for na, nb in graph:
proposed_nodes.add(na)
proposed_nodes.add(nb)
for name in proposed_nodes:
x = random(width * .25, width * .75)
y = random(height * .25, height * .75)
new_node = Node(x, y, name)
nodes.append(new_node)
for na, nb in graph:
n1 = Node.from_name(na) # find the Node object from its "name"
n2 = Node.from_name(nb) # for each connection, find Node obj
new_edge = Edge(n1, n2) # create an Edge object
edges.append(new_edge)
def draw():
background(BACKGROUND) # limpa a tela
# para cada Edge
for e in edges:
e.plot() # desenha a linha
e.ajust(EDGE_SIZE)
# para cada n
for n in nodes:
n.plot() # desenha
n.move() # atualiza posição
# Sob clique do mouse seleciona/deseleciona nodes ou Edgesho
def mouseClicked():
for n in nodes: # para cada n checa distância do mouse
if dist(mouseX, mouseY, n.x, n.y) < NODE_SIZE / 2:
n.sel = not n.sel # inverte status de seleção
def keyPressed(): # Quando uma tecla é pressionada
if key == 'r': # Se a tecla 'r' for pressionada
for n in nodes:
# sorteia nova posição
x = random(width * .25, width * .75)
y = random(height * .25, height * .75)
n.x, n.y = x, y
def mouseDragged(): # quando o mouse é arrastado
for n in nodes: # para cada n checa distância do mouse
if dist(mouseX, mouseY, n.x, n.y) < NODE_SIZE / 2:
n.x, n.y = mouseX, mouseY
n.v = PVector(0, 0)
class Node(PVector):
"""
Node object inherits from PVector so we can do subtraction and
find direction between two nodes.
"""
V_MAX = 2 # velocnameade máxima nas ortogonais vx e vy
V_MIN = .6
def __init__(self, x, y, name):
self.name = name
self.x = x
self.y = y
self.v = PVector(0, 0)
self.sel = False # se está selecionado, começa sem seleção
self.cor = color(random(128, 255), # R
random(128, 255), # G
random(128, 255), # B
255) # Alpha ~50%
def plot(self):
stroke(self.cor)
fill(BACKGROUND)
ellipse(self.x, self.y, NODE_SIZE, NODE_SIZE)
texto = self.name
if dist(mouseX, mouseY, self.x, self.y) < NODE_SIZE / 2:
stroke(255)
noFill()
ellipse(self.x, self.y, NODE_SIZE - 5, NODE_SIZE - 5)
elif self.sel:
stroke(0)
noFill()
ellipse(self.x, self.y, NODE_SIZE - 5, NODE_SIZE - 5)
fill(self.cor)
textAlign(CENTER, CENTER)
text(texto, self.x, self.y)
def move(self):
if self.x < NODE_SIZE:
self.x = NODE_SIZE
elif self.x > width - NODE_SIZE:
self.x = width - NODE_SIZE
if self.y < NODE_SIZE:
self.y = NODE_SIZE
elif self.y > height - NODE_SIZE:
self.y = height - NODE_SIZE
for n in nodes:
if n is not self:
self.ajust(n)
self.limit_v()
if not self.sel:
self.x += self.v.x
self.y += self.v.y
def ajust(self, other):
dir = PVector.sub(self, other)
ms = dir.magSq() / 20 + EPSILON
# dir.normalize()
self.v += dir.div(ms)
def limit_v(self):
""" limita à velocidade máxima e para se estiver devagar"""
if self.v.mag() < Node.V_MIN:
self.v = PVector(0, 0)
else:
self.v.limit(Node.V_MAX)
@staticmethod
def from_name(name):
for p in nodes:
if p.name == name:
return p
return None
class Edge():
""" Edges have two nodes"""
def __init__(self, n1, n2):
self.n1 = n1
self.n2 = n2
self.nodes = [n1, n2] # directed now...
def plot(self):
stroke(255)
arrow(self.n1.x, self.n1.y,
self.n2.x, self.n2.y,
shorter=NODE_SIZE / 2,
head=10)
def ajust(self, edge_size):
n1, n2 = self.n1, self.n2
d = dist(n1.x, n1.y, n2.x, n2.y)
delta = edge_size - d
dir = PVector.sub(n1, n2)
dir.mult(delta / 2000)
n1.v += dir
n2.v -= dir
@staticmethod
def find(n1, n2):
""" Is there an Edge with theses Nodes? """
for e in edges:
if n1 == e.nodes[0] and n2 == e.nodes[1]: # directed now...
return True
return False
def arrow(xa, ya, xb, yb, shorter=0, head=None):
L = dist(xa, ya, xb, yb)
siz = L - shorter
siz_ponta = head or siz / 4 * sqrt(2)
ang = atan2(yb - ya, xb - xa)
xp = xa + cos(ang) * siz
yp = ya + sin(ang) * siz
line(xa, ya, xp, yp) # corpo com sizanho fixo
xpe = xp + cos(ang + QUARTER_PI + PI) * siz_ponta
ype = yp + sin(ang + QUARTER_PI + PI) * siz_ponta
line(xp, yp, xpe, ype) # parte esquerda da ponta
xpd = xp + cos(ang - QUARTER_PI + PI) * siz_ponta
ypd = yp + sin(ang - QUARTER_PI + PI) * siz_ponta
line(xp, yp, xpd, ypd) # parte direita da ponta