Search code examples
javascriptvectorangle

Calculating the angle between a velocity (particles motion) and a line


So I am creating a simulation of a bouncing ball, and the user can place lines the ball can collide with on the canvas by dragging from one point to another. There are essentially four lines that can be created:

Four line options, with their respective save points in an object.

So the object that stores a line is defined as such:

export interface pathSection {
    xfrom: number;
    yfrom: number;
    xto: number;
    yto: number;
    length: number;
}

The first and third lines in the image for example dont give the same value from

Math.atan2(yto - yfrom, xto - from);

So given the (relative) complexity of the surfaces, I need to find the angle between a moving object and that surface at the point of collision:

ballstrike

The ball strikes the surface at an angle a, which is what I want!

However I am having trouble finding the angle between the two vectors. This is what I understood would work:

var dx = this.path[index_for_path_section].xfrom - this.path[index_for_path_section].xto;
var dy = this.path[index_for_path_section].yfrom - this.path[index_for_path_section].yto;
var posX = this.particle.pos.x;
var posY = this.particle.pos.y;
var posNextX = posX + this.particle.v.x;
var posNextY = posY + this.particle.v.y;

var angleOfRamp = Math.atan2(dy, dx);
var angleOfvelocity = Math.atan2(posNextY - posY, posNextX - posX);
var angleBetween =  angleOfRamp - angleOfvelocity;

This is then used to calculate the speed of the object after the collision:

var spd = Math.sqrt(this.particle.v.x * this.particle.v.x + this.particle.v.y * this.particle.v.y);
var restitution = this.elasticity / 100;

this.particle.v.x = restitution * spd * Math.cos(angleBetween);
this.particle.v.y = restitution * spd * Math.sin(angleBetween);

However the angle calculated is around -4.5 Pi, about -90 degrees for the object directly down and the surface at what looks to be around 45-60 degrees…

demo picture

The red arrow shows the path of the object moving through the surface - the white dots show where a collision has been detected between the surface and the object.

Any help on how to get the correct and usable angle between the two velocity and the line would be appreciated!

Note I have tried utilizing this solution, but have struggled to adapt it to my own work.


Solution

  • So it took me some time, and I am not 100% sure still of why it works because I think im finding the JavaScript angles system a bit tricky, but:

    var dx = this.path[collided].xfrom - this.path[collided].xto;
    var dy = this.path[collided].yfrom - this.path[collided].yto;
    var spd = Math.sqrt(this.particle.v.x * this.particle.v.x + this.particle.v.y * this.particle.v.y);
                     
    var angleOfRamp = Math.atan2(dy, dx);
    var angleOfvelocity = Math.atan2(this.particle.v.y, this.particle.v.x);
    var angleBetween =  angleOfRamp * 2 - angleOfvelocity; // not sure why :)
    
    if (angleBetween < 0) { angleBetween += 2*Math.PI; } // not sure why :)
                     
    const restitution = this.elasticity / 100;
    
    this.particle.v.x = restitution * spd * Math.cos(angleBetween);
    this.particle.v.y = restitution * spd * Math.sin(angleBetween);
    

    Thanks to all who looked :)