Help with specific Vector Addition

Hi,
I have a sketch where a mover moves along a sinusoidal path. From that mover two vectors emerge.
Vector A rotating in the direction of the path. Vector B pointing at a position at the bottom center of the canvas.

No I try to get the vector addition of A+B but somehow the result is not what I expect.
This is how it currently looks:


The result I get is way to long and when you let the sketch run it seems to be out of place too. Shouldn’t the resulting Vector of A+B always be positioned between A and B?

Here is how I expect it should look if executed correctly:

I guess I screwed something with the order or the fact that some parts are rotating and some not…

I’d appreciate any help or feedback on this!
Here is my code:

let anglex = 0;
let angley = 0;
let y = 0;
let x = 0;
let mover;

function setup() {
  createCanvas(600, 400);
  //  angleMode(DEGREES);
  angley = 0;
  anglex = 0;
  angley1 = 0;
  anglex1 = 0;
}

function draw() {
  background(0);
  mover = new Mover(x, y);
  fill(252, 238, 33);
  stroke(252, 238, 33);
  beginShape();
  y = map(sin(angley), -1, 1, 0, 200);
  x = map(sin(anglex), -1, 1, 0, 600);
  strokeWeight(4);
  angley += 0.1;
  anglex += 0.01;
  endShape();
  mover.update();
  mover.display();
}

class Mover {
  constructor(x, y) {
    this.position = createVector();
    this.velocity = createVector(x, y);
    this.r = 20;
    this.speed = 50;
  }

  update() {
    this.position.add(this.velocity);
  }

  display() {
    //Fixed Listener Position
    let listener = createVector(300, 400);
    fill(0, 255, 255);
    noStroke();
    ellipse(listener.x, listener.y, 20);

    //Mover
    stroke(50, 200, 50);
    noFill();
    ellipse(this.position.x, this.position.y, this.r);

    push();
    translate(this.position.x, this.position.y);

    //Vector Mover to Listener (Air Speed)
    let airspeed = p5.Vector.sub(listener, this.position);
    airspeed.setMag(100);
    stroke(0, 255, 255);
    line(0, 0, airspeed.x, airspeed.y);

    //Rotating Speed Vector
    let direction = map(sin(angley), -1, 1, PI, PI / 2);
    rotate(direction);
    let speedmag = createVector(50, 50);
    speedmag.setMag(100);
    let speedvector = p5.Vector.sub(this.position, speedmag);
    stroke(255, 0, 255);
    line(0, 0, speedmag.x, speedmag.y);

    //??Final Speed Vector (How to get a correct Vector addition here?)
    stroke(0, 255, 0);
    strokeWeight(1);
    let finalspeed = p5.Vector.add(speedvector, airspeed);
    line(0, 0, finalspeed.x, finalspeed.y);

    pop();
  }
}

Hello @Tilman,

I cooked this up quickly for the last post that you deleted.
It points in the direction you are heading… last point to current point is the direction.

// Vector Direction
// v1.0.0
// GLV 2022-10-01

// Rough code only!

//Global Variables
PVector vNow, vLast, vLine;
float x, y;

// Runs once
void setup() 
  {
  size(600, 400);
  vNow = new PVector(0, height/2);
  vLast = new PVector(0, 0);
  vLine = new PVector(0, 0); 
  x = 0;
  frameRate(10);
  }

// Loops at frameRate
void draw()
  {
  background(255);
  y = 150*sin((frameCount%60)*TAU/60) + height/2;
  x+=10;
  vNow.set(x, y);
  stroke(0);

  // Line from last point to current point
  line(vLast.x, vLast.y, vNow.x, vNow.y);
  
  // Using PVectors
  vLine = vNow.copy();
  vLine.sub(vLast).normalize().mult(50).add(vNow);
  stroke(0, 255, 0);
  line(vNow.x, vNow.y, vLine.x, vLine.y);
  
  stroke(255, 0, 0);
  strokeWeight(2);
  noFill();
  circle(x, y, 20);
  vLast.set(vNow.x, vNow.y);
  if (x>width) x = 0;
  }
  

It is in Processing Java… it may give you some insight.

References:

A p5.js example of vector addition and subtraction:

let v1 ;
let v2;
let vt;
let toggle = false;

