Two "Differential Growths" simultaneously - sort of - processing

I'm still new to Stackoverflow and new to the topic of Processing and Java, so apologies if I can't make my question as clear directly.
My goal is to create a "growing shape" with each mouse click. Below you will find my current code, which currently allows one of these shapes to be created with a mouse click. But as soon as I click again, my first shape stops growing and the second one starts (a bit hard to explain - best copy the code once and try it, then you know what I mean).
I've been trying for hours to somehow generate multiple shapes - one for each mouse click - which each continue to grow on their own, unfortunately without success. The goal is to have a lot of growing shapes at the same time.
Do any of you have an idea how to implement this?
If you need more info, just contact me!
Thank you
Lara
Code:
// PARAMETERS
float _maxForce = 0.9;
float _maxSpeed = 1;
float _desiredSeparation = 30;
float _separationCohesionRation = 1.1;
float _maxEdgeLen = 8;
boolean seed = false;
DifferentialLine _diff_line;
void setup() {
frameRate(60);
background(0);
size(1280, 720);
}
void draw() {
if(seed == true){
//println(frameCount);
background(0);
_diff_line.run();
_diff_line.render();
}
}
void mousePressed(){
seed = true;
malewas();
}
void malewas(){
_diff_line = new DifferentialLine(_maxForce, _maxSpeed, _desiredSeparation, _separationCohesionRation, _maxEdgeLen);
//fill(0);
float nodesStart = 3;
float angInc = TWO_PI/nodesStart;
float rayStart = 5;
for (float a=0; a<TWO_PI; a+=angInc) {
float x = mouseX + cos(a) * rayStart;
float y = mouseY + sin(a) * rayStart;
_diff_line.addNode(new Node(x, y, _diff_line.maxForce, _diff_line.maxSpeed, _diff_line.desiredSeparation, _diff_line.separationCohesionRation));
//println(mouseX);
//println(mouseY);
}
}
class DifferentialLine {
ArrayList<Node> nodes;
float maxForce;
float maxSpeed;
float desiredSeparation;
float separationCohesionRation;
float maxEdgeLen;
DifferentialLine(float mF, float mS, float dS, float sCr, float eL) {
nodes = new ArrayList<Node>();
maxSpeed = mF;
maxForce = mS;
desiredSeparation = dS;
separationCohesionRation = sCr;
maxEdgeLen = eL;
}
void run() {
for (Node n : nodes) {
n.run(nodes);
}
growth();
}
void addNode(Node n) {
nodes.add(n);
}
void addNodeAt(Node n, int index) {
nodes.add(index, n);
}
void growth() {
for (int i=0; i<nodes.size()-1; i++) {
Node n1 = nodes.get(i);
Node n2 = nodes.get(i+1);
float d = PVector.dist(n1.position, n2.position);
if (d>maxEdgeLen) { // Can add more rules for inserting nodes
int index = nodes.indexOf(n2);
PVector middleNode = PVector.add(n1.position, n2.position).div(2);
addNodeAt(new Node(middleNode.x, middleNode.y, maxForce, maxSpeed, desiredSeparation, separationCohesionRation), index);
}
}
}
void render() {
for (int i=0; i<nodes.size()-1; i++) {
PVector p1 = nodes.get(i).position;
PVector p2 = nodes.get(i+1).position;
line(p1.x, p1.y, p2.x, p2.y);
colorMode(HSB);
stroke(255);
//stroke(10,frameCount*0.3,100);
//stroke(255);//Farbe
strokeWeight(1); //Strichstärke
if (i==nodes.size()-2) {
line(p2.x, p2.y, nodes.get(0).position.x, nodes.get(0).position.y);
}
}
}
}
class Node {
PVector position;
PVector velocity;
PVector acceleration;
float maxForce;
float maxSpeed;
float desiredSeparation;
float separationCohesionRation;
Node(float x, float y) {
acceleration = new PVector(0, 0);
velocity =PVector.random2D();
position = new PVector(x, y);
}
Node(float x, float y, float mF, float mS, float dS, float sCr) {
acceleration = new PVector(0, 0);
velocity =PVector.random2D();
position = new PVector(x, y);
maxSpeed = mF;
maxForce = mS;
desiredSeparation = dS;
separationCohesionRation = sCr;
}
void run(ArrayList<Node> nodes) {
differentiate(nodes);
update();
}
void applyForce(PVector force) {
acceleration.add(force);
}
void differentiate(ArrayList<Node> nodes) {
PVector separation = separate(nodes);
PVector cohesion = edgeCohesion(nodes);
separation.mult(separationCohesionRation);
//cohesion.mult(1.0);
applyForce(separation);
applyForce(cohesion);
}
void update() {
velocity.add(acceleration);
velocity.limit(maxSpeed);
position.add(velocity);
acceleration.mult(0);
}
PVector seek(PVector target) {
PVector desired = PVector.sub(target, position);
desired.setMag(maxSpeed);
PVector steer = PVector.sub(desired, velocity);
steer.limit(maxForce);
return steer;
}
PVector separate(ArrayList<Node> nodes) {
PVector steer = new PVector(0, 0);
int count = 0;
for (Node other : nodes) {
float d = PVector.dist(position, other.position);
if (d>0 && d < desiredSeparation) {
PVector diff = PVector.sub(position, other.position);
diff.normalize();
diff.div(d); // Weight by distance
steer.add(diff);
count++;
}
}
if (count>0) {
steer.div((float)count);
}
if (steer.mag() > 0) {
steer.setMag(maxSpeed);
steer.sub(velocity);
steer.limit(maxForce);
}
return steer;
}
PVector edgeCohesion (ArrayList<Node> nodes) {
PVector sum = new PVector(0, 0);
int this_index = nodes.indexOf(this);
if (this_index!=0 && this_index!=nodes.size()-1) {
sum.add(nodes.get(this_index-1).position).add(nodes.get(this_index+1).position);
} else if (this_index == 0) {
sum.add(nodes.get(nodes.size()-1).position).add(nodes.get(this_index+1).position);
} else if (this_index == nodes.size()-1) {
sum.add(nodes.get(this_index-1).position).add(nodes.get(0).position);
}
sum.div(2);
return seek(sum);
}
}
Code after first Answer:
// PARAMETERS
float _maxForce = 0.9;
float _maxSpeed = 1;
float _desiredSeparation = 30;
float _separationCohesionRation = 1.1;
float _maxEdgeLen = 8;
boolean seed = false;
DifferentialLine _diff_line;
ArrayList<DifferentialLine> lines = new ArrayList<DifferentialLine>();
void setup() {
frameRate(60);
background(0);
size(1280, 720);
}
void draw() {
if(seed == true){
//println(frameCount);
background(0);
//_diff_line.run();
//_diff_line.render();
for (DifferentialLine line : lines) {
line.run();
line.render();
}
}
}
void mousePressed(){
seed = true;
DifferentialLine newLine = new DifferentialLine(_maxForce, _maxSpeed, _desiredSeparation, _separationCohesionRation, _maxEdgeLen);
malewas();
lines.add(newLine);
}
void malewas(){
_diff_line = new DifferentialLine(_maxForce, _maxSpeed, _desiredSeparation, _separationCohesionRation, _maxEdgeLen);
//fill(0);
float nodesStart = 3;
float angInc = TWO_PI/nodesStart;
float rayStart = 5;
for (float a=0; a<TWO_PI; a+=angInc) {
float x = mouseX + cos(a) * rayStart;
float y = mouseY + sin(a) * rayStart;
_diff_line.addNode(new Node(x, y, _diff_line.maxForce, _diff_line.maxSpeed, _diff_line.desiredSeparation, _diff_line.separationCohesionRation));
//println(mouseX);
//println(mouseY);
}
}
class DifferentialLine {
ArrayList<Node> nodes;
float maxForce;
float maxSpeed;
float desiredSeparation;
float separationCohesionRation;
float maxEdgeLen;
DifferentialLine(float mF, float mS, float dS, float sCr, float eL) {
nodes = new ArrayList<Node>();
maxSpeed = mF;
maxForce = mS;
desiredSeparation = dS;
separationCohesionRation = sCr;
maxEdgeLen = eL;
}
void run() {
for (Node n : nodes) {
n.run(nodes);
}
growth();
}
void addNode(Node n) {
nodes.add(n);
}
void addNodeAt(Node n, int index) {
nodes.add(index, n);
}
void growth() {
for (int i=0; i<nodes.size()-1; i++) {
Node n1 = nodes.get(i);
Node n2 = nodes.get(i+1);
float d = PVector.dist(n1.position, n2.position);
if (d>maxEdgeLen) { // Can add more rules for inserting nodes
int index = nodes.indexOf(n2);
PVector middleNode = PVector.add(n1.position, n2.position).div(2);
addNodeAt(new Node(middleNode.x, middleNode.y, maxForce, maxSpeed, desiredSeparation, separationCohesionRation), index);
}
}
}
void render() {
for (int i=0; i<nodes.size()-1; i++) {
PVector p1 = nodes.get(i).position;
PVector p2 = nodes.get(i+1).position;
line(p1.x, p1.y, p2.x, p2.y);
colorMode(HSB);
stroke(255);
//stroke(10,frameCount*0.3,100);
//stroke(255);//Farbe
strokeWeight(1); //Strichstärke
if (i==nodes.size()-2) {
line(p2.x, p2.y, nodes.get(0).position.x, nodes.get(0).position.y);
}
}
}
}
class Node {
PVector position;
PVector velocity;
PVector acceleration;
float maxForce;
float maxSpeed;
float desiredSeparation;
float separationCohesionRation;
Node(float x, float y) {
acceleration = new PVector(0, 0);
velocity =PVector.random2D();
position = new PVector(x, y);
}
Node(float x, float y, float mF, float mS, float dS, float sCr) {
acceleration = new PVector(0, 0);
velocity =PVector.random2D();
position = new PVector(x, y);
maxSpeed = mF;
maxForce = mS;
desiredSeparation = dS;
separationCohesionRation = sCr;
}
void run(ArrayList<Node> nodes) {
differentiate(nodes);
update();
}
void applyForce(PVector force) {
acceleration.add(force);
}
void differentiate(ArrayList<Node> nodes) {
PVector separation = separate(nodes);
PVector cohesion = edgeCohesion(nodes);
separation.mult(separationCohesionRation);
//cohesion.mult(1.0);
applyForce(separation);
applyForce(cohesion);
}
void update() {
velocity.add(acceleration);
velocity.limit(maxSpeed);
position.add(velocity);
acceleration.mult(0);
}
PVector seek(PVector target) {
PVector desired = PVector.sub(target, position);
desired.setMag(maxSpeed);
PVector steer = PVector.sub(desired, velocity);
steer.limit(maxForce);
return steer;
}
PVector separate(ArrayList<Node> nodes) {
PVector steer = new PVector(0, 0);
int count = 0;
for (Node other : nodes) {
float d = PVector.dist(position, other.position);
if (d>0 && d < desiredSeparation) {
PVector diff = PVector.sub(position, other.position);
diff.normalize();
diff.div(d); // Weight by distance
steer.add(diff);
count++;
}
}
if (count>0) {
steer.div((float)count);
}
if (steer.mag() > 0) {
steer.setMag(maxSpeed);
steer.sub(velocity);
steer.limit(maxForce);
}
return steer;
}
PVector edgeCohesion (ArrayList<Node> nodes) {
PVector sum = new PVector(0, 0);
int this_index = nodes.indexOf(this);
if (this_index!=0 && this_index!=nodes.size()-1) {
sum.add(nodes.get(this_index-1).position).add(nodes.get(this_index+1).position);
} else if (this_index == 0) {
sum.add(nodes.get(nodes.size()-1).position).add(nodes.get(this_index+1).position);
} else if (this_index == nodes.size()-1) {
sum.add(nodes.get(this_index-1).position).add(nodes.get(0).position);
}
sum.div(2);
return seek(sum);
}
}

