I am trying to draw the line formed by the intersections of two planes in 3D, but I am having trouble understanding the math, which has been explained here and here.
I tried to figure it out myself, but the closest that I got to a solution was a vector pointing along the same direction as the intersection line, by using the cross product of the normals of the planes. I have no idea how to find a point on the intersection line, any point would do. I think that this method is a dead end. Here is a screenshot of this attempt:
I tried to use the solution mentioned in this question, but it has a dead link to the original explanation, and the equation didn't work for me (it has unbalanced parentheses, which I tried to correct below).
var planeA = new THREE.Plane((new THREE.Vector3(0, 0, 1)).normalize(), 100);
var planeB = new THREE.Plane((new THREE.Vector3(1, 1, 1)).normalize(), -100);
var x1 = planeA.normal.x,
y1 = planeA.normal.y,
z1 = planeA.normal.z,
d1 = planeA.constant;
var x2 = planeB.normal.x,
y2 = planeB.normal.y,
z2 = planeB.normal.z,
d2 = planeB.constant;
var point1 = new THREE.Vector3();
point1.x = 0;
point1.z = (y2 / y1) * (d1 - d2) / (z2 - z1 * y2 / y1);
point1.y = (-z1 * point1.z - d1) / y1;
var point2 = new THREE.Vector3();
point2.x = 1;
point2.z = (y2 / y1) * (x1 * point2.x + d1) - (x2 * point2.x - d2) / (z2 - z1 * y2 / y1);
point2.y = (-z1 * point2.z - x1 * point2.x - d1) / y1;
console.log(point1, point2);
output:
THREE.Vector3 {x: -1, y: NaN, z: NaN, …}
THREE.Vector3 {x: 1, y: Infinity, z: -Infinity, …}
expected output:
- A point along the intersection where x = 0, and
- Another point on the same line where x = 1
If someone could point me to a good explanation of how this is supposed to work, or an example of a plane-plane intersection algorithm, I would be grateful.
When I have problems like this, I usually let a symbolic algebra package (Mathematica in this case) deal with it. After typing
and simplifying and substituting x=0 and x=1, I get
It is easy to let three.js solve this for you.
If you were to express your problem in matrix notation
Then the solution for x is
We'll use a 4x4 matrix for m, because three.js has an
inverse()
method for theMatrix4
class.The x-component of v will be equal to c, as desired, and the y- and z-components will contain the values you are looking for. The w-component is irrelevalent.
Now, repeat for the next value of c, c = 1.
three.js r.58
Here is an implementation of a solution for plane-plane intersections described at http://geomalgorithms.com/a05-_intersect-1.html . Essentially, you first use the cross product of the normals of the planes to find the direction of a line in both planes. Secondly, you use some algebra on the implicit equation of the planes (P . n + d = 0 where P is some point on the plane, n is the normal and d is the plane constant) to solve for a point which is on the intersection of the planes and also on one of the x=0, y=0 or z=0 planes. The solution is then the line described by a point and a vector. I was using three.js version 79
Prerequisites
Recall that to represent a line we need a vector describing its direction and a point through which this line goes. This is called parameterized form:
where
point_1
andpoint_2
are arbitrary points through which the line goes, andt
is a scalar which parameterizes our line. Now we can find any pointline_point(t)
on the line if we put arbitraryt
into the equation above.NOTE: The term
(point_2 - point_1)
is nothing, but a vector describing the direction of our line, and the termpoint_1
is nothing, but a point through which our line goes (of coursepoint_2
) would also be fine to use too.The Algorithm
Find the direction
direction
of the intersection line by taking cross product of plane normals, i.e.direction = cross(normal_1, normal_2)
.Take any plane, for example the first one, and find any 2 distinct points on this plane:
point_1
andpoint_2
. If we assume that the plane equation is of the forma1 * x + b1 * y + c1 * z + d1 = 0
, then to find 2 distinct points we could do the following:where
point_1 = (x1, y1, z1)
andpoint_2 = (x2, y2, z2)
.Now that we have 2 points, we can construct the parameterized representation of the line lying on this first plane:
line_point(t) = t * (point_2 - point_1) + point_1
, whereline_point(t)
describes any point on this line, andt
is just an input scalar (frequently called parameter).Find the intersection point
intersection_point
of the lineline_point(t)
and the second planea2 * x + b2 * y + c2 * z + d2 = 0
by using the standard line-plane intersection algorithm (pay attention to the Algebraic form section as this is all you need to implement line-plane intersection, if you haven't done so already).Our intersection line is now found and can be constructed in parameterized form as usual:
intersection_line_point(s) = s * direction + intersection_point
, whereintersection_line_point(s)
describes any point on this intersection line, ands
is parameter.NOTE: I didn't read this algorithm anywhere, I've just devised it from the top of my head based on my knowledge of linear algebra. That doesn't mean that it doesn't work, but it might be possible that this algorithm can be optimized further.
Conditioning
When 2 normal vectors
normal_1
andnormal_2
are almost collinear this problem gets extremely ill-conditioned. Geometrically it means that the 2 planes are almost parallel to each other and determining the intersection line with acceptable precision becomes impossible in finite-precision arithmetic which is floating-point arithmetic in this case.