如何判断点(x,y,z)是否在pointA和pointB之间的一条线上?
我想要的是一个布尔函数,它可以做到这一点:
pointA // random THREE.Vector3
pointB // random THREE.Vector3
pointToCheck // random THREE.Vector3
var isOnLine = THREE.pointOnLine(pointA, pointB, pointToCheck)
if (isOnLine) {
console.log('point is on the line');
}
以下是可视化图像:
答案 0 :(得分:2)
Cross product两个向量可以帮助我们解决这个问题。
function isPointOnLine (pointA, pointB, pointToCheck) {
var c = new THREE.Vector3();
c.crossVectors(pointA.clone().sub(pointToCheck), pointB.clone().sub(pointToCheck));
return !c.length();
}
THREE.isPointOnLineAndBetweenPoints = function (pointA, pointB, pointToCheck) {
if (!isPointOnLine(pointA, pointB, pointToCheck)) {
return false;
}
var dx = pointB.x - pointA.x;
var dy = pointB.y - pointA.y;
// if a line is a more horizontal than vertical:
if (Math.abs(dx) >= Math.abs(dy)) {
if (dx > 0) {
return pointA.x <= pointToCheck.x && pointToCheck.x <= pointB.x;
} else {
return pointB.x <= pointToCheck.x && pointToCheck.x <= pointA.x;
}
} else {
if (dy > 0 ) {
return pointA.y <= pointToCheck.y && pointToCheck.y <= pointB.y;
} else {
return pointB.y <= pointToCheck.y && pointToCheck.y <= pointA.y;
}
}
}
电话:
THREE.isPointOnLineAndBetweenPoints(new THREE.Vector3(1, 0, 0), new THREE.Vector3(2, 0, 0), new THREE.Vector3(2, 0, 0));
如果您想知道这一点是否在一条线上,请使用以下功能:
isPointOnLine(new THREE.Vector3(1, 0, 0), new THREE.Vector3(2, 0, 0), new THREE.Vector3(2, 0, 0));
答案 1 :(得分:0)
这种简单得多的方法。
derived_with_keys
答案 2 :(得分:-1)
您可以为三维线生成方程的对称形式,插入pointToCheck上的点,并确定它是否在线上。这是代码:
// Pick two arbitrary points to be on the line
var pointA = new THREE.Vector3( -70, -4, -100 );
var pointB = new THREE.Vector3( 65, 22, 14 );
// Equation that takes in three points, pointA and pointB
// on a three-dimensional line and pointToCheck unknown, and
// returns true if pointToCheck is on the line and false if not
// optional param betweenCheck will additionally check if point
// is between pointA and pointB
var isOnLine = function(pointA, pointB, pointToCheck, betweenCheck) {
xVector = pointB.x - pointA.x;
yVector = pointB.y - pointA.y;
zVector = pointB.z - pointA.z;
vector = [xVector, yVector, zVector];
if (!!betweenCheck) {
// test if point is between pointA and pointB
if (pointToCheck.x < Math.min[pointA.x, pointB.x] ||
pointToCheck.x > Math.max[pointA.x, pointB.x]) {
return false;
}
if (pointToCheck.y < Math.min[pointA.y, pointB.y] ||
pointToCheck.y > Math.max[pointA.y, pointB.y]) {
return false;
}
if (pointToCheck.z < Math.min[pointA.z, pointB.z] ||
pointToCheck.z > Math.max[pointA.z, pointB.z]) {
return false;
}
}
// equation for the vector function generating this line is:
// [pointA.x, pointA.y, pointA.z] + t[vector], or
// [pointA.x + t * xVector, pointA.y + t * yVector,
// pointA.z + t * zVector], or
// parametric form:
// x = pointA.x + (t * xVector)
// y = pointA.y + (t * yVector)
// z = pointA.z + (t * zVector), or
// symmetric form:
// x - pointA.x y - pointA.y z - pointA.z
// ------------ = -------------- = --------------
// xVector yVector zVector
//
// So to test for whether pointToCheck is on line, we plug in
// its coordinates to x, y and z in the symmetric form
// and see if the equations balance
var x = (pointToCheck.x - pointA.x) / xVector;
var y = (pointToCheck.y - pointA.y) / yVector;
var z = (pointToCheck.z - pointA.z) / zVector;
var results = [x, y, z];
// Handle any axis where no change occurred by removing the
// point to check, as it's irrelevent to determining whether
// point to check is on the line.
for (var i = 0; i < 2; i++) {
if (isNaN(results[i])) {
results.splice(i, 1);
}
}
var first = results[0];
// Cycle through remaining results and make sure they are all
// the same
for (var i = 0; i < results.length; i++) {
// If any point is different, return false, as the point to
// check is not on the line
if (results[i] !== first) {
return false
}
}
// All the symmetric equations were equal (or irrelevant) and
// the pointToCheck is on the line
return true;
}
以下是一些测试:
// Some quick testing on example lines (you can change the
// coords of pointA and pointB above and they will still pass)
pointsOnLine = [];
pointsOffLine = [];
pointsOnLineBetween = [];
pointsOffLineBetween = [];
var generatePoints = function() {
xVector = pointB.x - pointA.x;
yVector = pointB.y - pointA.y;
zVector = pointB.z - pointA.z;
vector = [xVector, yVector, zVector];
for (var i = 0; i < 100; i++) {
var t = parseInt(Math.random() * 100);
var direction = Math.random() < .5 ? true : false
if (!direction) {
t = -t;
}
var newPointCoords = new THREE.Vector3(
pointA.x + (xVector * t),
pointA.y + (yVector * t),
pointA.z + (zVector * t)
);
pointsOnLine.push(newPointCoords);
var newPointCoords = new THREE.Vector3(
pointA.x + (xVector * t) + parseInt(Math.random() * 100),
pointA.y + (yVector * t) - parseInt(Math.random() * 100),
pointA.z + (zVector * t) + parseInt(Math.random() * 100)
);
pointsOffLine.push(newPointCoords);
var x = ((Math.max(pointA.x, pointB.x) - Math.min(pointA.x, pointB.x)) /
2) + Math.min(pointA.x, pointB.x);
var y = ((Math.max(pointA.y, pointB.y) - Math.min(pointA.y, pointB.y)) /
2) + Math.min(pointA.y, pointB.y)
var z = ((Math.max(pointA.z, pointB.z) - Math.min(pointA.z, pointB.z)) /
2) + Math.min(pointA.z, pointB.z)
var newPointCoords = new THREE.Vector3(x, y, z);
pointsOnLineBetween.push(newPointCoords);
var x = ((Math.max(pointA.x, pointB.x) - Math.min(pointA.x, pointB.x)) /
Math.abs(t)) + Math.min(pointA.x, pointB.x);
var y = ((Math.max(pointA.y, pointB.y) - Math.min(pointA.y, pointB.y)) /
Math.abs(t) * 2) + Math.min(pointA.y, pointB.y)
var z = ((Math.max(pointA.z, pointB.z) - Math.min(pointA.z, pointB.z)) /
Math.abs(t) * 3) + Math.min(pointA.z, pointB.z)
var newPointCoords = new THREE.Vector3(x, y, z);
pointsOffLineBetween.push(newPointCoords);
}
}
generatePoints();
for (var i=0; i < pointsOnLine.length; i++) {
if (!isOnLine(pointA, pointB, pointsOnLine[i])) {
console.log('error', pointsOnLine[i]);
} else {
console.log('test passed -- point on line')
}
}
for (var i=0; i < pointsOffLine.length; i++) {
if (isOnLine(pointA, pointB, pointsOffLine[i])) {
console.log('error', pointsOffLine[i]);
} else {
console.log('test passed -- point off line')
}
}
for (var i=0; i < pointsOnLineBetween.length; i++) {
if (!isOnLine(pointA, pointB, pointsOnLineBetween[i], true)) {
console.log('error', pointsOnLineBetween[i]);
} else {
console.log('test passed -- point on line between')
}
}
for (var i=0; i < pointsOffLineBetween.length; i++) {
if (isOnLine(pointA, pointB, pointsOffLineBetween[i], true)) {
console.log('error', pointsOffLineBetween[i]);
} else {
console.log('test passed -- point off line between')
}
}