Setting (0,0) to bottom-left without switching X- and Y-axis in Processing(.org) - processing

I'd like to change the coordinate system in a 2d processing sketch, putting (0,0) in the bottom-left rather than the top-left. The following code will move (0,0) to the bottom-left:
transform(0, height);
rotate(radians(-90));
However, it also makes the X-axis the vertical axis. Is there a simple way to move (0,0) to the bottom-left and keep the X-axis horizontal?
One option I've considered is using P3D with a combination of rotate and rotateY, but would prefer a solution for the 2d case.
Thanks for any help!

You could simply translate without rotating:
transform(0, height);
And handle your coordinates as flipped:
boolean useVFlip = true;
void setup(){
size(400,400);
}
void draw(){
background(255);
if(useVFlip) translate(0,height);
drawAxes(100);
translate(width * .5, useVFlip ? (height-mouseY)*-1 : mouseY);
triangle(0,0,100,0,100,100);
}
void keyPressed(){ useVFlip = !useVFlip; }
void drawAxes(int size){
pushStyle();
strokeWeight(10);
stroke(192,0,0);
line(0,0,size,0);
stroke(0,192,0);
line(0,0,0,size);
popStyle();
}
If it makes it easier to get flipped coordinates, you could flip the whole coordinate system using the scale() method:
boolean useVFlip = true;
void setup(){
size(400,400);
}
void draw(){
background(255);
if(useVFlip){
scale(1,-1);
translate(0,-height);
}
drawAxes(100);
translate(width * .5, useVFlip ? height-mouseY : mouseY);
triangle(0,0,100,0,100,100);
}
void keyPressed(){ useVFlip = !useVFlip; }
void drawAxes(int size){
pushStyle();
strokeWeight(10);
stroke(192,0,0);
line(0,0,size,0);
stroke(0,192,0);
line(0,0,0,size);
popStyle();
}
You could do the same with a PMatrix2D, but not sure how familiar your are with them:
boolean useCustomCS = true;
PMatrix2D customCS;
void setup(){
size(400,400);
customCS = new PMatrix2D( 1, 0, 0,
0, -1,height);
fill(0);
}
void draw(){
background(255);
if(useCustomCS) applyMatrix(customCS);
drawAxes(100);
translate(width * .5, useCustomCS ? height-mouseY : mouseY);
text("real Y:" + mouseY + " flipped Y: " + (height-mouseY),0,0);
triangle(0,0,100,0,100,100);
}
void keyPressed(){ useCustomCS = !useCustomCS; }
void drawAxes(int size){
pushStyle();
strokeWeight(10);
stroke(192,0,0);
line(0,0,size,0);
stroke(0,192,0);
line(0,0,0,size);
popStyle();
}

Try the following:
translate(0,height);
scale(1,-1);

Related

I am trying to make an abstract kind of object i guess, referencing the book processing creative coding examples

Here is the code, i can get screenshots of everything if need be, but Im just getting one error - "syntax error you might be mixing active and static modes."
Im fairly new to this so any help would be great.
float boxSize = 40;
float margin = boxSize*2;
float depth = 400;
color boxFill;
void setup(){
size(500,500,P3D);
}
void draw(){
translate(width/2, height/2, -depth/2);
rotateY(frameCount*PI/60);
rotateX(frameCount*PI/60);
}
for (float i=-depth/2+margin; i<=depth/2-margin; i+=boxSize){
pushMatrix();
for (float j=-height/2+margin; j<=height/2-margin; j+=boxSize){
pushMatrix();
for (float k=-width/2+margin; k<=width/2-margin; k+=boxSize){
boxFill = color(abs(i), abs(j), abs(k), 50);
pushMatrix();
translate(k, j, i);
fill(boxFill);
box(boxSize, boxSize, boxSize);
popMatrix();
}
popMatrix();
}
popMatrix();
}
}
I recommend formatting your code first: Processing > Edit > Auto Format (CMD+T / Ctrl+T)
This will reveal this error right after the rotateX() call:
Missing left curly bracket "{"
What it actually means is that you have an extra } and it shouldn't be (as the for loop after should be part of the draw() function:
float boxSize = 40;
float margin = boxSize*2;
float depth = 400;
color boxFill;
void setup() {
size(500, 500, P3D);
}
void draw() {
translate(width/2, height/2, -depth/2);
rotateY(frameCount*PI/60);
rotateX(frameCount*PI/60);
for (float i=-depth/2+margin; i<=depth/2-margin; i+=boxSize) {
pushMatrix();
for (float j=-height/2+margin; j<=height/2-margin; j+=boxSize) {
pushMatrix();
for (float k=-width/2+margin; k<=width/2-margin; k+=boxSize) {
boxFill = color(abs(i), abs(j), abs(k), 50);
pushMatrix();
translate(k, j, i);
fill(boxFill);
box(boxSize, boxSize, boxSize);
popMatrix();
}
popMatrix();
}
popMatrix();
}
}

