I have the following 3D data:
ray origin (x, y, z)
ray direction (x, y, z)
four rectangle corners (x,y,z)
Now I am searching for a simple c++ function which calculates, if the rectangle is intersected by the ray. I don´t need the intersection coordinates, only a "yes/no" bool.
I have googled a lot but unfortunately I can´t find any simple function which fits to my requirements. I hope that I can avoid writing my own function because vector calculation is dawn long ago :-( ! If anyone has an idea, I´m greatful for any help.
Thanks....
Edit:
Thanks for your help. This was exactly what I am searching for, but I have a problem with the vxl library. First I have downloaded and compiled the sources. Then, while testing the lib, I got the following error when I try to create a plane with three 3D Points.
"undefined reference to `vgl_plane_3d::vgl_plane_3d(vgl_point_3d const&, vgl_point_3d const&, vgl_point_3d const&)'|"
My code:
// -----------------------------------------------
#include <vgl/vgl_point_3d.h>
#include <vgl/vgl_plane_3d.h>
#include <vgl/vgl_intersection.h>
void createTestPlane(void);
using namespace std;
int main()
{
createTestPlane();
return 0;
}
void createTestPlane()
{
vgl_point_3d<double> PlaneP0(1.0,0.0,0.0);
vgl_point_3d<double> PlaneP1(1.0,0.0,1.0);
vgl_point_3d<double> PlaneP2(1.0,1.0,0.0);
vgl_plane_3d<double> testConstruction();
vgl_plane_3d<double> Plane(PlaneP0,PlaneP1,PlaneP2);
}
// -----------------------------------------------
I don´t know where the problem is, because the constructor with three 3D points is available in the "" header. The default constructor seems to work correctly.
Part of the header file:
// -----------------------------------------------
// Default constructor: horizontal XY-plane (equation 1.z = 0)
inline vgl_plane_3d () : a_(0), b_(0), c_(1), d_(0) {}
//: Construct from three non-collinear points
// The plane will contain all three points \a p1, \a p2 and \a p3.
vgl_plane_3d (vgl_point_3d<T> const& p1,
vgl_point_3d<T> const& p2,
vgl_point_3d<T> const& p3);
// -----------------------------------------------
Does anybody have an idea what I am doing wrong ?
I am not allowed to post the graph. Here is the graph description:
rectangle points: V0, V1, V2, V3
ray origin: O
ray direction: Dir
surface normal: N^
P: the hit point on the rectangular plane. ( note: it may be outside )
I. compute hit point P:
N^ = ((V1 - V0) X (V3 -V0)).nomralize(). X is cross product; N^ length is 1, the surface normal.
Q = O - V0
H = Q * N^. * is dot product; H is the shortest distance to the rectangular surface
Dproj = Dir * (-N^); -N^ means revert N
Scale = H/Dproj.
P = O + (Dir).nomralized() * Scale. Dir is a normalized vector.
II. test if P is inside the rectangle by comparing the rectangular area and the four triangle areas
Reference about computing triangle/rectangle area:
http://en.wikipedia.org/wiki/Cross_product
a0 = ((V0 - P) X (V1 - P) ).length() * 0.5
a1 = ((V1 - P) X (V2 - P) ).length() * 0.5
a2 = ((V2 - P) X (V3 - P) ).length() * 0.5
a3 = ((V3 - P) X (V0 - P) ).length() * 0.5
Trec = ((V1 - V0) X (V3 - V0)).length()
if ( (a0+a1+a2+a3) > Trec ), P is outside, otherwise, it is inside.
Hope this explanation is useful for you.
You might want to look into VXL ( http://public.kitware.com/vxl/doc/development/core/vgl/html/vgl__intersection_8h_source.html ), starting at line 00240 is the declaration of the function you likely want. It's open source so you can either use the library or just download and inspect the code/
Related
(x - x0)^2/a^2 + (y - y0)^2/b^2 == 1
where (x0, y0) is the centre of the ellipse.
the centre point (x0, y0) is randomly located in the region [SIZE/4, 3*SIZE/4]x[SIZE/4, 3*SIZE/4],
and a, b in the interval [SIZE/4, SIZE/2] so that in most cases the complete curves can lie in figure.
I have to print out an ellipse on a X-Y axis of Size 15(0 to 14), using the given information.
I am using cout to print '.' on the entire graph, and have to print an ellipse using the given dimensions only on that portion of the graph using 'E'.
I have to use the equation to test which points are inside or outside of the curve.
I have to find the closest points to the curve.
For example, I can start from the center (x0, y0) and keep moving up until
I find a point (x0, y1), such as:
(x0 - x0)^2/a^2 + (y1 - y0)^2/b^2 >= 1
(x0 - x0)^2/a^2 + ((y1 - 1)- y0)^2/b^2 <= 1
Then (x0, y1 - 1) and (x0, y1) are candidates which are points closest to the curve on the line x = x0.
Not going to give you a full solution, but I think I see the general problem you are having. My comments were just some brainstorming. This is how I would actually approach it:
As you are using cout to print ., you should use a
std::array<std::string,N_ROWS> grid;
Initialize it properly with strings of correct size, and use a function std::pair<double,double> get_coordinates(int x,int y) to transform between discrete coordinates and "world coordinates".
To know if a grid point is part of the ellipsis or not, you have to realize that for a discrete grid, the equation
(x - x0)^2/a^2 + (y - y0)^2/b^2 == 1
will never be satisfied exactly for some grid coordinates x_i,y_i. However, this inequality:
(x - x0)^2/a^2 + (y - y0)^2/b^2 < 1
tells you if a point (x,y) is inside the area of the ellipsis. And if you consider the four neighboring points:
x_i,y_i
x_i+1,y_i
x_i,y_i+1
x_i+1,y_i+1
then eiter
all of them are inside -> grid[x_i][y_i] is inside of the ellipsis
none of them is inside -> grid[x_i][y_i] is not inside of the ellipsis
some are inside, some are outside -> grid[x_i][y_i] is part of the ellipsis, ie it gets a .
(In the last step i used grid[x_i][y_i] which should rather be grid[x_i + 1/2][y_i + 1/2], however this just shifts the whole grid by half a pixel and should not matter too much)
PS: in the meantime the question has been edited. It isnt perfeclty clear what is part of the requirements and what is part of your solution, so I don't know if this answer is of any help. I'll just leave it here...
First create a class to hold a Point:
struct Point
{
const int x;
const int y;
};
Next create a class to hold ellipse parameters and to check if a point is on that ellipse (or inside it):
struct Ellipse
{
const Point center;
const int a;
const int b;
bool is_on_ellipse(Point p) const
{
return std::pow(p.x - center.x, 2) / std::pow(a, 2) + std::pow(p.y - center.y, 2) / std::pow(b, 2) == 1.0;
}
bool is_inside_ellipse(Point p) const
{
return std::pow(p.x - center.x, 2) / std::pow(a, 2) + std::pow(p.y - center.y, 2) / std::pow(b, 2) < 1.0;
}
};
Then you can create an ellipse like this:
Ellipse e = {{0, 0}, 2, 3};
And check if the point is on the ellipse by calling: e.is_on_ellipse({px, py})
With C++20 it can be a little more verbose (but easier to verify correctness) :
Ellipse e = {.center = {.x = 0, .y = 0}, .a = 2, .b = 3};
//....
e.is_on_ellipse({.x = px, .y = py})
I have been reading a lot about the sutherland hodgman polygon clipping algorithm and understand the general idea. However, when I see the actual implementation of it (like the one below), I get confused about the coordinate comparisons such as those in the intersection and inside methods. Therefore, I was wondering if someone could elaborate on what and why? I see a ton of videos and articles explaining the general concepts but I really have trouble finding some explanation of the actual details regarding the implementation.
bool inside(b2Vec2 cp1, b2Vec2 cp2, b2Vec2 p) {
return (cp2.x-cp1.x)*(p.y-cp1.y) > (cp2.y-cp1.y)*(p.x-cp1.x);
}
b2Vec2 intersection(b2Vec2 cp1, b2Vec2 cp2, b2Vec2 s, b2Vec2 e) {
b2Vec2 dc( cp1.x - cp2.x, cp1.y - cp2.y );
b2Vec2 dp( s.x - e.x, s.y - e.y );
float n1 = cp1.x * cp2.y - cp1.y * cp2.x;
float n2 = s.x * e.y - s.y * e.x;
float n3 = 1.0 / (dc.x * dp.y - dc.y * dp.x);
return b2Vec2( (n1*dp.x - n2*dc.x) * n3, (n1*dp.y - n2*dc.y) * n3);
}
//http://rosettacode.org/wiki/Sutherland-Hodgman_polygon_clipping#JavaScript
//Note that this only works when fB is a convex polygon, but we know all
//fixtures in Box2D are convex, so that will not be a problem
bool findIntersectionOfFixtures(b2Fixture* fA, b2Fixture* fB, vector<b2Vec2>& outputVertices)
{
//currently this only handles polygon vs polygon
if ( fA->GetShape()->GetType() != b2Shape::e_polygon ||
fB->GetShape()->GetType() != b2Shape::e_polygon )
return false;
b2PolygonShape* polyA = (b2PolygonShape*)fA->GetShape();
b2PolygonShape* polyB = (b2PolygonShape*)fB->GetShape();
//fill subject polygon from fixtureA polygon
for (int i = 0; i < polyA->GetVertexCount(); i++)
outputVertices.push_back( fA->GetBody()->GetWorldPoint( polyA->GetVertex(i) ) );
//fill clip polygon from fixtureB polygon
vector<b2Vec2> clipPolygon;
for (int i = 0; i < polyB->GetVertexCount(); i++)
clipPolygon.push_back( fB->GetBody()->GetWorldPoint( polyB->GetVertex(i) ) );
b2Vec2 cp1 = clipPolygon[clipPolygon.size()-1];
for (int j = 0; j < clipPolygon.size(); j++) {
b2Vec2 cp2 = clipPolygon[j];
if ( outputVertices.empty() )
return false;
vector<b2Vec2> inputList = outputVertices;
outputVertices.clear();
b2Vec2 s = inputList[inputList.size() - 1]; //last on the input list
for (int i = 0; i < inputList.size(); i++) {
b2Vec2 e = inputList[i];
if (inside(cp1, cp2, e)) {
if (!inside(cp1, cp2, s)) {
outputVertices.push_back( intersection(cp1, cp2, s, e) );
}
outputVertices.push_back(e);
}
else if (inside(cp1, cp2, s)) {
outputVertices.push_back( intersection(cp1, cp2, s, e) );
}
s = e;
}
cp1 = cp2;
}
return !outputVertices.empty();
}
(code stolen from iforce2d :) )
You say you understand the general idea, presumably from reading something like Sutherland Hodgman Algorithm. That explains at a high level exactly what inside and intersection do.
As to the details of how they achieve their objectives, that is all just straight up text book linear algebra.
inside is testing the sign of (cp2 - cp2) cross (p - cp1) and returning true iff the sign is strictly greater than zero. You could rewrite the return statement as:
return (cp2.x-cp1.x)*(p.y-cp1.y) - (cp2.y-cp1.y)*(p.x-cp1.x) > 0;
by moving the second term to the left of the > which gives you exactly the cross product on the left.
Note that a cross product is typically a vec3 cross vec3 operation and requires computation of all three terms. However, we're doing this in 2d meaning the vec3s have the form (x, y, 0). Therefore we only need to compute the z output term, since the cross must be perpendicular to the xy plane, and therefore be of the form (0, 0, value).
intersection finds the point at which two vectors intersect using exactly the algorithm listed here: Line Intersection from Two Points. In particular, we care about the formula immediately following the text "The determinants can be written out as:"
In the context of that formula n1 is (x1 y2 - y1 x2), n2 is (x3 y4 - y3 x4) and n3 is 1 / ((x1 - x2) (y3 - y4) - (y1 - y2) (x3 - x4))
-- EDIT --
To cover the issue raised in the comments, here is as full an explanation as I can give for why the return value from inside() is a test of the sign of the cross product.
I'm going to go off on a slight tangent, show my age, and note that the cross product formula has a very simple memory aid. You just need to remember the first magic word from Woods and Crowther's text adventure game Colossal Cave. xyzzy.
If you have two vectors in three dimensions: (x1, y1, z1) and (x2, y2, z2), their cross product (xc, yc, zc) is evaluated thus:
xc = y1 * z2 - z1 * y2;
yc = z1 * x2 - x1 * z2;
zc = x1 * y2 - y1 * x2;
Now, look at the first line, remove the c, 1 and 2 suffixes from the terms, all the spaces and operators and just look at the remaining letters. It's the magic word. Then you just go vertically down, replacing x with y, y with z and z with x as you go from line to line.
Getting back to business, both the terms on the right of the expansions of xc and yc contain either z1 or z2. But we know that both of these are zero since our input vectors are in the xy plane, and therefore have a zero z component. That's why we can completely elide computing those two terms, because we know they'll be zero.
This is 100% consistent with the definition of what the cross product does, the resulting vector is always perpendicular to both input vectors. Hence if both input vectors are in the xy plane, we know the output vector must be perpendicular to the xy plane, and therefore have the form (0, 0, z)
So, what do we have for the z term?
zc = x1 * y2 - y1 * x2;
in this case vector 1 is cp2-cp1 and vector 2 is p-cp1. So plugging that into the above we get:
zc = (cp2.x-cp1.x)*(p.y-cp1.y) - (cp2.y-cp1.y)*(p.x-cp1.x);
But as noted, we don't care about its value, only it's sign. We want to know if that is greater than zero. Hence:
return (cp2.x-cp1.x)*(p.y-cp1.y) - (cp2.y-cp1.y)*(p.x-cp1.x) > 0;
which is then rewritten as:
return (cp2.x-cp1.x)*(p.y-cp1.y) > (cp2.y-cp1.y)*(p.x-cp1.x);
Finally, what does the sign of that term have to do with whether the point p is inside or outside the clipping polygon? You are quite correct that all the clipping takes place in the 2d xy plane, so why are we involving 3d operations at all?
The important thing to realize is that the cross product formula in 3d is not commutative. The order of the two vector operands is significant, in terms of the angle between them. The first image on the Wikipedia page for Cross Product shows it perfectly. In that diagram, if you look down from above, when evaluating a cross b, the shortest angular direction from a to b is counter-clockwise. In that instance, that leads to a cross product with a positive z value, assuming positive z goes up the page. However if you evaluate b cross a, the shotest angular distance from b to a is clockwise, and the cross product has a negative z value.
Thinking back to the Wikipedia page for the algorithm itself, you've got the blue "clipping" line that works its way counter-clockwise around the clipping polygon. If you think of that vector as always having positive magnitude in the counter-clockwise direction it'll always be cp2 - cp1 for any pair of adjacent vertices in the clipping polygon.
Keeping this in mind, imagine what you'd see if you stood at cp1, with your nose pointed straight at cp2. The interior of the clipping polygon will be on your left, and the exterior on the right. Now consider two points p1 and p2. We'll say p1 is inside the clipping poly, and p2 is outside. That means that the quickest way to point yourt nose at p1 is to rotate counter-clockwise, and the quickest way to point at p2 is to rotate clockwise.
So by studying the sign of the cross product, we're really asking 'Do we rotate clockwise or counter-clockwise from the current edge to look at the point' which equates to asking if the point is inside the clipping polygon or outside.
I'll add one final suggestion. If you're at all interested in this sort of thing, or 3d rendering, or any programming that involves modelling the mathematical representation of the real world, taking a good solid course in linear algebra that covers the likes of cross products, dot products, vectors, matrices and the interactions between them all will be one of the best things you can ever do. It will provide a very strong foundation for a fair amount of what is done with computers.
I am searching for an algorithm (using OpenCV C or C++) which does this:
Given the boundary image, I want to find the local curvature at all points and color map it, which is what is done in the image displayed above. I got this image from Wikipedia but haven't been able to find out a way to color the boundary in this way. Kindly let me know how it can be done.
If you observe the boundary, red denotes boundary has high slope, yellow shows that the boundary is almost linear.
How can this be done?
Edit
Just to give you an idea of how I was trying to do this since two days:
I used the openCV functions convexHull and convexityDefects but realized that I am going in the wrong direction. I have to work only on the contours/boundaries of the binary image.
You can solve the problem by fitting a path of cubic Bezier curves to the boundary, then taking the curvature analytically.
[elaborated]
The boundary consists of a list of points in x, y at pixel centres, each point 1px or root 2 px form the next in the list. You need to fit a smooth cubic Bezier path to this, using a technique by Schnider in Graphics Gems (Gems 1, pp 612, An algorithm for Fitting digitized curves).
The step along the curve taking tiny steps which are always sub-pixel, and
take the curvature using
double BezierCurve::Curvature(double t) const
{
// Nice mathematically perfect formula
//Vector2 d1 = Tangent(t);
//Vector2 d2 = Deriv2(t);
//return (d1.x * d2.y - d1.y * d2.x) / pow(d1.x * d1.x + d1.y * d1.y, 1.5);
// Get the cubic coefficients like this, I store them in the Bezier
// class
/*
a = p3 + 3.0 * p1 - 3.0 * p2 - p0;
b = 3.0 * p0 - 6.0 * p1 + 3.0 * p2;
c = 3.0 * p1 - 3.0 * p0;
d = p0;
*/
double dx, dy, ddx, ddy;
dx = 3 * this->ax * t*t + 2 * this->bx * t + this->cx;
ddx = 6 * this->ax * t + 2 * this->bx;
dy = 3 * this->ay * t*t + 2 * this->by * t + this->cy;
ddy = 6 * this->ay * t + 2 * this->by;
if (dx == 0 && dy == 0)
return 0;
return (dx*ddy - ddx*dy) / ((dx*dx + dy*dy)*sqrt(dx*dx + dy*dy));
}
OpenCV findContours used with mode= CV_RETR_EXTERNAL and method= CV_CHAIN_APPROX_NONE will give you all boundary pixels ordered such as two subsequent points are neighbors.
To get the radius of a circumference by three points, there are a lot of info in the Web. Because you only need the radius, not the center, this stackexchange answer is fast.
In pseudo code:
vector_of_points = OpenCV::findContours(...)
p1 = vector start
p2, p3 are next points in vector
//boundary is circular, so in the first loop pass we must adjust
p2 = next point
p3 = last point
//Use p1 as our iterator
while ( p1 <= vector.end )
{
//curvature
radius = calculateRadius(p1, p2, p3)
//set color for pixel p2
setColor(p, radius)
increment p1, p2, p3
adjust for start point = end point
}
I have a plane defined by the standard plane equation a*x + b*y + c*z + d = 0, which I would like to be able to draw using OpenGL. How can I derive the four points needed to draw it as a quadrilateral in 3D space?
My plane type is defined as:
struct Plane {
float x,y,z; // plane normal
float d;
};
void DrawPlane(const Plane & p)
{
???
}
EDIT:
So, rethinking the question, what I actually wanted was to draw a discreet representation of a plane in 3D space, not an infinite plane.
Base on the answer provided by #a.lasram, I have produced this implementation, which doest just that:
void DrawPlane(const Vector3 & center, const Vector3 & planeNormal, float planeScale, float normalVecScale, const fColorRGBA & planeColor, const fColorRGBA & normalVecColor)
{
Vector3 tangent, bitangent;
OrthogonalBasis(planeNormal, tangent, bitangent);
const Vector3 v1(center - (tangent * planeScale) - (bitangent * planeScale));
const Vector3 v2(center + (tangent * planeScale) - (bitangent * planeScale));
const Vector3 v3(center + (tangent * planeScale) + (bitangent * planeScale));
const Vector3 v4(center - (tangent * planeScale) + (bitangent * planeScale));
// Draw wireframe plane quadrilateral:
DrawLine(v1, v2, planeColor);
DrawLine(v2, v3, planeColor);
DrawLine(v3, v4, planeColor);
DrawLine(v4, v1, planeColor);
// And a line depicting the plane normal:
const Vector3 pvn(
(center[0] + planeNormal[0] * normalVecScale),
(center[1] + planeNormal[1] * normalVecScale),
(center[2] + planeNormal[2] * normalVecScale)
);
DrawLine(center, pvn, normalVecColor);
}
Where OrthogonalBasis() computes the tangent and bi-tangent from the plane normal.
To see the plane as if it's infinite you can find 4 quad vertices so that the clipped quad and the clipped infinite plane form the same polygon. Example:
Sample 2 random points P1 and P2 on the plane such as P1 != P2.
Deduce a tangent t and bi-tangent b as
t = normalize(P2-P1); // get a normalized tangent
b = cross(t, n); // the bi-tangent is the cross product of the tangent and the normal
Compute the bounding sphere of the view frustum. The sphere would have a diameter D (if this step seems difficult, just set D to a large enough value such as the corresponding sphere encompasses the frustum).
Get the 4 quad vertices v1 , v2 , v3 and v4 (CCW or CW depending on the choice of P1 and P2):
v1 = P1 - t*D - b*D;
v2 = P1 + t*D - b*D;
v3 = P1 + t*D + b*D;
v4 = P1 - t*D + b*D;
One possibility (possibly not the cleanest) is to get the orthogonal vectors aligned to the plane and then choose points from there.
P1 = < x, y, z >
t1 = random non-zero, non-co-linear vector with P1.
P2 = norm(P1 cross t1)
P3 = norm(P1 cross P2)
Now all points in the desired plane are defined as a starting point plus a linear combination of P2 and P3. This way you can get as many points as desired for your geometry.
Note: the starting point is just your plane normal < x, y, z > multiplied by the distance from the origin: abs(d).
Also of interest, with clever selection of t1, you can also get P2 aligned to some view. Say you are looking at the x, y plane from some z point. You might want to choose t1 = < 0, 1, 0 > (as long as it isn't co-linear to P1). This yields P2 with 0 for the y component, and P3 with 0 for the x component.
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.