function setup() {
createCanvas(300, 300);
  
v1 = createVector(50, 100);
v2 = createVector(100, 50);
vt = createVector(0, 0);        // temporary vector
}

function draw() 
  {
  background(255);
  translate(width/2, height/2);
  
  v1.set(50, 100);
  v2.set(100, 50);
  vt.set(0, 0);  
    
  strokeWeight(2);
  stroke(255, 0, 0);
  line(0, 0, v1.x, v1.y);
  stroke(0, 255, 0);
  line(0, 0, v2.x, v2.y);
  
  vt = v1.copy();
  vt.add(v2);
  
  stroke(0, 255, 255);
  line(0, 0, vt.x, vt.y);
  
  if(!toggle)
    {
    vt = v1.copy();
    vt.sub(v2);
    
    stroke(0, 0, 255);
    line(0, 0, vt.x, vt.y);
    }
  
    else
    {  
    vt = v1.copy();
    vt.sub(v2);
    vt.add(v2);
    stroke(0, 0, 255);
    line(v2.x, v2.y, vt.x, vt.y);
    
    vt = v1.copy();
    vt.add(v2);
    stroke(255, 0, 0);
    line(v2.x, v2.y, vt.x, vt.y);
    }
  
  strokeWeight(1);
  textAlign(CENTER);
  text("0, 0", 0, -5)
  }

function keyPressed()
  {
  toggle = !toggle;
  }

I wrote this quickly… I always write snippets of test code to help understand different elements of code.

:)

2 Likes

Thanks so much! @glv this really helps and opens my eyes simultaneously. I adapted everything for p5.js and will my progress later.

1 Like

@glv
I ported everything successfully to p5.js but struggle with the final vector addition. I double triple checked and seem to do everything as in your p5 example but must be missing something. The magnitude of the vector addition is way too long. But both vectors have only a magnitude of 50 so the addition should never exceed 100, correct? So the green Vector is way too long and should always be correctly placed evenly between the blue- and red vector. Correct?

I am missing some detail…

p5.js

//PVector vNow, vLast, vLine;
let x = 0;
let y = 0;
let vNow = 0;
let vLast = 0;
let xl = 0;
let yl = 0;
let vListener;
let objectspeed;
let airspeed;
let totalspeed;

// Runs once
function setup() {
  createCanvas(1200, 400);
  vNow = createVector(0, height / 2);
  vLast = createVector(0, 0);
  vLine = createVector(0, 0);
  vListener = createVector(0, 0);
  airspeed = createVector(0, 0);
  totalspeed = createVector(0, 0);
  objectspeed = createVector(0, 0);
  frameRate(30);
}

// Loops at frameRate
function draw(){
  background(255);
  xl = 600;
  yl = 400;
  
  fill(0, 0, 255)
  noStroke();
  circle(xl, yl, 20)
  
  y = 150 * sin(((frameCount % 60) * TAU) / 60) + height / 2;
  x += 10;
  vNow.set(x,y);
  vListener.set(xl,yl)
  
  stroke(200);
  // Line from last point to current point
  line(vLast.x, vLast.y, vNow.x, vNow.y);
  //line(vNow.x,vNow.y,vListener.x,vListener.y);
  
  //Object Speed Vector
  objectSpeed = vNow.copy();
  objectSpeed.sub(vLast).normalize().mult(50).add(vNow);
  strokeWeight(5);
  stroke(255, 0, 0);
  line(vNow.x, vNow.y, objectSpeed.x, objectSpeed.y);
  
  //Air Speed Vector
  airspeed = vListener.copy();
  airspeed.sub(vLast).normalize().mult(50).add(vNow);
  stroke(0, 0, 255);
  line(vNow.x,vNow.y,airspeed.x,airspeed.y);
  
  totalspeed = objectSpeed.copy();
  totalspeed.add(airspeed);
  
  //Total Speed = Object + Air
  stroke(0, 255,0);
  line(vNow.x,vNow.y, totalspeed.x, totalspeed.y);


  stroke(255, 0, 0);
  strokeWeight(2);
  noFill();
  circle(x, y, 20);
  
  vLast.set(vNow.x, vNow.y);
  if (x > width) x = 0;
}

1 Like

