#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# How do I create sinusoidal movement at an angle?

edited September 2014

This one's been eating away at me! Seems so simple but I can't get it to work. So if I have a particle traveling at 3 pixels per frame at a 60 degree angle away from the center point of the sketch, the code looks something like this (this is a simplified version):

``````stroke(255);
float velocity = 3;
float angle = 60;
PVector position = (width/2, height/2);

void draw() {
background(0);
position.x += cos(angle) * velocity;
position.y += sin(angle) * velocity;
point(position.x, position.y);
}
``````

However, when I try to make the particle oscillate up and down at right angles from the current trajectory, I can't seem to make it work! This is what I tried. It seemed to make sense but it doesn't give me a proper sine wave:

``````stroke(255);
float velocity = 3;
float angle = 60;
float t = 0; // Time
float amplitude = 20; // Amplitude of sine wave
PVector position = (width/2, height/2);

void draw() {
background(0);
position.x += cos(angle) * velocity;
position.y += sin(angle) * velocity;
position.x += (cos(angle +90)) * sin(t) * amplitude;
position.y += (sin(angle +90)) * sin(t) * amplitude;
point(position.x, position.y);
}
``````

My math skills aren't the best, so I'm hoping I'm missing something basic and that an intelligent forum-goer can assist me! Thank you in advance!

Tagged:

"this is a simplified version"
It wouldn't take much more work to make a "runnable" version...

``````float velocity = 3;
float angle = 60;
PVector position;

void setup()
{
size(800, 800);
stroke(255);
position = new PVector(width/2, height/2);
}

void draw()
{
background(0);
position.x += cos(angle) * velocity;
position.y += sin(angle) * velocity;
point(position.x, position.y);
}
``````

If I understand correctly your request, you must add an orthogonal vector to the current position of the vector.

``````float velocity = 1;
float angle = 60;
float t = 0; // Time
float amplitude = 20; // Amplitude of sine wave
PVector center, position;

void setup()
{
size(800, 800);
stroke(255);
center = new PVector(width/2, height/2);
position = center.get();
}

void draw()
{
background(0);
position.x += cos(angle) * velocity;
position.y += sin(angle) * velocity;
PVector a = perpendicular(PVector.sub(position, center, null));
a.normalize();
a.mult(sin(t) * amplitude);
point(position.x + a.x, position.y + a.y);
t += PI / 12;
println("--");
}

PVector perpendicular(PVector v)
{
return new PVector(-v.y, v.x);
}
``````
• edited September 2014

I've refactored @PhiLho's example for better performance! :ar!

``````// forum.processing.org/two/discussion/7103/
// how-do-i-create-sinusoidal-movement-at-an-angle

// by Hendeca, mods PhiLho & GoToLoop - 2014/Sep

static final float VEL = 1.5, ANG = 60.0, AMP = 30.0;
static final float VEL_X = VEL*cos(ANG), VEL_Y = VEL*sin(ANG);
float t;

final PVector center  = new PVector(), pos = new PVector();
final PVector perpend = new PVector();

void setup() {
size(600, 400, JAVA2D);
smooth(4);
frameRate(60);

strokeWeight(4);
stroke(-1);

center.set(width, height*.75);
}

void draw() {
if (pos.x<0 | pos.y<0)  pos.set(center);

PVector.sub(pos, center, perpend).set(-perpend.y, perpend.x);
perpend.setMag(AMP*sin(t += PI/12.0));

background(0);
point(pos.x+perpend.x, pos.y+perpend.y);
}
``````
• Thank you both very much! I have yet to implement your code, but I worked it out on paper and I'm very impressed by the elegance of it! Didn't think of that as a way to get the perpendicular velocity vector.

I am still a bit curious, however, as to why the calculation I did didn't work. Essentially I did the same calculation I did to the Particle's velocity vector, but using the amplitude instead of velocity and using the angle of the Particle + 90 degrees. Just wondering if anyone knows why that didn't work.

Thank you for this solution! Going to try to implement it now!

• edited September 2014

