Javascript 如何确定一个点是否位于其他两个点之间?

Javascript 如何确定一个点是否位于其他两个点之间?,javascript,math,three.js,geometry,Javascript,Math,Three.js,Geometry,我做了一个不太正常的小函数 function isPointbetweenTwoOthers (pA, pB, pToCheck) { var pApB = new THREE.Vector3(); pApB.subVectors(pA,pB).normalize(); var pBpA = new THREE.Vector3(); pBpA.subVectors(pB,pA).normalize(); var pA_pToCheck = new TH

我做了一个不太正常的小函数

function isPointbetweenTwoOthers (pA, pB, pToCheck) {
    var pApB = new THREE.Vector3();
    pApB.subVectors(pA,pB).normalize();

    var pBpA = new THREE.Vector3();
    pBpA.subVectors(pB,pA).normalize();

    var pA_pToCheck = new THREE.Vector3();
    pA_pToCheck.subVectors(pA,pToCheck).normalize();

    var pB_pToCheck = new THREE.Vector3();
    pB_pToCheck.subVectors(pB,pToCheck).normalize();

    if(pA_pToCheck.dot(pApB) <0 || pB_pToCheck.dot(pBpA) <0)
    return false
    else return true
}
现在(下图中的暗球体是C点),只要我加上0.999999,它就会输出这种情况。如果没有它,它在这种情况下可以正常工作。。。 但在另一个没有0.9999的情况下,它告诉我C不在A和B之间,使用以下几点

var t1 = new THREE.Vector3(1,1,1); //A
var t2 = new THREE.Vector3(-1,1,1); //B
var t3 = new THREE.Vector3(-0.3999999999999999,1,1);  //C

要检查C是否在A和B之间,请计算向量差
u=子向量(pB,pA)
v=子向量(pC,pA)
。分别计算两个向量的长度
lu
lv
。如果
lv>lu
,则返回false,因为C距离A比B远。如果不是这种情况,请检查
u
v
的点积是否等于
lu*lv
(或者如果它大于
0.9999*lu*lv
,则有一些数字公差),在这种情况下返回true,否则返回false。说明:如果C离A的距离不超过B,并且A到B和A到C的向量是平行的(但不是反平行的),则点积是
lu*lv
(cos(0度)=1,而cos(180度,反平行情况)=-1)和C位于A和B之间。

要检查C是否在A和B之间,例如,计算向量差
u=子向量(pB,pA)
v=子向量(pC,pA)
。分别计算两个向量的长度
lu
lv
。如果
lv>lu
,则返回false,因为C距离A比B远。如果不是这种情况,请检查
u
v
的点积是否等于
lu*lv
(或者如果它大于
0.9999*lu*lv
,则有一些数字公差),在这种情况下返回true,否则返回false。说明:如果C与A的距离不超过B,且A到B和A到C的矢量平行(但不是反平行),则点积为
lu*lv
(cos(0度)=1,而cos(180度,反平行情况)=-1)C位于A和B之间。

如果你想计算从点pA到点pB的向量,那么你必须从pB(
pbpa
)减去pA,而不是从pA(
papb
)减去pB。
注意,计算
a-b


简短回答

验证
pA
pToCheck
之间的距离以及
pB
pToCheck
之间的距离是否小于或等于
pA
pB
之间的距离
并验证向量形式分别
pA
pToCheck
pB
pToCheck
之间的角度是否接近于0:

这可以分别通过以下方式实现:

功能在扬声器之间显示(pA、pB、pToCheck){
设distAtoB=pA.distanceTo(pB);
设distAtoC=pA.distanceTo(pToCheck);
设distBtoC=pB.distanceTo(pToCheck);
如果(distAtoC>distAtoB | | distBtoC>distAtoB)
返回false;
设vAtoB=pB.clone().sub(pA);
设vBtoA=pA.clone().sub(pB);
让vAtoC=pToCheck.clone().sub(pA);
设vBtoC=pToCheck.clone().sub(pB);
设angleAC=vAtoB.angleTo(vAtoC);
设angleBC=vBtoA.angleTo(vBtoC);
设ε=0.0017;//弧度为0.1°
if(Math.abs(angleAC)>ε| | Math.abs(angleBC)>ε)
返回false;
返回true;
}

长答案

向量a和向量B之间的距离等于向量的大小(长度)和向量之间角度的余弦的乘积

A点B==|A |*| B |*cos(alpha)
如果这两个向量是(标准化的),则点积等于这两个向量之间角度的余弦:

uA=正常化(A)
uB=正常化(B)
uA点uB==cos(α)
如果角度α大于-90°且小于90°,则角度的余弦大于0;如果角度α大于-90°,则余弦为0;如果角度α小于-90°,则余弦为0。
如果角度为0°,则余弦为1.0;如果角度为180°,则余弦为-1.0

如果您只想验证pC是否位于pA和pB之间的直线上,则必须验证向量之间的角度是否分别为0°(或180°)。角度的余弦为1.0(或-1.0)。
由于运算精度有限,无法直接与1.0进行比较。您必须验证余弦是否大于接近1.0的值。
必须对矢量进行归一化,并使用与余弦(0.1°)相对应的~00016开关:

pA-pC-pB
x--------x--------x
瓦托布|----------------->|
vAtoC---->
vBtoC |(1-ε)和dot(nvAtoB,nvBtoC)<-(1-ε)
该功能必须是:

功能在扬声器之间显示(pA、pB、pToCheck){
var nvAtoB=new THREE.Vector3();
子向量(pB,pA).normalize();
var nvAtoC=new THREE.Vector3();
子向量(pToCheck,pA).normalize();
var nvBtoC=new THREE.Vector3();
子向量(pToCheck,pB).normalize();
设ε=0.0016;
设cos90epsi=1.0-ε;
返回nvAtoB.dot(nvAtoC)>cos90epsi和&nvAtoB.dot(nvBtoC)<-cos90epsi;
}

另一种方法是在从pA到pB的线路上找到距离pC最近的点pX。如果pX在pA和pB之间,并且从pX到pC的距离低于某个阈值,那么pC在pA到pB之间。由于pX位于由pA到pB定义的线上,因此将角度的余弦与0.0进行比较就足够了

如果有一条由单位方向向量
D
上的点
O
定义的直线,则交点
X
,可通过沿直线(
D
)移动点
O
)距离
D

X=O+D*D
因此,交点的公式为:

O。。。任意点o
var t1 = new THREE.Vector3(1,1,1); //A
var t2 = new THREE.Vector3(-1,1,1); //B
var t3 = new THREE.Vector3(-0.3999999999999999,1,1);  //C