Ray and Plane Intersection

I have an assingment due for my College program I'm in, and I'm stuck on getting the answers. This is the info I have.

Ray Start = 1,0,1
Ray Dir = 3,2,1

Plane = (2,1,0,-4)

This is the code I have with comments in it:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Vec3 Plane::intersectionPlane(Ray ray)
{
	// Set Plane Variables
	Vec3 N;
	N.x = plane.x;
	N.y = plane.y;
	N.z = plane.z;
	float D = plane.d;

	// Set Vec3 Variables
	Vec3 start = ray.start;
	Vec3 dir = ray.dir;

	// Find Dot Product 1
	float tempDot = N.Dot(start); // N.S
	std::cout << tempDot << endl;

	// Find Dot Product 2
	float tempDot1 = N.Dot(dir); // N.V
	std::cout << tempDot1 << endl;
	
	// float t = -(N.S + D) / N.V;
    float t = -((tempDot + D) / tempDot1);

	// tempDot + D;
	// float temp1 = tempDot + D;

	if (abs(tempDot) <= 0.00000001)
	{
		if (tempDot1 <= 0.0000001)
		{
			std::cout << "The line is contained on the plane." << endl;
		}

		else
			std::cout << "The line isn't touching." << endl;
	}

	else
	{
		std::cout << "There is point that is touching the plane." << endl;
	}

	Vec3 p = ray.currentPosition(t);
	return p;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
And this is my main.cpp
int main()
{
	Vec3 r1(1.0f, 0.0f, 1.0f); //first Ray Vec
	Vec3 r2(3.0f, 2.0f, 1.0f); //second Ray Vec

	Ray ray1(r1, r2); // Ray Variable

	Plane plane1(2, 1, 0, -4); // Plane Variable

	plane1.intersectionPlane(ray1); //find intersection point

	return 0;

}
Last edited on
1. Show ALL your code; we have to be able to run it.

2. You don't actually say WHAT your problem is.

3.
Plane = (2,1,0,-4)
is a silly statement. From the rest of your working (particularly the value of t) I would guess it meant that the equation of the plane is
2x+y+0z-4=0
i.e.
N.x+d=0
but there are multiple ways of expressing the equation of a plane and that last sign is crucial.

Let's assume that the vector equation of the ray is
x = a + t b (where a=start and b=dir in your notation)
and the equation of the plane is
N.x+d=0 (you still have to define whether that d is on the left or right).

Then the value of the parameter t (if there is one) comes from the intersection:
t = -(d+N.a)/(N.b)
and the intersection point is then
a + tb

That will work EXCEPT when N.b=0 (corresponding to the ray direction being parallel to the plane. So calculate N.b first. There are three cases:
(i) N.b=0 and d+N.a = 0
The ray lies IN the plane; any value of t will do.
(ii) N.b=0 and d+N.a is not equal to 0
There is NO intersection - ray is parallel to the plane.
(iii) N.b not equal to 0: then the solution is
t = -(d+N.a)/(N.b)
intersection = a + tb

You need to consider those possibilities in that order.

Obviously, testing for equality of floating-point numbers is fraught with difficulties associated with floating-point accuracy, so compare them with 0 up to a small tolerance (as your code appears to be trying to do).
Last edited on
It contains multiple files, I'm posting a link to the whole project.
https://drive.google.com/drive/folders/1PBWisZbSSx1k4zeuD9_R34G8rNbbv632?usp=sharing
This is how my teacher explained
Post the relevant code here - not some external site. Make sure that you have a minimal example capable of running this problem.
Ray.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "Ray.h"

Ray::Ray(Vec3 start_, Vec3 dir_)
{
	start_ = start;
	dir_ = dir;
}

void Ray::currentPosition(float t)
{
	Vec3 tempRay;

	tempRay.x = start.x + dir.x * t;
	tempRay.y = start.y + dir.y * t;
	tempRay.z = start.z + dir.z * t;

}
Vector.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include "Vector.h"

Vec3::Vec3()
{
	x = 0.0f;
	y = 0.0f;
	z = 0.0f;
}

/* Vec3 Constructor
	Set the vector's x, y, and z components to the parameters supplied*/
Vec3::Vec3(float x_, float y_, float z_)
{
	x = x_;
	y = y_;
	z = z_;
}

const Vec3 Vec3::operator+(const Vec3& v)
{
	// add two vectors
	return Vec3(x + v.x, y + v.y, z + v.z);
}

const Vec3 Vec3::operator-(const Vec3& v)
{
	// subtract two  vectors
	return Vec3(x - v.x, y - v.y, z - v.z);
}

Vec3& Vec3::operator=(const Vec3& v)
{
	// TODO: insert return statement here
	x = v.x;
	y = v.y;
	z = v.z;
	return *this;
}

const Vec3 Vec3::operator*(const float s)
{
	// mulitply two vectors
	return Vec3(s * x, s * y, s * z);
}

float Vec3::Mag()
{
	// find magniutde of vector
	float temp = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2));

	return temp;
}

