How non-integer coordinates work in Processing when drawing shapes? - processing

I'm trying to draw a series of lines and shapes that connect to each-other. Because of some calculations that I'm doing the coordinates for the lines/shapes end up being non-integer numbers and in this case there's a gap between lines that end and start at the same non-integer coordinate.
For example for this code:
void setup() {
noLoop();
size(500, 500);
}
void draw() {
stroke(1);
strokeWeight(100);
strokeCap(SQUARE);
line(0, 0, 0, 200.5);
line(0, 200.5, 0, 401);
}
I get this result (note the gap between the two lines):
Tried this also in p5.js with the same result. How is this working? Should I just always round to integers after doing my math?

After adding a background() call to the draw() the problem now appears to be with the SQUARE strokeCap as I initially thought and not the noLoop(). REM out strokeCap(SQUARE) and it runs ok. UN-REM it and the lines come back with or without noLoop(); PROJECT caps and no caps are still without lines, with or without noLoop(). I don't think the float values make a difference. Note that I removed the decimal values for strokeCap(SQUARE) to rule this out as a possibility. I'm unable to tell you why the lines occur with strokeCap(SQUARE), but the only way that I see to get rid of the lines is to use the PROJECT option, no caps at all, or keep them, but overlap the ends by 1 point. For whatever it's worth, Processing Reference states that all parameters for line() are floats.
void setup() {
size(500, 500);
noLoop();
}
void draw() {
background(209); // Added and it makes a difference
stroke(0);
strokeWeight(50);
// NO cap
line(60, 80, 180.3, 80);
line(180.3, 80, 280.8, 80);
line(280.8, 80, 380.5, 80);
// (SQUARE) cap
strokeCap(SQUARE); // REM this out to get rid of lines
line(60, 160, 160, 160);
line(160, 160, 260, 160);
line(260, 160, 360, 160);
// (PROJECT) cap
strokeCap(PROJECT);
line(60, 260, 160.5, 260);
line(160.5, 260, 260.5, 260);
line(260.5, 260, 360.5, 260);
// (SQUARE) cap with 1 point of overlap
strokeCap(SQUARE); // No lines with overlap
line(60, 360, 160.8, 360);
line(159.8, 360, 260.3, 360);
line(259.3, 360, 360.5, 360);
}

Related

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);
}

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?

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.

How to draw shapes along a bezier path

I would like to plot a series of ellipses along a bezier path but I am struggling to plot anything more than just the line of the path. I don't need it to move at all. So far I have:
void setup() {
size(150, 150);
background(255);
smooth();
// Don't show where control points are
noFill();
stroke(0);
beginShape();
vertex(50, 75); // first point
bezierVertex(25, 25, 125, 25, 100, 75);
endShape();
}
How do I plot ellipses to follow the bezier path instead of the line?
Why would you expect that code to draw circles? It doesn't contain any calls to the ellipse() function.
Anyway, it sounds like you're looking for the bezierPoint() function:
noFill();
bezier(85, 20, 10, 10, 90, 90, 15, 80);
fill(255);
int steps = 10;
for (int i = 0; i <= steps; i++) {
float t = i / float(steps);
float x = bezierPoint(85, 10, 90, 15, t);
float y = bezierPoint(20, 10, 90, 80, t);
ellipse(x, y, 5, 5);
}
(source: processing.org)
As always, more info can be found in the reference.

Easiest way to animate a collection of shapes in processing?