How to execute a function only once in voice draw(); but still have it displayed for the whole animation

I'm struggling with something here.
Basically I made an animation with several functions. I want the functions to be animated, except for one that I want to be still.
If I specify noLoop, then nothing gets animated, if I tell the function to run a set number of times, then after that number it stops being displayed. What I want is to have it run once but then be still displayed.
Do you guys have any idea of how I could do that ?
Here is the code :
int r1,r2,r3 = 0;
int i1, i2,i3;
void setup(){
size(800,800);
background(255,0);
//noLoop();
}
void draw(){
background(255,0);
rosace();
croix();
sillon1();
sillon2();
}
void rosace(){
for (i1 = 0;i1<230; i1++){
rectMode(CENTER);
noFill();
stroke(20);
strokeWeight(1);
pushMatrix();
translate(width/2,height/2);
translate(400,400);
rotate(radians(r1));
rect(0,0,400,400);
r1 +=1;
//println(r);
popMatrix();
println("rosace ex");
}
}
void croix(){
pushMatrix();
strokeWeight(2);
stroke(0);
translate(width/2, height/2);
rotate(radians(45));
line(-10,0,10,0);
line(0,-10,0,10);
popMatrix();
}
void sillon1(){
for (i2 =0; i2<360; i2++){
pushMatrix();
translate(width/2,height/2);
strokeWeight(int(random(0,7)));
rotate(radians(r2));
point(-330,0);
popMatrix();
r2 +=1;
}
}
void sillon2(){
for (i2 =0; i2<2000; i2++){
pushMatrix();
translate(width/2,height/2);
strokeWeight(int(random(1,3)));
rotate(radians(r2));
point(-360,0+(random(-2,2)));
popMatrix();
r2 +=1;
}
}
The void rosace(); is the one that I'd like to be non-animated.
The problem is that you're storing r1 as a global variable. This means that it keeps it's value after every iteration.
Instead, make it a local variable:
void rosace() {
int r1 = 0;
for (i1 = 0; i1<230; i1++) {
rectMode(CENTER);
noFill();
stroke(20);
strokeWeight(1);
pushMatrix();
translate(width/2, height/2);
translate(400, 400);
rotate(radians(r1));
rect(0, 0, 400, 400);
r1 +=1;
popMatrix();
println("rosace ex");
}
}
You can't just keep a part of the scene, when animations are drawn on top of it. You have to draw the entire scene in every frame. Ensure that rosace draws the same in every frame.
Just set r1 = 0 in every frame, then the algorithm in rosace generates the same rectangles in every frame:
void rosace(){
r1 = 0;
for (i1 = 0;i1<230; i1++){
// [...]
}
}

Processing - Move circle with cursor position

