Related
Imagine you have a 3D space between 0 and d meters in the x,y and z directions (it's a cube of length d). now let's assume I want to break this up into a 3D array of smaller cubes. We want n cubes in each direction. This means each cube has a length, width and height of d/n (you can assume that d/n divides perfectly).
This can be held in the following array:
Cube* cubes[n][n][n];
Now let us assume we can have a sphere of radius r and position p, where p can be anywhere inside the 3d space, and r has no constraints. What is the most efficient way of finding and returning all the cubes that intersect with this sphere?
Currently, I am looping through all the cubes in the array and using the Pythagorean theorem to check the distance between each cube and p, which I wrote the pseudo code for below.
Cube* getIntersectingCubes(r,p) {
Cube* cubes[n][n][n];
Cube* result[];
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
for(int k=0;k<n;k++) {
if(distanceBetween(cubes[i][j][k],p) < r) {
result.add(cubes[i][j][k]);
}
}
}
}
return result;
}
However, there is definitely a better way to do this. How could I return the same output but check as few cubes as possible?
If you are still having trouble working out a coordinate system and your algorithm, start with a diagram:
Essentially what you have is a 3D grid of cubes and your points p can be chosen any way you like so long as they describe a cube completely. What you want to determine is for which cubes does the radius r intersect any part of the cube. You can handle that with three vectors. You simply treat the cube origin as a vector. You know the lengths of the sides of each cube (d / n) you can use to form a second vector (call it the extent of p or p_extent) which you can add to the origin vector to determine the farthest point in the cube. So p_extent would equal d/ni + d/nj + d/nk.
You can create a struct to help in handling the coordinates as a vector, e.g.:
typedef struct {
double x, y, z;
} vect_pos;
With your two vectors, you can simply add them together (e.g. p + p_extent) to form a vector describing the farthest point in the cube from the origin. (you want the direction of the vector inside your cube to have the same sign direction as your origin vector (so you can simply multiply it with a unit vector in that direction). For example is your point is -3i -1j and 2k, you can multiple by the p_extent vector by -1i -1j 1k. (picture the cube origin vector in each of the 8-quadrants and the values that x, y, z would have in each.
To add two vector_pos together, you can simply use vector addition, e.g.
/* vector addition */
vect_pos vect_add (const vect_pos *a, const vect_pos *b)
{
vect_pos c = { .x = 0. };
c.x = a->x + b->x;
c.y = a->y + b->y;
c.z = a->z + b->z;
return c;
}
The last wrinkle that choosing the coordinate at a corner of the cube will require you solve is that the origin vector will not always point to the corner closest to the origin (picture in the diagram above where p would point if you rotated the origin counter-clockwise by 90 deg about the axis. (your alternative is to choose the center of the cube as its origin, but then you have twice the number of calculations).
You can handle the closest corner issue by a simple check and shifting the corner for the origin by a cube side length for purposes of the calculation of whether r is between the closest and farthest corners (the cube is still the same cube) With your cube origin and the farthest corner described, you can simply use the vector-distance formula to calculate the distance each is from the origin and if r is between the two, the sphere intersects that cube.
To choose the closest point to the origin before calculating the distances you can use:
/* point in cube closest to origin */
vect_pos closest_pt (const vect_pos *p, const int len)
{
vect_pos c = { p->x >= 0 ? p->x : p->x + len,
p->y >= 0 ? p->y : p->y + len,
p->z >= 0 ? p->z : p->z + len };
return c;
}
(choosing your cube at origin 0, 0, 0 with positive sides allows you to simply add a cube side length in the case that coordinate is negative to choose the closest point on the cube as the origin)
and for the distance calculations, a simple square-root of the sum of the squares:
/* vector distance */
double vect_dist (const vect_pos *p)
{
return sqrt (p->x * p->x + p->y * p->y + p->z * p->z);
}
To check if r falls between the closest and farthest distance within each cube you can put it altogether with a short function that handles choosing the extent vector in the same direction as the origin, adds the vectors and then compares the distances of each to r, e.g.
/* does r intersect cube at postition p */
int intersect (vect_pos *p, const double r, const int len)
{
vect_pos c = closest_pt (p, len), /* closest pt to origin */
p_extent = { .x = c.x >= 0 ? len : -len, /* length, unit vector */
.y = c.y >= 0 ? len : -len, /* pointing outward */
.z = c.z >= 0 ? len : -len },
p_farthest = vect_add (&c, &p_extent); /* farthest point in cube */
double nearest = vect_dist (&c), /* distance to nearest */
farthest = vect_dist (&p_farthest); /* distance to farthest */
return nearest <= r && r <= farthest; /* return radius in between */
}
That's basically it. You can add a short function to output the points to as a convenience, e.g.
void prn_pos (const vect_pos *p)
{
printf ("(% d, % d, % d)\n",
(int)p->x, (int)p->y, (int)p->z);
}
and then add a main() that allows entry of r, d and n and outputs the results:
int main (int argc, char **argv) {
double r = argc > 1 ? strtod (argv[1], NULL) : .9; /* r */
int d = argc > 2 ? strtol (argv[2], NULL, 0) : 1, /* d */
n = argc > 3 ? strtol (argv[3], NULL, 0) : d, /* n */
dn = 0, /* d/n */
nc = 0, /* number of cubes in each direction */
total = 0, /* total cubes in search grid */
intersecting = 0; /* number of cubes that intersect sphere */
if (r < 0 || d < 0) { /* validate length inputs */
fputs ("error: negtive length in input of r or d.\n", stderr);
return 1;
}
if (!n || n < 0) { /* validate n not zero or negative */
fputs ("error: n - divide by zero or negative.\n", stderr);
return 1;
}
if (d < r) { /* ensure d >= r */
int min_d = ceil (r);
n *= min_d / d;
d = min_d;
}
if (d % n) { /* validate d equally divisible by n */
fputs ("error: d not equally divisible by n.\n", stderr);
return 1;
}
dn = d / n; /* cube side length */
nc = ceil (r / dn) + 1; /* limit of cubes needed per-direction */
total = nc * nc * nc * 8; /* total number of cubes in search grid */
printf ("\nOut of %d cubes, the following intersect sphere of radius %.2f\n\n",
total, r);
for (int i = -d; i <= d; i += dn) /* loop -d to d */
for (int j = -d; j <= d; j += dn)
for (int k = -d; k <= d; k += dn) {
vect_pos p = { i, j, k }; /* vector to cube origin */
if (intersect (&p, r, dn)) { /* does it intersect sphere? */
prn_pos (&p); /* output cube origin */
intersecting++; /* increment count */
}
}
printf ("\nintersecting cubes: %d\n", intersecting);
}
Add the headers:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
and then compile linking against the math library -lm and you have a working program to test. If no arguments for r, d or n are provided, the code uses .90, 1, and 1 as defaults. Note the loop limits are at minimum from -(next int above r) to (next int above r) in each dimension or as given by d whichever is greater and not shorter than r.
Example Use/Output
Default case with r = .9 and d = 1 and n = 1:
$ ./bin/cube-sphere-intersect
Out of 64 cubes, the following intersect sphere of radius 0.90
(-1, -1, -1)
(-1, -1, 0)
(-1, 0, -1)
(-1, 0, 0)
( 0, -1, -1)
( 0, -1, 0)
( 0, 0, -1)
( 0, 0, 0)
intersecting cubes: 8
If you draw the cubes out on a grid, those are the 8 cubes surrounding the origin.
Choosing r = 5.5, d = 6 and n = 1 would give the same result other than the sides of the cubes being of different length:
$ ./bin/cube-sphere-intersect 5.5 6 1
Out of 64 cubes, the following intersect sphere of radius 5.50
(-6, -6, -6)
(-6, -6, 0)
(-6, 0, -6)
(-6, 0, 0)
( 0, -6, -6)
( 0, -6, 0)
( 0, 0, -6)
( 0, 0, 0)
intersecting cubes: 8
If you enter an r length of exacly 1, then this is where your choice of whether to consider r equal to the min or max length will come into play. There are arguments for saying "touching" a cube doesn't really mean it intersects as the point will technically lie on a tangent that distance out, but there are equally good arguments that say that intersects (the choice of whether you want to use <= or < in the comparison is left to you)
For example if you enter anything between 1.0 < sqrt(2) (1.414...) you will find 32 cube intersect, e.g.
$ ./bin/cube-sphere-intersect 1.1
Out of 216 cubes, the following intersect sphere of radius 1.10
(-2, -1, -1)
(-2, -1, 0)
(-2, 0, -1)
(-2, 0, 0)
(-1, -2, -1)
(-1, -2, 0)
(-1, -1, -2)
(-1, -1, -1)
(-1, -1, 0)
(-1, -1, 1)
(-1, 0, -2)
(-1, 0, -1)
(-1, 0, 0)
(-1, 0, 1)
(-1, 1, -1)
(-1, 1, 0)
( 0, -2, -1)
( 0, -2, 0)
( 0, -1, -2)
( 0, -1, -1)
( 0, -1, 0)
( 0, -1, 1)
( 0, 0, -2)
( 0, 0, -1)
( 0, 0, 0)
( 0, 0, 1)
( 0, 1, -1)
( 0, 1, 0)
( 1, -1, -1)
( 1, -1, 0)
( 1, 0, -1)
( 1, 0, 0)
intersecting cubes: 32
Then for radius between sqrt(2) <= sqrt(3) you would find 56 cube intersect and so on.
This is just one way to implement it. If you are curious, go rewrite it to use the center of each cube as the origin of the cube. You don't have to use a struct, you can just operate on each x, y, z directly, but the struct helps keep the logic clear. Look things over and let me know if you have further questions.
Divide and conquer:
Assume the entire domain as a single cube:
Figure out if there is an intersection
If so, divide into octants and repeat (1)
Because you only need to search the octants where an intersection is present, you won't have to preallocate a massive array of cells.
The intersection algorithm can be simplified to any cube where at least one of the nodes is less than the radius from p and at least one is greater. It should be possible to write this algorithm in a way that is easy to vectorise.
Note: Probably don't want to store your 3d array on the stack, even if you pick a relatively small number for n, say 50, that's already 125000 doubles, enough to cause a stack overflow on some systems.
I would start with the cube containing point p and go into any one direction while given cube still intersects the sphere. That would give you a distance +-1 to all "edge" cubes.
This provides early termination of the search through cubes you know won't intersect and gives you an approximation of end points in all directions.
Let's say a cube is in the outer shell if it intersects the sphere but isn't fully contained in the sphere. Say the initial point p = (x, y, z). We'll proceed by finding the cubes in the outer shell. Given these, it's easy to find interior cubes.
1. Find the cube containing p in O(1).
2. Find the most distant cube intersecting the sphere that can be reached by decreasing x.
3. Add this to a set: unexplored
4. repeatedly do the following (each iteration is O(1):
a. Pull a cube from unexplored.
b. Add any neighbors that intersect the outer shell and aren't explored to unexplored.
c. Mark the current cube as explored.
How long does this take? It's linear with the surface area of the sphere measured in cubes, so O(4pi(r/d)^2) = O((r/d)^2). I.e. the formula for the surface area of a sphere, but with the radius measured in cubes.
If it suffices to return the outer shell then you're done. If you need to return the contents then this grows to be linear with the output, which is O((r/d)^3)
First of all you need a function that will map any point in 3D into three integers:
(x,y,z) -> (floor(x/dx), floor(y/dy), floor(z/dz))
where, in your case, dx = dy = dz = d/n is the size (along axes x, y, z) of small cubes (which I shall rather call "cells") you divide the whole space into. This function maps any point in 3D into a discrete cell.
Now, you should find the minimum cuboid, which is made of cells, and which contains the sphere centered at P and of radius r. In a general case this is a cuboid, though often it will be just a cube. After all, it kinda circumscribes a sphere. Let your cube be denoted A, and let this cuboid be denoted B. The answer to your problem lies inside both A and B. For this reason find the intersection C of A and B. Focus entirely on C. This trick alone should result in a huge reduction of the problem complexity, with practically zero cost.
Now I assume you have a well written, well tested function distance(cube, point). Remember that the point on the cube that minimize the distance to point may lie on one of cube's corners, edges, sides or its interior volume and so such a function will need several if-else branches.
Check if distance returns a value less or equal than r. If not, the answer is an empty set, you're done.
If the distance is <= r, then you can apply a modified method reported here by M.A., but applied to C. This C is not a cube, so octants are no solution here. However, C is a cuboid, for an intersection of 2 cuboids is a cuboid. Denote its side lengths as Lx, Ly, Lz. Thee numbers are integers, becassue now you measure the lengths in units of dx, dy and dz along axes x, y, z, repectively. Find the largest of them. Suppose, for clarity, that it is Lx. If Lx > 1 you divide C along the x axis into two equal-sized (when Lx is even) or almost equal (Lx is odd) sub-cuboids. You check the distance to each of them. If it is larger than r then you reject this whole sub-cuboid. Otherwise you repeat the division along the largest side of the current cuboid. This is very similar to, for example, implementation of the BVH tree.
Once you reached the "sub-cuboid" of size 1x1x1, you verify if it intersects with the sphere. If yes, add it to the solution set.
* * *
This algorithm is very general because your question contains no details as to where the answer to this problem is to be used. For example, how large can n be? Will the solution be used for fixed radius and varying sphere centers? Knowing such details could help develop a better solution.
For example, the sphere can contain O(N^3) cells, so one might expect that he solution cannot be found in time smaller than O(N^3). But perhaps you do nod a list of the cells? Perhaps a different format would do?
The set of cells forming the solution can be regarded as a union of disjoint columns of cells, oriented along the z axis. With this representation, the solution can be written as a set of pairs (cell, height). Here cell denote the lowest cell in a column, and height - its height. If a solution in this format is OK. the problem can be solved in O(N^2) or at mot O(N^2 log N) time.
So i have two 3d line segments A and B the only givens are the origins of both line segments and their lenghts. I need to oriente the two line segments in a way that they end at the same position.
EX:
point3d common_end_position;
bool result= intersect_line_segments(
{0, 0, 0}, // position_0
2.0, // length_0
{2, 0, 0}, // position_1
2.0, // length_1
{0, 0, 1}, // hint_direction
&common_end_position);
The funciton should return true with the common end postion being {1, 0, 1.7321}
If they cannont be oriented so that they end at the same endpoint then the function would return false
Let positions are C1 and C2, difference vector is
D = C2-C1, distance is d = |D|, lengths are r and R.
Common end P does not exist if d > R + r or d < abs(R-r)
Otherwise projection of P onto C1C2 has length
x = (d^2 + R^2 - r^2) / (2d)
(mathworld page)
and distance of P from C1C2 is
y = sqrt(R^2-x^2)
If it is guaranteed that hint vector H is perpendicular to D, then the rest is simple:
1) Get normalized vector ud = D / d
2) Find projection point P' = C1 + ud * x
3) Add perpendicular vector P = P' + H * y (assuming unit H vector)
If H might be not perpendicular (but not parallel to C1C2!) then find
H' = ud x (H x ud)
using two vector multiplications and use H' instead.
I was doing a practice question and it was something like this,We are given N pair of coordinates (x,y) and we are given a central point too which is (x0,y0).We were asked to find maximum number of points lying on a line passing from (x0,y0).
My approach:- I tried to maintain a hash map having slope as the key and I thought to get the maximum second value to get maximum number of points on the same line.Something like this
mp[(yi-y0)/(xi-x0))]++; //i from 0 to n
And iterating map and doing something line this
if(it->second >max) //it is the iterator
max=it->second;
and printing max at last;
Problem With my approach- Whenever I get (xi-x0) as 0 I get runtime error.I also tried atan(slope) so that i would get degrees instead of some not defined value but still its not working.
What i expect->How to remove this runtime error and is my approach correct for finding maximum points on a line passing from a point(x0,y0).
P.S -My native language is not english so please ignore if something goes wrong.I tried my best to make everything clear If i am not clear enough please tell me
I'm assuming no other points have the same coordinates as your "origin".
If all your coordinates happen to be integers, you can keep a rational number (i.e. a pair of integers, i.e. a numerator and a denominator) as the slope, instead of a single real number.
The slope is DeltaY / DeltaX, so all you have to do is keep the pair of numbers separate. You just need to take care to divide the pair by their greatest common divisor, and handle the case where DeltaX is zero. For example:
pair<int, int> CalcSlope (int x0, int y0, int x1, int y1)
{
int dx = abs(x1 - x0), dy = abs(y1 - y0);
int g = GCD(dx, dy);
return {dy / g, dx / g};
}
Now just use the return value of CalcSlope() as your map key.
In case you need it, here's one way to calculate the GCD:
int GCD (int a, int b)
{
if (0 == b) return a;
else return gcd(b, a % b);
}
You have already accepted an answer, but I would like to share my approach anyway. This method uses the fact that three points a, b, and c are covariant if and only if
(a.first-c.first)*(b.second-c.second) - (a.second-c.second)*(b.first-c.first) == 0
You can use this property to create a custom comparison object like this
struct comparePoints {
comparePoints(int x0 = 0, int y0 = 0) : _x0(x0), _y0(y0) {}
bool operator()(const point& a, const point& b) {
return (a.first-_x0)*(b.second-_y0) - (b.first-_x0)*(a.second-_y0) < 0;
}
private:
int _x0, _y0;
};
which you can then use as a comparison object of a map according to
comparePoints comparator(x0, y0);
map<pair<int, int>, int, comparePoints> counter(comparator);
You can then add points to this map similar to what you did before:
if (!(x == x0 && y == y0))
counter[{x,y}]++;
By using comparitor as a comparison object, two keys a, b in the map are considered equal if !comparator(a, b) && !comparator(b,a), which is true if and only if a, b and {x0,y0} are collinear.
The advantage of this method is that you don't need to divide the coordinates which avoids rounding errors and problems with dividing by zero, or calculate the atan which is a costly operation.
Move everything so that the zero point is at the origin:
(xi, yi) -= (x0, y0)
Then for each point (xi, yi), find the greatest common divisor of xi and yi and divide both numbers by it:
k = GCD(xi, yi)
(xi', yi`) = (yi/k, yi/k)
Now points that are on the same ray will map to equal points. If (xi, yi) is on the same ray as (xj, yj) then (xi', yi') = (xj', yj').
Now find the largest set of equal points (don't forget any (xi, yi) = (0, 0)) and you have your answer.
You've a very original approach here !
Nevertheless, a vertical line has a infinite slope and this is the problem here: dividing by 0 is not allowed.
Alternative built on your solution (slope):
...
int mpvertical=0; // a separate couner for verticals
if (xi-x0)
mp[(yi-y0)/(xi-x0))]++;
else if (yi-y0)
mpvertical++;
// else the point (xi,yi) is the point (x0,y0): it shall not be counted)
This is cumbersome, because you have everything in the map plus this extra counter. But it will be exact. A workaround could be to count such points in mp[std::numeric_limits<double>::max()], but this would be an approximation.
Remark: the case were xi==x0 AND yi==y0 corresponds to your origin point. These points have to be discarded as they belong to every line line.
Trigonomic alternative (angle):
This uses the general atan2 formula used to converting cartesian coordinates into polar coordinates, to get the angle:
if (xi!=x0 && yi!=y0) // the other case can be ignored
mp[ 2*atan((yi-y0)/((xi-x0)+sqrt(pow(xi-x0,2)+pow(yi-y0,2)))) ]++;
so your key for mp will be an angle between -pi and +pi. No more extra case, but slightly more calculations.
You can hide these extra details and use the slighltly more optimized build in function:
if (xi!=x0 && yi!=y0) // the other case can be ignored
mp[ atan2(yi-y0, xi-x0) ]++;
you can give this approach a try
struct vec2
{
vec2(float a,float b):x(a),y(b){}
float x,y;
};
bool isColinear(vec2 a, vec2 b, vec2 c)
{
return fabs((a.y-b.y)*(a.x-c.x) - (a.y-c.y)*(a.x-b.x)) <= 0.000001 ;
}
I've found a nice algorithm to check tri/tri intersections, but I'd like it to fail if they only meet at a point along an edge or edge (no overlap). Basically want to overlap, and touch is not enough.
Anyone know how to adjust it?
http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/opttritri.txt
ex. should fail
float a1[3] = { 0, 0, 0 };
float a2[3] = { 2, 0, 0 };
float a3[3] = { 0, 1, 0 };
float b1[3] = { 0, 0, 0 };
float b2[3] = { 2, 0, 0 };
float b3[3] = { 0, -1, 0 };
bool inters = NoDivTriTriIsect(a1, a2, a3, b1, b2, b3);
A neat solution and an ad-hoc solution come to mind :). The ad-hoc one just adds additional tests to identify the edge-only-overlaps. The neat one directly computes the area of the overlap and says that the triangles intersect if area>0
The neater Area-of-overlap approach: Sutherland-Hodgman algorithm produce a polygon of the triangle-triangle overlap. And then just compute polygon area (How do I calculate the area of a 2d polygon?)
(https://math.stackexchange.com/questions/154628/find-the-area-of-overlap-of-two-triangles)
If you prefer an ad-hoc solution via filtering cases: first find overlapping borders by parameterising the edges as lines and look for lines with the same parameters. Then check if a point just above and below the starting point of the shortest edge is in both triangles. (http://www.blackpawn.com/texts/pointinpoly/default.html). If both points are in only one of them, then they only overlap by an edge.
I'm trying to implement at line-plane intersection algorithm. According to Wikipedia I need three non-colinear points on the plane to do that.
I therefore tried implementing this algorithm in C++, however. Something is definitely wrong, cause it makes no sense that I can choose whatever x and y coordinates and they'll fit in the plane. What if the plane is vertical and along the x-axis? No point with y=1 would then be in the plane.
I realize that this problem has been posted a lot on StackOverflow, and I see lots of solutions where the plane is defined by 3 points. But I only have a normal and a position. And I can't test my line-plane intersection algorithm before I sort out my non-colinear point finder.
The problem right now, is that I'm dividing by normal.z, and that obviously won't work when normal.z is 0.
I'm testing with this plane: Plane* p = new Plane(Color(), Vec3d(0.0,0.0,0.0), Vec3d(0.0,1.0,0.0)); // second parameter : position, third parameter : normal
The current code gives this incorrect answer:
{0 , 0 , 0} // alright, this is the original
{12.8377 , 17.2728 , -inf} // obviously this is not a non-colinear point on the given plane
Here's my code:
std::vector<Vec3d>* Plane::getThreeNonColinearPoints() {
std::vector<Vec3d>* v = new std::vector<Vec3d>();
v->push_back(Vec3d(position.x, position.y, position.z)); // original position can serve as one of the three non-colinear points.
srandom(time(NULL));
double rx, ry, rz, start;
rx = Plane::fRand(10.0, 20.0);
ry = Plane::fRand(10.0, 20.0);
// Formula from here: http://en.wikipedia.org/wiki/Plane_(geometry)#Definition_with_a_point_and_a_normal_vector
// nx(x-x0) + ny(y-y0) + nz(z-z0) = 0
// |-----------------| <- this is "start"
//I'll try to insert position as x0,y0,z0 and normal as nx,ny,nz, and solve the equation
start = normal.x * (rx - position.x) + normal.y * (ry - position.y);
// nz(z-z0) = -start
start = -start;
// (z-z0) = start/nz
start /= normal.z; // division by zero
// z = start+z0
start += position.z;
rz = start;
v->push_back(Vec3d(rx, ry, rz));
// TODO one more point
return v;
}
I realize that I might be trying to solve this totally wrong. If so, please link a concrete implementation of this. I'm sure it must exist, when I see so many line-plane intersection implementations.
Thanks in advance.
A plane can be defined with several ways. Typically a point on the plane and a normal vector is used. To get the normal vector from three points (P1, P2, P3 ) take the cross product of the side of the triangle
P1 = {x1, y1, z1};
P2 = {x2, y2, z2};
P3 = {x3, y3, z3};
N = UNIT( CROSS( P2-P1, P3-P1 ) );
Plane P = { P1, N }
The reverse, to go from a point P1 and normal N to three points, you start from any direction G not along the normal N such that DOT(G,N)!=0. The two orthogonal directions along the plane are then
//try G={0,0,1} or {0,1,0} or {1,0,0}
G = {0,0,1};
if( MAG(CROSS(G,N))<TINY ) { G = {0,1,0}; }
if( MAG(CROSS(G,N))<TINY ) { G = {1,0,0}; }
U = UNIT( CROSS(N, G) );
V = CROSS(U,N);
P2 = P1 + U;
P3 = P1 + V;
A line is defined by a point and a direction. Typically two points (Q1, Q2) define the line
Q1 = {x1, y1, z1};
Q2 = {x2, y2, z2};
E = UNIT( Q2-Q1 );
Line L = { Q1, E }
The intersection of the line and plane are defined by the point on the line r=Q1+t*E that intersects the plane such that DOT(r-P1,N)=0. This is solved for the scalar distance t along the line as
t = DOT(P1-Q1,N)/DOT(E,N);
and the location as
r = Q1+(t*E);
NOTE: The DOT() returns the dot-product of two vector, CROSS() the cross-product, and UNIT() the unit vector (with magnitude=1).
DOT(P,Q) = P[0]*Q[0]+P[1]*Q[1]+P[2]*Q[2];
CROSS(P,Q) = { P[1]*Q[2]-P[2]*Q[1], P[2]*Q[0]-P[0]*Q[2], P[0]*Q[1]-P[1]*Q[0] };
UNIT(P) = {P[0]/sqrt(DOT(P,P)), P[1]/sqrt(DOT(P,P)), P[2]/sqrt(DOT(P,P))};
t*P = { t*P[0], t*P[1], t*P[2] };
MAG(P) = sqrt(P[0]*P[0]+P[1]*P[1]+P[2]*P[2]);
One approach you may find easy to implement is to see where the plane intersects the coordinate axes. For the plane given by the equationaX + bY + cZ - d = 0 hold two variables at 0 and solve for the third. So the solutions would be (assuming a, b, c, and d are all non-zero):
(d/a, 0, 0)
(0, d/b, 0)
(0, 0, d/c)
You will need to consider the cases where one or more of the coefficients are 0 so you don't get a degenerate or colinear solutions. As an example if exactly one of the coefficients is 0 (say a=0) you instead use
(1, d/b, 0)
(0, d/b, 0)
(0, 0, d/c)
If exactly two of the coefficients are 0 (say a=0 and b=0) you can use:
(1, 0, d/c)
(0, 1, d/c)
(0, 0, d/c)
If d=0, the plane intersects the three axes at the origin, and so you can use:
(1, 0, -a/c)
(0, -c/b, 1)
(-b/a, 1, 0)
You will need to work out simular cases for d and exactly one other coefficient being 0, as well as d and two others being 0. There should be a total of 16 cases, but there are a few things that come to mind which should make that somewhat more manageable.
Where N=(Nx,Ny,Nz) is the normal, you could project the points N, (Ny,Nz,Nx), (Nz,Nx,Ny) onto the plane: they're guaranteed to be distinct.
Alternatively, if P and Q are on the plane, P+t(Q-P)xN is also on the plane for any t!=0 where x is the cross product.
Alternatively if M!=N is an arbitrary vector, K=MxN and L=KxN are colinear with the plane and any point p on the plane can be written as p=Origin+sK+tL for some s,t.