I have been working on learning processing and now feel fairly comfortable drawing shapes and editing color etc. I have tried to take the step towards animating one of my prior works, but I just seem to keep running into dead ends or I can't get the unit to move cohesively. Essentially I am trying to move this entire guitar around the screen in any manner whatsoever as long as it stays intact. If you have a recommendation I would greatly appreciate it!
Current code is as follows:
void setup() {
size(600,600);
smooth();
noLoop();
}
void draw() {
//pegs
strokeJoin(SQUARE);
fill(255,255,255);
rect(530,105,20,20);
rect(565,70,20,20);
rect(473,50,20,20);
rect(505,18,20,20);
//neck and head
strokeWeight(60);
strokeCap(SQUARE);
strokeJoin(ROUND);
stroke(165,42,42);
line(490,110,560,40);
fill(255,255,255);
strokeWeight(45);
strokeCap(SQUARE);
strokeJoin(ROUND);
line(300,295,500,105);
//guitar body
noStroke();
fill(222,184,135);
ellipse(200,400,200,200);
ellipse(280,310,150,150);
//Sound Hole
fill(255,140,0);
ellipse(235,360,110,110);
fill(0,0,0);
ellipse(235,360,100,100);
//strings
stroke(255,255,255);
strokeWeight(3);
line(170,390,540,40);
line(180,400,550,45);
line(195,410,560,50);
line(207,420,570,55);
//string attatchment bottom
strokeWeight(6);
strokeCap(SQUARE);
stroke(165,42,42);
line(210,425,170,385);
}
The following code will animate your guitar so that it will move along the positive x-axis. This is just an example to give you an idea how "animation" really works:
// this will be used to move the guitar along x
int alongX = 0;
void setup() {
background(128);
size(600, 600);
smooth();
//noLoop();
}
void draw() {
background(128);
//pegs
strokeJoin(SQUARE);
fill(255, 255, 255);
rect(530+alongX, 105, 20, 20);
rect(565+alongX, 70, 20, 20);
rect(473+alongX, 50, 20, 20);
rect(505+alongX, 18, 20, 20);
//neck and head
strokeWeight(60);
strokeCap(SQUARE);
strokeJoin(ROUND);
stroke(165, 42, 42);
line(490+alongX, 110, 560+alongX, 40);
fill(255, 255, 255);
strokeWeight(45);
strokeCap(SQUARE);
strokeJoin(ROUND);
line(300+alongX, 295, 500+alongX, 105);
//guitar body
noStroke();
fill(222, 184, 135);
ellipse(200+alongX, 400, 200, 200);
ellipse(280+alongX, 310, 150, 150);
//Sound Hole
fill(255, 140, 0);
ellipse(235+alongX, 360, 110, 110);
fill(0, 0, 0);
ellipse(235+alongX, 360, 100, 100);
//strings
stroke(255, 255, 255);
strokeWeight(3);
line(170+alongX, 390, 540+alongX, 40);
line(180+alongX, 400, 550+alongX, 45);
line(195+alongX, 410, 560+alongX, 50);
line(207+alongX, 420, 570+alongX, 55);
//string attatchment bottom
strokeWeight(6);
strokeCap(SQUARE);
stroke(165, 42, 42);
line(210+alongX, 425, 170+alongX, 385);
// incrementing alongX to move it along +x, decrement it to move it along -x
alongX++;
}
The idea is very simple. Animation is basically an illusion of movement. Objects appear such that they're moving but the effect is achieved very simply by drawing and redrawing (at a certain speed: frameRate) the objects on the screen in different locations in such a way that they appear to the viewer as though they're moving when in reality they're not.
For this effect to be effective, you have to have certain things in your sketch (or any other animation package):
You need to have variables that control the position of the object so
when you want to move the object, you can easily change the values
of the variables controlling the position in such a way that it would
give the illusion of movement.
You also, in this case, need to keep redrawing the background. That
is why I added the background(128); line in your draw() method.
If you comment that line out, you will see that the effect is
different and the guitar leaves a trail (maybe that's what you
want...a trail that later fades away? Its up to you!).
Another thing you need to consider in your sketch is that while
rects and ellipses only need to have one variable changed in
order for them to move from left to right (in the case of this
sketch), lines need to have both x values manipulated by your
variable.
noLoop() in setup() is specifically designed so you can stop
draw() from its infinite loop or game loop but stopping
draw() means no animation effects. You can have noLoop(), for
example, to stop the animation upon pressing a key but then you'd
also want to provide loop() to get the animation going upon
pressing a key. These are some things and decisions for you to think
about and play with.
Finally, I just changed your sketch a little to show you how
animation may work. You can add a ton of things to it to make it
awesome.
PS: Cool guitar!
UPDATE
After getting comfortable with the idea of moving objects around, I would look at vectors and how they can be used to set the direction, and velocity of objects. Take a look at PVector in Processing. This tutorial would be sufficient to get you going with PVectors. But I would do this on objects. For example, a full Guitar object. Not on individual lines and rects.

“Rotate” and “translate” in processing give me headaches