Problem
While you do in fact create a new shape with each mouse click, you're always assigning it to the same variable (_diff_line):
_diff_line = new DifferentialLine(_maxForce, _maxSpeed, _desiredSeparation, _separationCohesionRation, _maxEdgeLen);
So when you call _diff_line.run() and _diff_line.render() it is only ever operating on the one most recently created. The old ones no longer exist.
Solution
To fix this, you'd need to assign each new line to a different variable. Most likely you'd do this by creating an Array or ArrayList and adding a new DifferentialLine to the array on each click:
// create an ArrayList to hold all the lines
ArrayList<DifferentialLine> lines = new ArrayList<DifferentialLine>();
void mousePressed(){
// create the new line
DifferentialLine newLine = new DifferentialLine(_maxForce, _maxSpeed, _desiredSeparation, _separationCohesionRation, _maxEdgeLen);
// ... do your node setup stuff
// add the new line to the ArrayList
lines.add(newLine);
}
Then, when you want to render them, you can loop through the ArrayList (or Array) and draw each one:
for (DifferentialLine line : lines) {
line.run();
line.render();
}

Solution
// PARAMETERS
float _maxForce = 0.9;
float _maxSpeed = 1;
float _desiredSeparation = 30;
float _separationCohesionRation = 1.1;
float _maxEdgeLen = 8;
boolean seed = false;
//DifferentialLine _diff_line;
ArrayList<DifferentialLine> lines = new ArrayList<DifferentialLine>();
void setup() {
frameRate(60);
background(0);
size(1280, 720);
}
void draw() {
if (seed == true) {
//println(frameCount);
background(0);
//_diff_line.run();
//_diff_line.render();
for (DifferentialLine line : lines) {
line.run();
line.render();
}
}
}
void mousePressed() {
seed = true;
DifferentialLine newLine = new DifferentialLine(_maxForce, _maxSpeed, _desiredSeparation, _separationCohesionRation, _maxEdgeLen);
//drawseed();
float nodesStart = 3;
float angInc = TWO_PI/nodesStart;
float rayStart = 5;
for (float a=0; a<TWO_PI; a+=angInc) {
float x = mouseX + cos(a) * rayStart;
float y = mouseY + sin(a) * rayStart;
newLine.addNode(new Node(x, y, newLine.maxForce, newLine.maxSpeed, newLine.desiredSeparation, newLine.separationCohesionRation));
//println(mouseX);
//println(mouseY);
}
lines.add(newLine);
}
/*void drawseed() {
_diff_line = new DifferentialLine(_maxForce, _maxSpeed, _desiredSeparation, _separationCohesionRation, _maxEdgeLen);
//fill(0);
float nodesStart = 3;
float angInc = TWO_PI/nodesStart;
float rayStart = 5;
for (float a=0; a<TWO_PI; a+=angInc) {
float x = mouseX + cos(a) * rayStart;
float y = mouseY + sin(a) * rayStart;
_diff_line.addNode(new Node(x, y, _diff_line.maxForce, _diff_line.maxSpeed, _diff_line.desiredSeparation, _diff_line.separationCohesionRation));
//println(mouseX);
//println(mouseY);
}
}*/
class DifferentialLine {
ArrayList<Node> nodes;
float maxForce;
float maxSpeed;
float desiredSeparation;
float separationCohesionRation;
float maxEdgeLen;
DifferentialLine(float mF, float mS, float dS, float sCr, float eL) {
nodes = new ArrayList<Node>();
maxSpeed = mF;
maxForce = mS;
desiredSeparation = dS;
separationCohesionRation = sCr;
maxEdgeLen = eL;
}
void run() {
for (Node n : nodes) {
n.run(nodes);
}
growth();
}
void addNode(Node n) {
nodes.add(n);
}
void addNodeAt(Node n, int index) {
nodes.add(index, n);
}
void growth() {
for (int i=0; i<nodes.size()-1; i++) {
Node n1 = nodes.get(i);
Node n2 = nodes.get(i+1);
float d = PVector.dist(n1.position, n2.position);
if (d>maxEdgeLen) { // Can add more rules for inserting nodes
int index = nodes.indexOf(n2);
PVector middleNode = PVector.add(n1.position, n2.position).div(2);
addNodeAt(new Node(middleNode.x, middleNode.y, maxForce, maxSpeed, desiredSeparation, separationCohesionRation), index);
}
}
}
void render() {
for (int i=0; i<nodes.size()-1; i++) {
PVector p1 = nodes.get(i).position;
PVector p2 = nodes.get(i+1).position;
line(p1.x, p1.y, p2.x, p2.y);
colorMode(HSB);
stroke(255);
//stroke(10,frameCount*0.3,100);
//stroke(255);//Farbe
strokeWeight(1); //Strichstärke
if (i==nodes.size()-2) {
line(p2.x, p2.y, nodes.get(0).position.x, nodes.get(0).position.y);
}
}
}
}
class Node {
PVector position;
PVector velocity;
PVector acceleration;
float maxForce;
float maxSpeed;
float desiredSeparation;
float separationCohesionRation;
Node(float x, float y) {
acceleration = new PVector(0, 0);
velocity =PVector.random2D();
position = new PVector(x, y);
}
Node(float x, float y, float mF, float mS, float dS, float sCr) {
acceleration = new PVector(0, 0);
velocity =PVector.random2D();
position = new PVector(x, y);
maxSpeed = mF;
maxForce = mS;
desiredSeparation = dS;
separationCohesionRation = sCr;
}
void run(ArrayList<Node> nodes) {
differentiate(nodes);
update();
}
void applyForce(PVector force) {
acceleration.add(force);
}
void differentiate(ArrayList<Node> nodes) {
PVector separation = separate(nodes);
PVector cohesion = edgeCohesion(nodes);
separation.mult(separationCohesionRation);
//cohesion.mult(1.0);
applyForce(separation);
applyForce(cohesion);
}
void update() {
velocity.add(acceleration);
velocity.limit(maxSpeed);
position.add(velocity);
acceleration.mult(0);
}
PVector seek(PVector target) {
PVector desired = PVector.sub(target, position);
desired.setMag(maxSpeed);
PVector steer = PVector.sub(desired, velocity);
steer.limit(maxForce);
return steer;
}
PVector separate(ArrayList<Node> nodes) {
PVector steer = new PVector(0, 0);
int count = 0;
for (Node other : nodes) {
float d = PVector.dist(position, other.position);
if (d>0 && d < desiredSeparation) {
PVector diff = PVector.sub(position, other.position);
diff.normalize();
diff.div(d); // Weight by distance
steer.add(diff);
count++;
}
}
if (count>0) {
steer.div((float)count);
}
if (steer.mag() > 0) {
steer.setMag(maxSpeed);
steer.sub(velocity);
steer.limit(maxForce);
}
return steer;
}
PVector edgeCohesion (ArrayList<Node> nodes) {
PVector sum = new PVector(0, 0);
int this_index = nodes.indexOf(this);
if (this_index!=0 && this_index!=nodes.size()-1) {
sum.add(nodes.get(this_index-1).position).add(nodes.get(this_index+1).position);
} else if (this_index == 0) {
sum.add(nodes.get(nodes.size()-1).position).add(nodes.get(this_index+1).position);
} else if (this_index == nodes.size()-1) {
sum.add(nodes.get(this_index-1).position).add(nodes.get(0).position);
}
sum.div(2);
return seek(sum);
}
}

