将三维平面上的点转换为二维点的程序

4
我有平面的法向量。我想将3D点转换为2D平面,并保持它们之间的距离不变。基本上,我想做的是使平面上所有点的z坐标相等。我该如何实现并编写程序(最好使用C#)?是否有任何好的库可供使用?这个库会有用吗 Point Cloud Library
我的目标是,在3D空间中有几条线(在同一平面上),我想用它们的测量值表示这些线在2D中的形状。
问题示例平面:enter image description here 我正在为我在Unity中使用Google ARcore开发的应用程序做这件事

3D平面可以随机旋转,它不与默认平面(如xy平面)平行。 - Kitwradr
2
那么你只需应用我在链接问题中的答案,是吗? - MBo
1
如果飞机不平行于任何轴线,那么你如何使所有Z坐标相等? - meowgoesthedog
1
此外,这个问题可能对您有所帮助。 - meowgoesthedog
2
即使 OP 想要将他的向量投影到一个平面上,也并不意味着她需要这样做才能获得所需的效果。首选解决方案肯定是使用本地 2D 坐标,并使用 transform 组件应用所需的变换。我以前做过这两件事,我发誓我知道我在说什么。 - Rodrigo Rodrigues
显示剩余16条评论
2个回答

3

我在解决这个问题上已经花费了相当多的时间。由于我正在使用由Google提供的ARCore(增强现实SDK),因此我找到了一个简单的方法来解决这个问题。对于那些想要在不使用ARCore的情况下实现这一目标的人,请参考问题1问题2,其中必须创建一个新的正交基或旋转平面,以便与默认平面对齐。

对于那些在Unity中使用ARCore的人,可以在我在GitHub上创建的问题中找到更简单的解决方案。基本上,我们可以轻松地在3D平面上创建新坐标轴,并记录来自这个新坐标系的坐标。

如果您想要将3D点投影到平面上,则需要考虑一个2D坐标系。其中一个自然的选择是由全局坐标轴定义的坐标系,但这只适用于某种类型的平面(例如水平平面),而对于另一种类型的平面(例如垂直平面)则不适用。另一个坐标系选择是由CenterPose定义的,但它每一帧都会改变。因此,如果您只需要1帧的2D点,则可以写成:

x_local_axis = DetectedPlane.CenterPose.rotation * Vector3.forward;
z_local_axis = DetectedPlane.CenterPose.rotation * Vector3.right;
// loop over your points
x = Vector3.Dot(your_3d_point, x_local_axis);
z = Vector3.Dot(your_3d_point, z_local_axis);

如果您需要一个在帧之间保持一致的2D坐标系,您可能想将锚点附加到任何感兴趣的平面上,例如DetectedPlane.CenterPose,并执行与上文相同的数学运算,但使用锚点旋转而不是平面旋转。 锚点的x和z轴将提供一个在帧之间保持一致的二维坐标系。
因此,在平面中心创建了一个新的本地坐标系,并获得的点仅具有2个坐标。

0

我在Unity C#中需要这个,所以这里是我使用的一些代码。

首先,将该点投影到平面上。 然后使用目标变换的右和前向的点值,我得到了本地2D坐标。

因此,如果您想要标准坐标,请将右替换为(1,0),将前向替换为(0,1)

public static Vector3 GetClosestPointOnPlane(Vector3 point, Plane3D plane){
    Vector3 dir = point - plane.position;//Direction between the plane / Point
    plane.normal = plane.normal.normalized;
    float dotVal = Vector3.Dot(dir.normalized, plane.normal);//Check if the tow are facing each other.
    
    return point + plane.normal * dir.magnitude * (-dotVal);//Multiplying the angle(DotVal) with the magnitude gives the distance.
}


    Intersection.Plane3D tempPlane = new Intersection.Plane3D(transform.position, transform.up);//Plane3D is just a point and a normal.
    Vector3 closestPoint = Intersection.GetClosestPointOnPlane(testPoint.position, tempPlane);
    float xPos = Vector3.Dot((closestPoint - transform.position).normalized, transform.right);
    float yPos = Vector3.Dot((closestPoint - transform.position).normalized, transform.forward);

    float dist = (closestPoint - transform.position).magnitude;
    planePos = new Vector2(xPos * dist, yPos * dist);//This is the value that your looking for.

@William Martens FYI:GetClosestPointOnPlane函数是我十多年前在学校用C++编写的一些旧东西,现在已转换为C#。它可能基于我旧学校书中的某些内容,但我不能确定。其余部分是我自己制作的,在寻找一段时间后没有找到适合的内容。


欢迎来到StackOverflow。如果您引用了代码,请提供代码来源的参考或链接。如果是自己编写的代码,也可以提供文档链接。此外,最好添加注释以解释代码的功能。 - William Martens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接