/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.lgYAWdDaE9R/rev.661
*
* authors:
* Rui Gil
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
// new script
Network network;
void setup() {
size(512,512);
colorMode(HSB, 255);
smooth();
frameRate(30);
network = new Network();
}
void draw() {
background(0);
network.draw();
}
void mousePressed() {
network.initialize();
}
class Network {
ArrayList edges = new ArrayList();
ArrayList nodes = new ArrayList();
void initialize() {
edges.clear();
nodes.clear();
generate();
}
void generate() {
// create nodes
for(int i=0; i<20; i++) {
Node n = (Node)randomNode();
nodes.add(n);
}
// edges.add(new Edge(nodes.get(0),nodes.get(1)));
// connect to neightbours
for(int i=0; i<nodes.size(); i++) {
Node n = (Node)nodes.get(i);
ArrayList ns = getRandomNodes(n,1);
for(int j=0; j<ns.size(); j++) {
Edge e = new Edge(n,ns.get(j));
edges.add(e);
}
}
}
ArrayList getRandomNodes(Node original, int n) {
ArrayList candidates = new ArrayList();
ArrayList connectedNodes = new ArrayList();
candidates.addAll(nodes);
candidates.remove(original);
for (int i=0; i<n; i++) {
Node node = (Node)candidates.get(int(random(candidates.size())));
connectedNodes.add(node);
candidates.remove(node);
}
return connectedNodes;
}
Node randomNode() {
float c = random(255);
float r = 15;//+random(40);
Node node = new Node(random(width),random(height),r,c);
return node;
}
Edge randomEdge() {
// create an edge between two randoms nodes
int n1 = int(random(nodes.size()));
// the second node must different that the first.
int n2 = (1+n1+int(random(nodes.size()-1)))%(nodes.size());
Edge edge = new Edge((Node)nodes.get(n1),(Node)nodes.get(n2));
return edge;
}
void draw() {
// a "static" edge so nodes dont step into each other.
Edge edge = new Edge();
/*
unidrected graph
for (int i=0; i<nodes.size(); i++) {
for (int j=i+1; j<nodes.size(); j++) {
Node n1 = (Node)nodes.get(i);
Node n2 = (Node)nodes.get(j);
edge.repulse(n1,n2);
}
}*/
// in a directed graph
for (int i=0; i<nodes.size(); i++) {
for (int j=0; j<nodes.size(); j++) {
if (i!=j) {
Node n1 = (Node)nodes.get(i);
Node n2 = (Node)nodes.get(j);
edge.repulse(n1,n2);
}
}
}
for (int i=0; i<nodes.size(); i++) {
Node node = (Node)nodes.get(i);
node.draw();
}
for (int i=0; i<edges.size(); i++) {
Edge e = (Edge)edges.get(i);
e.update();
e.draw();
}
}
}
class Edge {
Node n1, n2;
float damping = 0.75;
Edge() {
}
Edge(Node node1, Node node2) {
n1 = node1;
n2 = node2;
}
void update() {
updatePos(n1,n2);
updateSync(n1,n2);
}
void repulse(Node node1, Node node2) {
float dista = PVector.dist(node1.position, node2.position);
if (dista < node1.radius+node2.radius) {
updatePos(node1,node2);
}
}
void updatePos(Node node1, Node node2) {
float dista = PVector.dist(node1.position, node2.position);
PVector force = PVector.sub(node1.position, node2.position);
force.normalize();
float factor = (dista - (node1.radius+node2.radius+30));//+4*(abs(n1.phase.x-n2.phase.x))));
force.mult(factor);
//node2.updatePos(force);
force.mult(-1);
node1.updatePos(force);
node1.velocity.mult(damping);
//node2.velocity.mult(damping);
}
void updateSync(Node node1, Node node2) {
float dista = PVector.dist(node1.position, node2.position);
PVector force = PVector.sub(node1.phase, node2.phase);
//force.mult(1/dista);
force.normalize();
float factor = (dista);//+4*(abs(n1.phase.x-n2.phase.x))));
force.mult(1/factor);
force.mult(-1);
node1.updatePhase(force);
//node2.updatePhase(force);
//node2.phasevelocity.mult(damping);
node1.phasevelocity.mult(damping);
}
void draw() {
stroke(255);
line(n1.position.x,n1.position.y,n2.position.x,n2.position.y);
}
}
class Node {
PVector position, velocity, aceleration, phase, phasevelocity;
float rotation, direction, mass, radius, innerRadius;
float clr;
float ss = 0;
Node(float gx, float gy, float r,float c) {
velocity = new PVector(0,0,0);
position = new PVector(gx,gy,0);
phase = new PVector(c*(TWO_PI/255),0,0);
phasevelocity = new PVector(0,0,0);
mass = r;
radius = r;
}
void updatePhase(PVector force) {
aceleration = PVector.div(force, mass);
phasevelocity.add(aceleration);
phase.add(phasevelocity);
}
void updatePos(PVector force) {
aceleration = PVector.div(force, mass);
velocity.add(aceleration);
position.add(velocity);
}
void draw() {
clr = 128+(cos(phase.x + ss)*128);
ss += PI/10;
noStroke();
fill(color(0,0,clr,255));
ellipse(position.x,position.y,radius*2,radius*2);
}
}