How to store co-ordinates of all shapes on a canvas - processing

I am trying to create a sketch which consists of randomly placed lines with random angulations and strokeWeight. The idea is that at each frame the lines change their tilt slightly according to a preset rule which in turn depends on the strokeWeight and other parameters. To do this I think I need to record the co-ordinates of each line at setup and then transform them and then record them again. If that makes sense.
Basically the question boils down to how can I record the co-ordinates of all the lines on a canvas?
Here is what I have written so far but how do I store the shape co-ordinates:
//Sets up the random lines on the canvas
//Sets up the authorities (line widths)
//Sets up the connections between lines
void setup() {
background(204);
size(800, 800);
for (int x=1;x <1000;x +=1){
fill(75, 70, 80);
//For the x y cords
float r = random(800);
float s = random(800);
//for the strokeWeight
float fat = random(5);
//for the stroke colour which varies with stroke weight
float col = random(350);
float red = random(350);
float g = random(350);
float b = random(350);
//for the initial tilt
float rot = random(360);
//stroke(242, 204, 47, 255);
strokeWeight(fat);
//stroke (red,green,blue,opacity)
stroke(fat*100, 180, 180);
//stroke(242, 204, 47, 255);
line(r,s,r+10,s+10);
rotate(radians(rot));
}
}
//This part is the diffusion animation
void draw() {
}