void Vec3::Normalize()
{
	// stored variable value
	float mag = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2));

	x = x / mag;
	y = y / mag;
	z = z / mag;

}

Vec3 Vec3::Cross(Vec3 otherVec)
{
	// cross product
	Vec3 temp;

	temp.x = ((y * otherVec.z) - (z * otherVec.y));
	temp.y = ((z * otherVec.x) - (x * otherVec.z));
	temp.z = ((x * otherVec.y) - (y * otherVec.x));

	return temp;
}

float Vec3::Dot(Vec3 b)
{
	// dot product
	float dot = ((x * b.x) + (y * b.y) + (z * b.z));
	return dot;
}
Vector4.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include "Vector4.h"
#include "Vector.h"

Vec4::Vec4()
{
	// set variables
	x = 0;
	y = 0;
	z = 0;
	d = 0;
}

Vec4::Vec4(float x_, float y_, float z_, float d_)
{
	// set variables
	x = x_;
	y = y_;
	z = z_;
	d = d_;
}

float Vec4::Mag()
{
	// find magnitude 
	float temp = sqrt((pow(x, 2) + pow(y, 2) + pow(z, 2) + pow(d, 2)));
	return temp;
}

void Vec4::Normalize()
{
	// find normalized vector
	float mag = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2) + pow(d, 2));

	x = x / mag;
	y = y / mag;
	z = z / mag;
	d = d / mag;
}

float Vec4::Dot(Vec4 otherVec)
{
	// find dot
	float dot = ((x * otherVec.x) + (y * otherVec.y) + (z * otherVec.z) + (d * otherVec.d));
	return dot;
}
Last edited on
If you want I can include the headers, the vector header include float and the functions in the above replies
zXFlameXz,

Please put ALL the relevant code in a SINGLE post. Yes - include the headers - because otherwise it would be completely impossible to run it, wouldn't it!

Remember to state what your input is, the desired output, and what exactly your problem is.
#include"Plane.h"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <cmath>
#include "Vector4.h"
#include "Vector.h"
#include "Ray.h"

class Plane
{
public:
	Vec4 plane;

	float x, y, z, d;

	Plane();
	Plane(float x_, float y_, float z_, float d_); // set variables for Plane

	void findNormal(Vec3 normal_, float d); // Find Normal for Plane

	void definePlane(const Vec3& v0, const Vec3& v1, const Vec3& v2); // define the plane using three planes

	void intersectionPlane(Ray ray); // find the intersection point of a ray passing through the plane

	float Dot(Vec3 tempVec, float t);
};


Plane.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include<iostream>
#include "Plane.h"
#include "Ray.h"
#include "Vector.h"
#include "Vector4.h"
using namespace std;

Plane::Plane()
{
	x = 0.0f;
	y = 0.0f;
	z = 0.0f;
	d = 0.0f;
}

Plane::Plane(float x_, float y_, float z_, float d_)
{
	plane.x = x_;
	plane.y = y_;
	plane.z = z_;
	plane.d = d_;
}

void Plane::findNormal(Vec3 normal_, float d_)
{
	plane.x = normal_.x;
	plane.y = normal_.y;
	plane.z = normal_.z;
	plane.d = d_;
}

void Plane::definePlane(const Vec3& v0, const Vec3& v1, const Vec3& v2)
{
	// Multiply two vectors
	Vec3 temp1;
	Vec3 temp2;

	temp1.x = v0.x - v1.x;
	temp1.y = v0.y - v1.y;
	temp1.z = v0.z - v1.z;

	temp2.x = v0.x - v2.x;
	temp2.y = v0.y - v2.y;
	temp2.z = v0.z - v2.z;

	// Find Cross Product 
	Vec3 crossProduct = temp1.Cross(temp2);

	// Normalize Cross Product
	crossProduct.Normalize();

	// Find Dot Product
	float dot = crossProduct.Dot(v0);

	// Find Normal
	findNormal(v0, dot);
}

void Plane::intersectionPlane(Ray ray)
{
	Vec3 N;
	N.x = plane.x;
	N.y = plane.y;
	N.z = plane.z;
	float D = plane.d;

	// Set Vec3 Variables
	Vec3 start = ray.start;
	Vec3 dir = ray.dir;

	// Find Dot Product
	float tempDot = plane.tDot(start, D); // N.S
	std::cout << tempDot << endl;

	// tempDot + D;
	float temp1 = tempDot + D;

	// float t = -(N.S + D) / N.D;
	// float t = -((tempDot + D) / N  * D);

	if (abs(tempDot) <= 0.00000001)
	{
		if (temp1 <= 0.0000001)
		{
			std::cout << "The line is contained on the plane." << endl;
		}

		else
			std::cout << "The line isn't touching." << endl;
	}

	else
	{
		std::cout << "There is point that is touching the plane." << endl;
	}
}


