Sierpinski carpet in processing - processing

So I made the Sierpinski carpet fractal in processing using a Square data type which draw a square and has a function generate() that generates 9 equal squares out of itself and returns an ArrayList of (9-1)=8 squares removing the middle one (it is not added to the returned ArrayList) in order to generate the Sierpinski carpet.
Here is the class Square -
class Square {
PVector pos;
float r;
Square(float x, float y, float r) {
pos = new PVector(x, y);
this.r = r;
}
void display() {
noStroke();
fill(120,80,220);
rect(pos.x, pos.y, r, r);
}
ArrayList<Square> generate() {
ArrayList<Square> rects = new ArrayList<Square>();
float newR = r/3;
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
if (!(i==1 && j==1)) {
Square sq = new Square(pos.x+i*newR, pos.y+j*newR, newR);
rects.add(sq);
}
}
}
return rects;
}
}
This is the main sketch which moves forward the generation on mouse click -
ArrayList<Square> current;
void setup() {
size(600, 600);
current = new ArrayList<Square>();
current.add(new Square(0, 0, width));
}
void draw() {
background(255);
for (Square sq : current) {
sq.display();
}
}
void mousePressed() {
ArrayList<Square> next = new ArrayList<Square>();
for(Square sq: current) {
ArrayList<Square> rects = sq.generate();
next.addAll(rects);
}
current = next;
}
The problem :
The output that I am getting has very thin white lines which are not supposed to be there :
First generation -
Second generation -
Third generation -
My guess is that these lines are just the white background that shows up due to the calculations in generate() being off by a pixel or two. However I am not sure about how to get rid of these. Any help would be appreciated!

Here's a smaller example that demonstrates your problem:
size(1000, 100);
noStroke();
background(0);
float squareWidth = 9.9;
for(float squareX = 0; squareX < width; squareX += squareWidth){
rect(squareX, 0, squareWidth, height);
}
Notice that the black background is showing through the squares. Please try to post this kind of minimal example instead of your whole sketch in the future.
Anyway, there are three ways to fix this:
Option 1: Call the noSmooth() function.
By default, Processing uses anti-aliasing to make your drawings look smoother. Usually this is a good thing, but it can also add some fuzziness to the edges of shapes. If you disable anti-aliasing, your shapes will be more clear and you won't see the artifacts.
Option 2: Use a stroke with the same color as the fill.
As you've already discovered, this draws an outline around the shape.
Option 3: Use int values instead of float values.
You're storing your coordinates and sizes in float values, which can contain decimal places. The problem is, the screen (the actual pixels on your monitor) don't have decimal places (there is no such thing as half a pixel), so they're represented by int values. So when you convert a float value to an int, the decimal part is dropped, which can cause small gaps in your shapes.
If you just switch to using int values, the problem goes away:
size(1000, 100);
noStroke();
background(0);
int squareWidth = 10;
for(int squareX = 0; squareX < width; squareX += squareWidth){
rect(squareX, 0, squareWidth, height);
}

Related

How to make this pattern to expand and shrink back

