4

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

Kitwradr
  • 1,986
  • 3
  • 18
  • 32
  • Are you using Unity? – lockstock Jun 28 '18 at 09:45
  • Yes I am using unity – Kitwradr Jun 28 '18 at 09:45
  • Why not just set the z component of each point to 0? – lockstock Jun 28 '18 at 09:46
  • The 3d plane can have random rotation , it is not parallel to default planes (like xy plane) – Kitwradr Jun 28 '18 at 09:48
  • Do you want to make projections of points onto the plane? – MBo Jun 28 '18 at 10:00
  • Yes , but I want the distances to be same , it shouldn't change . z coordinate should be equal for all points . It's similar to this [question](https://stackoverflow.com/questions/49769459/convert-points-on-a-3d-plane-to-2d-coordinates) – Kitwradr Jun 28 '18 at 10:05
  • Are you talking about vector projection? – pseudoabdul Jun 28 '18 at 10:43
  • And all your points lie in the same plane (as in linked question)? – MBo Jun 28 '18 at 10:46
  • Yes they lie in the same plane as in my main question(points on a 3D plane) – Kitwradr Jun 28 '18 at 11:07
  • 2
    So you can just apply my answer from linked question, can't you? – MBo Jun 28 '18 at 11:10
  • `z coordinate should be equal for all points` - so why not just use only the XY coordinates? – meowgoesthedog Jun 28 '18 at 11:43
  • Read the comments above , the 3D plane is not parallel to axes - it can have a random normal vector – Kitwradr Jun 28 '18 at 11:45
  • A plane is 2D already - the local co-ordinates on that plane already fulfil the requirement as written, don't they? – Mister Magoo Jun 28 '18 at 12:33
  • The plane is 3D not 2D – Kitwradr Jun 28 '18 at 12:37
  • A plane is a 2D shape. You may have it oriented and positioned within 3D space, but the local co-ordinates on the plane are 2D. – Mister Magoo Jun 28 '18 at 12:45
  • I have to ask what you are trying to achieve, actually - Unity has a good set of tools, and if you just want to display a 2D projection, like a side view of a building, you don't need to calculate anything. – Mister Magoo Jun 28 '18 at 12:50
  • 1
    If the plane is not parallel to any axes, then how would you make all Z coordinates equal? – meowgoesthedog Jun 28 '18 at 18:33
  • 1
    Also, [this question](https://stackoverflow.com/questions/49152154/getting-axis-aligned-coordinates-from-generic-plane) may be of use to you. – meowgoesthedog Jun 28 '18 at 18:39
  • Axis alligned coordinates will not work for what he is asking, he wants to have a plane with a random rotation. Basically he wants to Project his Vector onto the plane. This may help: https://math.stackexchange.com/questions/633181/formula-to-project-a-vector-onto-a-plane – AresCaelum Jun 28 '18 at 18:53
  • 2
    even if OP *wants* to project his vectors in a plane, id doesn't mean she *needs* to do that to obtain the desired effect. The prefered solution, definitely, is using local 2D coordinates and apllying the desired transformation with the transform component. I've done both things before and I swear I know what I'm saying. – Rodrigo Rodrigues Jun 29 '18 at 03:41
  • @eddge the question I linked has a misleading title - in fact the author was trying to project points onto an arbitrary plane, modify them in-plane, and project them back to 3D. The first step is what OP wants. – meowgoesthedog Jun 29 '18 at 07:33

2 Answers2

3

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 .

Kitwradr
  • 1,986
  • 3
  • 18
  • 32
0

I needed this in Unity C# so here's some code that I used.

First of, project the point onto the plane. Then using the dot values for the targeted transforms right and forward I got the local 2D coordinates.

So if you want the standard coords replace right with (1,0) and forward with (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: The GetClosestPointOnPlane function is part of some old stuff I made over a decade ago back in school made in C++ converted to C#. It might be based on something in my old school book but I cant say for sure. The rest I made my self after looking around for a while and not finding something that worked.

LocalDude
  • 1
  • 1
  • a reference to where you got the code/or if you made it yourself, a link/to docs would be good, otherwise i see no problem with this post. Other than, maybe comments to explain what the code does ^^ Welcome to StackOverflow, by the way. :) – William Martens Jan 13 '23 at 11:06