How can I restrict a for-loop pattern to stay within a shape? Basically, how can I fill a shape with a pattern instead of a color? - for-loop

I am trying to create concentric circles filled with lines moving in opposite directions (that follow the mouse). I can't figure out how to fill only the circles with the lines -- I used a for-loop to make lines, and want to cut them off outside of the radius of the circles. Basically, I am trying to fill the circles with a pattern of lines.
This is my code:
float r = 0;
float startAngle;
float density;
float radius;
void setup() {
size(500, 500);
background(255);
stroke(150, 0, 150);
}
void draw() {
int[] s = {
500, 325, 200, 100, 50, 25
};
for (int i = 0; i < 500; i = i+5) {
line(0, i, 500, i);
if(i > s[0]) {
noStroke();
}
}
translate(width/2, height/2);
rotate(r);
r = r + .01;
fill(0);
ellipse(0, 0, s[0], s[0]);
fill(50);
ellipse(0, 0, s[1], s[1]);
fill(100);
ellipse(0, 0, s[2], s[2]);
fill(150);
ellipse(0, 0, s[3], s[3]);
fill(200);
ellipse(0, 0, s[4], s[4]);
fill(255);
ellipse(0, 0, s[5], s[5]);
}
Any help would be appreciated!

It's hard to help with general "how do I do this" type questions. Stack Overflow is designed for more specific "I tried X, expected Y, but got Z instead" type questions. But I'll try to help in a general sense.
The best advice I can give you is to start smaller. Break your problem down into smaller pieces and take those pieces on one at a time.
For example, instead of starting with your whole program that shows multiple circles, why not start with a simpler example program that just shows a single circle? Try to get a pattern to display inside of that.
Like everything in programming, there are multiple ways to do that.
Option 1: You could probbaly use basic geometry and trig to figure out where the points should be on the circle, then draw them based on those points. The cos() and sin() functions would probably come in handy with this approach.
Option 2: You could also use image masking techniques. For example, you could create a texture of lines, and then use a circular mask to isolate a cirlce of those lines. The texture() function or the PImage#mask() functions would be your friends here.
Try out those approaches to see which one you like best. The Processing reference is your best friend: for example, here is a reference on the texture() function, and here is a reference on the PImage#mask() function. Then if you get stuck on a specific step, you can post a MCVE of just that step, and we'll go from there. Good luck.

Related

How to more + rotate 180 degree + move a group of shape using Processing?

