这是一道数学题。
x,y 坐标
- 首先排除三点相同的情况
- 然后判断是否可以连成一条线:将 其中一点平移到原点,其他两个点在
x
,y
轴上移动相同的距离,然后计算这两个点与原点形成的角度是否相同(区分正负)
如下 [[0, 1], [2, 0], [2, 2]]
三点
移动[0, 1]
到原点[0, 0]
,则[2, 0]
移动到了[2, -1]
,[2, 2]
移到了[2, 1]
,计算这两个点与x
轴的夹角分别为-45°
和45°
。夹角不同,所以不在一条直接上。
代码实现:
function isBoomerang(points: number[][]): boolean {
const x1 = points[0][0],
y1 = points[0][1],
x2 = points[1][0],
y2 = points[1][1],
x3 = points[2][0],
y3 = points[2][1]
const set = new Set([`${x1}.${y1}`, `${x2}.${y2}`, `${x3}.${y3}`])
// 各不相同
if (set.size !== 3) return false
// 不在一条直线上
let movedX2 = x2 - x1,
movedy2 = y2 - y1
let movedx3 = x3 - x1,
movedy3 = y3 - y1
if (getRate(movedX2, movedy2) === getRate(movedx3, movedy3)) return false
return true
}
// 求与x轴的夹角
function getRate(x: number, y: number) {
let xp = x ** 2
let yp = y ** 2
return ((x * y > 0 ? 1 : -1) * xp) / (xp + yp)
}
向量叉乘
除了x,y垂直坐标
,还可以用三点构成两个向量,然后根据平行的性质,叉乘为0
function isBoomerang_v2(points: number[][]): boolean {
const v1 = [points[1][0] - points[0][0], points[1][1] - points[0][1]]
const v2 = [points[2][0] - points[0][0], points[2][1] - points[0][1]]
return v1[0] * v2[1] - v1[1] * v2[0] != 0
}