计算速度(粒子运动)和直线之间的角度

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

所以我正在创建一个弹跳球的模拟,用户可以通过从一个点拖动到另一个点来在 canvas 上放置球可以碰撞的线。基本上可以创建四行:

所以存储一行的object是这样定义的:

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

例如,图像中的第一行和第三行与

给出的值不同
Math.atan2(yto - yfrom, xto - from);

鉴于表面的(相对)复杂性,我需要找到移动 object 与碰撞点的表面之间的角度:

球以角度a撞击表面,这就是我想要的!

但是我无法找到两个向量之间的角度。这是我所理解的可行的方法:

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;

然后用来计算碰撞后object的速度:

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);

然而,计算出的角度约为 -4.5 Pi,object 正下方约为 -90 度,表面看起来约为 45-60 度……

红色箭头显示 object 穿过表面的路径 - 白点显示在表面和 object 之间检测到碰撞的位置。

任何关于如何获得两个速度和线之间的正确和可用角度的帮助将不胜感激!

请注意,我已尝试 ,但很难使其适应我自己的工作。

所以我花了一些时间,我仍然不能 100% 确定它为什么有效,因为我认为我发现 JavaScript 角度系统有点棘手,但是:

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);

感谢所有看过的人:)