Related

different speed of three sphere

I am a new coder on processing, that's why please be gentle.I made a simple code for you. Normally my code is more longer and complex.However, I wrote a simple code for you.
//main class
ArrayList<Clouds> clouds = new ArrayList();
void setup() {
size(1200, 800, P3D);
for (int i = 0; i < 3; i++)
{
Clouds C = new Clouds();
clouds.add(C);
}
}
void draw() {
background(0);
for (int i = 0; i < clouds.size(); i++)
{
clouds.get(i).drawClouds();
}
}
//Clouds class
class Clouds
{
float xC, yC, zC, speedC;
public Clouds()
{
xC = 20;
yC = 40;
zC = 0;
noStroke();
speedC = 1;
}
public void drawClouds()
{
translate(xC,yC);
pushMatrix();
makingClouds(100, 100, 100);
popMatrix();
if (xC > width - 780) {
xC = -660;
}
xC += speedC;
}
public void makingClouds(float xF, float yF, float zF ) {
translate(xF, yF, zF);
pushMatrix();
lights();
scale(1, 1, 1);
sphere(20);
popMatrix();
}
}
I hope, I'm not doing wrong with writing two class in here but I've worked on it two whole days and made me sick. So my question is: Like you see, there are three sphere and they have same speed but when I run the program, they go to end with different speeds. How they have same speed? If you help me, you will be my hero! Thank you.
translate() do not just set a translation, it defines a translation matrix and multiplies the new translation matrix to the current matrix.
You have to construct the clouds at different positions:
void setup() {
// [...]
for (int i = 0; i < 3; i++) {
Clouds C = new Clouds(20, i*40);
clouds.add(C);
}
}
class Clouds {
float xC, yC, zC, speedC;
public Clouds(float x, float y) {
xC = x;
yC = y;
zC = 0;
// [...]
}
And to move translate in the pushMatrix() / popMatrix() block:
class Clouds {
// [...]
public void drawClouds() {
pushMatrix();
translate(xC,yC);
// [...]
popMatrix();
// [...]
}
public void makingClouds(float xF, float yF, float zF ) {
pushMatrix();
translate(xF, yF, zF);
// [...]
popMatrix();
}
Example code:
//main class
ArrayList<Clouds> clouds = new ArrayList();
void setup() {
size(1200, 800, P3D);
for (int i = 0; i < 3; i++) {
Clouds C = new Clouds(20, i*40);
clouds.add(C);
}
}
void draw() {
background(0);
for (int i = 0; i < clouds.size(); i++) {
clouds.get(i).drawClouds();
}
}
//Clouds class
class Clouds {
float xC, yC, zC, speedC;
public Clouds(float x, float y) {
xC = x;
yC = y;
zC = 0;
speedC = 1;
}
public void drawClouds() {
noStroke();
pushMatrix();
translate(xC,yC);
makingClouds(100, 100, 100);
popMatrix();
if (xC > width - 780) {
xC = -660;
}
xC += speedC;
}
public void makingClouds(float xF, float yF, float zF ) {
pushMatrix();
translate(xF, yF, zF);
lights();
scale(1, 1, 1);
sphere(20);
popMatrix();
}
}

Buggy bouncing balls

I was making a colliding ball sketch in Processing, and I encountered a weird bug. Despite having a condition for bouncing off of the walls, some balls get stuck to it. I can't find the source of error here. Can someone help? I also realise that there maybe few (a lot) bad coding practices, but I apologise beforehand.
I am posting the codes below.
1) Main : https://pastebin.com/hv0H14gZ
particle[] elec = new particle[5];
boolean record = false;
void setup(){
float x=0,y=0;
int i,j;
float diam = 100;
size(800,400);
//Initialising the particle objects
for (int k = 0; k < elec.length; k++){
x = random(width/10, width/1.2);
y = random(height/10, height/1.2);
elec[k] = new particle(x,y);
}
//Spawning at random places
for ( i = 0; i < elec.length; i++){
if (i!=0){
for ( j = 0; j < elec.length; j ++){
if (dist(x,y,elec[j].getX(),elec[j].getY()) <= diam){
x = random(width/10, width/1.2);
y = random(height/10, height/1.2);
j = -1;
}
}
}
elec[i] = new particle(x,y,diam,4,4,2);
}
}
void draw(){
background(0);
for (int i = 0; i < elec.length; i++){
elec[i].update(elec);
elec[i].move();
elec[i].bounce();
if(record){
saveFrame("collide_#####.png");
fill(255,0,0);
} else {
fill(0,255,0);
}
ellipse(width/1.01, height/1.01,5,5);
}
}
void keyPressed(){
if (key =='r' || key =='R'){
record = !record;
}
}
2) Classes : https://pastebin.com/Rt49sN9c
public class velocity{
float delx, dely;
//Constructor 1
public velocity(){}
//Constructor 2
public velocity(float delx, float dely){
this.delx = delx;
this.dely = dely;
}
//Mutators for xvelocity and y velocity
public float getdelx(){
return this.delx;
}
public float getdely(){
return this.dely;
}
//Accessors for xvelocity and y velocity
public void setdelx(float delx){
this.delx = delx;
}
public void setdely(float dely){
this.dely = dely;
}
}
public class particle{
private float xpos , ypos, delx , dely,size, decay, mass;
color colour;
//constructor 1
public particle(float x, float y){
this.xpos = x;
this.ypos = y;
}
//constructor 2
public particle(float xpos, float ypos, float size, float delx, float dely, float mass){
this.xpos = xpos;
this.ypos = ypos;
this.size = size;
this.delx = delx;
this.dely = dely;
this.mass = mass;
}
//Mutators for size, x velocity y velocity and velocity vector
public void setsize(float size){
this.size = size;
}
public void setDX(float delx){
this.delx = delx;
}
public void setDY(float dely){
this.dely = dely;
}
//Accessors for size, x position, y position, x velocity and y velocity
public float getsize(){
return this.size;
}
public float getX(){
return this.xpos;
}
public float getY(){
return this.ypos;
}
public float getDX(){
return this.delx;
}
public float getDY(){
return this.dely;
}
public float getmass(){
return this.mass;
}
public velocity getvel(){
velocity v = new velocity(this.getDX(), this.getDY());
return v;
}
//Functionality. Moving around, Bouncing off of walls, and basic display updates
public void move(){
this.xpos += this.delx;
this.ypos += this.dely;
}
public void bounce(){
if((this.xpos - this.size/2.0) < 0 || (this.xpos + this.size/2.0) > width){
this.setDX(this.getDX()*-1);
}
if((this.ypos - this.size/2.0) < 0 || (this.ypos + this.size/2.0) > height){
this.setDY(this.getDY()*-1);
}
}
public void update(particle[] elec){
for(int i =0; i< elec.length; i++){
if(this == elec[i]) continue;
if(dist(this.getX(),this.getY(),elec[i].getX(),elec[i].getY()) - this.getsize() <0){
collision(this, elec[i]);
//println(dist(this.getX(),this.getY(),elec[i].getX(),elec[i].getY()) - this.getsize()/2);
}
}
display();
}
public void display(){
stroke(0);
fill(119,240,153);
ellipse(this.xpos, this.ypos, this.size ,this.size);
}
}
velocity rotate(velocity v, float angle){
float x = v.getdelx()*cos(angle) - v.getdely()*sin(angle);
float y = v.getdelx()*sin(angle) + v.getdely()*cos(angle);
velocity vel = new velocity(x,y);
return vel;
}
void collision(particle p1, particle p2){
float xveldiff = p1.getDX()-p2.getDX();
float yveldiff = p1.getDY()-p2.getDY();
float xdist = p2.getX() - p1.getX();
float ydist = p2.getY() - p1.getY();
//Check for accidental overlaps of particles
if(xveldiff*xdist + yveldiff*ydist > 0){
float angle = -atan2(p2.getY() - p1.getY(), p2.getX() - p1.getY());
float m1 = p1.getmass();
float m2 = p2.getmass();
velocity u1 = rotate(p1.getvel(),angle);
velocity u2 = rotate(p2.getvel(),angle);
velocity v1 = new velocity(u1.getdelx() * (m1 - m2) / (m1 + m2) + u2.getdelx() * 2 * m2 / (m1 + m2), u1.getdely());
velocity v2 = new velocity(u2.getdelx() * (m1 - m2) / (m1 + m2) + u1.getdelx() * 2 * m2 / (m1 + m2), u2.getdely());
velocity vf1 = rotate(v1, -angle);
velocity vf2 = rotate(v2, -angle);
p1.setDX(vf1.getdelx());
p1.setDY(vf1.getdely());
p2.setDX(vf2.getdelx());
p2.setDY(vf2.getdely());
}
}
Nice animation, the issue is cased by the method bounce of class particle:
When the "ball" doesn't leave the wall in one step, then it sticks.
Note, if e.g the condition (this.xpos - this.size/2.0) < 0 is fulfilled twice, the the direction is inverted twice (this.getDX()*-1). This causes that the ball bounce into the wall continuously and leads to a trembling movement along the wall.
public void bounce(){
if((this.xpos - this.size/2.0) < 0 || (this.xpos + this.size/2.0) > width){
this.setDX(this.getDX()*-1);
}
if((this.ypos - this.size/2.0) < 0 || (this.ypos + this.size/2.0) > height){
this.setDY(this.getDY()*-1);
}
}
You have to ensure, the the direction (delx, dely) always points away from the wall, if the ball is to near to it:
public void bounce(){
if( this.xpos - this.size/2.0 < 0 ) {
this.setDX( Math.abs(this.getDX()) );
} else if( this.xpos + this.size/2.0 > width ) {
this.setDX( -Math.abs(this.getDX()) );
}
if( this.ypos - this.size/2.0 < 0 ) {
this.setDY( Math.abs(this.getDY()) );
} else if( this.ypos + this.size/2.0 > height ) {
this.setDY( -Math.abs(this.getDY()) );
}
}