@glv I think I got it!

 // vector calculation
  let totalspeed = p5.Vector.add(objSpeedV, airSpeedV);
  let magnitude = totalspeed.mag();
  totalspeed.add(vLast).normalize().mult(magnitude).add(vNow);
  stroke(0, 255, 0);
  line(vNow.x, vNow.y, totalspeed.x, totalspeed.y);

I don´t know why I had to normalize and multiply by its magnitude again. and I don´t know why, in this case, I had to add totalspeed**.add**(vLast) as for the other vectors it was sub… but this way the vector appeared somehow between the blue and red vector. But maybe the green addition vector is still not positioned correctly. Shouldn´t it be between the red and blue vector always? But it´s magnitude seems fine!

I hope this is all correct. I have to reread the vector chapters from NOC now :slight_smile:

The whole code:

//PVector vNow, vLast, vLine;
let x = 0;
let y = 0;
let vNow = 0;
let vLast = 0;
let xl = 0;
let yl = 0;
let vListener;
let objectspeed;
let airspeed;
let totalspeed;

// Runs once
function setup() {
  createCanvas(1200, 400);
  vNow = createVector(0, height / 2);
  vLast = createVector(0, 0);
  vLine = createVector(0, 0);
  vListener = createVector(0, 0);
  airspeed = createVector(0, 0);
  totalspeed = createVector(0, 0);
  objectspeed = createVector(0, 0);
  frameRate(30);
}

// Loops at frameRate
function draw() {
  background(255);
  xl = 600;
  yl = 400;

  fill(0, 0, 255);
  noStroke();
  circle(xl, yl, 20);

  y = 150 * sin(((frameCount % 60) * TAU) / 60) + height / 2;
  x += 10;
  vNow.set(x, y);
  vListener.set(xl, yl);

  stroke(200);
  // Line from last point to current point
  line(vLast.x, vLast.y, vNow.x, vNow.y);
  //line(vNow.x,vNow.y,vListener.x,vListener.y);

  //Object Speed Vector
  objectSpeed = vNow.copy();
  objectSpeed.sub(vLast).normalize().mult(50).add(vNow);
  strokeWeight(5);
  stroke(255, 0, 0);
  line(vNow.x, vNow.y, objectSpeed.x, objectSpeed.y);

  //Air Speed Vector
  airspeed = vListener.copy();
  airspeed.sub(vLast).normalize().mult(50).add(vNow);
  stroke(0, 0, 255);
  line(vNow.x, vNow.y, airspeed.x, airspeed.y);

  //totalspeed = objectSpeed.copy();
  let objSpeedV = p5.Vector.sub(objectSpeed, vNow);
  //print(objSpeedV.mag());
  let airSpeedV = p5.Vector.sub(airspeed, vNow);

  // vector calculation
  let totalspeed = p5.Vector.add(objSpeedV, airSpeedV);
  let magnitude = totalspeed.mag();
  totalspeed.add(vLast).normalize().mult(magnitude).add(vNow);
  stroke(0, 255, 0);
  line(vNow.x, vNow.y, totalspeed.x, totalspeed.y);

  stroke(255, 0, 0);
  strokeWeight(2);
  noFill();
  circle(x, y, 20);

  vLast.set(vNow.x, vNow.y);
  if (x > width) x = 0;
}

Thank you!!

1 Like

@glv sorry I hope I don´t bother with these requests…

The addition seems correct now BUT
I still struggle to make the vector addition vector to appear precisely between the two (blue, red) vectors:

//PVector vNow, vLast, vLine;
let x = 0;
let y = 0;
let vNow = 0;
let vLast = 0;
let xl = 0;
let yl = 0;
let vListener;
let objectspeed;
let airspeed;
let totalspeed;

// Runs once
function setup() {
  createCanvas(1200, 400);
  vNow = createVector(0, height / 2);
  vLast = createVector(0, 0);
  vLine = createVector(0, 0);
  vListener = createVector(0, 0);
  airspeed = createVector(0, 0);
  totalspeed = createVector(0, 0);
  objectspeed = createVector(0, 0);
  frameRate(30);
}

