Projecting a Point onto a Plane

Projecting a Point onto a Plane

This is done in a series of small steps;

  • Defining an Arbitrary point on the plane
  • Creating a Vector from the point to be Projected to the Arbitrary point
  • Define the Dot product of the two vectors
  • Translate the point to be Projected along the Planes Vector

A plane passing through the Point (P) = 1 ; 3 ; 2 and has Normal Vector (N) = 6 ; 7 ; 5, then the equation of the plane is;

Point (P) = 1 \space; \space 3 \space ; \space 2 \\
\overrightarrow{N} = 6 \space ; \space 7 \space ; \space 5 \\
Plane \space Equation =  6(x−1 \normalsize)+7(y−3 \normalsize)+5(z−2 \normalsize)=0 \\
= 6x - 6 + 7y-21+5z-10 = 0 \\
= 6x + 7y + 5z  -6 -21 -10 = 0 \\
= 6x + 7y + 5z  -37 = 0 \\

Defining the Arbitrary Point on the Plane

So now we have the plane equation that we want to work with. Lets start of with an easy one, a Point(B) 12 ; 23 ; 34 projected onto the plane, our first step is to create an arbitrary point on the plane, to do this well use Point(A) 5 ; 5 ; Z

Point (A) = 5 \space; \space 5 \space ; \space Z \\
Plane Equation = 6x + 7y + 5z  - 37 = 0 \\
= ( 6 * 5 ) + ( 7 * 5 ) + ( 5 * Z ) - 37 = 0 \\
= 30 + 35 + 5Z - 37 = 0 \\
= 5Z = - 30 - 35 + 37 \\
= 5Z = -28 \\
= Z = -28/5\\
= Z = -5.6

We have now fully resolved Point(A) 5 ; 5 ; -5.6, if we cant resolve for Z, then we should retry resolving for Y or X to define the arbitrary point on the surface.

Defining the Arbitrary Unit Vector

The next step is to create an additional vector from the arbitrary Point(A) 5 ; 5 ; -5.6 to the projection Point(B) 12 ; 23 ; 34

\overrightarrow{BA} \\
= Ax - Bx ; Ay - By ; Az - Bz \\
= 5 - 12 ; 5 - 23 ; -5.6 - 34 \\
\overrightarrow{BA}= -7 ; -18 ; -39.6 \\
I = -7 ; J = -18 ; K = -39.6

Dot Product of the Projection

First Step the magnitude of the planes vector.

||{N}|| = \sqrt{I^2 + J^2 + K^2}  \\
= \sqrt{6^2 + 7^2 + 5^2}  \\
= \sqrt{36 + 49 + 25}  \\
= \sqrt{110}  \\
= 10.488  \\

Next we can convert the planes vector into a unit vector.

\widehat{N} = \overrightarrow{N} / ||{N}|| \\
= (6/10.488) ; (7/10.488) ; (5/10.488)\\
= 0.572 ; 0.667 ; 0.476 \\

Ok so far so good. Now for the Dot Product of the Projection.

||BP|| = \overrightarrow{BA} \cdotp \widehat{N} \\
= (BA\tiny{X}\cdotp \normalsize N\tiny{X} \normalsize)+(BA\tiny{Y}\cdotp \normalsize N\tiny{Y} \normalsize)+(BA\tiny{Z}\cdotp \normalsize N\tiny{Z} \normalsize)\\
= ( -7 * 0.5721 ) + ( -18 * 0.6674 ) + ( -39.6 * 0.4767 ) \\
= -4.0047 + (-12.0132) + (-18.5913) \\
= -34.897

Translating the vector

Last steps

\overrightarrow{BP} = ||BP||\cdotp(\widehat{N}/||N||)\\
= (-34.897 * 0.5721) ; (-34.897 * 0.667) ; (-34.897 * 0.476) \\
= -19.964 ; -23.291 ; -16.636

Finally well add the projection point to the vector(BP)

Point(C) = \overrightarrow{BP} + Point(B)\\
= (12 + (-19.964)) ; (23 +(-23.291)) ; (34+(-16.636))\\
=-7.9636 ; -0.2909 ; 17.364

C# Code

Using the following C# Code this can be demonstrated.

We can see in the Point Class the Projection Code.

Wireframe Class

namespace BasicGeometry
{
    public interface IWireframe
    {

    }
    public class Wireframe:IWireframe
    {

    }
}

Point Class

namespace BasicGeometry
{
    public interface IPoint
    {
        double X { get; set; }
        double Y { get; set; }
        double Z { get; set; }
    }
    public class Point : Wireframe,IPoint
    {
        public double X { get; set; } = 0;
        public double Y { get; set; } = 0;
        public double Z { get; set; } = 0;

        public Point() { }
        public Point(double x, double y, double z)
        {
            X = x;
            Y = y;
            Z = z;
        }

        public Point(IPoint point, IPlane plane)
        {
            //5,5,Z is Arbitary but we Must Calculate Z
            double i = plane.UnitVector.I * -5;
            double j = plane.UnitVector.J * -5;
            double Z = (i + j + plane.D)/plane.UnitVector.K;
            Point pointOnPlane = new Point(5,5,Z);

            //Define a New Vector Back to the Poitn Being Projected
            Vector vector = new Vector(point, pointOnPlane);

            //Dot Projection of the Vector, get the distance from the point to the plane
            double dist = ((Math.Abs((plane.A * vector.I) + (plane.B * vector.J) + (plane.C * vector.K)))/plane.Vector.Length);

            //Move Original Point by Length and Distance
            IPoint projectionPoint = TranslatePointAlongVector(point, plane.UnitVector, dist*-1);

            this.X= projectionPoint.X;
            this.Y= projectionPoint.Y;
            this.Z= projectionPoint.Z;
        }

