Wave displaced circle

Hi guys,

I’m trying to replicate this animation in processing :

But I can’t figure out how to do it, this is my code :

Circle c1,c2;

void setup() {
  size(800, 800);
  
  c1 = new Circle(0,0,200,0);
  c2 = new Circle(0,0,200,HALF_PI);
}

void draw() {
  background(0);
  translate(width/2,height/2);
  
  c1.display();
  c2.display();
  
  c1.update();
  c2.update();
}


class Circle{
  int x,y,radius;
  float angle, angle_sin;
  
  Circle(int xx, int yy, int rad, float angle_start){
    x = xx;
    y = yy;
    radius = rad;
    angle = 0;
    angle_sin = angle_start;
  }
  
  void display(){
    noFill();
    stroke(255);
    strokeWeight(3);
    
    beginShape();
    
    for(float a = 0; a<TWO_PI;a+=0.01){
      float val = map(abs(a-angle),0,HALF_PI,50,0);
      float rad = radius + cos(angle_sin*4)*val;
      curveVertex(cos(a)*rad,sin(a)*rad);
    }
    endShape(CLOSE);
  }
  
  void update(){
    angle += 0.01;
    angle_sin += 0.02;
  }
}

I have a variable angle that controls the rotation of the circle and a angle_sin variable that controls the variation of the sin wave.

Thanks

Not the final product, but almost…

I put something a bit much but hopefully you can see my approach to arrive to the final product.

First I experiment with the frequency of the wave. For this I generate three waves at three different levels in my screen that spans along the full width of the screen.

Then I draw a circle.

Last I mix the frequency of interest in the first part with my green circle. The end result is the purplish circle.

The key here is that after I am able to create a sine wave along the width of the screen, then I want to map the x values to the full revolution of my circle:

x : range(0..width)     =>  range(0..TWO_PI)

So for every x in the wavy line, I take its amplitude and I mix it with the circle’s point at an angle theta. Notice that x and theta are now connected bc of my prev line. The mixing happens with cx0, cy0, dx0, dy0.

Kf

//REFERENCE: https://forum.processing.org/two/discussion/26716/how-can-i-code-this-animation-in-processing  
//REFERENCE: htps://processing.org/examples/sinewave.html


int xspacing = 9;   // How far apart should each horizontal location be spaced
int w;              // Width of entire wave

float theta = 0.0;  // Start angle at 0
float amplitude = 15.0;  // Height of wave
float period = 500.0;  // How many pixels before the wave repeats
float dx;  // Value for incrementing X, a function of period and xspacing
float[] yvalues;  // Using an array to store height values for the wave

float[] yvalueslow;
float[] yvaluesmed;
float[] yvalueshigh;

void setup() {
  size(640, 360);
  w = width+16;
  dx = (TWO_PI / period) * xspacing;
  yvalues = new float[w/xspacing];
  yvalueslow = new float[w/xspacing];
  yvaluesmed = new float[w/xspacing];
  yvalueshigh = new float[w/xspacing];
}

void draw() {
  background(0);
  calcWave();
  renderWave();
}

void calcWave() {
  // Increment theta (try different values for 'angular velocity' here
  theta += 0.02;

  // For every x value, calculate a y value with sine function
  float x = theta;
  for (int i = 0; i < yvalues.length; i++) {
    yvalues[i] = sin(x)*amplitude;

    float xx=map(x, 0, yvalues.length, 0, TWO_PI);
    yvalueslow[i] = sin(xx*100)*amplitude;
    yvaluesmed[i] = sin(xx*50)*amplitude;
    yvalueshigh[i] = sin(xx*20)*amplitude;
    x+=dx;
  }
}