// Loops at frameRate
function draw() {
  background(255);
  xl = 600;
  yl = 400;

  fill(0, 0, 255);
  noStroke();
  circle(xl, yl, 20);

  //y = 150 * sin(((frameCount % 60) * TAU) / 60) + height / 2;
  y=150;
  x += 10;
  vNow.set(x, y);
  vListener.set(xl, yl);

  stroke(200);
  // Line from last point to current point
  line(vLast.x, vLast.y, vNow.x, vNow.y);
  //line(vNow.x,vNow.y,vListener.x,vListener.y);

  //Object Speed Vector
  objectSpeed = vNow.copy();
  objectSpeed.sub(vLast).normalize().mult(50).add(vNow);
  strokeWeight(5);
  stroke(255, 0, 0);
  line(vNow.x, vNow.y, objectSpeed.x, objectSpeed.y);

  //Air Speed Vector
  airspeed = vListener.copy();
  airspeed.sub(vLast).normalize().mult(50).add(vNow);
  stroke(0, 0, 255);
  line(vNow.x, vNow.y, airspeed.x, airspeed.y);

  //totalspeed = objectSpeed.copy();
  let objSpeedV = p5.Vector.sub(objectSpeed, vNow);
  //print(objSpeedV.mag());
  let airSpeedV = p5.Vector.sub(airspeed, vNow);

  // vector calculation
  let objectplusair = p5.Vector.add(airSpeedV,objSpeedV);

  let totalspeed = p5.Vector.sub(objectplusair,vNow);
  let magnitude = objectplusair.mag();
  totalspeed.sub(vLast).normalize().mult(magnitude).add(vNow);
  stroke(0, 255, 0);
  line(vNow.x,vNow.y,totalspeed.x,totalspeed.y);
  
  
  
  
  stroke(255, 0, 0);
  strokeWeight(2);
  noFill();
  circle(x, y, 20);

  vLast.set(vNow.x, vNow.y);
  if (x > width) x = 0;
  

}

1 Like

@glv
I finally got it!! Now I have to clean up the code
Thank you!

//PVector vNow, vLast, vLine;
let x = 0;
let y = 0;
let vNow = 0;
let vLast = 0;
let xl = 0;
let yl = 0;
let vListener;
let objectspeed;
let airspeed;
let totalspeed;

// Runs once
function setup() {
  createCanvas(1200, 400);
  vNow = createVector(0, height / 2);
  vLast = createVector(0, 0);
  vLine = createVector(0, 0);
  vListener = createVector(0, 0);
  airspeed = createVector(0, 0);
  totalspeed = createVector(0, 0);
  objectspeed = createVector(0, 0);
  frameRate(30);
}

// Loops at frameRate
function draw() {
  background(255);
  xl = 600;
  yl = 400;

  fill(0, 0, 255);
  noStroke();
  circle(xl, yl, 20);

  y = 150 * sin(((frameCount % 60) * TAU) / 60) + height / 2;
  //y = 150;
  x += 10;
  vNow.set(x, y);
  vListener.set(xl, yl);

  stroke(200);
  // Line from last point to current point
  line(vLast.x, vLast.y, vNow.x, vNow.y);
  //line(vNow.x,vNow.y,vListener.x,vListener.y);

  //Object Speed Vector
  objectSpeed = vNow.copy();
  objectSpeed.sub(vLast).normalize().mult(50).add(vNow);
  strokeWeight(5);
  stroke(255, 0, 0);
  line(vNow.x, vNow.y, objectSpeed.x, objectSpeed.y);

  //Air Speed Vector
  airspeed = vListener.copy();
  airspeed.sub(vLast).normalize().mult(50).add(vNow);
  stroke(0, 0, 255);
  line(vNow.x, vNow.y, airspeed.x, airspeed.y);

  let objectplusair = p5.Vector.add(objectSpeed, airspeed);
  let totalspeed = p5.Vector.sub(objectplusair, vNow);
  let magnitude = objectplusair.mag();
  objectplusair.sub(vLast).normalize().mult(magnitude).add(vNow);

  stroke(0, 255, 0);
  line(vNow.x, vNow.y, totalspeed.x, totalspeed.y);

  stroke(255, 0, 0);
  strokeWeight(2);
  noFill();
  circle(x, y, 20);

  vLast.set(vNow.x, vNow.y);
  if (x > width) x = 0;
}

1 Like