ポイントがダイヤモンドの内側にあるかどうかを直接確認する方法と、アフィン変換を使用する方法の 2 つが考えられます。両方について説明します。
ダイレクトポイント位置確認
ポイントがダイヤモンドの内側にあるかどうかを判断するには、ダイヤモンドの中心点からの偏差を確認する必要があります。X と Y の偏差を、ダイヤモンドの X と Y の範囲に比例させる必要があります。2 つの要素が得られます。ダイヤモンド内のすべてのポイントについて、これらの係数のモジュロ値の合計は 1 以下です。コードでは、次のようになります。
var dx = Math.abs(coords[0] - middle[0]);
var dy = Math.abs(coords[1] - middle[1]);
if (dx / size[0] + dy / size[1] <= 1)
alert("Inside diamond");
else
alert("Outside diamond");
したがって、各ダイアモンドの中間点 (サイズはすべての場合で同じ) を決定し、テストしている点がその内部にあるかどうかを確認するだけです。
作業例: http://jsfiddle.net/z98hr/
アフィン変換
アフィン変換を使用して、上のダイヤモンドのコーナー座標を (0,0)、(1,0)、(0,1)、および (1,1) に変更できます。次に、テストする必要があるポイントに同じ変換を適用すると、それがどのダイヤモンドに属しているかを判断するのは簡単になります。
最初に、(225,2) 点を座標の原点に移動するための平行移動ベクトルが必要になります。上のひし形を決定する 4 つの座標 (左右の座標、上下の座標) があるとします。
var topDiamond = [[113, 2], [337, 227]];
次に、ダイヤモンドの頂点をゼロ座標に移動するための平行移動ベクトルは次のようになります。
var translationVector = [-(topDiamond[0][0] + topDiamond[1][0]) / 2,
-topDiamond[0][1]];
次のように元の座標に適用できます。
function add(vector1, vector2)
{
return [vector1[0] + vector2[0], vector1[1] + vector2[1]];
}
topDiamond = [add(topDiamond[0], translationVector),
add(topDiamond[1], translationVector)];
次に、回転行列が必要になります。
var angle = -Math.atan2(topDiamond[1][1] - topDiamond[0][1],
topDiamond[1][0] - topDiamond[0][0]);
var rotMatrix = [[Math.cos(angle), -Math.sin(angle)],
[Math.sin(angle), Math.cos(angle)]];
この行列を乗算した後、点 (225,2) と (337,114.5) が X 軸上に配置されます。しかし、今あなたが持っているのは台形です。次に、水平方向のせん断変換を行って、ダイヤモンドの反対側を Y 軸に揃える必要があります。
function multiply(matrix, vector)
{
return [matrix[0][0] * vector[0] + matrix[0][1] * vector[1],
matrix[1][0] * vector[0] + matrix[1][1] * vector[1]];
}
var point = [topDiamond[0][0], (topDiamond[0][1] + topDiamond[1][1]) / 2];
point = multiply(rotMatrix, point);
var shearMatrix = [[1, -point[0] / point[1]], [0, 1]];
この行列を掛けると、長方形になります。これで、角の X 座標と Y 座標の値が 0 と 1 になるように、スケーリング マトリックスだけが必要になります。
point = multiply(shearMatrix, point);
var point2 = [topDiamond[1][0], (topDiamond[0][1] + topDiamond[1][1]) / 2];
point2 = multiply(rotMatrix, point2);
point2 = multiply(shearMatrix, point2);
var scaleMatrix = [[1/point2[0], 0], [0, 1/point[1]]];
これで、これらの変換を任意のポイントに適用できるようになりました。
alert(
multiply(scaleMatrix,
multiply(shearMatrix,
multiply(rotMatrix,
add(translationVector, [260, 179])
)
)
)
);
これにより、0.94,0.63
両方の値が(0..1)
範囲内にあり、それが一番上のダイヤモンドであることを意味します。[420,230]
入力として取得すると、範囲内の1.88,0.14
X と(1..2)
範囲内の Y0..1
は右のひし形を意味します。等々。
作業例: http://jsfiddle.net/FzWHe/
振り返ってみると、これはおそらく、ダイヤモンドのような単純な幾何学的図形には多すぎる作業でした.