I'm having this Processing issue where I'm trying to make my ariplane do a 180 turn-over right before it gets to the end of the drawing... It looks fairly simple but I just can't get it to work. Help would be much appreciated.
As I have other shapes (not showned in code below) I finally managed to use pushMatrix(); & popMatrix(); to only impact the airplane. Although rotating it brings me sideways.
int globalX = 0;
int globalY = 600;
int vitesse = 3;
void setup() {
size(800, 600);
rectMode(CENTER);
}
void draw() {
background(255);
pushMatrix();
bouger();
tourner();
dessinerAvion(globalX, globalY);
popMatrix();
}
void bouger() {
// Change the x location by vitesse
//globalX = globalX + vitesse;
globalY = globalY - vitesse;
}
void tourner() {
if (globalY < 0) {
for (int i = 10; i > 0; i = i-1) {
rotate(PI/3.0);
//rotate(radians(10));
}
for (int i = 10; i > 0; i = i-1) {
rotate(PI/3.0);
//rotate(radians(10));
vitesse = vitesse * -1;
}
}
}
void dessinerAvion(int x, int y) {
rectMode(CENTER);
// corps
fill(156,21,21);
ellipse(x + 250, y + 100, 50, 100);
rect(x + 250, y + 200, 50, 250,60);
// reacteur gauche
rect(x + 125, y + 225, 25, 50, 75);
// reacteur droite
rect(x + 375, y + 225, 25, 50, 75);
fill(210,14,14);
// aile gauche
quad(x + 75, y + 275, x + 75, y + 250, x + 225, y + 175, x + 225, y + 250);
// aile droite
quad(x + 425, y + 275, x + 425, y + 250, x + 275, y + 175, x + 275, y + 250);
fill(112,14,14);
// ailette gauche
triangle(x + 225, y + 290, x + 226, y + 310, x + 175, y + 310);
// ailette droites
triangle(x + 275, y + 290, x + 274, y + 310, x + 325, y + 310);
// aile verticale arrière
triangle(x + 250, y + 285, x + 248, y + 310, x + 252, y + 310);
}
Matrix are weird animals. They let you take a bunch of shapes and translate, rotate or scale them all at once, but only through playing with the coordinate system, which implies that the way you draw the shapes that you'll process will have a huge impact on how they react.
This is your plane on a neutral grid (by which I mean that globalX and globalY are 0):
Every square on this grid has a 20 pixels side. As you can see, your plane is far from the [0, 0] point, which is the start of the coordinate system it's drawn into. Also, when you modify it's coordinates, you're doing it through modifying it's coordinates, as we can see on this line of code:
void dessinerAvion(int x, int y)
The problem here is that applying a geometric transformation to an object with these coordinates can be counterintuitive. To simplify the matter, imagine the whole coordinate system that the plane use as if it was an image, like a png. The top left of the image is the [0, 0] point. When you change the plane's y coordinates for a higher number, your png image gets taller. If you change the x coordinate of the plane for a bigger number, the png image gets wider. You get the general idea.
When you apply a rotation to the plane, it's the entire 'png image', the entire coordinate system, that gets rotated. It's the same for any other transformation, too. Now, experimentally, look at what happens if I do this:
for(float i=0; i<20; i+=1) {
pushMatrix();
rotate(PI/i);
dessinerAvion(0, 0);
popMatrix();
}
As you can see, the plane isn't rotating on itself. It's the whole coordinate system that rotates, pivoting on the [0, 0] point, and it brings the plane with itself. That's the deal with matrix: they keep a lot of geometry waaay more simple, but you have to work accordingly.
Which brings me back to the previous point: you're updating the coordinates where you draw the plane. Then you use a matrix. Your updated plane will rotate in an unexpected way because you apply 2 different logic to your transformations: on one hand you modify coordinates (which is fine), while on the other you apply a transformation on a matrix (which is fine too). The issue is to mix those without acknowledging their differences.
Honestly, unless you have a specific thing in mind, you shouldn't mix those to move a single object.
The obvious solution to the first part of this issue would be to translate the plane instead of moving it's coordinates:
void draw() {
background(255);
bouger(); // updating coordinates, this doesn't need to be in the matrix block
pushMatrix();
//tourner();
translate(globalX, globalY);
dessinerAvion(0, 0); // zero here as the translation is doing that part of the job now
popMatrix();
}
Now you should see... well, you should see no difference at all. That's normal. The real difference is not in how the sketch appears, but how it's processed behind the scenes. Now your plane is a static object on which we apply geometric transformations.
Now to the other part of your problem: animating an object. Well, to be honest the animation part is quite easy, but there's a lot of work to do beforehand, more precisely to fix the plane's original coordinates so they are easier to manage. Let me explain:
If you look at the first image where I show the plane without any geometric transformation, you'll notice that the left wing starts at about ~75 pixels from the 0 point, and that the nose of the plane is ~45 pixels away from the 0 on the y axis. Currently, that's the rotation's anchor point. If you want to rotate the plane in a gracious manner, you'll have to fix this. There are many ways to proceed, follow me.
Take notes, because for some reason very few people will explain in simple words how to rotate on an anchor point using a matrix.
To rotate a shape on a specific anchor point, you have to proceed as follow:
pushMatrix
translate to the shape's destination
rotate
draw the shape using [0, 0] as it's anchor point
popMatrix
So if you want to rotate your plane on itself, thus deciding on an angle then moving it to it's destination before you draw the plane, you act as follow:
void draw() {
background(255);
// grid
stroke(0);
for (int i=0; i<height; i+=20) {
line(0, i, width, i);
}
for (int i=0; i<width; i+=20) {
line(i, 0, i, height);
}
pushMatrix();
translate(200, 200); // for the demonstration only
globalAngle--;
rotate(radians(globalAngle)); // I'm lazy and I don't want to do this in radians so I use degrees and convert them
dessinerAvion(-250, -200); // the center of the plane is the [250, 200] point. That's my anchor point.
popMatrix();
}
Which gives us this result:
Now, using the first translate, you can draw the plane wherever you want, and you can use the rotation to make it face any direction you want it to face.
Using these, it would be real easy to make the plane cross the screen back and forth:
void draw() {
background(255);
drawGrid();
// implementing the "u-turn"
globalY -= vitesse;
if (globalY < -200) {
globalX -= 200;
globalAngle = 180;
vitesse = -vitesse;
}
// drawing the sketch
pushMatrix();
translate(globalX, globalY);
rotate(radians(globalAngle));
dessinerAvion(-250, -200);
popMatrix();
}
Now, if we want to watch the plane turn, we have several options. You can rotate the plane frame by frame while plotting it's course. That's a good option. But I'm lazy, as previously stated, so instead I'll move the anchor point somewhere left of the plane and use it to rotate around it in a gracious manner:
void draw() {
background(255);
drawGrid();
pushMatrix();
translate(globalX, globalY);
tourner();
bouger();
dessinerAvion(0, -200); // this coordinate sets my anchor point
popMatrix();
}
void tourner() {
if (globalY < 300) { // starting the u-turn
vitesse = 0; // The plane won't move while it's rotating... except for the rotation itself
globalAngle--; // rotating counterclockwise 1 degree per frame
if (globalAngle<-180) { // u-turn completed
globalAngle = -180;
vitesse = -3;
}
}
rotate(radians(globalAngle));
}
I think that does it. I hope this helps. I'll lurk around in case you have questions about this answer.
Have fun!

