今日、以前、平面と非平行線の交点に問題があったことに気づき、前回のブログと関連しすぎたので、誤り訂正のために特別に記事を書きました。
こんな状況は今までに一度もなかったので、すごいとしか言いようがありません コードは以下の通りです。
/// <summary>
/// 计算两射线交点
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="p4"></param>
/// <param name="p3"></param>
/// <returns></returns>
private Vector2 CalculateLineCross(Vector2 p1, Vector2 p2, Vector2 p4, Vector2 p3)
{
//构建直线参数k和a
float k1 = (p2.y - p1.y) / (p2.x - p1.x);
float a1 = p2.y - k1 * p2.x;
float k2 = (p3.y - p4.y) / (p3.x - p4.x);
float a2 = p3.y - k2 * p3.x;
//根据求解计算交点
float y = (k2 * a1 - k1 * a2) / (k2 - k1);
float x = 0;
if (k1 != 0)
{
x = (y - a1) / k1;
}
else if (k2 != 0)
{
x = (y - a2) / k2;
}
return new Vector2(x, y);
}
問題を参照してください。(p2.x - p1.x) または (p3.x - p4.x) が 0 に等しい場合、傾き k は存在せず、この存在しない傾き k に基づいて計算された結果は間違っています。
ただし、C# の算術演算分母 = 0 はエラーを報告せず、実際の開発シナリオでは傾き k が存在しないという計算結果に遭遇しないため、無視されます。
したがって、次のように、この計算の適応性を完成させ、線形方程式系を使用してそれを解く必要があります。
その後、次のように 4 つの座標を通じて線形方程式のパラメータを構築するだけで済みます。
次にアルゴリズムを構築します。
/// <summary>
/// 计算平面直线相交
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="p4"></param>
/// <param name="p3"></param>
/// <returns></returns>
private Vector2 CalculateLineCross(Vector2 p1, Vector2 p2, Vector2 p4, Vector2 p3)
{
float[] abc1 = GetLineEquationParams(p1, p2);
float[] abc2 = GetLineEquationParams(p4, p3);
float a1 = abc1[0], b1 = abc1[1], c1 = abc1[2];
float a2 = abc2[0], b2 = abc2[1], c2 = abc2[2];
float x = (c2 * b1 - c1 * b2) / (a1 * b2 - a2 * b1);
float y = (c2 * a1 - c1 * a2) / (b1 * a2 - b2 * a1);
return new Vector2(x, y);
}
/// <summary>
/// 构建平面直线方程参数A、B、C
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <returns></returns>
private float[] GetLineEquationParams(Vector2 p1, Vector2 p2)
{
float a, b, c;
//L1
if (p1.y == p2.y)
{
a = 0;
b = 1;
c = -p1.y;
}
//L2
else if (p1.x == p2.x)
{
a = 1;
b = 0;
c = -p1.x;
}
//L3
else
{
float k = (p2.y - p1.y) / (p2.x - p1.x);
//y-y1=k(x-x1)
a = k;
b = -1;
c = p1.y - k * p1.x;
}
return new float[] {
a, b, c };
}
実際のプロジェクトで試したところ、効果は以下の通りです。
平面非平行線の交点の補正方法です。