点对于某个对称轴镜像翻转,这里用二维演示,思路及外围办法都是统一的,二维能较好阐明。
找到在对称轴上与点最近的点
// 将对称轴整成线段
const line = new THREE.Line3(axis, new THREE.Vector3(0, 0, 0))
const linePoint = new THREE.Vector3()
line.closestPointToPoint(arr[i], false, linePoint)
// linePOint 就是 arr[i] 点在线段上最近的点
得出点与线段上的点的间隔 S1
// linePoint 是线段上的点 vec3 是须要翻转的点
const distance = linePoint.distanceTo(vec3)
按方向缩短 S1 的间隔至 S 点
// 简略的勾股定理
const p = Math.sqrt(2) * 0.5
x = linePoint.x + p * distance
y = linePoint.y - p * distance
须要进行判断
对于上方的后果只是点在对称轴左侧才成立, 须要判断点的方位
/**
* 判断是否在左侧
* 因为数据是否在左右侧关系到 xy 的符号问题, 间隔是没有正数的,而坐标是存在正负的
*/
function leftORRight() {
let left = true;
const line = new THREE.Line3(axis, new THREE.Vector3(0, 0, 0))
const linePoint = new THREE.Vector3()
for (let i = 0; i < arr.length; i++) {line.closestPointToPoint(arr[i], false, linePoint)
if (linePoint.x < arr[i].x) {
// 右侧
left = false;
break;
}
}
return left;
}
All Code
import * as THREE from 'three'
/**
* 实现点绕制订对称轴镜像转换的性能
*/
function axisRound(scene) {
// const arr = [// new THREE.Vector3(-1, 1, 0),
// new THREE.Vector3(-2, -1, 0),
// new THREE.Vector3(-1, -1, 0),
// new THREE.Vector3(-1, 2, 0),
// ]
// 提供测试的数据
const arr = [new THREE.Vector3(1, -1, 0),
new THREE.Vector3(2, -1, 0),
new THREE.Vector3(1, 1, 0),
new THREE.Vector3(1, -2, 0),
]
const material = new THREE.MeshBasicMaterial({color: 'red', side: THREE.DoubleSide});
arr.forEach(row => {const geometry = new THREE.PlaneGeometry(0.5, 0.5);
const plane = new THREE.Mesh(geometry, material);
scene.add(plane);
plane.position.set(row.x, row.y, row.z)
})
const axis = new THREE.Vector3(1, 1, 0)
{const points = [];
points.push(axis);
points.push(new THREE.Vector3(-10, -10, 0))
points.push(new THREE.Vector3(10, 10, 0))
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const line = new THREE.Line(geometry, material);
scene.add(line);
}
arr.forEach(row => {const geometry = new THREE.PlaneGeometry(0.5, 0.5);
const plane = new THREE.Mesh(geometry, material);
scene.add(plane);
const n = t(row, axis)
console.log(n);
plane.position.set(n.x, n.y, n.z)
})
// 正式开始计算
function t(vec3, axis) {const line = new THREE.Line3(axis, new THREE.Vector3(0, 0, 0))
const linePoint = new THREE.Vector3()
line.closestPointToPoint(vec3, false, linePoint)
// 得出 2 的算术平方根的 1 /2
const p = Math.sqrt(2) * 0.5
const distance = linePoint.distanceTo(vec3)
let x, y;
if (leftORRight()) {
x = linePoint.x + p * distance
y = linePoint.y - p * distance
} else {
x = linePoint.x - p * distance
y = linePoint.y + p * distance
}
return new THREE.Vector3(x, y, 0)
}
/**
* 判断是否在左侧
* 因为数据是否在左右侧关系到 xy 的符号问题, 间隔是没有正数的,而坐标是存在正负的
*/
function leftORRight() {
let left = true;
const line = new THREE.Line3(axis, new THREE.Vector3(0, 0, 0))
const linePoint = new THREE.Vector3()
for (let i = 0; i < arr.length; i++) {line.closestPointToPoint(arr[i], false, linePoint)
if (linePoint.x < arr[i].x) {
// 右侧
left = false;
break;
}
}
return left;
}
}
export {axisRound}