void renderWave() {
  noStroke();

  // A simple way to draw the wave with an ellipse at each location
  for (int x = 0; x < yvalues.length; x++) {

    float xval=x*xspacing;


    //Draw three lines with different frequency spanning the 
    //  width of the screen, at three different heights

    fill(120);
    ellipse(xval, height*0.25+yvalueslow[x], 10, 10);

    fill(190);
    ellipse(xval, height*0.5+yvaluesmed[x], 12, 12);

    fill(240);
    ellipse(xval, height*0.75+yvalueshigh[x], 16, 16);

    //draw a static green circle
    fill(0, 255, 0);
    float ca=map(x, 0, yvalues.length, 0, TWO_PI);
    float cx=10*amplitude*cos(ca);
    float cy=10*amplitude*sin(ca);
    ellipse(cx+width/2, cy+height/2, 5, 5);

    //draw a wavy purpulish circle
    fill(220, 0, 200);
    float ca0=map(x, 0, yvalues.length, 0, TWO_PI);
    float cx0=10*amplitude*cos(ca);
    float cy0=10*amplitude*sin(ca);
    float dx0=yvalueslow[x]*cos(ca);
    float dy0=yvalueslow[x]*sin(ca);
    ellipse(cx0+dx0+width/2, cy0+dy0+height/2, 5, 5);
  }
}

Keyword: kf_keyword wavy_circle wave_effect frequency

1 Like

Thanks for you answer, this is what I did :

But there’s a bug and it doesn’t work quite well.
Another problem is closing the curveVertex shape.

The code :

Circle c1,c2;

void setup() {
  size(800, 800);
  
  c1 = new Circle(0,0,200,0);
  c2 = new Circle(0,0,200,PI);
}

void draw() {
  background(0);
  translate(width/2,height/2);
  
  c1.display();
  c2.display();
  
  c1.update();
  c2.update();
}


class Circle{
  int x,y,radius;
  float angle, angle_sin;
  
  Circle(int xx, int yy, int rad, float angle_start){
    x = xx;
    y = yy;
    radius = rad;
    angle = 0;
    angle_sin = angle_start;
  }
  
  void display(){
    noFill();
    stroke(255);
    strokeWeight(3);
    
    beginShape();
    
    for(float a = 0; a<=TWO_PI;a+=0.01){
      float val = map(abs(a-angle),0,TWO_PI,40,0);
      float rad = radius + cos(angle_sin*3)*val;
      curveVertex(cos(a)*rad,sin(a)*rad);
      angle_sin += 0.02;
    }
    endShape(CLOSE);
  }
  
  void update(){
    angle += 0.01;
    if(angle>TWO_PI){
      angle = 0;
    }
  }
}
1 Like

Here’s my take on it


WaveCircle circ1, circ2;

void setup() {
  size(400, 400, P3D);
  circ1 = new WaveCircle();
  circ2 = new WaveCircle();
}

float radDist(float t1, float t2) {
  while (t1>=TWO_PI) t1-= TWO_PI;
  while (t1<0) t1 += TWO_PI;

  while (t2>=TWO_PI) t2-= TWO_PI;
  while (t2<0) t2 += TWO_PI;

  float d = abs(t1-t2);
  if (d>=PI) {
    d = PI-(d-PI);
  }
  return d;
}

float inc = 0.01;
float circSize = 100;
float distortSize = 1.0;
int freq = 20;

float z =0;
float s = 0;
void draw() {

  inc = 0.01;
  circSize = 100;
  distortSize = 1.0;
  freq = 10;

  strokeWeight(2);
  s += 0.003;
  //if (s >= TWO_PI) s -= TWO_PI;

  float speed = 0.05;

  z += speed;
  if (z >= TWO_PI) z-= TWO_PI;

  clear();
  circ1.draw(z, 1);
  circ2.draw(z+0.0, -1);

  saveFrame("gif/####.png");
}

class WaveCircle {


  WaveCircle() {
  }

  void draw(float z, float q) {
    pushMatrix();
    noFill();
    stroke(255);
    beginShape();

    translate(2*circSize, 2*circSize);
    for (float i = 0; i <= TWO_PI; i+=inc) {
      float rad = circSize;
      float dist  = pow(radDist(i, z), 2.0);
      rad += q*distortSize*dist*sin(i*freq);
      vertex(rad*sin(i+s), rad*cos(i+s));
    }
    endShape();
    popMatrix();
  }
}

wave

1 Like

Good job !

I was stuck on this part :

float radDist(float t1, float t2) {
  while (t1>=TWO_PI) t1-= TWO_PI;
  while (t1<0) t1 += TWO_PI;

  while (t2>=TWO_PI) t2-= TWO_PI;
  while (t2<0) t2 += TWO_PI;

  float d = abs(t1-t2);
  if (d>=PI) {
    d = PI-(d-PI);
  }
  return d;
}

Thanks @lmccandless @kfrajer