如何确定一个 3 维向量是否包含在由其他三个向量形成的锐角区域内?
How do I determine whether a 3-dimensional vector is contained within the acute region formed by three other vectors?
我正在用 C# 开发一个项目,我在 R3 中有三个向量,我需要查明这些向量形成的区域内是否包含第三个向量。三个基向量中任意两个之间的夹角最大为90度,均在单位球面上归一化。它们可以是负数。
到目前为止,我已经尝试了矩阵向量乘法来找到向量的变换坐标。从那里,我检查所有三个组件是否都是积极的。
此方法适用于大多数情况,但在处理特定向量集时存在一些问题。问题似乎出在基向量的顺序上。基向量的处理没有特定顺序。我需要一种方法按 (x, y, z) 顺序对这三个基向量进行排序,以确保转换正确地将我的目标向量映射到 space 的正区域,当它是 "inside" 这些向量时,并在 "outside".
时进入 space 的负区域
非常感谢所有帮助。
二维相关讨论:How to determine if a vector is between two other vectors?
编辑:这些是我最终使用的解决方案。第一个非常接近 Edward 的解决方案,第二个为了在我的项目中保持一致而略有改动。
public bool Vec3Between(Vector3 s, Vector3 p, Vector3 q, Vector3 r)
{
Vector3 cross = Vector3.Cross(q, r);
float ds = cross.x * s.x + cross.y * s.y + cross.z * s.z;
float dp = cross.x * p.x + cross.y * p.y + cross.z * p.z;
bool same_qr = (ds * dp >= 0);
cross = Vector3.Cross(r, p);
ds = cross.x * s.x + cross.y * s.y + cross.z * s.z;
float dq = cross.x * q.x + cross.y * q.y + cross.z * q.z;
bool same_rp = (ds * dq >= 0);
cross = Vector3.Cross(p, q);
ds = cross.x * s.x + cross.y * s.y + cross.z * s.z;
float dr = cross.x * r.x + cross.y * r.y + cross.z * r.z;
bool same_pq = (ds * dr >= 0);
return same_qr && same_rp && same_pq;
}
public bool Vec3Between(Vector3 vTarget, Vector3[] vRef)
{
bool same_side = true;
for (int i = 0; i < 3; i++)
{
int i1 = (i < 2) ? (i + 1) : 0;
int i2 = (i > 0) ? (i - 1) : 2;
Vector3 cross = Vector3.Cross(vRef[i1], vRef[i2]);
float plane_vTarget = cross.x * vTarget.x + cross.y * vTarget.y + cross.z * vTarget.z;
float plane_vRef = cross.x * vRef[i].x + cross.y * vRef[i].y + cross.z * vRef[i].z;
same_side = same_side && (plane_vTarget * plane_vRef >= 0);
}
return same_side;
}
如果您发布一些示例,也许还有一些代码,那就太好了。
在没有这些信息的情况下,让我建议另一种方法。令定义space区域的三个向量为p=(p1,p2,p3)
、q=(q1,q2,q3)
、r=(r1,r2,r3)
和第四个点s=(s1,s2,s3)
。我们需要执行 3 个测试:
1) s
和p
在q
和r
形成的平面的同一侧吗?
2) s
是否与r
和p
形成的平面的q
在同一侧?
3) s
是否与p
和q
形成的平面的r
在同一侧?
所有三个问题的答案都是肯定的,这相当于您正在寻找的几何 属性。我会告诉你如何回答 1)。那么2)和3)类推。
我们通过叉积q x r = (q2*r3-q3*r2, q3*r1-q1*r3, q1*r2-q2*r1) = (a,b,c)
找到通过q、r和原点的平面。那么平面的方程就是a*x + b*y + c*z = 0
.
我们把s
的坐标代入上式的lhs,得到表达式a*s1 + b*s2 + c*s3
,它有一些值ds
,比如说。我们把p
的坐标代入上面公式的lhs,得到表达式a*p1 + b*p2 + c*p3
,它有一些值dp
,比如说
如果ds
和dp
符号相同,则s
和p
在平面的同一侧。如果 ds
和 dp
符号不同,则 s
和 p
在平面的两侧。
这是一个用于整体测试的布尔表达式:
(
((q2*r3-q3*r2)*s1 + (q3*r1-q1*r3)*s2 + (q1*r2-q2*r1)*s3)
*((q2*r3-q3*r2)*p1 + (q3*r1-q1*r3)*p2 + (q1*r2-q2*r1)*p3)
> 0
)
&&
(
((r2*p3-r3*p2)*s1 + (r3*r1-p1*r3)*s2 + (r1*p2-r2*p1)*s3)
*((r2*p3-r3*p2)*q1 + (r3*p1-r1*p3)*q2 + (r1*p2-r2*p1)*q3)
> 0
)
&&
(
((p2*q3-p3*q2)*s1 + (p3*q1-p1*q3)*s2 + (p1*q2-p2*q1)*s3)
*((p2*q3-p3*q2)*r1 + (p3*q1-p1*q3)*r2 + (p1*q2-p2*q1)*r3)
> 0
)
我正在用 C# 开发一个项目,我在 R3 中有三个向量,我需要查明这些向量形成的区域内是否包含第三个向量。三个基向量中任意两个之间的夹角最大为90度,均在单位球面上归一化。它们可以是负数。
到目前为止,我已经尝试了矩阵向量乘法来找到向量的变换坐标。从那里,我检查所有三个组件是否都是积极的。
此方法适用于大多数情况,但在处理特定向量集时存在一些问题。问题似乎出在基向量的顺序上。基向量的处理没有特定顺序。我需要一种方法按 (x, y, z) 顺序对这三个基向量进行排序,以确保转换正确地将我的目标向量映射到 space 的正区域,当它是 "inside" 这些向量时,并在 "outside".
时进入 space 的负区域非常感谢所有帮助。
二维相关讨论:How to determine if a vector is between two other vectors?
编辑:这些是我最终使用的解决方案。第一个非常接近 Edward 的解决方案,第二个为了在我的项目中保持一致而略有改动。
public bool Vec3Between(Vector3 s, Vector3 p, Vector3 q, Vector3 r)
{
Vector3 cross = Vector3.Cross(q, r);
float ds = cross.x * s.x + cross.y * s.y + cross.z * s.z;
float dp = cross.x * p.x + cross.y * p.y + cross.z * p.z;
bool same_qr = (ds * dp >= 0);
cross = Vector3.Cross(r, p);
ds = cross.x * s.x + cross.y * s.y + cross.z * s.z;
float dq = cross.x * q.x + cross.y * q.y + cross.z * q.z;
bool same_rp = (ds * dq >= 0);
cross = Vector3.Cross(p, q);
ds = cross.x * s.x + cross.y * s.y + cross.z * s.z;
float dr = cross.x * r.x + cross.y * r.y + cross.z * r.z;
bool same_pq = (ds * dr >= 0);
return same_qr && same_rp && same_pq;
}
public bool Vec3Between(Vector3 vTarget, Vector3[] vRef)
{
bool same_side = true;
for (int i = 0; i < 3; i++)
{
int i1 = (i < 2) ? (i + 1) : 0;
int i2 = (i > 0) ? (i - 1) : 2;
Vector3 cross = Vector3.Cross(vRef[i1], vRef[i2]);
float plane_vTarget = cross.x * vTarget.x + cross.y * vTarget.y + cross.z * vTarget.z;
float plane_vRef = cross.x * vRef[i].x + cross.y * vRef[i].y + cross.z * vRef[i].z;
same_side = same_side && (plane_vTarget * plane_vRef >= 0);
}
return same_side;
}
如果您发布一些示例,也许还有一些代码,那就太好了。
在没有这些信息的情况下,让我建议另一种方法。令定义space区域的三个向量为p=(p1,p2,p3)
、q=(q1,q2,q3)
、r=(r1,r2,r3)
和第四个点s=(s1,s2,s3)
。我们需要执行 3 个测试:
1) s
和p
在q
和r
形成的平面的同一侧吗?
2) s
是否与r
和p
形成的平面的q
在同一侧?
3) s
是否与p
和q
形成的平面的r
在同一侧?
所有三个问题的答案都是肯定的,这相当于您正在寻找的几何 属性。我会告诉你如何回答 1)。那么2)和3)类推。
我们通过叉积q x r = (q2*r3-q3*r2, q3*r1-q1*r3, q1*r2-q2*r1) = (a,b,c)
找到通过q、r和原点的平面。那么平面的方程就是a*x + b*y + c*z = 0
.
我们把s
的坐标代入上式的lhs,得到表达式a*s1 + b*s2 + c*s3
,它有一些值ds
,比如说。我们把p
的坐标代入上面公式的lhs,得到表达式a*p1 + b*p2 + c*p3
,它有一些值dp
,比如说
如果ds
和dp
符号相同,则s
和p
在平面的同一侧。如果 ds
和 dp
符号不同,则 s
和 p
在平面的两侧。
这是一个用于整体测试的布尔表达式:
(
((q2*r3-q3*r2)*s1 + (q3*r1-q1*r3)*s2 + (q1*r2-q2*r1)*s3)
*((q2*r3-q3*r2)*p1 + (q3*r1-q1*r3)*p2 + (q1*r2-q2*r1)*p3)
> 0
)
&&
(
((r2*p3-r3*p2)*s1 + (r3*r1-p1*r3)*s2 + (r1*p2-r2*p1)*s3)
*((r2*p3-r3*p2)*q1 + (r3*p1-r1*p3)*q2 + (r1*p2-r2*p1)*q3)
> 0
)
&&
(
((p2*q3-p3*q2)*s1 + (p3*q1-p1*q3)*s2 + (p1*q2-p2*q1)*s3)
*((p2*q3-p3*q2)*r1 + (p3*q1-p1*q3)*r2 + (p1*q2-p2*q1)*r3)
> 0
)