我想做的是:
我有两个 (x, y) 点,p1 和 p2,以及一个来自 p1 的旋转值(以弧度表示的 Angular )。
P2 还有另外两个变量,宽度和高度,我称之为 p2w 和 p2h。我想检查 p1 的 Angular 是否与 p2 的边界相交,半径为宽度和/或高度。
换句话说,如果这个 Angular “穿过”中心p2、宽度p2w和高度p2h的正方形。
为了更好地理解,这里有一个图表:
http://i.imgur.com/Y7WFD36.png
我一直在尝试做的是:
if( p1.rot > (Math.atan2(p2.y-p2h, p2.x-p2w))
&& p1.rot < (Math.atan2(p2.y+p2h, p2.x+p2w)) )
//There's an intersection
但如您所料,它并没有按预期工作;还有其他方法吗?
最佳答案
数学队长来救援!
你问的是一条射线是否与一个矩形相交。这是我们需要做的。
首先,使用点和矢量或点和 Angular 来定义射线。由于使用矢量更容易,让我们将 Angular 转换为矢量。使用毕达哥拉斯定理,您的 Angular phi 等于向量 n = {x: Math.cos(phi), y: Math.sin(phi)}
。
我将重命名您的变量以使符号更容易。我将用 p 表示你的 p1,用 r 表示你隐式定义的矩形。
现在,对于位于射线上的任意随机点 M,必须满足以下等式:
M.x = p.x + n.x * alpha (1)
M.y = p.y + n.y * alpha
对于一些真正的阿尔法。类似地,对于位于矩形内的任意随机点 M,必须满足以下不等式:
M.x >= r.x
M.x <= r.x + r.w
M.y >= r.y
M.y <= r.y + r.h
对于一个既位于射线上又位于矩形内的点,方程和不等式都必须成立。代入上述值,我们得到:
p.x + n.x * alpha >= r.x
p.x + n.x * alpha <= r.x + r.w
p.y + n.y * alpha >= r.y
p.y + n.y * alpha <= r.y + r.h
求解 alpha,我们得到:
alpha >= (r.x - p.x) / n.x
alpha <= (r.x + r.w - p.x) / n.x
alpha >= (r.y - p.y) / n.y
alpha <= (r.y + r.h - p.y) / n.y
当且仅当:
var lowerLimitX = (r.x - p.x) / n.x;
var lowerLimitY = (r.y - p.y) / n.y;
var upperLimitX = (r.x + r.w - p.x) / n.x;
var upperLimitY = (r.y + r.h - p.y) / n.y;
var minAlpha = Math.max(lowerLimitX, lowerLimitY);
var maxAlpha = Math.min(upperLimitX, upperLimitY);
var hasSolution = minAlpha<= maxAlpha;
现在,如果上面的系统有解,则必须至少有一个点同时位于射线和矩形上,换句话说,它们相交。
编辑:这是一个working demo .移动鼠标以查看结果。请注意,由于 Y 轴在 HTML Canvas API 中向下增长,因此必须交换 Y 轴的下限和上限。
编辑 2:如果您按照@pfannkuchen_gesicht 的建议关心交点(请注意,交点通常是线段,而不是点),这也很容易。正如我们已经知道的,对于交点上的点,射线方程必须成立。要自己找到点,只需将 alpha 替换为 [minAlpha; 范围内的值即可。 maxAlpha] 在 (1) 中。例如,最近的点是 p + minAlpha * n
,最远的点是 p + maxAlpha * n
,中间的随机点是 p +(minAlpha + Math.random() * (maxAlpha - minAlpha)) * n
.
关于javascript - 检查矢量/Angular 是否与区域相交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30004165/