Search code examples
algorithmunity-game-engine3dgeometryarcore

Program to convert points on 3D plane to 2D points


I have the normal vector of the plane . I want to convert the 3D points onto a 2D plane maintaining the same distances between them. Basically what I want to do is make the z coordinate of all the points on the plane equal. How do I go about achieving this and writing a program for it (Preferably C#)? . Are there any good libraries that I can use . Will this library be useful Point Cloud Library

My objective in doing this is I have several lines(on the same plane) in 3D space and I want to represent these lines in 2D along with their measurements

An example plane of my problem. enter image description here

I am doing this for an application I am developing in unity using Google ARcore


Solution

  • Ok I have invested a fair amount of time in finding a solution to this problem . I figured out a simple solution to this problem using ARcore as I am doing this using ARCore(Augmented reality SDK provided by Google) . For those who want to achieve this without using ARcore refer these questions Question 1 Question 2 where a new orthonormal basis has to be created or the plane has to be rotated in order to align with the default planes.

    For those who are using ARcore in unity , there is a simpler solution given in this issue on GitHub created by me . Basically we can easily create new axes on the 3D plane and record coordinates from this newly created coordinate system.

    If you want to project 3d points on a plane, you need to have a 2d coordinate system in mind. A natural one is the one defined by the global axis, but that will work well with one kind of planes (say horizontal) but not another (say vertical). Another choice of coordinates is the one defined by CenterPose, but it can change every frame. So if you need the 2d points only for 1 frame, this is can be written as:

    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);
    

    If you need a 2d coordinate system that is consistent between frames, you probably would want to attach an anchor to any plane of interest, maybe at DetectedPlane.CenterPose, and do the same math as above, but with anchor rotation instead of plane rotation. The x and z axes of the anchor will provide a 2d frame of coordinates that is consistent between frames.

    So here , a new local axes are created on the center of the plane and the points obtained would have only 2 coordinates .