假设我有两个点代表一条线A,比如:
var A = [ { x: 385, y: 380 }, { x: 420, y: 400 }]
我还有另外两点 B 和 C,例如:
var B = { x: 385, y: 420 }
var C = { x: 405, y: 423 }
如何确定 B 和 C 是否都在 A 线的同一侧?为了添加一点上下文,我正在尝试对六边形进行 HitTest ,其中 B 是六边形的中心点,C 是当前鼠标位置,A 是六边形的每一行。所有这些点基本上都是像素坐标,其中 0,0 是左上角。
我不需要它变得非常快,我只是想尽可能地创建最简单的六边形 HitTest 算法。我的理论是,如果我可以确定 C 与 B 在六边形每条线的同一侧,那么 HitTest 就成功了。我已经阅读了几种用于执行此操作的数学算法,但它们似乎总是处于不同类型的坐标系中,我正在努力将其转换为可在 javascript 中使用的东西。
编辑:这是我的实际六边形函数,给出了下面的答案。这个问题的答案在更新函数中。
var TILE_WIDTH = 70
var TILE_HEIGHT = 80
function Hexagon(x, y) {
var normalColor = 'rgb(207, 226, 243)'
var hilightColor = 'rgb(204, 204, 204)'
var currentColor = normalColor
var coords = new TileCoordinates(x, y)
var points = [
{ x: coords.x, y: coords.y - TILE_HEIGHT / 2 },
{ x: coords.x + TILE_WIDTH / 2, y: coords.y - TILE_HEIGHT / 4 },
{ x: coords.x + TILE_WIDTH / 2, y: coords.y + TILE_HEIGHT / 4 },
{ x: coords.x, y: coords.y + TILE_HEIGHT / 2 },
{ x: coords.x - TILE_WIDTH / 2, y: coords.y + TILE_HEIGHT / 4 },
{ x: coords.x - TILE_WIDTH / 2, y: coords.y - TILE_HEIGHT / 4 },
]
var sides = [
[points[0], points[1]],
[points[1], points[2]],
[points[2], points[3]],
[points[3], points[4]],
[points[4], points[5]],
[points[5], points[0]]
]
this.update = function (totalTime, updateTime) {
var B = coords
var C = Mouse.state
var inside = C != null
if (inside) {
for (i in sides) {
var A = sides[i]
var w = { y: A[1].x - A[0].x, x: -(A[1].y - A[0].y) }
var P = A[1]
inside = ((B.x - P.x) * w.x + (B.y - P.y) * w.y) * ((C.x - P.x) * w.x + (C.y - P.y) * w.y) > 0
if (!inside) break
}
}
if (inside)
currentColor = hilightColor
else
currentColor = normalColor
}
this.draw = function (ctx) {
ctx.fillStyle = currentColor
ctx.strokeStyle = 'rgb(11, 83, 148)'
ctx.beginPath()
ctx.moveTo(points[0].x, points[0].y)
ctx.lineTo(points[1].x, points[1].y)
ctx.lineTo(points[2].x, points[2].y)
ctx.lineTo(points[3].x, points[3].y)
ctx.lineTo(points[4].x, points[4].y)
ctx.lineTo(points[5].x, points[5].y)
ctx.lineTo(points[0].x, points[0].y)
ctx.fill()
ctx.stroke()
ctx.fillStyle = '#000'
var text = coords.pos_x + ',' + coords.pos_y
var measure = ctx.measureText(text)
ctx.fillText(text, coords.x - measure.width / 2, coords.y + 12 + (TILE_HEIGHT / 4))
}
}
// this is in a separate function because other objects that render into the hex
// need the pixel coordinates of the tile also
function TileCoordinates(x, y) {
this.pos_x = x
this.pos_y = y
this.x = x * TILE_WIDTH + ((y + 1) * TILE_WIDTH / 2)
this.y = (y + 1) * (3 / 4 * TILE_HEIGHT)
}
为了确定同边性,我将 B 和 C 的结果相乘,如果结果 > 0,那么它们要么都是正数,要么都是负数。我正在使用 setInterval 循环将六边形渲染并更新到 Canvas 中。
最佳答案
表示 A 的线由向量 v = { x: 420 - 385, y: 400 - 380 } = { x: 35, y: 20 }
和起点 P = { x: 385, y: 380 }
。给定二维向量 (x, y)
,向量 (y, -x)
始终与其成直 Angular 。所以向量 w = { x: 20, y: -35 }
与 v
成直 Angular 。线性代数告诉我们,(B - P) dot w
的符号告诉我们您在直线的哪一侧,dot
是标准点积。 (该线本身为零。)
因此在您的示例中,我们需要做的计算是这样的:
For B:
(B - P) dot w
= { x: 385 - 385, y: 420 - 380 } dot { x: 20, y: -35 }
= { x: 0, y: 40} dot { x: 20, y: -35 }
= (0 * 20) + (40 * (-35))
= -1400
For C:
(C - P dot w
= { x: 405 - 385, y: 423 - 380 } dot { x: 20, y: -35 }
= { x: 20, y: 43} dot { x: 20, y: -35 }
= (20 * 20) + (43 * (-35))
= -1105
由于符号相同,所以它们在同一侧。
其实我们可以说的更多。如果您位于 A
的起点并面向终点,那么这两个点都将位于您的左侧。 (左边为负,右边为正。)
关于javascript - 确定两个点是否在javascript中一条线的同一侧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5973372/