さて、線が円を横切るかどうか(少なくとも円の内側の線の一部)を計算できるようにしたいと思います。これに対するいくつかの答えを見つけましたが、複雑すぎると思ったので、これを思いつきました。私は数学の男ではないので、今ちょっと行き詰まっています。行が垂直に配置されている場合、「radius >= Math.sqrt(len * len + len * len - o);」true になります (45° の角度では 0 になります)。なぜこれが起こるのか分かりません。ありがとう :)
function lineInCircle(sx, sy, x, y, cx, cy, radius) {
cx -= sx; x -= sx; //sx is the first point's x position
cy -= sy; y -= sy;//sy is the first point's y position
len = Math.sqrt((cy * cy) + (cx * cx))//hypotenuse of circle (cy, cx) to (0, 0) (with offset)
atanx = Math.atan(y / x); //angle of (0, 0) to (x, y) in radians
atany = atanx - Math.atan(cy / cx); //to center
var o = 2 * len * len * Math.cos(atany);
var o = o < 0 ? -o:o//Had to do this, at some point the value can become inverted
return radius >= Math.sqrt(len * len + len * len - o);
}
編集:
function lineInCircle(sx, sy, x, y, cx, cy, radius) {
cx -= sx; x -= sx; //sx is the first point's x position
cy -= sy; y -= sy;//sy is the first point's y position
ctp = Math.sin(Math.atan(y / x) - Math.atan(cy / cx)) * Math.sqrt((cy * cy) + (cx * cx));
return radius >= ctp && ctp >= -radius;
}
ほとんど同じように動作しますが、より高速です。問題は、無限の行を計算することです。どうすれば修正できますか?
編集2:
function lineInCircle(sx, sy, x, y, cx, cy, radius) {
cx -= sx; x -= sx;
cy -= sy; y -= sy;
var h = Math.sqrt(cy * cy + cx * cx)
ctp = Math.sin(Math.atan(y / x) - Math.atan(cy / cx)) * h;
sideb = Math.sqrt(h * h - ctp * ctp);
line = Math.sqrt(x * x + y * y)
if (sideb - radius > line) {return false}
return radius >= ctp && ctp >= -radius;
}
部分修正、ラインから一方向(ラインエンド)の無限遠に進まない
編集 3: 少し長くなりますが、2 倍以上の速さで、振り出しに戻ります
function lineInCircle2(sx, sy, x, y, cx, cy, radius) {
var ysy = y - sy
var xsx = x - sx
var k = ((y-sy) * (cx-sx) - (x-sx) * (cy-sy)) / (ysy * ysy + xsx * xsx)
var ncx = cx - k * (y-sy)
var ncy = cy + k * (x-sx)
ncx -= cx
ncy -= cy
var ctp = Math.sqrt(ncx * ncx + ncy * ncy)
return radius >= ctp && ctp >= -radius;
}
編集 4: 成功!
function lineInCircle(sx, sy, x, y, cx, cy, radius) {
if (sx > cx + radius && x > cx + radius || x < cx - radius && sx < cx - radius) {return false;}
if (sy > cy + radius && y > cy + radius || y < cy - radius && sy < cy - radius) {return false;}
var k = ((y - sy) * (cx - sx) - (x - sx) * (cy - sy)) / ((y - sy) * (y - sy) + (x - sx) * (x - sx))
var ncx = k * (y - sy)
var ncy = k * (x - sx)
return radius >= Math.sqrt(ncx * ncx + ncy * ncy);
}
最初のバージョンの10秒以上と比較して、100000000回の反復で4.5〜4.6秒に最適化しましたが、それでもはるかに正確です(特定の角度で奇妙な動作がなくなることを意味します)。私は満足しています:D