Processing Line tracing

I am a student studying Processing.
I watch an example video I recently discovered to study Processing, and I ask a question because there is a concept that is difficult to understand.
rotate the triangle so that the top vertex of the triangle always faces the point.
Also, a line that runs vertically from the midpoint of the base of the triangle must be connected to the point.
I am not sure where to start fixing the problem.
If you understand the problem, I would appreciate it if you could provide a brief explanation and code.
It looks like a great demonstration of the rotate function, perhaps combined with the translate function. Look at this Processing tutorial for a good description of what you can do with these functions.
To get the desired effect, the program can select a random angle and a random distance between the triangle and the circle. Using the rotate and translate functions, you can basically draw the triangle, circle & line at fixed coordinates and have Processing do the calculations for you (except the distance between the triangle and the circle). The program could look like this:
void settings() {
size(800, 600);
}
void setup() {
frameRate(2);
}
void draw() {
background(128);
float angle = random(-QUARTER_PI, QUARTER_PI);
float ballDistance = random(100, 400);
translate(width / 2, height - 28);
rotate(angle);
noStroke();
fill(255, 0, 0);
circle(0, -ballDistance, 12);
stroke(120, 200, 120);
line(0, 0, 0, -ballDistance);
noStroke();
fill(0, 0, 255);
triangle(-16, 0, 16, 0, 0, -64);
}

PGraphics + noSmooth() + alpha = drawing artifacts

Note: I also asked this question on the Processing forum here.
I have this sample code:
PGraphics pg;
void setup() {
size(400, 500);
pg = createGraphics(width, height);
pg.noSmooth();
pg.beginDraw();
pg.background(0, 0, 255);
pg.endDraw();
}
void draw() {
if (mousePressed) {
pg.beginDraw();
pg.stroke(255, 254);
pg.point(mouseX, mouseY);
pg.endDraw();
}
image(pg, 0, 0, width, height);
}
I would expect this code to show a point wherever the user presses the mouse. Instead, I am only able to see points in a couple rectangular areas:
If I remove the call to pg.noSmooth() or if I remove the alpha value in the pg.stroke() call, then it works fine:
If I replace the pg.point() call with pg.ellipse() or pg.rect() then it also works fine.
It seems like the combination of using a PGraphics, the noSmooth() function, the point() function, and an alpha value results in this buggy behavior. I’ve tried in Processing 3.3 and Processing 3.5.2 and I see the same behavior in both.
Am I missing something obvious?
After a wee bit of digging up turns out the JAVA2D renderer draws a point as a diagonal line(line(x, y, x + EPSILON, y + EPSILON);) with a very very very small spacing (static final float EPSILON = 0.0001f;). My guess is this particular configuration the lack aliasing might mean both points of this diagonal line land on the same pixel and end up not being rendered on the top right area which. Why that area and how come this small distance I don't know, but it sounds a bit like the headaches Jakub Valtar and Andres Colubri had to deal with.
FWIW here's a hacky workaround: using a larger distance that does get rendered with transparency and no aliasing:
PGraphics pg;
void setup() {
size(400, 500);
noSmooth();
pg = createGraphics(width/20, height/20);
pg.beginDraw();
// just for debug purposes: rectangle with edge
pg.fill(0, 0, 255);
pg.rect(0,0,pg.width-1,pg.height-1);
pg.stroke(255,255,255, 128);
pg.endDraw();
}
void pointNoSmooth(PGraphics pg, float x,float y){
pg.beginShape();
pg.vertex(x,y);
pg.vertex(x + 0.75,y);//any less than 0.75 distance between vertices and there's nothing to render with aliasing
pg.endShape();
}
void draw() {
background(255);
if (mousePressed) {
pg.beginDraw();
pointNoSmooth(pg,mouseX,mouseY);
pg.endDraw();
}
// render upscaled
image(pg, 0, 0, width, height);
// render small preview in TL corner
image(pg,0,0);
}
Notice that I've set the PGraphics resolution 20 times smaller, then drawn it upscaled so it's easier to see where the pixels land on the PGraphics. I'm not scaling the mouseX,mouseY coordinates though, so you'll need to draw in the small top left preview when testing. That 0.75 distance does the trick: from what I've tested, anything smaller than 0.7499995 starts acting buggy again.

