Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

直線と直線の交点を求めるプログラム

これも結構間違えた実装してました…

前提

以下の変数AB、CDは直線です。それぞれ対応する方程式「ax + by + c = 0」のa、b、cをプロパティとして持っています。

つまり、「AB.a * x + AB.b * y + AB.c = 0」が直線ABを表す方程式となります。

また、aが0のときbは1、bが0のときaは1とします。「0x + by + c = 0」を変形すればいいので問題はありません。

aもbも0の場合は、そもそも直線とみなさないことにします。

コード

const getIntersection = (AB, CD) => {
    if (AB.a * CD.b === CD.a * AB.b) {
        return false;
    }
    const y = (CD.a * AB.c - AB.a * CD.c) / (AB.a * CD.b - CD.a * AB.b); // AB.a * CD.b - CD.a * AB.b !== 0
    let x;
    if (AB.a === 0) {
        x = -1 * (CD.b * y + CD.c) / CD.a;
    } else {
        x = -1 * (AB.b * y + AB.c) / AB.a;
    }
    return new Point(x, y);

};

軽い解説

まず、 AB.a * CD.b === CD.a * AB.b ですが、この式は整理すると AB.a / AB.b === CD.a / CD.b となり、傾きが等しいことを示す式となります。しかし、AB.bまたはCD.bが0のとき、この式は正しく動いてくれません。そこで、はじめのような式となります。

次に、交点のy座標を求めます。これは、 AB.a * CD.b !== CD.a * AB.b つまり AB.a * CD.b - CD.a * AB.b !== 0 であるので、0除算でないことが保証されています。よって安全に求めることができます。

最後に交点のx座標を求めます。ここではどうしてもゼロ除算の可能性が生まれるので、場合分けを行っています。

もしAB.aが0ならば、AB.a * CD.b は 0です。この行にくるためには AB.a * CD.b !== CD.a * AB.b でなければなりません。よってよってCD.a * AB.b は0ではありません.AB.bは1なので、明らかにCD.aは0ではありません。これで、CD.aで割ることができます。

else節ではAB.aが0でないので、安全にAB.aで割ることができます。

終わりに

x座標のところが見落としがちです。気をつけましょう(←見落としたまま半年放置してた)。