Deformed circles

Hi there! I am trying to draw something as this made by hand circles with processing. I know this two ways, but deforming an ellipse is still too geometric and rounded corners of a rect is not bad but not as spontaneous as the doodle that I am sending. So is there another way to deform a circle to make it really natural?

size(400, 400);
rect(120, 80, 220, 220, 200, 360, 300, 240);
ellipse(100,100,80,100);

Add together a few sine waves with random phase shifts.

Hit Enter to cycle through some random ones.

void setup() {
  size( 900, 900 );
  noLoop();
}

float sn( float x ) { return sin( TAU*x ); }
float cs( float x ) { return cos( TAU*x ); }

void draw() {
  translate( width/2, height/2 );
  scale( height/4. );
  strokeWeight( 0.05 );
  stroke(255);
  noFill();
  background( 0 );
  float r1 = random(1), r2 = random(1), r3 = random(1);
  beginShape();
  int N = 200;
  for( int i=0; i<=N; i++ ) {
    float u = 1.*i/N;
    float r = 1 + 0.1*(sn( 2*u+r1 )/2 + sn( 3*u+r2 )/3 + sn( 5*u+r3 )/5);
    vertex( r*cs(u), r*sn(u) );
  }
  endShape();
}

void keyPressed() { redraw(); }
2 Likes

Or use a noise function to vary the radius:

void setup() {
  size( 900, 900 );
  noLoop();
}

float sn( float x ) { return sin( TAU*x ); }
float cs( float x ) { return cos( TAU*x ); }

void drawNoiseWobble() {
  float r1 = random(1), r2 = random(1), r3 = random(1);
  beginShape();
  int N = 360;
  for( int i=0; i<=N*1.05; i++ ) {
    float u = 1.*i/N+r3;
    float r = 1 + 0.5*(noise( 17*r1, 4*u+20*r2 )-0.5);
    vertex( r*cs(u), r*sn(u) );
  }
  endShape();
}

void draw() {
  translate( width/2, height/2 );
  scale( height/4. );
  strokeWeight( 0.05 );
  stroke(255);
  noFill();
  background( 0 );
  drawNoiseWobble();
}

void keyPressed() { redraw(); }
1 Like

Thank you so much for your help @scudly . I have found this tutorial on youtube, but when I try to run it I found this

OutOfMemoryError: You may need to increase the memory setting in Preferences.

So what can I do?

float noiseMax = 0.5;

void setup() {
  size(600,600);
}

void draw() {
  background(255,255,255);
  translate(width/2, height/2);
  stroke(0,0,0);
  noFill();
  beginShape();
   for (int a=0; a<TWO_PI; a+=0.1){
     float xoff=map(cos(a),-1,1,0,noiseMax);
     float yoff=map(sin(a),-1,1,0,noiseMax);
     float r= map(noise(xoff,yoff),0,1,100,200);
     float x = r * cos(a);
     float y = r * sin(a);
     vertex(x,y);
   } 
  endShape(CLOSE);
  noLoop();
}
1 Like

In your for loop, int a should be float a.

2 Likes

Now I would like to draw a loop of concentric circles, so I have created a function with the organic shape. But I don’t even know if it is working because I don’t see it anymore. Could you please help me?

float noiseMax = 0.7;

void setup() {
  size(1000,1000);
}

void drawCircle(float i, float j){
  translate(width/2, height/2);
  stroke(0,0,0);
  noFill();
  beginShape();
   for (float a=0; a<TWO_PI; a+=0.1){
     float xoff=map(cos(a),-1,1,0,noiseMax);
     float yoff=map(sin(a),-1,1,0,noiseMax);
     float r= map(noise(xoff,yoff),0,1,i,j);
     float x = r * cos(a);
     float y = r * sin(a);
     vertex(x,y);
   } 
  endShape(CLOSE);
  //noLoop();
}
  


void draw() {
  background(255,255,255);
  for (float i=0; i<100; i+=5){
    for (float j=0; j<100; j+=5){
  drawCircle(i,j);
  }
  }
  }

Try this one. You can tweak noiseScale to make it more or less jagged.

float noiseScale = 0.005;

void setup() {
  size(1000,1000);
  noLoop();
}

void drawCircle( float innerR, float outerR ){
  stroke(0,0,0);
  noFill();
  beginShape();
   for( float i=0; i<360; i++ ) {
     float a = TAU*i/360;
     float xoff = 2000 + innerR * noiseScale * cos(a);
     float yoff = 2000 + innerR * noiseScale * sin(a);
     float r = innerR + (outerR-innerR) * noise( xoff, yoff );
     float x = r * cos(a);
     float y = r * sin(a);
     vertex(x,y);
   } 
  endShape(CLOSE);
}
  
