Joshua Garcia
Joshua Garcia

Reputation: 87

Concentric ring of ellipses

I'm trying to recreate an array of increasing sized circles that each are being divided to create points to create ellipses that pulsate. I know how to divide each circle by a num of points and draw ellipses. And I know how to create a series of concentric circles, but I can't seem to wrap my mind around putting them together. When I do, I receive a result that looks like this..

Circle Overlap

This result is happening because each individual ellipse is adding a number of ellipses in increasing distances from the original ellipse. Nevertheless, I'm not sure how to fix the original issue of having a series of circles divided by a number of points to create ellipses.

Thanks.

Blackhole b;

void setup() {
  size(750, 500);
  smooth();
  b = new Blackhole();
}

void draw() {
  b.divide();
  b.display();

}

class Blackhole {
  PVector location;
  PVector velocity;
  PVector acceleration;
  PVector center;
  float speed = 0;

  int [] eSize = {0, 25, 50, 75, 100, 125, 150, 175};
  float radius = 100;
  int numPoints = 16;
  float angle = TWO_PI/(float)numPoints;
  float [] [] xyArray;

  Blackhole() {
    location = new PVector(width/2, height/2);
    velocity = new PVector(0, 0);
    acceleration = new PVector(.0, 0);
  }

  void divide() {
    xyArray = new float [numPoints][3]; 
    for (int i=0; i<numPoints; i++) { 
      float x = radius*sin(angle*i)+width/2;
      float y = radius*cos(angle*i)+height/2;
      xyArray[i][0] = x; 
      xyArray[i][1] = y;
    }
   }



  void display() {
    background(#202020);


    speed = speed + 0.05;
    float pulse = noise(speed);
    pulse = map(pulse, 0, 1, 150, 175);

    noFill();
    stroke(255, 100);
     for ( int j = 0; j < eSize.length; j++) {
      for ( int i = 0; i < numPoints; i++) {
        float x = xyArray[i][0];
         float y = xyArray[i][1];
         ellipse(width/2, height/2, pulse + eSize[j], pulse + eSize[j]);
         ellipse(x, y, 5, 5);
       }
     }
   }
 }

Upvotes: 1

Views: 562

Answers (1)

George Profenza
George Profenza

Reputation: 51837

Drawing a circle of circles shouldn't be complicated and you already understand how to the polar to cartesian coordinate system conversion. Something as simple as this would work:

/*
    draws a large circle with each vertex drawn as a smaller circle
    sides = circle detail, the more sides, the more detaild the circle will be
    largeRadius = large circle radius
    smallRadius = radius of each small circle
*/
void circleOfCircles(int sides,float largeRadius, float smallRadius){
  float angleIncrement = TWO_PI / sides;
  for(int i = 0 ; i < sides; i++){
    float x = cos(angleIncrement * i) * largeRadius;
    float y = sin(angleIncrement * i) * largeRadius;
    ellipse(x,y,smallRadius,smallRadius);
  }
}

Which using your values would look like this:

float speed = 0;
int [] eSize = {0, 25, 50, 75, 100, 125, 150, 175};
float radius = 100;
int numPoints = 16;


void setup(){
  size(750,500);
  smooth();
}
void draw(){
  background(#202020);
  translate(width * 0.5, height * 0.5);

  speed = speed + 0.05;
  float pulse = noise(speed);
  pulse = map(pulse, 0.0, 1.0, 150, 175);

  noFill();
  stroke(255, 100);
   for ( int j = 0; j < eSize.length; j++) {
     circleOfCircles(numPoints,pulse + eSize[j], 5);
   }
}
/*
    draws a large circle with each vertex drawn as a smaller circle
    sides = circle detail, the more sides, the more detaild the circle will be
    largeRadius = large circle radius
    smallRadius = radius of each small circle
*/
void circleOfCircles(int sides,float largeRadius, float smallRadius){
  float angleIncrement = TWO_PI / sides;
  for(int i = 0 ; i < sides; i++){
    float x = cos(angleIncrement * i) * largeRadius;
    float y = sin(angleIncrement * i) * largeRadius;
    ellipse(x,y,smallRadius,smallRadius);
  }
}

If the polar to cartesian conversion is confusing, you can simply isolate transformations using pushMatrix() and popMatrix():

void circleOfCircles(int sides,float largeRadius, float smallRadius){
  float angleIncrement = TWO_PI / sides;
  for(int i = 0 ; i < sides; i++){
    pushMatrix();
      rotate(angleIncrement * i);
      translate(largeRadius,0);
      ellipse(0,0,smallRadius,smallRadius);
    popMatrix();
  }
}

Generally it's best to keep things are simple as possible. You are using a class and that's great! It's good to encapsulate functionality. It will make it easier to plug into other sketches in the future.

However, I there are some unused variables in your class:

PVector location;
  PVector velocity;
  PVector acceleration;
  PVector center;

Some of these are initialised in the constructor, but never used again.

The main issue in terms of drawing circles of circles is around the divide() and xyArray. In divide() you are computing points around a circle with a single radius, although in display() it looks like you want to use varying radii. I've removed the divide() function which removed the need to use the xyArray and loop over it twice (once to set positions, then to read it). Notice instead of radius, pulseRadius is used now which takes pulse and eSize into account.

Here is a simplified version of your code using radius, but also pulse and eSize which is probably what you were trying to do:

Blackhole b;

void setup() {
  size(750, 500);
  smooth();
  b = new Blackhole();
}

void draw() {
  background(#202020);
  b.display();
}

class Blackhole {
  float speed = 0;

  int [] eSize = {0, 25, 50, 75, 100, 125, 150, 175};
  float radius = 100;
  int numPoints = 16;
  float angle = TWO_PI/(float)numPoints;

  Blackhole() {

  }

  void display() {

    speed = speed + 0.05;
    float pulse = noise(speed);
    pulse = map(pulse, 0, 1, 150, 175);

    noFill();
    stroke(255, 100);
     for ( int j = 0; j < eSize.length; j++) {
      for ( int i = 0; i < numPoints; i++) {

        float pulseRadius = radius + pulse + eSize[j];
        float x = pulseRadius * sin(angle*i)+width/2;
        float y = pulseRadius * cos(angle*i)+height/2;
        ellipse(x, y, 5, 5);
       }
     }
   }
 }

Just as an exploration, here is a javascript demo of the code using a function and sine calls to vary the number of points in the large circle and the two radii.

int numPoints = 16;


void setup(){
  size(750,500);
  smooth();
  noFill();
}
void draw(){
  background(#202020);
  translate(width * 0.5, height * 0.5);

  for(int i = 0 ; i < numPoints; i++){
    stroke(255, (i+1) * 10);
    circleOfCircles((int)map(sin(frameCount * .001 + i),-1.0,1.0,12 , 64),//number of sides
                         map(sin(frameCount * .010 + i),-1.0,1.0,100,225),//large radius
                         map(sin(frameCount * .100 + i),-1.0,1.0,  1, 30));//small radius
  }
}
/*
    draws a large circle with each vertex drawn as a smaller circle
    sides = circle detail, the more sides, the more detaild the circle will be
    largeRadius = large circle radius
    smallRadius = radius of each small circle
*/
void circleOfCircles(int sides,float largeRadius, float smallRadius){
  float angleIncrement = TWO_PI / sides;
  for(int i = 0 ; i < sides; i++){
    pushMatrix();
      rotate(angleIncrement * i);
      translate(largeRadius,0);
      ellipse(0,0,smallRadius,smallRadius);
    popMatrix();
  }
}

circles animation preview

Have fun!

Upvotes: 1

Related Questions