【发布时间】:2016-08-24 13:48:07
【问题描述】:
我从 Kinect 输出的图像中选择 4 个点,因此每个点都有其 (x, y, z) 坐标。
我的目标是确定这 4 个点是否落在同一平面上。
这是我的功能:
public bool isValidPlane()
{
for (int i = 0; i < edgesPoints.Length; i++)
{
double absPlaneEquation = Math.Abs(distance -
(normal.X * edgesPoints[i].X + normal.Y * edgesPoints[i].Y + normal.Z * edgesPoints[i].Z));
if (absPlaneEquation > 1500) /* 1500 is a tolerance error*/
{
return false;
}
}
return true;
}
normal 也是平面的法线(平面上 2 个向量的叉积,之前是从 4 个所选点中的 3 个计算得出的)到平面并已归一化:
private void calcPlaneNormalVector()
{
if (lastEdgeNumber < 3)
{
return;
}
Vector3D vec1 = new Vector3D(edgesPoints[0], edgesPoints[1]);
Vector3D vec2 = new Vector3D(edgesPoints[0], edgesPoints[2]);
vec2 = vec1.crossProduct(vec2);
double lengthNormal = Math.Sqrt(Math.Pow(vec2.X, 2) + Math.Pow(vec2.Y, 2) + Math.Pow(vec2.Z, 2));
//normalizing:
normal = new Vector3D((vec2.X / lengthNormal), (vec2.Y / lengthNormal), (vec2.Z / lengthNormal));
distance = (-1) * (edgesPoints[0].X * normal.X + edgesPoints[0].Y * normal.Y + edgesPoints[0].Z + normal.Z);
}
Vector3D是一个类来表示一个向量:
public class Vector3D
{
private double x, y, z;
public Vector3D(Point3D p1, Point3D p2)
{
x = p2.X - p1.X;
y = p2.Y - p1.Y;
z = p2.Z - p1.Z;
}
public Vector3D(double a = 0, double b = 0, double c = 0)
{
x = a;
y = b;
z = c;
}
<get properties for x, y, z >
public Vector3D crossProduct(Vector3D u)
{
double tmpX = 0, tmpY = 0, tmpZ = 0;
tmpX = y * u.Z - z * u.Y;
tmpY = z * u.X - x * u.Z;
tmpZ = x * u.Y - y * u.X;
return new Vector3D(tmpX, tmpY, tmpZ);
}
public double dotProduct(Vector3D u)
{
return x * u.X + y * u.Y + z * u.Z;
}
}
即使选择了 4 个点,我总是得到1300 <= absPlaneEquation <= 1400,这样它们就不会在同一个平面上。
检测这 4 个点是否指向同一平面的最佳方法是什么?
【问题讨论】:
-
@MattWilko,这不是重复的。您发布的问题更具理论性,在这里我更加重视技术实施。此外,与您所说的问题的理想情况不同,kinect 存在一定程度的错误。
-
实际上,该问题有一个公认的解决方案,其中包含一个 C++ 函数来准确计算您正在寻找的内容。看起来它会转换为 C# 而不会更改大约三个字符。
-
不确定这是否有帮助,但这里有一篇关于如何做到这一点的文章(更多是从数学角度而不是计算机科学角度,但仍然......):quora.com/…