Help applying a sine wave through a series of points

edited July 2014 in Questions about Code

I have a circle and I'm trying to pass through a sine wave to make it look like its wobbling (if that makes sense) but I fail so I need your help :)

Here is what I have so far:

int numPoints = 10;
float radius = 100;
float theta = TWO_PI / numPoints;
PVector[] points = new PVector[numPoints];
PVector[] npoints = new PVector[numPoints];


void setup() {
  size(640, 480);
  rectMode(CENTER);

  for (int i = 0; i < numPoints; i++) {
    float px = cos(theta * i) * radius;
    float py = sin(theta * i) * radius;
    points[i] = new PVector(px, py);
    npoints[i] = new PVector(px, py);
  }
}

void draw() {
  background(0);

  pushMatrix();
  translate(width / 2, height / 2);
  noStroke();
  fill(255);
  for ( int i = 0; i < numPoints; i++) {
    PVector np = npoints[i];
    np.normalize();

    float sineSeed = (millis() / 100) + (points[i].y * 0.5);

    points[i].x += np.x * sin(sineSeed);
    points[i].y += np.y * sin(sineSeed);

    ellipse(points[i].x, points[i].y, 5, 5);
  }
  noFill();
  stroke(255, 0, 0);
  rect(0, 0, 150, 150);
  popMatrix();
}

If you run the code you will see how the dots at the top and bottom start to drop down, but I'm passing the sine values through the normalized points so they should stay in place but they are not so there is obviously something wrong that I cannot see...

Any help will be much appreciated

Tagged:

Answers

  • Answer ✓

    Instafixed. You either forgot, or didn't know, that the trigonometric functions (sin, cos, tan, etc.) use radians, and not degrees. Change line 31 to the following:

    float sineSeed = (millis() / 100) + (radians(points[i].y) * 0.5);
    

    -- MenteCode

  • Also, in case you wonder why the ellipses look a little off after applying the fix I provided, change the ellipseMode to CENTER. That's all.

  • edited July 2014

    It works better but the circle still drift upwards, not only that after a few seconds it starts to deform completely any ideas?

  • AHA! I've found your problem!

    In fact, radians() has nothing to do with the problem. Silly me.

    Now take a look at line 31 of your code, and realize that the PVectors in the points[] array are constantly changing. You are using a constantly changing array.

    Now for how easy the solution really was. It's mostly my fault for not noticing.

    Change the points[i] array in sineSeed to npoints[i]. That's it. Simple but disastrous.

  • I will warn you. You are gonna get wacky results if you change the millis() part of sineSeed to change any slower.

  • edited July 2014

    Thanks the change to npoints[] works fine but what is so "disastrous" about that?

    I would love to see how you approach this so is not so catastrophic as I did ;)

  • The change to impact ratio is drastic, which is why I say "disastrous."

  • Alright. Here's my alternative of your code:

    int particleCount = 10;
    float radius = 100;
    PVector center = new PVector(0, 0);
    PVector[] particles = new PVector[particleCount];
    
    void setup() {
      size(640, 480);
      noStroke();
      ellipseMode(CENTER);
      float theta = 0;
      for(int index = 0; theta < 360; theta += 360/particleCount, index++) {
        float x = sin(radians(theta)) * radius;
        float y = cos(radians(theta)) * radius;
        particles[index] = new PVector(x, y);
      }
    }
    
    void draw() {
      background(0);
      translate(width/2, height/2);
      for(PVector i : particles) {
        PVector custom = PVector.sub(center, i);
        custom.mult(sin(millis()/200f + i.y) * 0.1 + 1);
        ellipse(custom.x, custom.y, 10, 10);
      }
    }
    

    The difference between mine and yours is that mine doesn't rely as much on the millis() method to change position. Rather, it uses 2D version of linear interpolation. Much more stable. Play around with it. Things should be pretty self-explanatory.

Sign In or Register to comment.