You might want to create a Line class that holds the information necessary to draw a line. Something like this:
class Line{
float x1, y1, x2, y2;
public Line(float x1, float y1, float x2, float y2){
this.x1 = x1;
this.y1 = y1
this.x2 = x2;
this.y2 = y2;
}
public void draw(){
line(x1, y1, x2, y2);
}
public boolean intersects(Line other){
//left as exercise for reader
}
}
Then you can randomly generate lines:
ArrayList<Line> lines = new ArrayList<Line>();
void setup(){
for(int i = 0; i < 10; i++){
lines.add(new Line(random(width), random(height), random(width), random(height));
}
}
void draw(){
background(0);
for(Line line : lines){
line.draw();
}
}
This is what I was getting at when I told you in your other question that you need to create a data structure and store your line coordinates. From here you can write logic that moves your lines around, or detects intersections, etc.

Related

How can add interaction and animation to shapes drawn in Processing?

I'm trying to code a canvas full of shapes(houses) and animate them in processing.
Here's an example of shape:
void house(int x, int y) {
pushMatrix();
translate(x, y);
fill(0, 200, 0);
triangle(15, 0, 0, 15, 30, 15);
rect(0, 15, 30, 30);
rect(12, 30, 10, 15);
popMatrix();
}
By animation I mean moving them in random directions.
I would also like to add basic interaction: when hovering over a house it's colour would change.
At the moment I've managed to render a canvas full of houses:
void setup() {
size(500, 500);
background(#74F5E9);
for (int i = 30; i < 500; i = i + 100) {
for (int j = 30; j < 500; j = j + 100) {
house(i, j);
}
}
}
void house(int x, int y) {
pushMatrix();
translate(x, y);
fill(0, 200, 0);
triangle(15, 0, 0, 15, 30, 15);
rect(0, 15, 30, 30);
rect(12, 30, 10, 15);
popMatrix();
}
Without seeing source code: your attempted sketch it's very hard to tell.
They can be animated in many ways and it's unclear what you mean. For example, is that the position/rotation/scale of each square, is it the corners/vertices of each square, both ?
You might have a clear idea in your mind, but the current form of the question is ambiguous. We also don't know you're comfort level with various notions such as classes/objects/PVector/PShape/etc. If you were to 'story board' this animation what would it look like ? Breaking the problem down and explaining it in a way that anyone can understand might actually help you figure out a solution on your own as well.
Processing has plenty of examples. Here are a few I find relevant based on what my understanding is of your problem.
You can have a look at the Objects and Create Shapes examples:
File > Examples > Basics > Objects > Objects: Demonstrates grouping drawing/animation (easing, damping). You can tweak this example draw a single square and once you're happy with the look/motion you can animate multiple using an array or ArrayList
File > Examples > Topics > Create Shapes > PolygonPShapeOOP3: Great example using PShape to animate objects.
File > Examples > Topics > Create Shapes > WigglePShape: This example demonstrates how to access and modify the vertices of a PShape
For reference I'm simply copy/pasting the examples mentioned above here as well:
Objects
/**
* Objects
* by hbarragan.
*
* Move the cursor across the image to change the speed and positions
* of the geometry. The class MRect defines a group of lines.
*/
MRect r1, r2, r3, r4;
void setup()
{
size(640, 360);
fill(255, 204);
noStroke();
r1 = new MRect(1, 134.0, 0.532, 0.1*height, 10.0, 60.0);
r2 = new MRect(2, 44.0, 0.166, 0.3*height, 5.0, 50.0);
r3 = new MRect(2, 58.0, 0.332, 0.4*height, 10.0, 35.0);
r4 = new MRect(1, 120.0, 0.0498, 0.9*height, 15.0, 60.0);
}
void draw()
{
background(0);
r1.display();
r2.display();
r3.display();
r4.display();
r1.move(mouseX-(width/2), mouseY+(height*0.1), 30);
r2.move((mouseX+(width*0.05))%width, mouseY+(height*0.025), 20);
r3.move(mouseX/4, mouseY-(height*0.025), 40);
r4.move(mouseX-(width/2), (height-mouseY), 50);
}
class MRect
{
int w; // single bar width
float xpos; // rect xposition
float h; // rect height
float ypos ; // rect yposition
float d; // single bar distance
float t; // number of bars
MRect(int iw, float ixp, float ih, float iyp, float id, float it) {
w = iw;
xpos = ixp;
h = ih;
ypos = iyp;
d = id;
t = it;
}
void move (float posX, float posY, float damping) {
float dif = ypos - posY;
if (abs(dif) > 1) {
ypos -= dif/damping;
}
dif = xpos - posX;
if (abs(dif) > 1) {
xpos -= dif/damping;
}
}
void display() {
for (int i=0; i<t; i++) {
rect(xpos+(i*(d+w)), ypos, w, height*h);
}
}
}
PolygonPShapeOOP3:
/**
* PolygonPShapeOOP.
*
* Wrapping a PShape inside a custom class
* and demonstrating how we can have a multiple objects each
* using the same PShape.
*/
// A list of objects
ArrayList<Polygon> polygons;
// Three possible shapes
PShape[] shapes = new PShape[3];
void setup() {
size(640, 360, P2D);
shapes[0] = createShape(ELLIPSE,0,0,100,100);
shapes[0].setFill(color(255, 127));
shapes[0].setStroke(false);
shapes[1] = createShape(RECT,0,0,100,100);
shapes[1].setFill(color(255, 127));
shapes[1].setStroke(false);
shapes[2] = createShape();
shapes[2].beginShape();
shapes[2].fill(0, 127);
shapes[2].noStroke();
shapes[2].vertex(0, -50);
shapes[2].vertex(14, -20);
shapes[2].vertex(47, -15);
shapes[2].vertex(23, 7);
shapes[2].vertex(29, 40);
shapes[2].vertex(0, 25);
shapes[2].vertex(-29, 40);
shapes[2].vertex(-23, 7);
shapes[2].vertex(-47, -15);
shapes[2].vertex(-14, -20);
shapes[2].endShape(CLOSE);
// Make an ArrayList
polygons = new ArrayList<Polygon>();
for (int i = 0; i < 25; i++) {
int selection = int(random(shapes.length)); // Pick a random index
Polygon p = new Polygon(shapes[selection]); // Use corresponding PShape to create Polygon
polygons.add(p);
}
}
void draw() {
background(102);
// Display and move them all
for (Polygon poly : polygons) {
poly.display();
poly.move();
}
}
// A class to describe a Polygon (with a PShape)
class Polygon {
// The PShape object
PShape s;
// The location where we will draw the shape
float x, y;
// Variable for simple motion
float speed;
Polygon(PShape s_) {
x = random(width);
y = random(-500, -100);
s = s_;
speed = random(2, 6);
}
// Simple motion
void move() {
y+=speed;
if (y > height+100) {
y = -100;
}
}
// Draw the object
void display() {
pushMatrix();
translate(x, y);
shape(s);
popMatrix();
}
}
WigglePShape:
/**
* WigglePShape.
*
* How to move the individual vertices of a PShape
*/
// A "Wiggler" object
Wiggler w;
void setup() {
size(640, 360, P2D);
w = new Wiggler();
}
void draw() {
background(255);
w.display();
w.wiggle();
}
// An object that wraps the PShape
class Wiggler {
// The PShape to be "wiggled"
PShape s;
// Its location
float x, y;
// For 2D Perlin noise
float yoff = 0;
// We are using an ArrayList to keep a duplicate copy
// of vertices original locations.
ArrayList<PVector> original;
Wiggler() {
x = width/2;
y = height/2;
// The "original" locations of the vertices make up a circle
original = new ArrayList<PVector>();
for (float a = 0; a < radians(370); a += 0.2) {
PVector v = PVector.fromAngle(a);
v.mult(100);
original.add(new PVector());
original.add(v);
}
// Now make the PShape with those vertices
s = createShape();
s.beginShape(TRIANGLE_STRIP);
s.fill(80, 139, 255);
s.noStroke();
for (PVector v : original) {
s.vertex(v.x, v.y);
}
s.endShape(CLOSE);
}
void wiggle() {
float xoff = 0;
// Apply an offset to each vertex
for (int i = 1; i < s.getVertexCount(); i++) {
// Calculate a new vertex location based on noise around "original" location
PVector pos = original.get(i);
float a = TWO_PI*noise(xoff,yoff);
PVector r = PVector.fromAngle(a);
r.mult(4);
r.add(pos);
// Set the location of each vertex to the new one
s.setVertex(i, r.x, r.y);
// increment perlin noise x value
xoff+= 0.5;
}
// Increment perlin noise y value
yoff += 0.02;
}
void display() {
pushMatrix();
translate(x, y);
shape(s);
popMatrix();
}
}
Update
Based on your comments here's an version of your sketch modified so the color of the hovered house changes:
// store house bounding box dimensions for mouse hover check
int houseWidth = 30;
// 30 px rect height + 15 px triangle height
int houseHeight = 45;
void setup() {
size(500, 500);
}
void draw(){
background(#74F5E9);
for (int i = 30; i < 500; i = i + 100) {
for (int j = 30; j < 500; j = j + 100) {
// check if the cursor is (roughly) over a house
// and render with a different color
if(overHouse(i, j)){
house(i, j, color(0, 0, 200));
}else{
house(i, j, color(0, 200, 0));
}
}
}
}
void house(int x, int y, color fillColor) {
pushMatrix();
translate(x, y);
fill(fillColor);
triangle(15, 0, 0, 15, 30, 15);
rect(0, 15, 30, 30);
rect(12, 30, 10, 15);
popMatrix();
}
// from Processing RollOver example
// https://processing.org/examples/rollover.html
boolean overRect(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}
// check if the mouse is within the bounding box of a house
boolean overHouse(int x, int y){
// offset half the house width since the pivot is at the tip of the house
// the horizontal center
return overRect(x - (houseWidth / 2), y, houseWidth, houseHeight);
}
The code is commented, but here are the main takeaways:
the house() function has been changed so you can specify a color
the overRect() function has been copied from the Rollover example
the overHouse() function uses overRect(), but adds a horizontal offset to take into account the house is drawn from the middle top point (the house tip is the shape's pivot point)
Regarding animation, Processing has tons of examples:
https://processing.org/examples/sinewave.html
https://processing.org/examples/additivewave.html
https://processing.org/examples/noise1d.html
https://processing.org/examples/noisewave.html
https://processing.org/examples/arrayobjects.html
and well as the Motion / Simulate / Vectors sections:
Let's start take sine motion as an example.
The sin() function takes an angle (in radians by default) and returns a value between -1.0 and 1.0
Since you're already calculating positions for each house within a 2D grid, you can offset each position using sin() to animate it. The nice thing about it is cyclical: no matter what angle you provide you always get values between -1.0 and 1.0. This would save you the trouble of needing to store the current x, y positions of each house in arrays so you can increment them in a different directions.
Here's a modified version of the above sketch that uses sin() to animate:
// store house bounding box dimensions for mouse hover check
int houseWidth = 30;
// 30 px rect height + 15 px triangle height
int houseHeight = 45;
void setup() {
size(500, 500);
}
void draw(){
background(#74F5E9);
for (int i = 30; i < 500; i = i + 100) {
for (int j = 30; j < 500; j = j + 100) {
// how fast should each module move around a circle (angle increment)
// try changing i with j, adding i + j or trying other mathematical expressions
// also try changing 0.05 to other values
float phase = (i + frameCount) * 0.05;
// try changing amplitude to other values
float amplitude = 30.0;
// map the sin() result from it's range to a pixel range (-30px to 30px for example)
float xOffset = map(sin(phase), -1.0, 1.0, -amplitude, amplitude);
// offset each original grid horizontal position (i) by the mapped sin() result
float x = i + xOffset;
// check if the cursor is (roughly) over a house
// and render with a different color
if(overHouse(i, j)){
house(x, j, color(0, 0, 200));
}else{
house(x, j, color(0, 200, 0));
}
}
}
}
void house(float x, float y, color fillColor) {
pushMatrix();
translate(x, y);
fill(fillColor);
triangle(15, 0, 0, 15, 30, 15);
rect(0, 15, 30, 30);
rect(12, 30, 10, 15);
popMatrix();
}
// from Processing RollOver example
// https://processing.org/examples/rollover.html
boolean overRect(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}
// check if the mouse is within the bounding box of a house
boolean overHouse(int x, int y){
// offset half the house width since the pivot is at the tip of the house
// the horizontal center
return overRect(x - (houseWidth / 2), y, houseWidth, houseHeight);
}
Read through the comments and try to tweak the code to get a better understanding of how it works and have fun coming up with different animations.
The main changes are:
modifying the house() function to use float x,y positions (instead of int): this is to avoid converting float to int when using sin(), map() and get smoother motions (instead of motion that "snaps" to whole pixels)
Mapped sine to positions which can be used to animate
Wrapping the 3 instructions that calculate the x offset into a reusable function would allow you do further experiment. What if you used a similar technique the y position of each house ? What about both x and y ?
Go through the code step by step. Try to understand it, change it, break it, fix it and make new sketches reusing code.

How to make a shape move while keeping a shape static without re-rendering the static shape?

In Processing, I'm trying to animate a spinning polygon. In the background, I have a series of 50 triangles that act as a gradient. These are both created in my draw function. How do I ensure that the polygon keeps spinning, but the triangles stay in the background without having to keep re-rendering the 50 triangles? Perhaps there's a cleaner way to create this triangular gradient?
int n = 9;
float ceiling = 350;
float floor = 250;
float diff = (ceiling - floor)/2;
float per = 0;
float dir = -1;
float rate = 0.01;
void setup() {
size(800, 800);
background(125,25,25);
frameRate(30);
}
void draw() {
background(125,25,25);
// Creates the triangles in background
for (float k=0; k<50; k++) {
strokeWeight(1);
stroke(#5E4622);
fill(47,74,57,100*(k/50));
triangle(100,height,width-100,height,width/2,height*k/50);
}
stroke(0);
// Creates spinning nonagons
pushMatrix();
translate(width/2, height/2);
rotate(2*PI*(dir*per));
stroke(#F4EA4A);
strokeWeight(6);
noFill();
polygon(0,0,floor+(diff*sin(2*PI*per))+10,n);
stroke(0);
strokeWeight(3);
float[] vertices = polygon(0, 0, floor+(diff*sin(2*PI*per)), n);
connect(vertices);
per += rate;
popMatrix();
}
// Takes a center (x,y) and draws an n-gon of radius r around it
// Returns an array of floats representing the points of the polygon
// Like: {x1,y1,x2,y2,...,xn,yn}
float[] polygon(float x, float y, float r, int n) {
float angle = 2*PI/n;
float[] vertices = new float[2*n];
beginShape();
for (int i=0; i<n; i++) {
float vX = r*cos(i*angle) + x;
float vY = r*sin(i*angle) + y;
vertex(vX, vY);
vertices[2*i] = vX;
vertices[2*i+1] = vY;
}
endShape(CLOSE);
return vertices;
}
// Takes in an array of vertices of a polygon and connects them together.
// Ignores neighboring vertices when considering which vertices to connect
// to a vertex.
void connect(float[] vertices) {
int n = vertices.length / 2;
for (int i=0; i<n; i++) {
float x = vertices[2*i];
float y = vertices[2*i+1];
for (int j=0; j<n; j++) {
if (j!=i || j!=(i-1)%n || j!=(i+1)%n) {
float endX = vertices[2*j];
float endY = vertices[2*j+1];
line(x, y, endX, endY);
}
}
}
}
This code creates what I want, but it runs pretty choppily due to having to re-render the triangles
How do I ensure that the polygon keeps spinning, but the triangles stay in the background without having to keep re-rendering the 50 triangles?
Render the static background to a PGraphics at initialization, in the setup function:
PGraphics pg;
void setup() {
size(800, 800);
// Creates the triangles in background
pg = createGraphics(800, 800);
pg.beginDraw();
pg.background(125,25,25);
for (float k=0; k<50; k++) {
pg.strokeWeight(1);
pg.stroke(#5E4622);
pg.fill(47,74,57,100*(k/50));
pg.triangle(100,height,width-100,height,width/2,height*k/50);
}
pg.endDraw();
frameRate(30);
}
Draw the background image to the scene by image(), in every frame, instead of filling the background by background():
void draw() {
// background image to screen
image(pg, 0, 0);
stroke(0);
// Creates spinning nonagons
// ...
}
Perhaps there's a cleaner way to create this triangular gradient?
If you want to get a smooth gradient background and get rid of the lines, then use pg.noStroke() rather than of pg.stroke(#5E4622);.
Additionally vary the size of the triangle on ist base, too:
for (float k=0; k<50; k++) {
pg.noStroke();
pg.fill(47,74,57,100*(k/50));
pg.triangle(k/50*width/2,height,width-k/50*width/2,height,width/2,height*k/50);
}

How to remove previous shape after draw() in Processing

I cant figure this out. I have a sketch with little rotating rectangles on it. They rotate on every draw(). However the previous rectangle remains visible. I tried moving background() around but it either gets rid of all the rectangles apart from one or it doesn't clear the screen. I would like to be able to clear all the rectangles after each draw.
Here is the code:
//Create array of objects
ArrayList<Circle> circles = new ArrayList<Circle>();
ArrayList<Connector> centrePoint = new ArrayList<Connector>();
void setup(){
size(800, 800);
frameRate(1);
rectMode(CENTER);
background(204);
for(int i = 1; i < 50; i++){
float r = random(100,height-100);
float s = random(100,width-100);
float t = 20;
float u = 20;
println("Print ellipse r and s " + r,s);
circles.add(new Circle(r,s,t,u,color(14,255,255),random(360),random(5),random(10)));
}
//Draw out all the circles from the array
for(Circle circle : circles){
circle.draw();
float connectStartX = circle.x1;
float connectStartY = circle.y1;
println("PrintconnectStartX and Y " + connectStartX,connectStartY);
for(Circle circleEnd : circles){
float connectEndX = (circleEnd.x1);
float connectEndY = (circleEnd.y1);
centrePoint.add(new Connector(connectStartX,connectStartY,connectEndX,connectEndY));
}
}
//For each ellipse, add the centre point of the ellipse to array
for(Connector connectUp : centrePoint){
println(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
stroke(100, 0, 0);
if (dist(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY) < 75){
connectUp.draw(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
}
}
//For the line weight it should equal the fat of the node it has come from ie
//for each circle, for each connectUp if the x==connectStartX and y==connectStartY then make the line strokeWeight==fat
for(Circle circle : circles){
for(Connector connectUp : centrePoint){
if (connectUp.connectStartX == circle.x1 & connectUp.connectStartY == circle.y1 & (dist(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY) < 75)){
print(" true "+ circle.fat);
float authority = circle.fat;
strokeWeight(authority*1.5);
connectUp.draw(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
}
}
}
}
void update(){
}
void draw() {
for(Circle circle : circles){
circle.rot =+0.02;
circle.draw();
circle.rot = random(-6,6);
}
}
//Need to connect each ellipse to all the other ellipses
class Connector {
public float connectStartX;
public float connectStartY;
public float connectEndX;
public float connectEndY;
public color cB;
public float thickness;
public Connector(float connectStartX, float connectStartY, float connectEndX, float connectEndY){
this.connectStartX = connectStartX;
this.connectStartY = connectStartY;
this.connectEndX = connectEndX;
this.connectEndY = connectEndY;
//this.cB = tempcB;
//this.thickness = thickness;
}
void draw(float connectStartX, float connectStartY, float connectEndX, float connectEndY){
line(connectStartX, connectStartY, connectEndX, connectEndY);
// float fat = random(255);
//fill(fat);
stroke(100, 0, 0);
}
}
class Circle{
public float x1;
public float y1;
public float x2;
public float y2;
public color cB;
public float rot;
public float fat = random(5);
public float fert = 0.1;
public Circle(float x1, float y1, float x2, float y2, color tempcB, float rot, float fat, float fert){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.cB = tempcB;
//Tilt - I think this is done in radians
this.rot = rot;
//Authority -this is the fill
this.fat = fat;
//Fertility- this is a multiplier for the tilt
this.fert = fert;
}
void draw(){
pushMatrix();
translate(x1, y1);
fert = random(0.5);
rot = random(-6,6);
rotate(rot*fert);
translate(-x1, -y1);
//float fat = random(255);
fill(fat);
rect(x1, y1, 24, 36);
popMatrix();
}
}
You've got a few things going on in your code that I've seen in your previous posts. The way you're doing your drawing doesn't make a ton of sense, and I'll explain why.
Here's what most Processing sketches do:
Use the setup() function to setup any data structures you'll use in your program. Don't do any drawing from the setup() function.
Call background() every frame to clear out old frames.
Draw everything you want to be drawn in the frame in the draw() function.
Modify the data structures to change what you're drawing on the screen.
Your code is a bit too long for an MCVE, so here's a little example that handles the drawing in a more standard way:
ArrayList<PVector> circles = new ArrayList<PVector>();
void setup() {
size(500, 500);
ellipseMode(RADIUS);
//setup your data structures here
circles.add(new PVector(250, 250));
//don't do any drawing yet
}
void mousePressed() {
//modify the data structure whenever you want to change what's on the screen
circles.add(new PVector(mouseX, mouseY));
}
void keyPressed() {
//modify the data structure whenever you want to change what's on the screen
if (!circles.isEmpty()) {
circles.remove(0);
}
}
void draw() {
//call background every frame to clear out old frames
background(0);
//draw everything
for (PVector p : circles) {
ellipse(p.x, p.y, 20, 20);
}
}
Notice how this is different from what you're doing. Here's what you do:
You use the setup() function to setup your data structures, but then you draw the background and some of the objects to the screen.
You then don't call background() from draw(), so you're always stuck with whatever has already been drawn.
You then only draw a subset of what you want on the screen, so you can't redraw your whole scene.
You have to modify your code to no longer draw anything from setup(), to call the background() function every frame, and to draw everything you want on the screen every frame.
What you are doing is printing every single circle or line...ect. You need to have a timer that removes them every so often. If you do it too fast you get a strobe like look. So have a timer that removes the first rect from the array list every so often.

How to rotate a line in a circle (radar like) in Processing while also plotting points?

I am trying to rotate a line around in a circle that represents the direction a sensor is facing, while also plotting distance measurements. So I can't use background() in the draw function to clear the screen, because it erases the plotting of the distance readings. I've tried pggraphics and a few others ways, but can't seem to find a way to do it.
This is what I have right now:
void setup() {
background(255,255,255);
size(540, 540);
}
void draw() {
translate(width/2, height/2);
ellipse(0,0,100,100);
newX = x*cos(theta)- y*sin(theta);
newY = x*sin(theta)+ y*cos(theta);
theta = theta + PI/100;
//pushMatrix();
fill(255, 255);
line(0, 0, newX, newY);
rotate(theta);
//popMatrix();
}
I am new to Processing, and coding in general, but can anyone point me in the right direction on how to do this? Thanks
This is what it outputs: http://imgur.com/I825mjE
You can use background(). You just need to redraw the readings on each frame. You could store the readings in an ArrayList, which allows you to add new readings, change them and remove them.
An example:
ArrayList<PVector> readings;
int readingsCount = 15;
void setup() {
size(540, 540);
// create collection of random readings
readings = new ArrayList<PVector>();
for(float angle = 0; angle < TWO_PI; angle += TWO_PI/ readingsCount) {
float distance = random(100, 200);
// the new reading has an angle...
PVector newReading = PVector.fromAngle(angle);
// ... and a distance
newReading.mult(distance);
// Add the new reading to the collection
readings.add(newReading);
}
}
void draw() {
background(255);
// Put (0, 0) in the middle of the screen
translate(width/2, height/2);
float radius = 250;
noFill();
ellipse(0, 0, 2*radius, 2*radius);
// draw spinning line
float angle = frameCount * 0.1;
line(0, 0, radius * cos(angle), radius * sin(angle));
// draw readings
for(PVector p : readings) {
ellipse(p.x, p.y, 20, 20);
}
}

How to animate a 3D curve between two points on a map?

I am trying to do a twitter visualization.
I using curves to connect two points on the map.
Here is the code which I am using for it. It has been taken from an example by Chrisir from the processing forums.
void setup()
{
size( 800, 800, P3D );
} // setup
void draw()
{
// myCurveTest() ;
PVector firstpoint = new PVector (120, 320, -30);
PVector secondpoint = new PVector (320, 220, -30);
myCurve (firstpoint, secondpoint ) ;
firstpoint = new PVector (420, 220, 30);
secondpoint = new PVector (620, 120, -30);
myCurve (firstpoint, secondpoint ) ;
}
void myCurve (
PVector firstpoint,
PVector secondpoint) {
PVector beginningcontrolpoint = new PVector (120, firstpoint.y+1200, -30);
PVector endingcontrolpoint = new PVector (720, secondpoint.y+1200, -30);
myPointPVector(beginningcontrolpoint, color(255, 0, 0));
myPointPVector(firstpoint, color(0, 0, 255));
myPointPVector(secondpoint, color(0, 0, 255));
myPointPVector(endingcontrolpoint, color(255, 0, 0));
stroke (255);
noFill();
curve(
beginningcontrolpoint.x, beginningcontrolpoint.y, beginningcontrolpoint.z,
firstpoint.x, firstpoint.y, firstpoint.z,
secondpoint.x, secondpoint.y, secondpoint.z,
endingcontrolpoint.x, endingcontrolpoint.y, endingcontrolpoint.z);
}
void myPointPVector (PVector test, color col1) {
MyBox(test.x, test.y, test.z,
test.x+3, test.y, test.z,
9,
col1);
}
void MyBox(float x1, float y1, float z1, float x2, float y2, float z2, float weight, color strokeColour)
// was called drawLine; programmed by James Carruthers
// see http://processing.org/discourse/yabb2/YaBB.pl?num=1262458611/0#9
{
PVector p1 = new PVector(x1, y1, z1);
PVector p2 = new PVector(x2, y2, z2);
PVector v1 = new PVector(x2-x1, y2-y1, z2-z1);
float rho = sqrt(pow(v1.x, 2)+pow(v1.y, 2)+pow(v1.z, 2));
float phi = acos(v1.z/rho);
float the = atan2(v1.y, v1.x);
v1.mult(0.5);
pushMatrix();
translate(x1, y1, z1);
translate(v1.x, v1.y, v1.z);
rotateZ(the);
rotateY(phi);
noStroke();
fill(strokeColour);
box(weight, weight, p1.dist(p2)*1.2);
popMatrix();
}
I want to animated this 3D curve so that I can see them being drawn on the map. Can anyone help me out with this. I have tried everything from framecount to advanced animation libraried in processing but no luck yet :(
Thanks.
You may just calculate a parabola point by point, draw it using curveVertex and orbit it in 3D using translate and rotate, here an example (using 1.5.1/P3D/fontMode(SCREEN)):
float initial_x = -200;
float x = initial_x;
float y;
float y_offset;
float r = 200;// change this to change the height of the parabola
ArrayList<PVector> pts = new ArrayList<PVector>();
float mx = 70, my = -15, tmx, tmy;
boolean animating = false;
PFont f;
void setup() {
size( 800, 400, P3D);
background(255);
smooth();
f = createFont("Arial", 15);
textMode(SCREEN);
}
void draw() {
//lights();
background(255);
fill(100);
textFont(f, 15);
text("drag to orbit", width - 10 - textWidth("drag to orbit"), height -30);
text("any key to redraw parabola", width - 10 - textWidth("any key to redraw parabola"), height -10);
//rotate 3d
translate(width/4, height/2);
rotateY(radians(mx));
rotateZ(radians(my));
// to mark origin and help view 3d
noFill();
stroke(100);
box(20);
pushMatrix();
translate(100, 5, -100);
stroke(200);
fill(0, 20);
box(600, 2, 600);
popMatrix();
//store y offset
if (x == initial_x) {
y_offset = (sq(x)+2*x)/r;
}
// stop parabola
if ( x == initial_x || x < -initial_x + 2) {
x+=2;
animating = true;
// add to curve storage
pts.add(new PVector(x, y));
}
else {
animating = false;
}
//calc y
y = (sq(x)+2*x)/r - y_offset;
stroke(50, 30, 7);
noFill();
strokeWeight(1);
//draw at origin
translate(-initial_x, 0);
//draw curve
beginShape();
for (PVector p:pts) {
curveVertex(p.x, p.y);
}
endShape();
//draw a ball
if (!animating) {
translate(pts.get(frameCount%pts.size()).x, pts.get(frameCount%pts.size()).y);
noStroke();
fill(220, 190, 35);
sphere(4);
}
}
void mousePressed() {
tmx = mouseX;
tmy = mouseY;
}
void mouseDragged() {
mx = tmx - mouseX;
my = tmy - mouseY;
}
void keyPressed() {
x = -200;
pts.clear();
}
You're drawing the curves using the curve() command (http://processing.org/reference/curve_.html) which draws a Catmull-Rom spline. In your code, you're only drawing a single spline section (the one between the two control points), so what you're really interested in is "how can I draw only part of a Catmull-Rom spline section". I don't have the answer for that one, but if you change your curve(control1, first, second, control2) call into a bezier(first,c1,c2,second) call (where you will now have to come up with the code for the control points c1 and c2) instead, then you can use de Casteljau's algorithm to cut up a curve into two segments anywhere along it. If you slide up the where-to-cut-it point every frame, and then only draw the first segment that you get from the split operation, it'll look like a curve that draws itself from the start to the end point. See http://pomax.github.io/bezierinfo/#splitting for the description on how to do this (bonus: the source code is even in Processing)
Make use of the curvePoint() method. Here is a resolution to a similar problem:
http://forum.processing.org/one/topic/animation-with-curve.html.

Resources