void draw() {
  translate(width/2, height/2);
  background(255,255,255);
  for (float i=0; i<500; i+=20){
      drawCircle(i,i+100);
  }

Oh! That is amazing! :star_struck: Thank you so much! They are concentric but now I have this problem

Noise is making these circles like circles made by humans, but it is also making every circle similar to closer one. And I was actually looking for independent concentric circles, as if they would be drawn by hand, like in this doodle:


So how could I use noise in every shape but not in the loop?

Each circle is tracing out a circular path through the noise. If you don’t want the circles correlated, pick a random point to circle around. noise() is symmetric about the origin so to avoid that, I move everything over by 2000 in addition to adding a random amount.

float noiseScale = 0.005;

void setup() {
  size(1000,1000);
  noLoop();
}

void drawCircle( float innerR, float outerR ){
  stroke(0,0,0);
  noFill();
  float rx = random(2000), ry = random(2000);
  beginShape();
   for( float i=0; i<360; i++ ) {
     float a = TAU*i/360;
     float xoff = 2000 + rx + innerR * noiseScale * cos(a);
     float yoff = 2000 + ry + innerR * noiseScale * sin(a);
     float r = innerR + (outerR-innerR) * noise( xoff, yoff );
     float x = r * cos(a);
     float y = r * sin(a);
     vertex(x,y);
   } 
  endShape(CLOSE);
}
  
void draw() {
  translate(width/2, height/2);
  background(255,255,255);
  for (float i=0; i<500; i+=5){
      drawCircle(i,i+100);
  }
}
3 Likes

Now I am trying to give the loop three colors but they are only working two of them, do you know why?

float noiseScale = 0.002;

void setup() {
  size(1000,1000);
  noLoop();
}

void drawCircle( float innerR, float outerR ){
  
  noFill();
  float rx = random(2000), ry = random(2000);
  beginShape();
   for( float i=0; i<360; i++ ) {
     float a = TAU*i/360;
     float xoff = 2000 + rx + innerR * noiseScale * cos(a);
     float yoff = 2000 + ry + innerR * noiseScale * sin(a);
     float r = innerR + (outerR-innerR) * noise( xoff, yoff );
     float x = r * cos(a);
     float y = r * sin(a);
     vertex(x,y);
   } 
  endShape(CLOSE);
}
  
void draw() {
  translate(width/2, height/2);
  background(255,255,255);
  for (float i=0; i<500; i+=3){
    if((i>500) && (random(1)>0.3)) {
  stroke(255,0,0); 
}
else if((i>200) && (random(1)>0.2)){
 stroke(0,0,255); 
}
else if((i>0) && (random(1)>0.1)){
 stroke(0,255,0); 
}
   drawCircle(i,i+100);
  }
}

since i goes only up to 500 the condition is never met

try i>400

Or this one randomizes the colors with more red in the middle and more blue to the outside:

float noiseScale = 0.002;

void setup() {
  size(1000,1000);
  noLoop();
}

void drawCircle( float innerR, float outerR ){
  noFill();
  float rx = random(2000), ry = random(2000);
  beginShape();
   for( float i=0; i<360; i++ ) {
     float a = TAU*i/360;
     float xoff = 2000 + rx + innerR * noiseScale * cos(a);
     float yoff = 2000 + ry + innerR * noiseScale * sin(a);
     float r = innerR + (outerR-innerR) * noise( xoff, yoff );
     float x = r * cos(a);
     float y = r * sin(a);
     vertex(x,y);
   } 
  endShape(CLOSE);
}
  
void draw() {
  translate(width/2, height/2);
  background(255,255,255);
  for (float i=0; i<500; i+=3) {
    float u = 1.*i/500;
    stroke( 0, 255, 0 );
    if( random(1) > u ) { stroke(255,0,0); }
    else if( random(1) < u*u ) { stroke(0,0,255); }
    drawCircle(i,i+100);
  }
}
1 Like

Or if you want strictly 3 regions, I would write it like this:

void draw() {
  translate(width/2, height/2);
  background(255,255,255);
  int nCircles = 500;
  for (float i=0; i<nCircles; i+=3) {
    float u = 1.*i/nCircles;
    if( u < 0.3333 ) { stroke( 255, 0, 0 ); }
    else if( u < 0.6666 ) { stroke( 0, 255, 0 ); }
    else stroke( 0, 0, 255 );
    drawCircle(i,i+100);
  }
}

thank you so much, @scudly ,this is amazing!

I am trying some different options about color. I have thought about a gradient. So I have typed this sketch to make it simpler, trying to create a gradient in a loop. But it only works when I use the same variable in color that I have used to multiply lines , It does not work if I try to use another variable with other values.

size(500,500);
strokeWeight(5);
colorMode(HSB,360,100,100);
for (int i =0; i <500; i+=20){
 //for(int j=100; i<300; i+=1){
  stroke(i);
  line(i,0,i,500);
}
//}
size(500,500);
strokeWeight(5);
colorMode(HSB,1, 1, 1);
for (int i =0; i <500; i+=5){
  float u = 1.*i/500;
  stroke(u, 0.7, 1);
  line(i,0,i,500);
}

well, thank you so much again, @scudly , your code produces amazing results : D

I have typed a line to see different designs pressing enter and I have discovered that all of them work really good as a stop motion, if you see one every second or half a second. How could I make and export an infinite loop with, for example, 10 designs restarting again and again?

float noiseScale = 0.002;


void setup() {
  size(1000,1000);
  noLoop();
}


void drawCircle( float innerR, float outerR ){
  noFill();
  float rx = random(2000), ry = random(2000);
  beginShape();
   for( float i=0; i<360; i++ ) {
     float a = TAU*i/360;
     float xoff = 2000 + rx + innerR * noiseScale * cos(a);
     float yoff = 2000 + ry + innerR * noiseScale * sin(a);
     float r = innerR + (outerR-innerR) * noise( xoff, yoff );
     float x = r * cos(a);
     float y = r * sin(a);
     vertex(x,y);
   } 
  endShape(CLOSE);
}
  
void draw() {
  color a = color(204,255,255);
  color b = color(204,153,255);
  color c = color(255,0,102);
  translate(width/2, height/2);
  background(255,255,255);
  for (float i=-40; i<400; i+=1) {
    float u = 1.*i/450;
    //middle
    stroke(b);
    //inside
    if( random(1) > u ) { stroke(a); }
    //outside
    else if( random(1) < u*u ) { stroke(c); }
    drawCircle(i,i+100);
    
  }
}

void keyPressed() {
  if( keyCode == ENTER ) draw();
  else if( key == '+' ) saveFrame();
  redraw();
}

We are using both random() and noise() so to repeat, we need to set both randomSeed() and noiseSeed() to get a repeating set of values. Both of those take integers whereas random() gives us a float so I have to scale it up and cast to an int. floats only have 24 bits of precision, so to keep it uniform, I only sample from 2**24 values (the 1<<24 part). Each time through draw(), I initialize the random stream with the next random seed and then use its first value to initialize the noiseSeed value as well.

float noiseScale = 0.002;
int repeatCount = 10;
int baseSeed;

void setup() {
  size(1000,1000);
  noLoop();
  baseSeed = int(random(1<<24));
}


void drawCircle( float innerR, float outerR ){
  noFill();
  float rx = random(2000), ry = random(2000);
  beginShape();
   for( float i=0; i<360; i++ ) {
     float a = TAU*i/360;
     float xoff = 2000 + rx + innerR * noiseScale * cos(a);
     float yoff = 2000 + ry + innerR * noiseScale * sin(a);
     float r = innerR + (outerR-innerR) * noise( xoff, yoff );
     float x = r * cos(a);
     float y = r * sin(a);
     vertex(x,y);
   } 
  endShape(CLOSE);
}
  
void draw() {
  randomSeed( baseSeed + (frameCount % repeatCount) );
  noiseSeed( int(random(1<<24)) );
  color a = color(204,255,255);
  color b = color(204,153,255);
  color c = color(255,0,102);
  translate(width/2, height/2);
  background(255,255,255);
  for (float i=-40; i<400; i+=1) {
    float u = 1.*i/450;
    //middle
    stroke(b);
    //inside
    if( random(1) > u ) { stroke(a); }
    //outside
    else if( random(1) < u*u ) { stroke(c); }
    drawCircle(i,i+100);
    
  }
}

void keyPressed() {
  if( keyCode == ENTER ) draw();
  else if( key == '+' ) saveFrame();
  redraw();
}
1 Like

Thank you again! And one last question. Could I split the static image into 3 layers if I would want to print it with a pen plotter? Is it possible?

I haven’t tested this, but something like this should work:

void draw() {
  translate(width/2, height/2);
  for( int ipass=0; ipass<3; ipass++ ) {
    randomSeed( baseSeed + (frameCount % repeatCount) );
    noiseSeed( int(random(1<<24)) );
    color a = color(204,255,255);
    color b = color(204,153,255);
    color c = color(255,0,102);
    background(255,255,255);
    for (float i=-40; i<400; i+=1) {
      float u = 1.*i/450;
      //middle
      stroke(b);
      int icolor=0;
      //inside
      if( random(1) > u ) { stroke(a);  icolor=1; }
      //outside
      else if( random(1) < u*u ) { stroke(c);  icolor=2; }
      if( icolor == ipass )
        drawCircle(i,i+100);
    }
    save("image-"+(frameCount%repeatCount)+"-"+ipass+".png");
  }
}

For a plotter, I imagine you’d want SVG and I don’t know how to deal with those.