How to use Hashmap or Array to create a "list" of countries with attributes

I'm trying to visualize migration data using particle systems. Each row of the dataset contains: source country, destination country, year, and various amounts.
Each row should be represented as a particle system representing that data.
QUESTION:
What will be the best way to create a list of countries or country objects, with x,y location attributes and maybe some other attributes that could be added later?
Entire code for reference:
// Based on Example Written by Casey Reas and Ben Fry
// Edited by Tom Bar-Gal
//particlesystem()
//addparticle()
//particle()
// ========== Table Data Stuff
Table table;
int k = 0;
String[] destCountryArray = new String[0];
String[] sourceCountryArray = new String[0];
String destCountry = "";
String prevDestCountry = "";
String sourceCountry;
// ========
int maxParticles = 12000;
ParticleSystem ps;
ParticleSystem ps2;
int n = 0, n2=0;
int emmitMultiplyer = 1;
int emmitFreq = 1;
float particleSpeed = 0.002;
float locationX = 250;
float locationY = 450;
int[] sourceX = {10, 40, 200, 400, 700};
int[] destX = {300, 600, 300, 600, 600};
int[] amount = {10, 100, 500, 800, 1000};
int highestAmount = max(amount);
// a,b,c... max*a/{a+b+c...}
ParticleSystem[] PSystems;
void setup() {
size(1200, 800);
//=============== load table and create an array of countries
table = loadTable("asylum_seekers.csv", "header");
destCountryArray = (String[]) append(destCountryArray, "Israel");
for (TableRow row : table.rows()) {
//println("going over row" + row.getString("Country / territory of asylum/residence"));
String tempCountryHolder = row.getString("Country / territory of asylum/residence");
//println("Got a temp country holder" + tempCountryHolder);
boolean exists = countryExists(tempCountryHolder);
if (exists==true) {
//println("exists, skipping");
continue;
}
println("Appending "+tempCountryHolder+" to list of length " +destCountryArray.length);
destCountryArray = (String[]) append(destCountryArray, tempCountryHolder);
println("destCountryArray length = "+ destCountryArray.length);
}
//============================
PSystems = new ParticleSystem[destCountryArray.length];
//frameRate(30);
//colorMode(RGB,255,255,255,255);
for (int i = 0; i<destCountryArray.length; i++) {
// Particle Systems syntax = multiplyer, source, destination, amount);
PSystems[i] = new ParticleSystem(1, new Vector3D(i*40+40, 100, 0), new Vector3D(i*40+40, 500, 0), 1/(i+1));
//println("PSystems " + i + " is " +PSystems[i]);
}
//ps = new ParticleSystem(1, new Vector3D(width/2, height/2, 0));
//ps2 = new ParticleSystem(1, new Vector3D(100, 200, 0));
smooth();
}
void draw() {
background(250);
//ellipse(locationX, locationY, 5, 5);
//ellipse(width/2, height/2, 5, 5);
//ellipse(100, 200, 5, 5);
//println(PSystems.length);
for (int i = 0; i<destCountryArray.length; i++) {
//println(PSystems[i]);
PSystems[i].run();
}
for (int i = 0; i<emmitMultiplyer; i++) {
for (int k = 0; k<destCountryArray.length; k++) {
if (frameCount % (k+1) == 0) {
PSystems[k].addParticle();
n++;
}
}
}
n2+=emmitMultiplyer;
fill(0);
text("Frame rate: "
+ int(frameRate), 10, 20);
println(n);
println(n);
}
// ==============================// A simple Particle class // ===============================================//
class Particle {
Vector3D loc;
Vector3D des;
Vector3D vel;
Vector3D acc;
Vector3D locHome, b, c;
float relativeSpeed;
float r;
float timer;
float t=0.0;
// Another constructor (the one we are using here)
Particle(Vector3D l, Vector3D m) {
//acc = new Vector3D(0,0.0005,0); // particle acceleration
acc = new Vector3D(0, 0, 0); // new Vector3D(random(-0.1, 0.1), random(-0.02, 0), 0);
loc = l.copy();
des = m.copy();
locHome = l.copy();
locHome.x = locHome.x+random(-2, 2);
locHome.y = locHome.y+random(-2, 2);
des.x = des.x+random(-2, 2);
des.y=des.y+random(-2, 2);
relativeSpeed = random(0.5, 1.2);
r = random(0.9, 2.3); // particle radius
timer = 10000.0; // particles lifespan
// * emmitMultiplyer = number of living
b=new Vector3D(locHome.x+random(-20, 20), locHome.y+random(120, 180), 0);
c=new Vector3D(des.x+random(-20, 30), des.y-random(120, 180), 0);
}
void run() {
update();
render();
}
// Method to update location
void update() {
if (t>=1)
return;
// https : // www.processing.org/reference/bezierPoint_.html
loc.x = bezierPoint(locHome.x, b.x, c.x, des.x, t);
loc.y = bezierPoint(locHome.y, b.y, c.y, des.y, t);
t = lerp(t, 1, particleSpeed*relativeSpeed);
//t+=particleSpeed*relativeSpeed;
// curvePoint(a, b, c, d, t)
// vel.add(acc);
// loc.add(vel);
//timer -= 1.0;
}
// Method to display
void render() {
ellipseMode(CENTER);
noStroke();
fill(70, 255);
ellipse(loc.x, loc.y, r, r);
}
// Is the particle still useful?
boolean dead() {
// if (timer <= 0.0||t>=1.0) {
if (t>=0.95) {
return true;
} else {
return false;
}
}
}
// ==============================// A ParticleSystem // ===============================================//
// A class to describe a group of Particles
// An ArrayList is used to manage the list of Particles
class ParticleSystem {
ArrayList particles; // An arraylist for all the particles
Vector3D origin; // An origin point for where particles are birthed
Vector3D dest;
int freq;
//ParticleSystem( number of particles / frame, source, destination, frequency);
ParticleSystem(int num, Vector3D v, Vector3D d, float f) {
particles = new ArrayList(); // Initialize the arraylist
origin = v.copy(); // Store the origin point
dest = d.copy();
//if (frameCount % (1/f) == 0){
for (int i = 0; i < num; i++) {
particles.add(new Particle(origin, dest)); // Add "num" amount of particles to the arraylist
}
//}
}
void run() {
// Cycle through the ArrayList backwards b/c we are deleting
for (int i = particles.size()-1; i >= 0; i--) {
Particle p = (Particle) particles.get(i);
p.run();
if (p.dead()) {
particles.remove(i);
n--;
}
}
}
void addParticle() {
particles.add(new Particle(origin, dest));
}
//void addParticle(Particle p) {
// particles.add(p);
//}
// A method to test if the particle system still has particles
boolean dead() {
if (particles.isEmpty()) {
return true;
} else {
return false;
}
}
}
//=================================================== Class Country
public class Country {
public float countryIndex;
public float countryLocationX;
public float countryLocationY;
public float countryName;
}
// ================================================ Simple Vector3D Class
public class Vector3D {
public float x;
public float y;
public float z;
Vector3D(float x_, float y_, float z_) {
x = x_;
y = y_;
z = z_;
}
Vector3D(float x_, float y_) {
x = x_;
y = y_;
z = 0f;
}
Vector3D() {
x = 0f;
y = 0f;
z = 0f;
}
void setX(float x_) {
x = x_;
}
void setY(float y_) {
y = y_;
}
void setZ(float z_) {
z = z_;
}
void setXY(float x_, float y_) {
x = x_;
y = y_;
}
void setXYZ(float x_, float y_, float z_) {
x = x_;
y = y_;
z = z_;
}
void setXYZ(Vector3D v) {
x = v.x;
y = v.y;
z = v.z;
}
public float magnitude() {
return (float) Math.sqrt(x*x + y*y + z*z);
}
public Vector3D copy() {
return new Vector3D(x, y, z);
}
public Vector3D copy(Vector3D v) {
return new Vector3D(v.x, v.y, v.z);
}
public void add(Vector3D v) {
x += v.x;
y += v.y;
z += v.z;
}
public void sub(Vector3D v) {
x -= v.x;
y -= v.y;
z -= v.z;
}
public void mult(float n) {
x *= n;
y *= n;
z *= n;
}
public void div(float n) {
x /= n;
y /= n;
z /= n;
}
public void normalize() {
float m = magnitude();
if (m > 0) {
div(m);
}
}
public void limit(float max) {
if (magnitude() > max) {
normalize();
mult(max);
}
}
public float heading2D() {
float angle = (float) Math.atan2(-y, x);
return -1*angle;
}
public Vector3D add(Vector3D v1, Vector3D v2) {
Vector3D v = new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
return v;
}
public Vector3D sub(Vector3D v1, Vector3D v2) {
Vector3D v = new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
return v;
}
public Vector3D div(Vector3D v1, float n) {
Vector3D v = new Vector3D(v1.x/n, v1.y/n, v1.z/n);
return v;
}
public Vector3D mult(Vector3D v1, float n) {
Vector3D v = new Vector3D(v1.x*n, v1.y*n, v1.z*n);
return v;
}
public float distance (Vector3D v1, Vector3D v2) {
float dx = v1.x - v2.x;
float dy = v1.y - v2.y;
float dz = v1.z - v2.z;
return (float) Math.sqrt(dx*dx + dy*dy + dz*dz);
}
}
boolean countryExists(String tempCountryHolder) {
for (int i = 0; i < destCountryArray.length; i++) {
//println("comparing '" +tempCountryHolder +"' with '"+destCountryArray[i] + "'");
if (tempCountryHolder.equals(destCountryArray[i]) == true) {
//println("found : "+ tempCountryHolder);
return true; // it exists
} //if
} //for
return false ; // not found
}//func
answer was: hashmap of hashmaps
HashMap<String, HashMap> countries = new HashMap<String, HashMap>();
for (int i=0; i<destCountryArray.length; i++) {
HashMap<String, Float> country = new HashMap<String, Float>();
countries.put(destCountryArray[i], country);
country.put("x", i*20.0);
country.put("y", i*40.0);
}
for (Map.Entry me : countries.entrySet()) {
print(me.getKey() + " is ");
println(me.getValue());
}
You probably don't want to use a nested HashMap like your answer suggests. You probably want to use your own class instead. Something like this:
HashMap<String, Point> countries = new HashMap<String, Point>();
void setup(){
countries.put("one", new Point(2, 3));
countries.put("four", new Point(5, 6));
}
void draw(){
Point pOne = countries.get("one");
point(pOne.x, pOne.y);
}
class Point{
float x;
float y;
public Point(float x, float y){
this.x = x;
this.y = y;
}
}
Or better yet, you could just use Processing's PVector class, which already represents points:
HashMap<String, PVector> countries = new HashMap<String, PVector>();
void setup(){
countries.put("one", new PVector(2, 3));
countries.put("four", new PVector(5, 6));
}
void draw(){
PVector pOne = countries.get("one");
point(pOne.x, pOne.y);
}
More info can be found in the reference. Shameless self-promotion: here is a tutorial on using classes, and here is a tutorial on creating your own classes.