How can I adjust this code to include vertexes in the for loops?

//Study and use beginShape() and endShape() to draw 3 separate sketches. Each sketch must contain vertices ( vertex() ). tools you will need: beginShape(), endShape(), vertex(), for loop.
//We are supposed to be making Moire patterns. I have gotten the desired result with the code below but it does not include vertexes as the assignment asks. How can I edit adjust this code to include vertices but give the same output?
var theta = 0.0;
var circWidthMultiplier = 17.5;
var circHeightMultiplier = 12.5;
var rectWidthMultiplier = 12.5;
var rectHeightMultiplier =17.5;
var rotationSpeed = 0.005;
function setup() {
createCanvas(windowWidth,windowHeight);
rectMode(CENTER);
}
function draw() {
background(100);
noFill();
push();
beginShape();
translate(width/2, height/2);
for(var i =0; i < 50; i+=5){
ellipse(0, 0,
i*rectWidthMultiplier,
i*rectHeightMultiplier);
}
endShape();
pop();
push();
beginShape();
translate(width/2, height/2);
rotate(theta);
for(var i =0; i < 50; i+=5){
ellipse(0, 0,
i*circWidthMultiplier,
i*circHeightMultiplier);
}
endShape();
pop();
beginShape();
translate(width/2, height/2);
for(var i =0; i < 50; i+=2){
rect(0, 0,
i*circWidthMultiplier,
i*circHeightMultiplier);
}
endShape();
pop();
theta += rotationSpeed;
}
Right now you're using functions like ellipse() and rect() to draw your shapes. You could use beginShape(), vertex(), and endShape() to draw your shapes instead.
Start with replacing the rect() function. You already know the position and size of the rectangle. So it should be pretty easy to replace that with four calls to the vertex() function.
The circles are a little bit trickier, but still doable. You'd need to use basic trigonometry to figure out the vertexes around the circle. Google is your friend here.
But honestly, this seems a little bit pointless. Why bother using vertex() to draw shapes that Processing already draws for you? You might want to check with your instructor to make sure that you're understanding the assignment correctly.

(Newbie Processing Q) How do you slow down the the fading of colors? And how do you stop a moving object?

I'm a newbie who working on processing code. I'm using a variable to fade light blue into a darker blue and that's working fine, but I was wondering how I could slow the process of it fading.
Another question(hope people don't mind me asking two on one post), is how do I make a shape stop moving at a certain point? I have a ellipse there labelled the sun. I'd like it to stop when x=700.
Here's my coding:
float x = 0;
float y = 0;
float r = 0;
int gb = 0;
void setup() {
size(800, 600);
background(gb, gb, 255);
imageMode(CENTER);
noStroke();
}
void draw() {
background(0, gb, 255);
gb++;
if (gb>50) {
//the sun
fill(243, 230, 0);
ellipse(x, 60, 75, 75);
fill(243, 230, 0, 80);
ellipse(x, 60, 90, 90);
x++;
}
fill(0, 255, 0);
rect(0, 380, 800, 450);
}
I was wondering how I could slow the process of it fading.
Check out this line:
gb++;
Here you're incrementing (adding 1 to) your gb variable, which you're using to determine the color. To slow down the color changing, just add a smaller value to it. Something like this:
gb = gb + .1;
Which can be shortened to:
gb += .1;
For this to work, you'll have to change your gb variable to be a float so it can hold decimals.
You might also want to check out the lerp() and map() functions in the reference.
Another question(hope people don't mind me asking two on one post), is how do I make a shape stop moving at a certain point? I have a ellipse there labelled the sun. I'd like it to stop when x=700.
In the future, please only ask one question per post. And try to put together a MCVE for each question instead of posting your whole sketch.
But you can do this with an if statement that only increments x when it is less than 700. Like this:
if(x < 700){
x++;
}
Shameless self-promotion: I wrote a tutorial on using if statements to create animations in Processing available here.

Resources