I made a simple drawing program to draw lines and increase/decrase the thickness of the line:
float strokeWeight = 2;
void setup() {
size(640, 360);
noSmooth();
fill(126);
background(255);
strokeWeight(strokeWeight);
}
void draw() {
background(0);
ellipse(mouseX, mouseY, strokeWeight/2, strokeWeight/2);
background(255);
if (mousePressed) {
stroke(0);
line(mouseX, mouseY, pmouseX, pmouseY);
}
if (keyPressed) {
if (key == '+') {
strokeWeight = strokeWeight + 0.5;
}
if (key == '-') {
strokeWeight = strokeWeight - 0.5;
}
if (strokeWeight >= 0.5) {
strokeWeight(strokeWeight);
}
}
}
Now I want to move a circle with my cursor that indicates the current thickness of the line. I tried something like this:
ellipse(mouseX, mouseY, strokeWeight/2, strokeWeight/2)
But this way it draws ellipses over and over again. Is there a way to "erase" the circle made before?
I am not 100% sure that I've understood your question, but you probably want to use PGrahics, on one you keep the lines, on the other you draw the circle.
float strokeWeight = 2;
PGraphics canvas;
PGraphics thickness_circle;
void setup() {
size(640, 360);
canvas = createGraphics(width, height);
thickness_circle = createGraphics(width, height);
thickness_circle.beginDraw();
thickness_circle.noFill();
thickness_circle.strokeWeight(1);
thickness_circle.stroke(255, 0, 0);
thickness_circle.endDraw();
}
void draw() {
background(255);
if (keyPressed) {
if (key == '+') {
strokeWeight += 0.5;
}
if (key == '-') {
strokeWeight -= 0.5;
}
strokeWeight = strokeWeight >= 0.5 ? strokeWeight : 0.5;
}
if (mousePressed) {
canvas.beginDraw();
canvas.strokeWeight(strokeWeight);
canvas.line(mouseX, mouseY, pmouseX, pmouseY);
canvas.endDraw();
}
image(canvas, 0, 0);
thickness_circle.beginDraw();
thickness_circle.clear();
thickness_circle.ellipse(mouseX, mouseY, strokeWeight, strokeWeight);
thickness_circle.endDraw();
image(thickness_circle, 0, 0);
}

Using pushMatrix(), popMatrix(), translate(), and rotate()

I have a program that draws a flower with 4 petals to the screen where ever you click. Instead of redoing the petals one at a time I was just going to attempt to rotate the flower by a quarter turn and have it overlay the first flower, so it appears to have 8 petals. The problem is that it draws the second flower some distance away from the first in the x and y direction, but as I get closer to (0,0) they get closer to overlapping (and do at (0, 0)). I'm not sure why this is happening and would appreciate any help. I'm using Processing 3 for this program.
int c_center = 15;
int c_petal = 20;
int petalsize = 70;
color rcol;
void setup(){
fullScreen();
background(0);
}
void draw(){
rcol = color(random(255), random(255), random(255));
}
void mouseClicked(){
pushMatrix();
flower();
translate(mouseX, mouseY);
rotate(PI/4);
flower();
popMatrix();
}
void flower(){
//left petal
make_petal(mouseX - (petalsize - c_petal), mouseY, petalsize, c_petal);
//right petal
make_petal(mouseX + (petalsize - c_petal), mouseY, petalsize, c_petal);
//top petal
make_petal(mouseX, mouseY - (petalsize - c_petal), c_petal, petalsize);
//bottom petal
make_petal(mouseX, mouseY + (petalsize - c_petal), c_petal, petalsize);
//flower center
fill(random(255), random(255), random(255));
ellipse(mouseX, mouseY, c_center, c_center);
}
void make_petal(int a, int b, int c, int d){
fill(rcol);
ellipse(a, b, c, d);
}
You're mixing two styles of drawing together: your flower() function uses mouseX and mouseY to determine where to draw the petals, but then you're also calling translate(mouseX, mouseY);. So you're drawing petals relative to the mouse, but then moving the entire canvas by the mouse position, and then drawing more petals relative to the mouse again.
Instead, you probably want to only use one style of drawing. Specifically, you probably don't want your flower() function to care about the mouse position. Treat it like a "stamp" that draws things around the origin at 0,0. Then move the origin by calling translate() and rotate the stamp by calling rotate().
I corrected the code thanks to feedback, so it works now in case anyone is interested. I condensed it a little by just making one petal then rotating it through a loop.
int c_center = 20;
int c_petal = int(random(5, 15));
int petalsize = int(random(30, 60));
color rcol;
void setup(){
fullScreen();
background(0);
}
void draw(){
rcol = color(random(255), random(255), random(255));
}
void mouseClicked(){
pushMatrix();
translate(mouseX, mouseY);
for(int r = 0; r < 360; r+=5){
rotate(radians(r));
flower();
}
popMatrix();
}
void flower(){
//petal
make_petal(0, 0 - (petalsize - c_petal), c_petal, petalsize);
//flower center
fill(random(255), random(255), random(255));
ellipse(0, 0, c_center, c_center);
}
void make_petal(int a, int b, int c, int d){
fill(rcol);
ellipse(a, b, c, d);
}

