JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

JavaScriptで複数の座標が同一直線上にあるかどうかを判定する方法

はじめに

本記事では、配列の中に配列(二次元配列)を受け取り、そこに含まれる座標がすべて同一直線上にあるかどうかを判定するJavaScript関数を作成します。

各サブ配列は必ず2つの要素、つまりx座標とy座標を保持するものとします。関数の役割は、与えられた座標群が一本の直線を形成しているか否かをチェックすることです。

たとえば、次のような入力があった場合:

[[4, 5], [5, 6]] → true を返す

なお、入力配列には最低でも2つのサブ配列が含まれることが保証されています。

実装コード

実際のコードは以下の通りです。

const coordinates = [
    [4, 5],
    [5, 6]
];
const checkStraightLine = (coordinates = []) => {
    if(coordinates.length === 0) return false;
    let x1 = coordinates[0][0];
    let y1 = coordinates[0][1];
    let slope1 = null;
    for(let i=1;i<coordinates.length;i++){
        let x2= coordinates[i][0];
        let y2= coordinates[i][1];
        if(x2-x1 === 0){
            return false;
        }
        if(slope1 === null){
            slope1 = (y2-y1) / (x2-x1);
            continue;
        }
        let slope2 = (y2-y1) / (x2-x1);
        if(slope2 != slope1){
            return false;
        }
    }
    return true;
};
console.log(checkStraightLine(coordinates));

コードの解説

このアプローチの考え方は非常にシンプルです。基準となる最初の点に対して、残りすべての点の傾き(勾配)を計算し、その傾きがすべて一致していれば直線上にあると判断します。逆に、一つでも異なる傾きを持つ点が存在すれば、その点群は同じ直線上にはないことになります。

処理の流れを整理すると、以下のようになります。

  • 最初の点 (x1, y1) を基準点として取得する
  • ループ内で各点 (x2, y2) の傾きを (y2 - y1) / (x2 - x1) として求める
  • x2 - x1 === 0 の場合は false を返して終了する
  • 最初の比較時のみ傾き slope1 を記録し、以降の点では計算した傾きと照合する
  • 傾きが一致しない時点で false を返し、最後まで一致すれば true を返す

補足: 垂直線への対応について

上記の実装では x2 - x1 === 0(x座標の変化がゼロ)のケースを除外していますが、数学的には垂直線も立派な直線です。垂直線も含めて厳密に判定したい場合は、除算を伴わない「外積」を用いた手法が有効です。

const checkStraightLine = (coords = []) => {
    const [x1, y1] = coords[0];
    const [x2, y2] = coords[1];
    for(let i = 2; i < coords.length; i++){
        const [x3, y3] = coords[i];
        // 外積が0なら3点は同一線上にある
        if((x2 - x1) * (y3 - y1) !== (y2 - y1) * (x3 - x1)){
            return false;
        }
    }
    return true;
};

この方法ならゼロ除算の心配もなく、あらゆる直線パターンに対応できます。

出力結果

冒頭のコードをコンソールで実行すると、出力は次のようになります。

true

まとめ

座標群が直線上にあるかの判定は、「基準点から見た傾きが全点で等しいか」を確認するだけで実現できます。計算量はO(n)と効率的で、直線の方程式を解くような複雑な処理は不要です。ただし、垂直線の扱いなどエッジケースを考慮する場合は、外積を使った判定方式を採用するとより堅牢になります。

  1. JavaScriptで配列の要素が2乗の関係かどうかをチェックする方法

    問題 2つの数値の配列 arr1 と arr2 をそれぞれ第1・第2引数として受け取るJavaScript関数を作成することを考えます。 この関数は、arr2 のすべての要素が、出現順序に関係なく arr1 のいずれかの要素の2乗と一致する場合にのみ true を返し、それ以外の場合は false を返す必要があります。 たとえば、関数への入力が次のようであった場合を考えてみましょう。 入力 const arr1 = [4, 1, 8, 5, 9]; const arr2 = [81, 1, 25, 16, 64]; 出力 const output = true; この場合、81 = 9²、

  2. JavaScriptで行列の対角線がすべて同じ要素かどうかを判定する方法

    問題概要 リテラルを要素とする2次元配列 arr を第一引数(唯一の引数)として受け取るJavaScript関数を作成します。 この関数の役割は、行列の左上から右下へ向かうすべての対角線が同じ要素で構成されているかどうかを判定することです。これは、いわゆる「トゥーマトリックス(Toeplitz行列)」と呼ばれる行列の判定問題に相当します。 条件を満たしていれば true を、そうでなければ false を返します。 例として、次の入力を関数に渡した場合を考えてみましょう。 入力 const arr = [ [6, 7, 8, 9], [2, 6, 7, 8], [1,