Better

Ethan的博客,欢迎访问交流

绘制一个任意旋转角度的矩形

通过鼠标响应,完成一个任意选择角度矩形的绘制。

需求描述

鼠标在场景点击确定 p1 点,再次点击确定 p2,此时确定一条边,这时候拖动鼠标,只会响应垂直于边的分量,从而完成任意角度矩形的绘制。

假定已有 CoordsUtils.worldVecFromEvent(mouseEvent);

具体实现

这种类型的绘制需求,如果用代数的方式解决,会显得特别的复杂。从向量的角度出发,利用已有的 api 会十分简单。

方式一:利用叉积转变为平行四边形求高问题,利用旋转特性确定方向

const v1 = CoordsUtil.worldVecFromEvent(e1);
const v2 = CoordsUtil.worldVecFromEvent(e2);
// 矩形的一条边
const bw = v2.clone().sub(v1);
const t = CoordsUtil.worldVecFromEvent(e2);
// 得到类似平行四边形对角线的向量
t.sub(v1);
// 得到垂直该平面的向量,长度为所构成平行四边形面积,问题又变成了根据平行四边形以 bw 为底,求高即可
t.cross(bw);
// 旋转到该平面
t.applyAxisAngle(bw.clone().normalize(), Math.PI / 2);
const length = t.length();
// 转变为高
t.setLength(length / bw.length());
// 这样的就得到四个顶点了
const v4 = v1.clone().add(t);
const v3 = v2.clone().add(t);

方式二:利用通过投影分量求解,类似三角函数

const v1 = CoordsUtil.worldVecFromEvent(e1);
const v2 = CoordsUtil.worldVecFromEvent(e2);
// 矩形的一条边
const bw = v2.clone().sub(v1);
const t = CoordsUtil.worldVecFromEvent(e2);
// 得到类似平行四边形对角线的向量
t.sub(v1);
// 确定旋转轴向量
const normal = t.clone().cross(bw).normalize();
// 得到垂直于 bw 的向量
const verticalVec = bw.clone().applyAxisAngle(normal, -Math.PI / 2);
// 计算投影分量向量
t.projectOnVector(verticalVec);
const v4 = v1.clone().add(t);
const v3 = v2.clone().add(t);


留言