i have a task to make a pattern of circles and squares as described on photo, and i need to animate it so that all objects smoothly increase to four times the size and then shrink back to their original size and this is repeated. i tried but i cant understand problem
{
size(500,500);
background(#A5A3A3);
noFill();
rectMode(CENTER);
ellipseMode(CENTER);
}
void pattern(int a, int b)
{
boolean isShrinking = false;
for(int x = 0; x <= width; x += a){
for(int y = 0; y <= height; y += a){
stroke(#1B08FF);
ellipse(x,y,a,a);
stroke(#FF0000);
rect(x,y,a,a);
stroke(#0BFF00);
ellipse(x+25,y+25,a/2,a/2);
if (isShrinking){a -= b;}
else {a += b;}
if (a == 50 || a == 200){
isShrinking = !isShrinking ; }
}
}
}
void draw()
{
pattern(50,1);
}
this is what pattern need to look like
Great that you've posted your attempt.
From what you presented I can't understand the problem either. If this is an assignment, perhaps try to get more clarifications ?
If you comment you the isShrinking part of the code indeed you have an drawing similar to image you posted.
animate it so that all objects smoothly increase to four times the size and then shrink back to their original size and this is repeated
Does that simply mean scaling the whole pattern ?
If so, you can make use of the sine function (sin()) and the map() function to achieve that:
sin(), as the reference mentions, returns a value between -1 and 1 when you pass it an angle between 0 and 2 * PI (because in Processing trig. functions use radians not degrees for angles)
You can use frameCount divided by a fractional value to mimic an even increasing angle. (Even if you go around the circle multiple times (angle > 2 * PI), sin() will still return a value between -1 and 1)
map() takes a single value from one number range and maps it to another. (In your case from sin()'s result (-1,1) to the scale range (1,4)
Here's a tweaked version of your code with the above notes:
void setup()
{
size(500, 500, FX2D);
background(#A5A3A3);
noFill();
rectMode(CENTER);
ellipseMode(CENTER);
}
void pattern(int a)
{
for (int x = 0; x <= width; x += a) {
for (int y = 0; y <= height; y += a) {
stroke(#1B08FF);
ellipse(x, y, a, a);
stroke(#FF0000);
rect(x, y, a, a);
stroke(#0BFF00);
ellipse(x+25, y+25, a/2, a/2);
}
}
}
void draw()
{
// clear frame (previous drawings)
background(255);
// use the frame number as if it's an angle
float angleInRadians = frameCount * .01;
// map the sin of the frame based angle to the scale range
float sinAsScale = map(sin(angleInRadians), -1, 1, 1, 4);
// apply the scale
scale(sinAsScale);
// render the pattern (at current scale)
pattern(50);
}
(I've chosen the FX2D renderer because it's smoother in this case.
Additionally I advise in the future formatting the code. It makes it so much easier to read and it barely takes any effort (press Ctrl+T). On the long run you'll read code more than you'll write it, especially on large programs and heaving code that's easy to read will save you plenty of time and potentially headaches.)

Calculate ellipse size in relation to distance from center point

I want to achieve a slow fade in size on every collapse into itself. In other words, when the circle is at its biggest, the ellipses will be at the largest in size and conversely the opposite for the retraction. So far I am trying to achieve this affect by remapping the cSize from the distance of the center point, but somewhere along the way something is going wrong. At the moment I am getting a slow transition from small to large in ellipse size, but the inner ellipses are noticeably larger. I want an equal distribution of size amongst all ellipses in relation to center point distance.
I've simplified the code down to 4 ellipses rather than an array of rows of ellipses in order to hopefully simplify this example. This is done in the for (int x = -50; x <= 50; x+=100).
I've seen one or two examples that slightly does what I want, but is more or less static. This example is kind of similar because the ellipse size gets smaller or larger in relation to the mouse position
Distance2D
Here is an additional diagram of the grid of ellipses I am trying to create, In addition, I am trying to scale that "square grid" of ellipses by a center point.
Multiple ellipses + Scale by center
Any pointers?
float cSize;
float shrinkOrGrow;
void setup() {
size(640, 640);
noStroke();
smooth();
fill(255);
}
void draw() {
background(#202020);
translate(width/2, height/2);
if (cSize > 10) {
shrinkOrGrow = 0;
} else if (cSize < 1 ) {
shrinkOrGrow = 1;
}
if (shrinkOrGrow == 1) {
cSize += .1;
} else if (shrinkOrGrow == 0) {
cSize -= .1;
}
for (int x = -50; x <= 50; x+=100) {
for (int y = -50; y <= 50; y+=100) {
float d = dist(x, y, 0, 0);
float fromCenter = map(cSize, 0, d, 1, 10);
pushMatrix();
translate(x, y);
rotate(radians(d + frameCount));
ellipse(x, y, fromCenter, fromCenter);
popMatrix();
}
}
}
The values you're passing into the map() function don't make a lot of sense to me:
float fromCenter = map(cSize, 0, d, 1, 100);
The cSize variable bounces from 1 to 10 independent of anything else. The d variable is the distance of each ellipse to the center of the circle, but that's going to be static for each one since you're using the rotate() function to "move" the circle, which never actually moves. That's based only on the frameCount variable, which you never use to calculate the size of your ellipses.
In other words, the position of the ellipses and their size are completely unrelated in your code.
You need to refactor your code so that the size is based on the distance. I see two main options for doing this:
Option 1: Right now you're moving the circles on screen using the translate() and rotate() functions. You could think of this as the camera moving, not the ellipses moving. So if you want to base the size of the ellipse on its distance from some point, you have to get the distance of the transformed point, not the original point.
Luckily, Processing gives you the screenX() and screenY() functions for figuring out where a point will be after you transform it.
Here's an example of how you might use it:
for (int x = -50; x <= 50; x+=100) {
for (int y = -50; y <= 50; y+=100) {
pushMatrix();
//transform the point
//in other words, move the camera
translate(x, y);
rotate(radians(frameCount));
//get the position of the transformed point on the screen
float screenX = screenX(x, y);
float screenY = screenY(x, y);
//get the distance of that position from the center
float distanceFromCenter = dist(screenX, screenY, width/2, height/2);
//use that distance to create a diameter
float diameter = 141 - distanceFromCenter;
//draw the ellipse using that diameter
ellipse(x, y, diameter, diameter);
popMatrix();
}
}
Option 2: Stop using translate() and rotate(), and use the positions of the ellipses directly.
You might create a class that encapsulates everything you need to move and draw an ellipse. Then just create instances of that class and iterate over them. You'd need some basic trig to figure out the positions, but you could then use them directly.
Here's a little example of doing it that way:
ArrayList<RotatingEllipse> ellipses = new ArrayList<RotatingEllipse>();
void setup() {
size(500, 500);
ellipses.add(new RotatingEllipse(width*.25, height*.25));
ellipses.add(new RotatingEllipse(width*.75, height*.25));
ellipses.add(new RotatingEllipse(width*.75, height*.75));
ellipses.add(new RotatingEllipse(width*.25, height*.75));
}
void draw() {
background(0);
for (RotatingEllipse e : ellipses) {
e.stepAndDraw();
}
}
void mouseClicked() {
ellipses.add(new RotatingEllipse(mouseX, mouseY));
}
void mouseDragged() {
ellipses.add(new RotatingEllipse(mouseX, mouseY));
}
class RotatingEllipse {
float rotateAroundX;
float rotateAroundY;
float distanceFromRotatingPoint;
float angle;
public RotatingEllipse(float startX, float startY) {
rotateAroundX = (width/2 + startX)/2;
rotateAroundY = (height/2 + startY)/2;
distanceFromRotatingPoint = dist(startX, startY, rotateAroundX, rotateAroundY);
angle = atan2(startY-height/2, startX-width/2);
}
public void stepAndDraw() {
angle += PI/64;
float x = rotateAroundX + cos(angle)*distanceFromRotatingPoint;
float y = rotateAroundY + sin(angle)*distanceFromRotatingPoint;
float distance = dist(x, y, width/2, height/2);
float diameter = 50*(500-distance)/500;
ellipse(x, y, diameter, diameter);
}
}
Try clicking or dragging in this example. User interaction makes more sense to me using this approach, but which option you choose really depends on what fits inside your head the best.

How do only update pixels once

My pixels are updating every frame causing the effect to be re-applied to the previous frame. How can i make this effect only happen once and without using noLoop(). I just want there to be a large circle around the triangle. Please help. Thanks.
Here is the whole program. I set the frameRate to 1 so you can see the problem easier:
boolean up;
int x =-300;
int y =-300;
void setup()
{
size(600, 600);
frameRate(1);
}
void draw()
{
pushMatrix();
translate(300, 300);
float a = atan2(mouseY-300, mouseX-300);
rotate(a);
for (int i = x; i < x+width; i+=40)
for (int j = y; j < y+height; j+=40)
rect(i, j, 40, 40);
loadPixels();
for (int i = 0; i < pixels.length; i++)
{
x = i%width;
y = i/width;
color c = pixels[x+y*width];
float d = dist(x, y, width/2, height/2);
pixels[x+y*width] = color(brightness(c) - d);
}
updatePixels();
popMatrix();
fill(255, 0, 0);
triangle(280, 300, 300, 200, 320, 300);
if (up)
{
x += sin(a)*5;
y += cos(a)*5;
}
}
void keyPressed()
{
if (key=='w')up=true;
}
void keyReleased()
{
if (key=='w')up=false;
}
Re-draw everything in one frame.
Remember before you use your filter, you must undo the filter effects of the last time.
The usual ordering in your draw() function goes as follows:
Add a background / clear all the objects you added in the last frame & clearing the filter of your last frame.
Add your objects.
Lay your filter on top.
Try to refrain from doing any graphic related stuff in setup, hence it will be destroyed by this draw() function - paradigma.
This should already suffice as your answer. Quick note:
When you work with for e.g. a 3D - Shadow filter, applying the filter can take a very long time. Instead we try to store as many calculations we did on the previous frame, so we don't need to calculate everything over again. The same goes for the objects-layer. You don't want to calculate the shortest-path for a minion every frame, instead you calculate the shortest path once and only recalculate it, when something changes: Position of a box, player position, etc..
If you want just use your filter and move fluently around update your effect like this:
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
color c = pixels[x+y*width];
float d = dist(x, y, width/2, height/2);
pixels[x+y*width] = color(brightness(c) - d);
}
}
You had unnecessary calculation that consume lot of CPU resources. Redrawing background also helps to make clearer animation.
If you want generate this effect only once and then apply it. PGraphics could achieve something similar.

Processing Spacing

I'm trying to draw bears in processing, (Just simple circles), how can I get the bears equally spaced apart, and have the same space from the edge of the screen to the bears, on either side? As well as vertically.
I know this is vague, but I'm terrible at explaining things
Because you does not provide any code or example I will just tell you how to place circle in the middle of sketch.
For simplicity imagine this set up:
void setup(){
size(400, 400);
}
1) Very basic approach would be to hard code position of this circle into ellipse draw function.
ellipse(200, 200, 50, 50);
Where first two parameters are coordinates for circle center. Simple find out from size 400x400 that mid is on coord 200x200. This is bad approach and you should avoid using it.
2) Better approach would be to calculate center coord using global variables width and height
ellipse(width/2, height/2, 50, 50);
3) When you are drawing or moving more complex objects it is preferred to use some function to draw this objects always with same fixed position in our example
void draw_circle(){
ellipse(0, 0, 50, 50);
}
And just moving center of drawing using transformations so our draw function will looks like this
void draw(){
pushMatrix();
translate(width/2, height/2);
draw_circle();
popMatrix();
}
Using this you could be able to draw bears equally spaced apart and from sides.
It sounds like you want a grid of equally spaced circles. For that you just need to divide your space into a grid in the x and y directions. The simplest way to do this is to wrap the kind of thing Majlik showed inside a double loop to move from cell to cell in your 'virtual' grid. To see this more clearly, in the code below there is an extra little bit so that if you press the 'g' key (for grid) you'll see the grid cells, with a circle centered in each one. You can press any other key to make the grid go away.
You can see that each way gives the same result: inside draw() uncomment the one you want and comment out the other 2.
int nx = 4; // number of circles horizontally
int ny = 5; // number of circles vertically
int divx;
int divy;
int diameter = 40;
void setup() {
size(600, 600);
// calculate width and hegith of each cell of the grid
divx = width/nx;
divy = height/ny;
}
// 3 ways to draw a regular grid of circles
void draw() {
background(200);
// show the cell layout if the g key was typed, otherwise don't
if(key == 'g')
drawGrid();
// 1 way
for(int i = 0; i < nx; i++) {
for(int j = 0; j < ny; j++ ) {
ellipse(i * divx + divx/2, j * divy + divy/2, diameter, diameter);
}
}
// another way
// for(int i = divx/2; i < width; i += divx) {
// for(int j = divy/2; j < height; j += divy ) {
// ellipse(i, j, diameter, diameter);
// }
// }
// yet another way
// for(int i = divx/2; i < width; i += divx) {
// for(int j = divy/2; j < height; j += divy ) {
// pushMatrix();
// translate(i, j);
// ellipse(0, 0, diameter, diameter);
// popMatrix();
// }
// }
}
void drawGrid() {
// draw vertical lines
for(int i = 1; i < nx; i++) {
line(i * divx, 0, i * divx, height);
}
// draw horizontal lines
for(int j = 1; j < ny; j++ ) {
line(0, j * divy, width, j * divy);
}
}

make curtain like behaviour in drawing of lines

I am new to Processing.js and need a little bit support with this issue. I have made a HTML-Canvas animation where I have lines with a curtain like behavior which can be seen here:
Click
this is made with a canvas plugin called Paper.js
I now want to get similar effect on processing but don't really know how to figure it out. My attempt was:
float x;
float y;
void setup() {
size(1024, 768);
strokeWeight(2);
background(0, 0, 0);
}
void mouseMoved() {
x = mouseX;
y = mouseY;
}
void draw() {
background(0);
line(50, 50, x += x - x/5, y += y - y/5);
stroke(255, 255, 255);
line(50, 700, x += x - x/15, y += y - y/15);
stroke(255, 255, 255);
line(75, 50, x += x - x/25, y += y - y/25);
stroke(255, 255, 255);
line(75, 700, x += x - x/35, y += y - y/35);
// and so on, would create it within a loop
}
So what I am trying to do is basically get the same effect which I have done in HTML and adapt it in Processing.js.
Thanks in advance.
I'd strongly recommend ignoring the paper.js and reimplementing this properly. We're seeing a sequence of lines that connect to a historical line of coordinates, based on mouse position, so let's just implement that:
class Point {
float x, y;
Point(float _x, float _y) { x=_x; y=_y; }}
// our list of historical points
ArrayList<Point> points;
// the horizontal spacing of our lines has fixed interval
float interval;
// how many lines do we want to draw?
int steps = 50;
void setup() {
size(500, 500);
// initialise the "history" as just the midpoint
points = new ArrayList<Point>();
for (int i=0; i<steps; i++) {
points.add(new Point(width/2, height/2));
}
// compute the horizontal interval, because it's
// width-dependent. Never hard code dependent values.
interval = width/(float)steps;
// the lower we set this, the slower it animates.
frameRate(60);
}
void draw() {
// white background, black lines
background(255);
stroke(0);
// for each historic point, draw two
// lines. One from height 0 to the point,
// another from height [max] to the point.
Point p;
for (int i=0; i<steps; i++) {
p = points.get(i);
line(interval/2 + i*interval, 0, p.x, p.y);
line(interval/2 + i*interval, height, p.x, p.y);
}
// when we move the mouse, that counts as a new historic point
points.remove(0);
points.add(new Point(mouseX, mouseY));
}
Sketch running in the browser: http://jsfiddle.net/M2LRy/1/
(You could speed this up by using a round-robin array instead of an ArrayList, but ArrayLists are pretty convenient here)

Resources