        private IPoint TranslatePointAlongVector(IPoint point, IUnitVector vector, double offset)
        {
            IPoint returnPoint = new Point();
            returnPoint.X = (vector.I * offset) + point.X;
            returnPoint.Y = (vector.J * offset) + point.Y;
            returnPoint.Z = (vector.K * offset) + point.Z;
            return returnPoint;
        }
    }
}

Line Class

namespace BasicGeometry
{
    public interface ILine
    {
        Point SPt { get; set; }
        Point EPt { get; set; }

        double Length { get; }
    }
    public class Line : Wireframe, ILine
    {
        public Point SPt { get; set; } = new Point(0,0,0);
        public Point EPt { get; set; } = new Point(0,0,1);

        public double Length 
        { 
            get{
                return 
                    Math.Sqrt(
                          Math.Pow((EPt.X - SPt.X),2)
                        + Math.Pow((EPt.Y - SPt.Y),2)
                        + Math.Pow((EPt.Z - SPt.Z),2)
                    );
            }
        }
    }
}

Vector Class

namespace BasicGeometry
{
    public interface IVector
    {
        double I { get; set; }
        double J { get; set; }
        double K { get; set; }
        double Length { get;}
        UnitVector UnitVector { get;}
    }
    public class Vector : Wireframe, IVector
    {
        public double I { get; set; } = 0;
        public double J { get; set; } = 0;
        public double K { get; set; } = 1;

        public double Length
        {
            get
            {
                return
                    Math.Sqrt(
                          Math.Pow(I, 2)
                        + Math.Pow(J, 2)
                        + Math.Pow(K, 2)
                    );
            }
        }

        public UnitVector UnitVector
        {
            get
            {
                return new UnitVector(this);
            }
        }

        public Vector() { }

        public Vector(double i, double j, double k)
        {
            I = i;
            J = j;
            K = k;
        }
        public Vector(IPoint SPt, IPoint EPt)
        {
            I = EPt.X-SPt.X;
            J = EPt.Y-SPt.Y;
            K = EPt.Z-SPt.Z;
        }
    }
}

Unit Vector Class

namespace BasicGeometry
{
    public interface IUnitVector
    {
        double I { get; }
        double J { get; }
        double K { get;}
        double Length { get; }
    }
    public class UnitVector : Wireframe, IUnitVector
    {
        public double I { get; } = 0;
        public double J { get; } = 0;
        public double K { get;  } = 1;

        public double Length
        {
            get
            {
                return
                    Math.Sqrt(
                          Math.Pow(I, 2)
                        + Math.Pow(J, 2)
                        + Math.Pow(K, 2)
                    );
            }
        }

        public UnitVector() { }

        public UnitVector(IVector vector) 
        { 
            I = vector.I/vector.Length;
            J = vector.J/vector.Length;
            K = vector.K/vector.Length;     
        }
    }
}

Plane Class

namespace BasicGeometry
{
    public interface IPlane
    {
        double A { get; set; }
        double B { get; set; }
        double C { get; set; }
        double D { get; set; }
        UnitVector UnitVector { get; }
        Vector Vector { get;}
    }
    public class Plane : Wireframe, IPlane
    {
        public double A { get; set; } = 0;
        public double B { get; set; } = 0;
        public double C { get; set; } = 1;
        public double D { get; set; } = 0;

        public UnitVector UnitVector 
        {
            get 
            {
                return new UnitVector(new Vector(A, B, C));
            }
        }

        public Vector Vector
        {
            get
            {
                return new Vector(A, B, C);
            }
        }

        public Plane() {}

        public Plane(double a, double b, double c, double d)
        {
            A = a;
            B = b;
            C = c;
            D = d;
        }

        public Plane(Vector vector,Point point)
        {
            A = vector.I;
            B = vector.J;
            C = vector.K;
            D = ((point.X * UnitVector.I) + (point.Y * UnitVector.J) + (point.Z * UnitVector.K));
        }

        public Plane(Vector vector1,Vector vector2,Point point) 
        {
            Vector vector3 = VectorCrossProduct(vector1, vector2);

            A = vector3.I;
            B = vector3.J;
            C = vector3.K;
            D = ((point.X * UnitVector.I) + (point.Y * UnitVector.J) + (point.Z * UnitVector.K));
        }

        public Plane(Point point1, Point point2, Point point3)
        {
            Vector vector1 = new Vector(point1, point2);
            Vector vector2 = new Vector(point1, point3);

            Vector vector3 = VectorCrossProduct(vector1, vector2);

            A = vector3.I;
            B = vector3.J;
            C = vector3.K;
            D = ((point1.X* UnitVector.I) + (point1.Y * UnitVector.J) + (point1.Z * UnitVector.K));
        }

        private Vector VectorCrossProduct(Vector vector1, Vector vector2)
        {
            double i = (vector1.J * vector2.K) - (vector2.J * vector1.K);
            double j = -((vector1.I * vector2.K) - (vector2.I * vector1.K));
            double k = (vector1.I * vector2.J) - (vector2.I * vector1.J);
            return new Vector(i, j, k);
        }

        private double distance(Point point)
        {

            return
                Math.Sqrt(
                        Math.Pow((point.X), 2)
                    + Math.Pow((point.Y), 2)
                    + Math.Pow((point.Z), 2)
                );
        }
    }
}