Ray.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef RAY_H
#define RAY_H
#include "Vector.h"
#include "Vector4.h"

class Ray
{
public:
	Vec3 start; // startiing position of ray

	Vec3 dir; // direction of direction

	Ray(Vec3 start_, Vec3 end_); //set variables

	void currentPosition(float t); // calculate position of Ray
};

#endif 


Ray.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

#include "Ray.h"

Ray::Ray(Vec3 start_, Vec3 dir_)
{
	start_ = start;
	dir_ = dir;
}

void Ray::currentPosition(float t)
{
	Vec3 tempRay;

	tempRay.x = start.x + dir.x * t;
	tempRay.y = start.y + dir.y * t;
	tempRay.z = start.z + dir.z * t;

}


Vector.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef VECTOR_H
#define VECTOR_H
#include <iostream>
#include <cmath>

/// This is used in normalizing vectors. Dividing by zero is a well known
/// problem but dividing by nearly zero is also a problem. 1.0x10-7 is very
/// small in "float" percision. 

class Vec3
{
public:
	float x;
	float y;
	float z;

	Vec3();
	Vec3(float x_, float y_, float z_);

	/// Add two Vec3s
	const Vec3 operator+ (const Vec3& v);
	const Vec3 operator- (const Vec3& v);

	// assignment operator   
	Vec3& operator= (const Vec3& v);

	/// Multiply a Vec3 by a scalar
	const Vec3  operator * (const float s);

	//Find mag
	float Mag();

	//Normalize Vector
	void Normalize();

	//Dot Product 
	Vec3 Cross(Vec3 b);

	//Cross Product
	float Dot(Vec3 otherVec);
};
#endif 


Vector.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

#include "Vector.h"

Vec3::Vec3()
{
	x = 0.0f;
	y = 0.0f;
	z = 0.0f;
}

/* Vec3 Constructor
	Set the vector's x, y, and z components to the parameters supplied*/
Vec3::Vec3(float x_, float y_, float z_)
{
	x = x_;
	y = y_;
	z = z_;
}

const Vec3 Vec3::operator+(const Vec3& v)
{
	// add two vectors
	return Vec3(x + v.x, y + v.y, z + v.z);
}

const Vec3 Vec3::operator-(const Vec3& v)
{
	// subtract two  vectors
	return Vec3(x - v.x, y - v.y, z - v.z);
}

Vec3& Vec3::operator=(const Vec3& v)
{
	// TODO: insert return statement here
	x = v.x;
	y = v.y;
	z = v.z;
	return *this;
}

const Vec3 Vec3::operator*(const float s)
{
	// mulitply two vectors
	return Vec3(s * x, s * y, s * z);
}

float Vec3::Mag()
{
	// find magniutde of vector
	float temp = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2));

	return temp;
}

void Vec3::Normalize()
{
	// stored variable value
	float mag = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2));

	x = x / mag;
	y = y / mag;
	z = z / mag;

}

Vec3 Vec3::Cross(Vec3 otherVec)
{
	// cross product
	Vec3 temp;

	temp.x = ((y * otherVec.z) - (z * otherVec.y));
	temp.y = ((z * otherVec.x) - (x * otherVec.z));
	temp.z = ((x * otherVec.y) - (y * otherVec.x));

	return temp;
}

float Vec3::Dot(Vec3 b)
{
	// dot product
	float dot = ((x * b.x) + (y * b.y) + (z * b.z));
	return dot;
}

Vector4.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef VECTOR4_H
#define VECTOR4_H
#include <iostream>
#include <cmath>
#include "Vector.h"

class Vec4
{
public:

	float x, y, z, d;

	Vec4();
	Vec4(float x_, float y_, float z_, float d_);

	//Find magnitude
	float Mag();

	//Normalize Vec4
	void Normalize();

	//Find Dot Product
	float Dot(Vec4 otherVec);

	//Find Dot 
	float tDot(Vec3 tempVec, float D);
};
#endif 


Vector4.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include "Vector4.h"
#include "Vector.h"

Vec4::Vec4()
{
	// set variables
	x = 0;
	y = 0;
	z = 0;
	d = 0;
}

Vec4::Vec4(float x_, float y_, float z_, float d_)
{
	// set variables
	x = x_;
	y = y_;
	z = z_;
	d = d_;
}

float Vec4::Mag()
{
	// find magnitude 
	float temp = sqrt((pow(x, 2) + pow(y, 2) + pow(z, 2) + pow(d, 2)));
	return temp;
}

void Vec4::Normalize()
{
	// find normalized vector
	float mag = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2) + pow(d, 2));

	x = x / mag;
	y = y / mag;
	z = z / mag;
	d = d / mag;
}