As a small homework to get into Processing, I had to write some code to get the following:
Using
public void setup() {
size(300,200);
noFill();
rect(100, 20, 40, 80);
ellipseMode(CENTER);
fill(#000000);
ellipse(width/2, height/2, 5,5);
noFill();
translate(width/2, height/2);
rotate(radians(65));
rect(-20, -40, 40, 80);
}
public void draw() {
}
this worked very good, so far. But I don’t like that I had to change the coordinates inside of the bottom rect instruction in order to get the rotation right. I know that by rotating you don’t rotate single elements but in fact the whole coordinate system.
What I don’t know is which values to put into the translate instruction to have the output be like in the picture above while also still using the same coordinates within the rect command.
The task is already done with the code I used, I just don’t like it too much. So this isn’t mere asking for somebody else doing my homework but pure interest.
EDIT: More generalised attempt of a question: How do I know which values to pit into translate before rotate to get whatever result I want? Is there a way to calculate them? For sure, it’s not just trying out, is it?
A lot of the confusion in processing is the coordinate system. In Processing the origin (0,0) is at the top left of the screen and only positive coordinates display on the screen. The very common workaround for this is to call:
translate(width/2, height/2);
at the beginning of your void draw() method. That way 0,0 is now at the center of the sketch, and any subsequent methods called such as rotate(radians(65)) will take action from the center of the sketch.
This is also good because sketches that use the P3D or OPENGL renderer often call translate to change the coordinate system into something that is easier to use. For example an object at 0,0 or 0,0,0 is at the center and it makes it easier to orbit the camera around the object or have the object rotate around its center.
another popular way of drawing objects would be to set the origin as above and instead of giving the coordinates of each object, i.e. rect(-100, -50, 50, 50) is to use popMatrix() and pushMatrix before a translate before drawing each object at 0,0 as illustrated below:
translate(width/2, height/2);
pushMatrix();
translate(-100, -50);
rect(0,0,50,50);
popMatrix();
This is a good approach to use in a 2d renderer if you think you might move to 3d renderer eventually, because you can easily replace rect() with box() or sphere() or create your own method or object that draws geometry assuming the origin is at 0,0.
If you replace the x and y coordinates with variables or iterate through an array in a for loop it becomes very easy to draw hundreds or thousands of shapes in either 2d or 3d with minimal effort and minimal rewriting of the code.
update: added clarification for the original poster, per their comment.
I have changed the problem slightly to show you how I would approach this. I am showing the translate / rotate method I described above using push and pop matrix. I am just guessing at the values, but if you want something pixel accurate you can take measurements in an image editing program like photoshop or preview.
translate(180, 150);
rect(0, 0, 180, 80);
translate(185, 170);
rotate(radians(65));
rect(0, 0, 180, 80);
translate(180, 250);
ellipse(0, 0, 8, 8);
Putting it all together with pushMatrix() and popMatrix().
void setup(){
size(400,400);
}
void draw(){
// rect1
noFill();
pushMatrix();
translate(180, 150);
rect(0, 0, 180, 80);
popMatrix();
// rect2
pushMatrix();
translate(185, 170);
rotate(radians(65));
rect(0, 0, 180, 80);
popMatrix();
// ellipse
fill(0);
pushMatrix();
translate(180, 250);
ellipse(0, 0, 8, 8);
popMatrix();
}
in my particular example, know how to translate and rotate to get the
result in the picture without changing the rectangle coordinates?
Well, you need to draw at origin to use rotate properly, so you are just dealing with the origin of the rect... As it is in your code, the default, the origin is the upper left corner, so you made an off set (from (0,0)) to draw it's centre, not the corner, at coordinate(0,0), then rotate by the middle. Well done. It is not coincidence that the values you found was minus half rect width(-20) and minus half rect height(-40). If you change to rectMode(CENTER) than you can just draw at (0,0). The same applies to translate, you can just translate to the desired point, the center of the screen, where there is the ellipse. What is done using half width and half height...
look:
public void setup() {
size(300, 200);
smooth();
ellipseMode(CENTER);
rectMode(CENTER);
noFill();
// here converting the coordinates to work with CENTER mode
//could have changed the rect mode just after this
// but i kept as an illustration
int rwidth = 40;
int rheight = 80;
int xpos = 100 + rwidth/2;
int ypos = height/2 - rheight/2 ;
rect(xpos, ypos, rwidth, rheight);
fill(#000000);
ellipse(width/2, height/2, 5, 5);
noFill();
pushMatrix();
translate(width/2, height/2);
//draw at origin gray
stroke(150);
rect(0, 0, 40, 80);
// then rotate
rotate(radians(65));
// draw again black
stroke(0);
rect(0, 0, 40, 80);
popMatrix();
// here using the cordinates calculated before as a translate value
// we draw at origin, but it appears at same place
stroke(230,230,100);
// a bit to the left...
translate(xpos-2, ypos-2);
rect(0, 0, 40, 80);
}
Rotation is aways applied to origin point (0,0), so you want to draw your axis for rotating at origin. Or move the coordinate system origin, to your axis. It is indeed confusing. When using transformations I tend to draw at origin always. Try this to see if it makes things more clear... or less :)
Also there is push/popMatrix() to control the scope of transformations...
public void setup() {
size(300, 380);
smooth();
}
public void draw() {
background(0);
stroke(255);
//use push/pop Matrix to control scope of translate and rotate
pushMatrix();
//move coordinates system origin to center of screen
translate(width/2, height/2);
// rotate with origin as axis
rotate(radians(mouseY));
//draw at origin (now temp moved to center of screen)
// white line
line(0, 0, 150, 0);
// here all coordinate system is back to normal
popMatrix();
//draw with normal system red line at origin
stroke(255, 0, 0);
line(0, 0, 150, 0);
//draw with normal system blue line at centre
stroke(0, 0, 255);
line(width/2, height/2, width/2 + 150, height/2);
}

Resources