Stop background from refreshing?

I am trying to get my gif to do something similar to this gif.
I have been able to get the line to draw, and the 'planets' to orbit, but can't figure out how to keep the line connecting the two circles, like the gif does.
Here's the basic code:
int x = 500;
int y = 500;
int radius = y/2;
int cX = x/2;
int cY = y/2;
String text1;
int lg_xBall;
int lg_yBall;
int sm_xBall;
int sm_yBall;
void setup() {
size(x, y);
smooth();
colorMode(RGB);
}
void draw() {
background(0);
stroke(255);
float t = millis()/1000.0f;
drawSmBallOrbit(100);
drawLgBallOrbit(100);
moveSmBall(t);
moveLgBall(t);
sun();
// showMouse();
connectingLines();
}
void drawCircle() { // This will draw a simple circle
stroke(1);
// x1=a+r*cos t, y1=b+r*sin t
ellipse(x/2, y/2, x/2, y/2);
}
void drawLines() { // This will draw lines from the center of the circle.
stroke(1);
line(x/2, y/2, radius/2, radius); // line from 6 to center
line(x/2, y/2, x/2, y/4); // line from 12 to center
for (int i = 0; i <= 5; i+=2.5) {
float x1 = x/2+radius/2*cos(i);
float y1 = y/2+radius/2*sin(i);
line(x/2, y/2, x1, y1);
}
}
void moveSmBall(float ky) { // This will create, and move, a small 'planet'
pushStyle();
stroke(100);
sm_xBall = (int)(cX+radius*cos(ky));
sm_yBall = (int)(cY+radius*sin(ky));
fill(190, 0, 0);
// background(0);
ellipse(sm_xBall, sm_yBall, 10, 10);
popStyle();
}
void drawSmBallOrbit(float opacity) {
pushStyle();
stroke(255, opacity);
strokeWeight(1);
noFill();
ellipse(x/2, y/2, cX+radius, cY+radius);
popStyle();
}
void moveLgBall(float kx) {
kx = kx/.7;
pushStyle();
lg_xBall = (int)(cX+radius*cos(kx)*.6);
lg_yBall = (int)(cY+radius*sin(kx)*.6);
fill(0, 0, 230);
ellipse(lg_xBall, lg_yBall, 30, 30);
popStyle();
}
void drawLgBallOrbit(float opacity) {
pushStyle();
stroke(255, opacity);
strokeWeight(1);
noFill();
ellipse(x/2, y/2, (cX+radius)*.6, (cY+radius)*.6);
popStyle();
}
void sun() {
pushStyle();
fill(250, 250, 0);
ellipse(cX, cY, 40, 40);
popStyle();
}
void connectingLines() {
line(sm_xBall, sm_yBall, lg_xBall, lg_yBall);
}
void showMouse() {
text("X: " + mouseX, x/2, y/2-30);
text("Y: " + mouseY, x/2, y/2-50);
}
Thanks for any help/advice!
The problem is that you're calling background() during every frame, which will clear away anything you've already drawn.
So you either need to stop calling background(), or you need to redraw the old lines every frame.
If you simply move the call to background() out of your draw() function and into your setup() function, you're about 50% there already:
void setup() {
size(x, y);
smooth();
colorMode(RGB);
background(0);
}
void draw() {
// background(0);
stroke(255);
float t = millis()/1000.0f;
drawSmBallOrbit(100);
drawLgBallOrbit(100);
moveSmBall(t);
moveLgBall(t);
sun();
// showMouse();
connectingLines();
}
However, the original animation does not show the previous positions of the ellipses. So you need to clear away the previous frame by calling the background() function, and then redraw previous line positions. You'd do that by having an ArrayList that holds those previous positions.
Here's a simple example that uses an ArrayList to redraw anywhere the mouse has been:
ArrayList<PVector> points = new ArrayList<PVector>();
void setup() {
size(500, 500);
}
void draw() {
background(0);
stroke(255);
points.add(new PVector(mouseX, mouseY));
for(PVector p : points){
ellipse(p.x, p.y, 10, 10);
}
}
You would need to do something very similar, but you'd have to keep track of two points at a time instead of one, since you're tracking two ellipses and not just the mouse position.

Resources