float Vec4::Dot(Vec4 otherVec)
{
	// find dot
	float dot = ((x * otherVec.x) + (y * otherVec.y) + (z * otherVec.z) + (d * otherVec.d));
	return dot;
}


main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
#include"Vector.h"
#include"Vector4.h"
#include"Ray.h"
#include"Plane.h"
using namespace std;

int main()
{
	Vec3 r1(1.0f, 0.0f, 1.0f); //first Ray Vec
	Vec3 r2(3.0f, 2.0f, 1.0f); //second Ray Vec

	Ray ray1(r1, r2); // Ray Variable

	Plane plane1(2, 1, 0, -4); // Plane Variable

	plane1.intersectionPlane(ray1); //find intersection point

	return 0;
}
Last edited on
This is it with .cpp at the previous comments
zXFlameXz

(1) Please put ALL the relevant code in a SINGLE post. That's all the .cpp files and all the .h files together in a SINGLE post.

(2) Please state your input and desired output and what your actual problem is.

What exactly don't you understand about those instructions?

I edited to comment, that should be everything, I need to find the point of intersection.
The equation she gave was R = [1,0,1] + [3,2,1]t and the variables for the Plane is [2,1,0,-4]
and the results should be [1.75, 0.5, 1.25].
I can't get the output, my teacher told me to find the dot product for both N.S which is dot of the starting point, and N.V for the direction, and use this equation float t = -t = -(N.S + D) / N.D, I'm suppose to use the variables to describe if it's on the line, a point through a line, or not touching at all
Last edited on
Your code is over-complicated and in too many files, so it took a long time to debug.


First of all, you didn't test your ray.cpp routines. The constructor needs to be corrected in ray.cpp
1
2
3
4
5
Ray::Ray(Vec3 start_, Vec3 dir_)
{
        start = start_;     // <==== NOTE which way round!
        dir = dir_;         // <==== DITTO
}



Your intersection code should really return a Vec3, not be a void function. So, in plane.h change the declaration to
Vec3 intersectionPlane(Ray ray); // find the intersection point of a ray passing through the plane


The actual routine is then straightforward. In plane.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Vec3 Plane::intersectionPlane(Ray ray)                    // <==== Return a vector
{
        const float EPS = 1.0e-9f;                        // <==== you need a small tolerance

        Vec3 N( plane.x, plane.y, plane.z );
        float D = plane.d;

        // Set Vec3 Variables
        Vec3 start = ray.start;
        Vec3 dir = ray.dir;

        // Find Dot Products etc
//      float tempDot = plane.tDot(start, D); // N.S     // <==== This is complete nonsense
        float NdotS = N.Dot(start); // N.S               // <==== Try this one
        float Ndotdir = N.Dot(dir); // N.V               // <====   and this
        float top = NdotS + D;                           // <==== Numerator
        Vec3 result;                                     // <==== Default is (0,0,0)

        // Start by making sure that the denominator isn't 0
        if ( abs( Ndotdir ) <= EPS )                     // <==== denominator is "zero"
        {
           if ( abs( top ) <= EPS )
           {
              std::cout << "The line is contained on the plane." << endl;
           }
           else
           {
              std::cout << "The line isn't touching." << endl;
           }
        }
        // Only then can you use the general formula
        else
        {
           float t = -top / Ndotdir;                       // <==== Now you can find t
           result = start + dir * t;                       // <==== and calculate intersection
        }

        return result;                                     // <==== Have to return something
}



Finally, you should print the intersection point out in main(). File main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
#include"Vector.h"
#include"Vector4.h"
#include"Ray.h"
#include"Plane.h"
using namespace std;

int main()
{
        Vec3 r1(1.0f, 0.0f, 1.0f); //first Ray Vec
        Vec3 r2(3.0f, 2.0f, 1.0f); //second Ray Vec

        Ray ray1(r1, r2); // Ray Variable

        Plane plane1(2, 1, 0, -4); // Plane Variable

        Vec3 result = plane1.intersectionPlane(ray1);   // find intersection point
        std::cout << result.x << ", " << result.y << ", " << result.z << endl;       // and output it

        return 0;
}



There's a lot else that could be improved. A useful adjunct would be to overload the << operator for a Vec3, so that outputting these vectors is easier (especially during debugging).


For your given problem you get:
1.75, 0.5, 1.25

so your teacher's answer is correct.
Last edited on
Thanks for the help
Where do I write where a single point on the plane, the question asked for a point on the plane, if the ray is contained on the plane, and if the line isn't touching the plane
Look at the routine Plane::intersectionPlane
It already writes information for the singular cases (ray in the plane or ray parallel to, but not in, the plane). If you want to shout about the single-point case as well then you can cout that information in the last else block.
Last edited on
Topic archived. No new replies allowed.