Outta curiosity's sake, converted the example to http://p5js.org "mode":
Very disappointed b/c I can't specify a whole RGB value & Vector there doesn't have a 3rd "target" parameter!

``````// forum.processing.org/two/discussion/7103/
// how-do-i-create-sinusoidal-movement-at-an-angle

// by Hendeca, mods PhiLho & GoToLoop - 2014/Sep

var VEL = 1.5, ANG = 60, AMP = 30, STEP = PI/12;
var VEL_X = VEL*cos(ANG), VEL_Y = VEL*sin(ANG);
var t = 0;

var center  = createVector(), pos = createVector();
var perpend = createVector();

function setup() {
createCanvas(600, 400);
smooth(4).frameRate(60).strokeWeight(4).stroke(255);
center.set(width, height*.75);
}

function draw() {
if (pos.x<0 | pos.y<0)  pos.set(center);

perpend.set(pos).sub(center)
.set(-perpend.y, perpend.x)
.setMag(AMP*sin(t += STEP));

background(0);
point(pos.x+perpend.x, pos.y+perpend.y);
}
``````
• I'd say that your first problem was that you were trying to use degrees (60, 90) in the trig functions when they are expecting radians.

• edited September 2014

Just for completeness' sake, same code now in "CoffeeScript Mode": :>

``````# forum.processing.org/two/discussion/7103/
# how-do-i-create-sinusoidal-movement-at-an-ang

# by Hendeca, mods PhiLho & GoToLoop - 2014/Sep

VEL = 1.5; ANG = 60; AMP = 30; STEP = Processing::PI/12
VEL_X = VEL*Math.cos ANG; VEL_Y = VEL*Math.sin ANG
t = 0

center  = new Processing::PVector; pos = new Processing::PVector
perpend = new Processing::PVector

setup: ->

size 600, 400, JAVA2D; smooth 4; frameRate 60
strokeWeight 4; stroke -1

center.set width, height*.75, 0

draw: ->

pos.add VEL_X, VEL_Y, 0
pos.set center  if pos.x<0 | pos.y<0

perpend.set pos; perpend.sub center
perpend.set -perpend.y, perpend.x, 0
do perpend.normalize; perpend.mult AMP*sin t += STEP

background 0
point pos.x+perpend.x, pos.y+perpend.y
``````
• "for better performance"
Very funny. :-)

Anyway, good idea to use setMag in place of normalize() and mult() sequence.

• edited September 2014

HEHE! I still had to use normalize() + mult() in "CoffeeScript Mode".
B/c the processing.js v1.4.1 it's based upon doesn't have setMag()! :(
And neither p5js nor "JS & CS Modes" got PVector methods w/ a 3rd "target" parameter! X(

• If I understand correctly your request, you must add an orthogonal vector to the current position of the vector.

Thanks PhiLho! Your solution worked for me :] Very elegant! It makes a lot of sense and is much simpler than what I was doing before. Thanks also to GoToLoop for offering some changes and alternatives. Really appreciate your help! I got the sinusoidal movement working very quickly once I understood the concept of creating a perpendicular vector, normalizing it, and multiplying it by the velocity. This also works well with the code I had before in that I wasn't using a PVector for my velocity value but rather just a float value that can be applied to the angle of the particle.

I haven't taken the time to try the other versions of the code that GoToLoop offered, but I'd like to look through them more when I finish my current project! Thank you!

• edited September 2014

I haven't taken the time to try the other versions of the code that GoToLoop offered,...

For the p5js example, you can go to http://p5js.org/reference/, choose some of its reference functions,
like http://p5js.org/reference/#/p5/alpha for example, click the "edit" button and paste the code there,
replacing the original. Then click at "run" button and watch it working inside your browser! (*)

For the CS latest example, you gotta install "CoffeeScript Mode" from Processing's IDE. Choose "Add Mode...".
Select CS Mode and paste the code there. Make sure it's using a 2-space indentation.
Press Run and your default browser will open up and run your CS code compiled already as JS,
running from a local server provided by the IDE itself! :ar!