整数演算と加算、減算、乗算の基本演算だけで、ポイントがセクター内にあるかどうかを確認できます。
ポイントが扇形の内側にあるためには、次のテストを満たす必要があります。
- セクターの開始「アーム」から反時計回りに配置する必要があります。
- セクターのエンドアームから時計回りに配置する必要があります。
セクターの半径よりも円の中心に近い必要があります。

時計回りのテスト
ベクトルv2が別のベクトルv1に対して時計回りであるかどうかをテストするには、次の手順を実行します。
v1の反時計回りの法線ベクトルを見つけます。法線ベクトルは、元のベクトルに対して90度の角度にあります。これは簡単に実行できます。の場合v1=(x1,y1)
、反時計回りの法線はn1=(-y1,x1)
です。
法線上のv2の投影のサイズを見つけます。これは、v2と法線の内積を計算することで実行できます。
projection = v2.x*n1.x + v2.y*n1.y
射影が正の数の場合、v2はv1に対して反時計回りに配置されます。それ以外の場合、v2はv1に対して時計回りです。
反時計回りの例を次に示します。

そして時計回りの例:

手順を組み合わせることができます。
function areClockwise(v1, v2) {
return -v1.x*v2.y + v1.y*v2.x > 0;
}
半径テスト
半径テストは簡単です。円の中心からの点の距離が目的の半径よりも小さいかどうかを確認してください。平方根の計算を回避するために、代わりに距離の2乗と半径の2乗を比較できます。
function isWithinRadius(v, radiusSquared) {
return v.x*v.x + v.y*v.y <= radiusSquared;
}
それを一緒に入れて
完全なセクターテストは次のようになります。
function isInsideSector(point, center, sectorStart, sectorEnd, radiusSquared) {
var relPoint = {
x: point.x - center.x,
y: point.y - center.y
};
return !areClockwise(sectorStart, relPoint) &&
areClockwise(sectorEnd, relPoint) &&
isWithinRadius(relPoint, radiusSquared);
}
次のサンプルページは、これを数千ポイント以上示しています。http://jsbin.com/oriyes/8/editでコードを試すことができます。

サンプルソースコード
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<style>
.canvas {
position: absolute;
background: #f4f4f4;
border: 8px solid #f4f4f4;
width: 400px;
height: 400px;
}
.dot {
position: absolute;
font: 16px Arial;
}
.out { color: #ddd; }
.in { color: #00dd44; }
</style>
<script>
function isInsideSector(point, center, sectorStart, sectorEnd, radiusSquared) {
var relPoint = {
x: point.x - center.x,
y: point.y - center.y
};
return !areClockwise(sectorStart, relPoint) &&
areClockwise(sectorEnd, relPoint) &&
isWithinRadius(relPoint, radiusSquared);
}
function areClockwise(v1, v2) {
return -v1.x*v2.y + v1.y*v2.x > 0;
}
function isWithinRadius(v, radiusSquared) {
return v.x*v.x + v.y*v.y <= radiusSquared;
}
$(function() {
var $canvas = $("#canvas");
var canvasSize = 400;
var count = 4000;
// define the sector
var center = { x: canvasSize / 2, y: canvasSize / 2 };
var sectorStart = { x: 4, y: 1 };
var sectorEnd = { x: 1, y: 4 };
var radiusSquared = canvasSize * canvasSize / 4;
// create, draw and test a number of random points
for (var i = 0; i < count; ++i) {
// generate a random point
var point = {
x: Math.random() * canvasSize,
y: Math.random() * canvasSize
};
// test if the point is inside the sector
var isInside = isInsideSector(point, center, sectorStart, sectorEnd, radiusSquared);
// draw the point
var $point = $("<div class='dot'></div>")
.css({
left: point.x - 3,
top: canvasSize - point.y - 8 })
.html("•")
.addClass(isInside ? "in" : "out")
.appendTo($canvas);
}
});
</script>
</head>
<body>
<div id="canvas" class="canvas"></div>
</body>
</html>
注意事項、警告および制限
ベクトルの観点からセクターの境界を指定する必要があります。たとえば、上のスクリーンショットは、(4,1)と(1,4)のベクトルの間で伸びる扇形を示しています。
セクターが角度などの他の用語で指定されている場合は、tan()
関数を使用するなどして、最初にそれをベクトルに変換する必要があります。幸いなことに、これを行う必要があるのは1回だけです。
ここでのロジックは、内角が180度未満のセクターで機能します。セクターがより大きな角度にまたがることができる場合は、それを変更する必要があります。
さらに、このコードは、セクターの境界ベクトルのどれが「開始」で、どれが「終了」であるかがわかっていることを前提としています。そうでない場合は、areClockwise()
それらを実行して調べることができます。
これはすべて整数演算で実行できますが、半径と時計回りの両方のテストでは、xとyを二乗し、それらを乗算するため、より広い範囲の数値を使用することに注意してください。結果を保持するのに十分なビットの整数を使用するようにしてください。