Array is only displaying 1 object instead of the full amount of variables

I'm new to coding (as I'm sure you might be able to tell). The program runs and generates 1 Tubble, but the additional objects don't show.
Here's my class:
class Tubble {
float x;
float y;
float diameter;
float yspeed;
float tempD = random(2,86);
Tubble() {
x = random(width);
y = height-60;
diameter = tempD;
yspeed = random(0.1, 3);
}
void ascend() {
y -= yspeed;
x = x + random(-2, 2);
}
void dis() {
stroke(0);
fill(127, 100);
ellipse(x, y, diameter, diameter);
}
void top() {
if (y < -diameter/2) {
y = height+diameter/2;
}
}
}
Class
class Particle {
float x, y;
float r;
float speed = 2.2;
int direction = 1;
PImage pbubbles;
Particle(float x_, float y_, float r_) {
x = x_;
y = y_;
r = r_;
}
void display() {
stroke(#F5D7D7);
strokeWeight(2.2);
noFill();
ellipse(x, y, r*2, r*2);
}
boolean overlaps(Particle other) {
float d = dist(x, y, other.x, other.y);
if (d < r + other.r) {
return true;
} else {
return false;
}
}
void move() { //testing
x += (speed * direction);
if ((x > (width - r)) || (x < r)) {
direction *= -1;
}
}
void updown() {
y += (speed * direction);
if ((y > (height - r)) || (y < r)) {
direction *= -1;
}
}
}
Main sketch:
Tubble[] tubbles = new Tubble [126];
PImage bubbles;
Particle p1;
Particle p2;
Particle p3;
Particle p4;
Particle p5;
float x,y;
float speed;
int total = 0;
int i;
//int direction = 1;
void setup() {
size(800, 925);
bubbles = loadImage("purple_bubbles.png");
p1 = new Particle (100, 100, 50);
p2 = new Particle (500, 200, 100);
p3 = new Particle (600, 600, 82);
p4 = new Particle (height/2, width/2, 200);
p5 = new Particle ((height/3), (width/3), 20);
for (int i = 0; i < tubbles.length; i++); {
tubbles[i] = new Tubble();
}
}
void mousePressed() {
total = total + 1;
}
void keyPressed() {
total = total - 1;
}
void draw() {
image(bubbles, 0, 0, 800, 925);
//background(0);
for (int i = 0; i < tubbles.length; i++); {
tubbles[i].ascend();
tubbles[i].dis();
tubbles[i].top();
}
if ((p2.overlaps(p1)) && (p2.overlaps(p4))) {
background(#BF55AB, 25);
}
if ((p3.overlaps(p2)) && (p3.overlaps(p4))) {
background(#506381, 80);
}
p2.x = mouseX;
p3.y = mouseY;
p1.display();
p2.display();
p3.display();
p4.display();
p5.display();
p4.move();
p5.updown();
// for (int i = 0; i < tubbles.length; i++); {
// tubbles[i].dis();
// tubbles[i].ascend();
// tubbles[i].top();
// }
}
There are extra semicolons in the lines
for (int i = 0; i < tubbles.length; i++); {
for (int i = 0; i < tubbles.length; i++); {
// for (int i = 0; i < tubbles.length; i++); {
It make the for loop do virtually nothing.
Then the block after the for loop will read the global variable i and do the action only once.
Remove the semicolons like this to put the block in the loop.
for (int i = 0; i < tubbles.length; i++) {
for (int i = 0; i < tubbles.length; i++) {
// for (int i = 0; i < tubbles.length; i++) {

why do the circles disappear from the screen?

Processing code as below, one quick question: why do the circles disappear from the screen when my mouse is playing with them? i've already add the boundary check however it does not seem to work. why???
int maxCircle = 200;
float minDistance=30;
float distance1;
float distance2;
Circle [] circles= new Circle[maxCircle];
void setup() {
size(800,800);
smooth();
for(int i=0;i<maxCircle;i++){
circles[i] = new Circle(random(width),random(height),random(2,20));
}
}
void draw() {
background(255,255);
for(int i=0;i<maxCircle;i++) {
circles[i].update(width,height);
for (int j=0; j<maxCircle; j++) {
distance1 = dist(circles[i].x,circles[i].y,circles[j].x,circles[j].y);
if ( distance1 < minDistance ) {
stroke(0,10);
noFill();
line(circles[i].x,circles[i].y,circles[j].x,circles[j].y);
}
}
circles[i].display();
}
}
void mouseMoved() {
for(int i = 0; i<maxCircle;i++) {
distance2 = dist(mouseX,mouseY,circles[i].x,circles[i].y);
circles[i].x-=(mouseX-circles[i].x)/distance2;
circles[i].y-=(mouseX-circles[i].y)/distance2;
if(circles[i].x<circles[i].r || circles[i].x>width-circles[i].r) {
circles[i].vx*=-1;
};
if(circles[i].y<circles[i].r || circles[i].y> height-circles[i].r) {
circles[i].vy*=-1;
}
}
}
class Circle {
float x,y,vx,vy,r,speed;
Circle(float tempx, float tempy, float tempr) {
x=tempx;
y=tempy;
vx=random(-1,1);
vy=random(-1,1);
r=tempr;
}
void update(int w,int h) {
x+=vx;
y+=vy;
if(x<r || x>w-r) {
vx*=-1;
}
if(y<r || y>h-r) {
vy*=-1;
}
}
void display() {
fill(0,50);
noStroke();
ellipse(x,y,r,r);
}
}
Oh i found the solution:
int maxCircle = 200;
float minDistance = 20;
Circle [] circles = new Circle[maxCircle];
void setup() {
size(800, 800);
smooth();
for (int i = 0; i < maxCircle; i++) {
circles[i] = new Circle();
}
}
void draw() {
background(255, 255);
for (int i = 0; i < maxCircle; i++) {
circles[i].update();
noFill();
for (int j = 0; j < maxCircle; j++) {
if (i == j)
continue;
float distance = dist(circles[i].x, circles[i].y, circles[j].x, circles[j].y);
if (distance < minDistance) {
stroke(0, 20);
line(circles[i].x, circles[i].y, circles[j].x, circles[j].y);
}
}
circles[i].display();
}
}
void mouseMoved() {
for (int i = 0; i < maxCircle; i++) {
float distance = dist(mouseX, mouseY, circles[i].x, circles[i].y);
circles[i].x -= (mouseX - circles[i].x) / distance;
circles[i].y -= (mouseX - circles[i].y) / distance;
circles[i].checkBounds();
}
}
class Circle {
float x, y, vx, vy, r, speed;
Circle() {
vx = random(-1, 1);
vy = random(-1, 1);
r = random(1, 10); // See below
x = random(r, width - r);
y = random(r, height - r);
}
void checkBounds() {
if (x < r || x > width - r) {
vx *= -1;
if (x < r) {
x = r;
} else {
x = width - r;
}
}
if (y <= r || y >= height - r) {
vy *= -1;
if (y < r) {
y = r;
} else {
y = width - r;
}
}
}
void update() {
x += vx;
y += vy;
checkBounds();
}
void display() {
fill(0, 50);
noStroke();
ellipse(x, y, r * 2, r * 2);
}
}
in your update() method, when you calculate a new coordinate with your vector, you are potentially setting the coordinate offscreen. I have added 4 conditional statements that reset the value to the bounds of the screen if it exceeds it.
void update(int w,int h) {
x+=vx;
y+=vy;
if(x<r || x>w-r) {
vx*=-1;
if (x>w-r) x = w-r;
if (x<r) x = r;
}
if(y<r || y>h-r) {
vy*=-1;
if (y>h-r) y = h-r;
if (y<r) y = r;
}
}

Resources