在 threejs
创建的三维空间中,可以计算两条线段是否有交点,或者线段的延长线是否有交点,使用其中一条线段创建射线,使用另一条线段创建平面,获取射线和平面的交点就可以了。
还可以在三维空间的某个点上计算最近的线段,分别计算点到线段的距离就可以了。
下面是参考代码:
// 获取两条线的交点
var getPublicDot = function ( line1Dot, line1Direction, line2Dot, line2Direction ) {
var dotPublic = new THREE.Vector3('x', 'y', 'z');
function run () {
var ray = new THREE.Ray( line1Dot, line1Direction );
var line2DotPro = line2Dot.clone();
var line2Vertical = line2Direction.clone();
line2Vertical.applyAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI/2);
line2DotPro.projectOnVector(line2Vertical);
var line2Pos = (line2DotPro.x * line2Vertical.x > 0 ? -1 : 1) * line2DotPro.distanceTo(new THREE.Vector3(0, 0, 0));
var plane2 = new THREE.Plane( line2Vertical, line2Pos );
ray.intersectPlane( plane2, dotPublic );
}
run();
if ( dotPublic.x !== 'x' ) {
return dotPublic;
} else {
line1Direction.applyAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI);
run();
line1Direction.applyAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI);
if ( dotPublic.x !== 'x' ) {
return dotPublic;
} else {
console.log('无法获取交点:', dotPublic);
return null;
}
}
}
// 获取最近的线段
var getCloseLine = function ( dot, lines, refer ) {
var lineDirection, lineVertical, lenMin, lineMin, dotPro, dotMin,
dotProDir1, dotProDir2, check = false, dots, axisY = new THREE.Vector3(0, 1, 0);
for (var i = 0, il = lines.length; i < il; i++) {
dots = refer.getObjDots( lines[i] );
for (var j = 0, jl = dots.length; j < jl-1; j++) {
lineDirection = dots[j+1].clone();
lineDirection = lineDirection.sub(dots[j]);
lineVertical = lineDirection.clone();
lineVertical.applyAxisAngle(axisY, Math.PI/2);
lineDirection.normalize();
lineVertical.normalize();
dotPro = dot.clone();
dotPro.projectOnPlane(lineVertical);
dotPro.sub(dot);
dotPro = refer.getPublicDot(dot, dotPro, dots[j], lineDirection);
if (!dotPro) return null;
dotProDir1 = dotPro.clone();
dotProDir2 = dotPro.clone();
dotProDir1.sub(dots[j]);
dotProDir2.sub(dots[j+1]);
dotProDir1.normalize();
dotProDir2.normalize();
check = dotProDir1.dot(dotProDir2);
if ( ( !lenMin || lenMin > dotPro.distanceTo(dot) ) && (check.toFixed(4) === '-1.0000') ) {
lenMin = dotPro.distanceTo(dot);
lineMin = lines[i];
dotMin = dotPro.clone();
}
}
}
if (lenMin) {
return {
dot: dotMin,
line: lineMin
};
} else {
return null;
}
}
// 查找模型的端点
var getObjDots = function ( obj, refer ) {
var dots = [], dotAll, dotTemp;
if ( obj.geometry.type === 'Geometry' ) {
dotAll = obj.geometry.vertices;
for (var i = 0, il = dotAll.length; i < il; i++) {
dotTemp = dotAll[i].clone();
obj.localToWorld( dotTemp );
if ( !refer ) {
dots.push( dotTemp );
} else if ( dotTemp[refer.axis] <= refer.max && dotTemp[refer.axis] >= refer.min ) {
dots.push( dotTemp );
}
}
} else if ( obj.geometry.type === 'BufferGeometry' ) {
dotAll = obj.geometry.attributes.position;
dotTemp = new THREE.Vector3();
for (var i = 0, il = dotAll.count * 3; i < il; i+=3) {
dotTemp.set(dotAll.array[i], dotAll.array[i+1], dotAll.array[i+2]);
obj.localToWorld( dotTemp );
if ( !refer ) {
dots.push( dotTemp.clone() );
} else if ( dotTemp[refer.axis] <= refer.max && dotTemp[refer.axis] >= refer.min ) {
dots.push( dotTemp.clone() );
}
}
}
return dots;
}