前几天看到一个面试题,如下图:
大概意思就是任意给一个鼠标位置,求鼠标位置是在哪个区域,上三角?下三角?还是正好在分割线上?
解法很简单原文里有介绍: 用x/y和宽/高比较下就能得到结果。
原文中也提到了可以用线性代数来解这道题,正好最近在研究线性代数,下面介绍下自己的解题思路:
第一步: 画一个坐标轴,随意取了一个向量(红线)。这里用了[1,1];
// 省略了部分代码,可去github上查看全部代码(文末有链接)
const axis = new Axis(world, {
x: [-5, 6],
y: [-5, 6],
});
const target = [1, 1];
// 渲染标准空间坐标系,(设为A空间)
axis.render();
axis.renderV(target);
第二步: 利用空间变换将坐标轴逆时针旋转(为了更方便做对比,我保留了原坐标系图),变换后的正方向X轴可以看做是题目中的上下三角的分割线。
axis.setBasis([
[Math.cos((Math.PI / 180) * 30), Math.sin((Math.PI / 180) * 30) * -1, 0],
[Math.sin((Math.PI / 180) * 30), Math.cos((Math.PI / 180) * 30), 0],
[0, 0, 1],
]);
// 渲染变换后坐标系,(设为B空间)
axis.render();
axis.renderV(target);
第三部: 把变换前的[1,1]向量(图中黄色向量)用变换后的坐标系的向量来表示,即可得到解。
// B空间的基取逆后,点乘A空间的向量就是: 用B空间的向量表示A空间的此向量
const tmp = transform(
inv([
[Math.cos((Math.PI / 180) * 30), Math.sin((Math.PI / 180) * 30) * -1, 0],
[Math.sin((Math.PI / 180) * 30), Math.cos((Math.PI / 180) * 30), 0],
[0, 0, 1],
]),
target
);
axis.renderV(tmp, 'yellow');
console.log(tmp); // [1.3660254037844386, 0.36602540378443876]
原坐标系向量[1,1],用变换后的坐标系来表示为[1.3660254037844386, 0.36602540378443876], y值为大于0的值,所以[1,1]在上三角区域里。