确定从切线到椭圆的反射矢量
Determining reflection vector from tangent to ellipse
我在椭圆内部发射了一条光线,它需要反射出椭圆并继续在椭圆内部飞行。我发现最简单的方法可能是找到撞击点的切线向量,然后从那里计算反射角。
虽然我不确定如何在代码中实现它。
这是我目前所拥有的,我有以下函数绘制椭圆及其半长轴 (a) 和半短轴 (b)。 t 在更新函数中递增。
void drawEllipse(float t) {
float x = a * cos(t);
float y = b * sin(t);
PVector ellipseDotPosition = new PVector(x, y).add(ellipseCenter);
circle(ellipseDotPosition.x, ellipseDotPosition.y, 2);
}
我用这个函数判断光线是否发生碰撞:
boolean hasCollided(PVector pointToCheck) {
return pow((pointToCheck.x - ellipseCenter.x) / a, 2) +
pow((pointToCheck.y - ellipseCenter.y) / b, 2) > 1;
}
这是我尝试计算反射矢量的方法。
PVector getReflectionVector(PVector pointOfImpact) {
// Differentiate to get tangent to the collision point.
// PVector tangent = new PVector(-a / b * pointOfImpact.y, b / a * pointOfImpact.x);
// PVector tangent = new PVector(-(a * pointOfImpact.y / b), (b * pointOfImpact.x / a));
// circle(tangent.x, tangent.y, 10);
// Treat the tangent as the surface to be reflected off.
// Determine angle of reflection off the surface.
// Return reflection vector.
return new PVector();
}
我数学不好吗?是的。请帮助:)
根据 wikipedia 所说:
Analytically, the equation of a standard ellipse centered at the origin with width 2a and height 2b is:
其中,如果我们对其求导(即 returns 其在该点的切线)结果为:
导数只适用于以 (0, 0) 为中心的椭圆。
另请注意,如果 y = 0,您将获得异常。这是因为它会给出无穷大,因为切线是完全垂直的。
要将切线视为曲面,我们将执行代码中解释的以下步骤:
// OriginalRay will be the direction of the colliding ray.
// You may also define the origin as the last collision point.
PVector getReflectionVector(PVector pointOfImpact, PVector originalRay){
// Differentiate to get tangent to the collision point.
// atan() to get angle of tangent line from 0X
float tangentAngle;
if(pointOfImpact.y != 0){
float tangent = -1*pointOfImpact.x*sq(b)/(pointOfImpact.y*sq(a));
tangentAngle = atan(tangent);
}else{
tangentAngle = PI/2;
}
// Treat the tangent as the surface to be reflected off.
// Determine angle of reflection off the surface.
float rayAngle = atan2(originalRay.y, originalRay.x);
// We now transform the case as it had collided on an horizontal surfface to simplify.
//float tempRayAngle = rayAngle - tangentAngle;
// Calc the reflectionAngle
//float tempReflectionAngle = PI - tempRayAngle;
// And undo the transformation
//float newRayAngle = rayAngle - tempReflectionAngle;
float newRayAngle = 2*rayAngle - tangentAngle - PI; //End result
// Return reflection vector. (The direction vector with abs() = 1)
PVector reflectedRay = new PVector(cos(newRayAngle), sin(newRayAngle));
return reflectedRay;
}
我在椭圆内部发射了一条光线,它需要反射出椭圆并继续在椭圆内部飞行。我发现最简单的方法可能是找到撞击点的切线向量,然后从那里计算反射角。
虽然我不确定如何在代码中实现它。
这是我目前所拥有的,我有以下函数绘制椭圆及其半长轴 (a) 和半短轴 (b)。 t 在更新函数中递增。
void drawEllipse(float t) {
float x = a * cos(t);
float y = b * sin(t);
PVector ellipseDotPosition = new PVector(x, y).add(ellipseCenter);
circle(ellipseDotPosition.x, ellipseDotPosition.y, 2);
}
我用这个函数判断光线是否发生碰撞:
boolean hasCollided(PVector pointToCheck) {
return pow((pointToCheck.x - ellipseCenter.x) / a, 2) +
pow((pointToCheck.y - ellipseCenter.y) / b, 2) > 1;
}
这是我尝试计算反射矢量的方法。
PVector getReflectionVector(PVector pointOfImpact) {
// Differentiate to get tangent to the collision point.
// PVector tangent = new PVector(-a / b * pointOfImpact.y, b / a * pointOfImpact.x);
// PVector tangent = new PVector(-(a * pointOfImpact.y / b), (b * pointOfImpact.x / a));
// circle(tangent.x, tangent.y, 10);
// Treat the tangent as the surface to be reflected off.
// Determine angle of reflection off the surface.
// Return reflection vector.
return new PVector();
}
我数学不好吗?是的。请帮助:)
根据 wikipedia 所说:
Analytically, the equation of a standard ellipse centered at the origin with width 2a and height 2b is:
其中,如果我们对其求导(即 returns 其在该点的切线)结果为:
导数只适用于以 (0, 0) 为中心的椭圆。
另请注意,如果 y = 0,您将获得异常。这是因为它会给出无穷大,因为切线是完全垂直的。
要将切线视为曲面,我们将执行代码中解释的以下步骤:
// OriginalRay will be the direction of the colliding ray.
// You may also define the origin as the last collision point.
PVector getReflectionVector(PVector pointOfImpact, PVector originalRay){
// Differentiate to get tangent to the collision point.
// atan() to get angle of tangent line from 0X
float tangentAngle;
if(pointOfImpact.y != 0){
float tangent = -1*pointOfImpact.x*sq(b)/(pointOfImpact.y*sq(a));
tangentAngle = atan(tangent);
}else{
tangentAngle = PI/2;
}
// Treat the tangent as the surface to be reflected off.
// Determine angle of reflection off the surface.
float rayAngle = atan2(originalRay.y, originalRay.x);
// We now transform the case as it had collided on an horizontal surfface to simplify.
//float tempRayAngle = rayAngle - tangentAngle;
// Calc the reflectionAngle
//float tempReflectionAngle = PI - tempRayAngle;
// And undo the transformation
//float newRayAngle = rayAngle - tempReflectionAngle;
float newRayAngle = 2*rayAngle - tangentAngle - PI; //End result
// Return reflection vector. (The direction vector with abs() = 1)
PVector reflectedRay = new PVector(cos(newRayAngle), sin(newRayAngle));
return reflectedRay;
}