# Intersection between point and plane in 3D or more

I try to find a way to know if a 3D point is in a 3D plane or not, but I don’t find a clear topic to do that in Java or in Processing. If any body have a topic or code to do that I’m very interesting.

Topics about 3D intersection, but my math and code level is very too cheap to understand what I must do
http://paulbourke.net/geometry/pointlineplane/
http://geomalgorithms.com/a06-_intersect-2.html
https://math.stackexchange.com/questions/83990/line-and-plane-intersection-in-3d
https://rosettacode.org/wiki/Find_the_intersection_of_a_line_with_a_plane#Java

may be something in this code https://www.openprocessing.org/sketch/470615

My empty code :

``````void setup() {
size(125,125,P3D);
// a, b , c define the plane
PVector a = new PVector(35,60,4);
PVector b = new PVector(40,45,9);
PVector c = new PVector(10,23,45);

PVector any = new PVector(1,2,3);

println(in_plane(a,b,c,any));
println(in_poly(a,b,c,any));
}

boolean in_plane(PVector a, PVector b, PVector c , PVector any) {
boolean in_plane_is = false;
// no idea what I must write here ????
return in_plane_is;
}

boolean in_poly(PVector a, PVector b, PVector c , PVector any) {
boolean in_poly_is = false;
// no idea what I must write here ????
return in_poly_is;
}
``````

sounds like some good math needed ( and possibly above my level )
show something:

``````//https://discourse.processing.org/t/intersection-between-point-and-plane-in-3d-or-more/10780

PVector a, b, c, any;

void setup() {
size(200, 200, P3D);
a = new PVector(35, 60, 4);
b = new PVector(40, 45, 9);
c = new PVector(10, 23, 45);

any = new PVector(10, 20, 30);

info_print();                                          // Tab ptz
}

void draw () {
background(200, 200, 0);
PTZ();
}

//_____________________________________________________
void draw_object() {                                     // called by / from inside ptz
axis();
show_sphere();
}

void axis() {
int max = 100;
stroke(200, 0, 0);
line(0, 0, 0, max, 0, 0);
stroke(0, 200, 0);
line(0, 0, 0, 0, max, 0);
stroke(0, 0, 200);
line(0, 0, 0, 0, 0, max);
}
void show_sphere() {
fill(200, 0, 200);
noStroke();
push();
translate(a.x, a.y, a.z);
sphere(3);
pop();
push();
translate(b.x, b.y, b.z);
sphere(3);
pop();
push();
translate(c.x, c.y, c.z);
sphere(3);
pop();
push();
translate(any.x, any.y, any.z);
fill(0, 200, 200);
sphere(3);
pop();
stroke(200, 0, 200);
line(a.x, a.y, a.z, b.x, b.y, b.z);
line(b.x, b.y, b.z, c.x, c.y, c.z);
line(c.x, c.y, c.z, a.x, a.y, a.z);
}

/*

println("in_plane: "+in_plane(a, b, c, any));
println("in_poly: "+in_poly(a, b, c, any));

boolean in_plane(PVector a, PVector b, PVector c, PVector any) {
boolean in_plane_is = false;
// no idea what I must write here ????
return in_plane_is;
}

boolean in_poly(PVector a, PVector b, PVector c, PVector any) {
boolean in_poly_is = false;
// no idea what I must write here ????
return in_poly_is;
}

*/

// tab ptz
int mode = 0;
float Zmag = 2;
int Zaxis=-100;
float Xmag, Ymag = 0;
float newXmag, newYmag = 0;
int newZmag = 0;
float newxpos, newypos = 0;       // for PAN
float xposd, yposd = 0;           // for PAN

//_________________________________________________________________ ROTATE / TILDE and MOVE / PAN
void mousePressed() {
if      (mouseButton == LEFT)   mode=1;  // ORBIT
else if (mouseButton == RIGHT)  mode=2;  // PAN
// else if (mouseButton == CENTER) mode=3;  // zoom mouse wheel
}

//_________________________________________________________________ mouse PT end
void mouseReleased() {
mode = 0;
}

//_________________________________________________________________ mouseWheel ZOOM
void mouseWheel(MouseEvent event) {
float e = event.getCount();
//println(e);
if ( !keyPressed ) {
float newZmag = event.getCount()/3.0;
Zmag += newZmag;
//println("mouse event: "+newZmag+" Zmag "+Zmag);
}
}

//_______________________________________________ OPERATION
void keyPressed() {
if ( keyCode == UP   )   Ymag -= 0.1 ;
if ( keyCode == DOWN )   Ymag += 0.1 ;
if ( keyCode == RIGHT)   Xmag -= 0.1 ;
if ( keyCode == LEFT )   Xmag += 0.1 ;
if ( keyCode == 16 )     Zmag -= 0.2 ;  // [Page Down]
if ( keyCode == 11 )     Zmag += 0.2 ;  // [Page Up  ]
//println("key: "+key); println("keyCode: "+keyCode);
}

//_______________________________________________
void keyReleased() { }

//________________________________________________ Pan Tilde Zoom
void PTZ() {
pushMatrix();
translate(width/2, height/2, Zaxis);
// get new mouse operation
if ( mode == 2 ) {                              // PAN ( right mouse button pressed)
xposd = (mouseX-float(width/2));
yposd = (mouseY-float(height/2));
}
newxpos = xposd;// xposd=0;
newypos = yposd;// yposd = 0;
translate(newxpos, newypos, 0);          // move object
if ( mode == 1 ) {  // ORBIT ( left mouse button pressed)
newXmag = mouseX/float(width) * TWO_PI;
newYmag = mouseY/float(height) * TWO_PI;

float diff = Xmag-newXmag;
if (abs(diff) >  0.01)   Xmag -= diff/4.0;
diff = Ymag-newYmag;
if (abs(diff) >  0.01)   Ymag -= diff/4.0;
}
rotateX(-Ymag);
rotateY(-Xmag);
scale(Zmag);
draw_object();                                // THE OBJECT
popMatrix();
}

//_______________________________________________ SETUP PRINT INFO
void info_print() {
println("PTZ info:");
println("key UP DOWN RIGHT LEFT -> rotate // key PAGE UP DOWN -> zoom");
println("mouse LEFT press drag up down right left -> rotate");
println("mouse RIGHT press -> move ");
println("mouse WHEEL turn -> zoom");
}
//_______________________________________________
``````

2 Likes

That’s not solve my problem but I love your code, the camera is very good ! thx for trick

1 Like

i know, still looking,

I have done the is_on_plane bit. When you say is in poly I assume you mean in the plane and inside the triangle made by a,b,c - please confirm.

``````PVector a, b, c, any;

void setup() {
size(125, 125, P3D);
// a, b , c define the plane
a = new PVector(35, 60, 4);
b = new PVector(40, 45, 9);
c = new PVector(10, 23, 45);
// The center of abc as it must be on the plane
any = getCenter(a, b, c);
// Try modifying PVector any to test in_plane
any.x += 0.1;
println(any);
//println(getPlaneNormal(a, b, c));

println(in_plane(a, b, c, any));
//println(in_poly(a, b, c, any));
}

PVector getCenter(PVector a, PVector b, PVector c) {
PVector center = new PVector(a.x + b.x + c.x, a.y + b.y + c.y, a.z + b.z + c.z);
return center.div(3);
}

PVector getPlaneNormal(PVector a, PVector b, PVector c) {
return (PVector.sub(a, c).cross(PVector.sub(b, c))).normalize();
}

boolean in_plane(PVector a, PVector b, PVector c, PVector any) {
PVector n = getPlaneNormal(a, b, c);
// Calculate nearest distance between the plane represented by the vectors
// a,b and c, and the point any
float d = n.x*any.x + n.y*any.y + n.z*any.z - n.x*a.x - n.y*a.y - n.z*a.z;
// A perfect resuult would be d==0 but this will not hapen with realistic
// float data so the smaller d the closer the point. Here I have decided
// the point is on the plane if the distance is less than 1 uint.
return abs(d) < 1.0;
}

boolean in_poly(PVector a, PVector b, PVector c, PVector any) {
boolean in_poly_is = false;
// no idea what I must write here ????
return in_poly_is;
}
``````
1 Like

If you already have the intersection and are trying to to find out if the intersection actually lies within the 3 points that define the plane, one easy solution is checking the area formed by the three triangles and comparing that with the original area

for a more complicated shape: divide the shape into triangles and test for each triangle

I should mention that A+B+C may never be exactly equal to area(a,b,c), so you should check within a small margin

1 Like

so, also play little bit more

-a- using a axis transformation with following idea

• move axis so point a is center

• rotate point b is on x axis in 2 rotation steps

• rotate point c so it is in x y plane ( z == 0 )

• ( now the x-y plane is the triangle plane )
• how to check if the point d is in the plane?
if ( d.z == 0 )

note: for all above axis translations it must be done for all 4 points to work.

add, the 3 rotations are not possible with PVector.rotate(angle) in 3D
to use it anyway i hack that by using always only 2 axis, looks bad… but seem to work.

now all comes with the show
you can follow each of the transformations by key [n] next key [p] prev

-b- found some code for point inside triangle
https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle , what says it is for 2D ( and i did not fully check … )

have fun:

``````//https://discourse.processing.org/t/intersection-between-point-and-plane-in-3d-or-more/10780

PVector a, b, c, d;                // abc triangle and checkpoint d
PVector at1, bt1, ct1, dt1;        // after trans 1
PVector at2, bt2, ct2, dt2;        // after trans 2
PVector at3, bt3, ct3, dt3;        // after trans 3
PVector at4, bt4, ct4, dt4;        // after trans 4
int step = 0;
boolean dprint = true, dinplane = false, dintriangle = false;

void setup() {
size(500, 500, P3D);
// triangle / plane
a = new PVector(35, 60, 4);
b = new PVector(40, 45, 9);
c = new PVector(10, 23, 45);
// check point
d = new PVector(1, 2, 3);
/*
// test
a = new PVector(35, 60, 0);
b = new PVector(40, 20, 0);
c = new PVector(10, 23, 0);
// check point
d = new PVector(30, 40, 0);
*/

info_print();                                          // Tab ptz
println("here add: key [n] next step, [p] prev step");
}

void draw () {
background(200, 200, 0);
PTZ();
}

//_____________________________________________________
void draw_object() {                                     // called by / from inside ptz
axis();
show_sphere();
trans();
}

void trans() {
// axis transform step 1 move a to 0
at1 = a.copy().sub(a);
bt1 = b.copy().sub(a);
ct1 = c.copy().sub(a);
dt1 = d.copy().sub(a);

// axis transform step 2 rotate b ( by y ) to x axis first step
float angby = -1.0*new PVector(bt1.x, bt1.y, 0).heading();
at2 = new PVector(at1.x, at1.y);
at2.rotate(angby);
at2.set(at2.x, at2.y, at1.z);

bt2 = new PVector(bt1.x, bt1.y);
bt2.rotate(angby);
bt2.set(bt2.x, bt2.y, bt1.z);

ct2 = new PVector(ct1.x, ct1.y);
ct2.rotate(angby);
ct2.set(ct2.x, ct2.y, ct1.z);

dt2 = new PVector(dt1.x, dt1.y);
dt2.rotate(angby);
dt2.set(dt2.x, dt2.y, dt1.z);

// axis transform step 3 rotate b ( by z ) to x axis second step
float angbz = -1.0*new PVector(bt2.x, bt2.z, 0).heading();
at3 = new PVector(at2.x, at2.z);
at3.rotate(angbz);
at3.set(at3.x, at2.y, at3.y);

bt3 = new PVector(bt2.x, bt2.z);
bt3.rotate(angbz);
bt3.set(bt3.x, bt2.y, bt3.y);

ct3 = new PVector(ct2.x, ct2.z);
ct3.rotate(angbz);
ct3.set(ct3.x, ct2.y, ct3.y);

dt3 = new PVector(dt2.x, dt2.z);
dt3.rotate(angbz);
dt3.set(dt3.x, dt2.y, dt3.y);

// axis transform step 4 rotate c ( by x ) to y axis ( so z = 0 )
float angcz = -1.0*new PVector(ct3.y, ct3.z, 0).heading();
at4 = new PVector(at3.y, at3.z);
at4.rotate(angcz);
at4.set(at3.x, at4.x, at4.y);

bt4 = new PVector(bt3.y, bt3.z);
bt4.rotate(angcz);
bt4.set(bt3.x, bt4.x, bt4.y);

ct4 = new PVector(ct3.y, ct3.z);
ct4.rotate(angcz);
ct4.set(ct3.x, ct4.x, ct4.y);

dt4 = new PVector(dt3.y, dt3.z);
dt4.rotate(angcz);
dt4.set(dt3.x, dt4.x, dt4.y);

show_sphere_trans(step);
// what was the job? oh yes,
// is vector d in the plane made by a b c ?  easy, d.z must be 0  (but check float problem )
if ( dprint ) {
if ( dt4.z <= 0.01 && dt4.z > -0.01 )         dinplane = true;
if ( pointInTriangle (dt4, at4, bt4, ct4) )   dintriangle = true;
println("d_in plane: "+dinplane+" d_in triangle: "+dintriangle);
dprint = false;  // only print one time
}
}

void show_sphere_trans(int step) {
PVector as, bs, cs, ds;

//  if ( step == 1 ) {
fill(0, 200, 100);
as = new PVector(at1.x, at1.y, at1.z);
bs = new PVector(bt1.x, bt1.y, bt1.z);
cs = new PVector(ct1.x, ct1.y, ct1.z);
ds = new PVector(dt1.x, dt1.y, dt1.z);
//  }
if ( step == 2 ) {
fill(0, 100, 200);
as = new PVector(at2.x, at2.y, at2.z);
bs = new PVector(bt2.x, bt2.y, bt2.z);
cs = new PVector(ct2.x, ct2.y, ct2.z);
ds = new PVector(dt2.x, dt2.y, dt2.z);
}
if ( step == 3 ) {
fill(200, 100, 200);
as = new PVector(at3.x, at3.y, at3.z);
bs = new PVector(bt3.x, bt3.y, bt3.z);
cs = new PVector(ct3.x, ct3.y, ct3.z);
ds = new PVector(dt3.x, dt3.y, dt3.z);
}
if ( step == 4 ) {
fill(200, 0, 100);
as = new PVector(at4.x, at4.y, at4.z);
bs = new PVector(bt4.x, bt4.y, bt4.z);
cs = new PVector(ct4.x, ct4.y, ct4.z);
ds = new PVector(dt4.x, dt4.y, dt4.z);
}
if ( step > 0) {
noStroke();
push();
translate(as.x, as.y, as.z);
sphere(3);
pop();
push();
translate(bs.x, bs.y, bs.z);
sphere(3);
pop();
push();
translate(cs.x, cs.y, cs.z);
sphere(3);
pop();
push();
translate(ds.x, ds.y, ds.z);
//fill(200);
sphere(3);
pop();
stroke(200);
line(as.x, as.y, as.z, bs.x, bs.y, bs.z);
line(bs.x, bs.y, bs.z, cs.x, cs.y, cs.z);
line(cs.x, cs.y, cs.z, as.x, as.y, as.z);
}
if ( step > 0 && step < 3 ) {  // show coords for point b
stroke(100);
strokeWeight(0.5);
line(bs.x, 0, 0, bs.x, bs.y, bs.z);
line(0, bs.y, 0, bs.x, bs.y, bs.z);
line(0, 0, bs.z, bs.x, bs.y, bs.z);
}
if ( step >= 3 ) {
stroke(100);
strokeWeight(0.5);
line(cs.x, 0, 0, cs.x, cs.y, cs.z);
line(0, cs.y, 0, cs.x, cs.y, cs.z);
line(0, 0, cs.z, cs.x, cs.y, cs.z);
}
}

void axis() {
int max = 100;
stroke(200, 0, 0);
strokeWeight(1);
line(0, 0, 0, max, 0, 0);
strokeWeight(0.3);
line(0, 0, 0, -max, 0, 0);
fill(200, 0, 0);
text("x", max, 0);
stroke(0, 200, 0);
strokeWeight(1);
line(0, 0, 0, 0, max, 0);
strokeWeight(0.3);
line(0, 0, 0, 0, -max, 0);
fill(0, 200, 0);
text("y", 0, max);
stroke(0, 0, 200);
strokeWeight(1);
line(0, 0, 0, 0, 0, max);
strokeWeight(0.3);
line(0, 0, 0, 0, 0, -max);
fill(0, 0, 200);
text("z", 0, 0, max);
fill(100, 100, 0, 10); // trans not work
noStroke();
max = 20;
rect(-max, -max, 2*max, 2*max);   // xy plane
}

void show_sphere() {
fill(200, 0, 200);
noStroke();
push();
translate(a.x, a.y, a.z);
sphere(3);
pop();
push();
translate(b.x, b.y, b.z);
sphere(3);
pop();
push();
translate(c.x, c.y, c.z);
sphere(3);
pop();
push();
translate(d.x, d.y, d.z);
fill(0, 200, 200);
sphere(3);
pop();
stroke(200, 0, 200);
line(a.x, a.y, a.z, b.x, b.y, b.z);
line(b.x, b.y, b.z, c.x, c.y, c.z);
line(c.x, c.y, c.z, a.x, a.y, a.z);
}

void step_keyPressed() {
if ( key == 'n' ) {
step++;
if ( step > 4 ) step = 0;
println("step: "+step);
}
if ( key == 'p' ) {
step--;
if ( step < 0 ) step = 4;
println("step: "+step);
}
}

// ok now need some math
// https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle

float sign (PVector p1, PVector p2, PVector p3) {
return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
}

boolean pointInTriangle (PVector pt, PVector v1, PVector v2, PVector v3)
{
float d1, d2, d3;
boolean has_neg, has_pos;

d1 = sign(pt, v1, v2);
d2 = sign(pt, v2, v3);
d3 = sign(pt, v3, v1);

has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0);
has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0);

return !(has_neg && has_pos);
}

// tab ptz
int mode = 0;
float Zmag = 2;
int Zaxis=-100;
float Xmag, Ymag = 0;
float newXmag, newYmag = 0;
int newZmag = 0;
float newxpos, newypos = 0;       // for PAN
float xposd, yposd = 0;           // for PAN

//_________________________________________________________________ ROTATE / TILDE and MOVE / PAN
void mousePressed() {
if      (mouseButton == LEFT)   mode=1;  // ORBIT
else if (mouseButton == RIGHT)  mode=2;  // PAN
// else if (mouseButton == CENTER) mode=3;  // zoom mouse wheel
}

//_________________________________________________________________ mouse PT end
void mouseReleased() {
mode = 0;
}

//_________________________________________________________________ mouseWheel ZOOM
void mouseWheel(MouseEvent event) {
float e = event.getCount();
//println(e);
if ( !keyPressed ) {
float newZmag = event.getCount()/3.0;
Zmag += newZmag;
//println("mouse event: "+newZmag+" Zmag "+Zmag);
}
}

//_______________________________________________ OPERATION
void keyPressed() {
if ( keyCode == UP   )   Ymag -= 0.1 ;
if ( keyCode == DOWN )   Ymag += 0.1 ;
if ( keyCode == RIGHT)   Xmag -= 0.1 ;
if ( keyCode == LEFT )   Xmag += 0.1 ;
if ( keyCode == 16 )     Zmag -= 0.2 ;  // [Page Down]
if ( keyCode == 11 )     Zmag += 0.2 ;  // [Page Up  ]
//println("key: "+key); println("keyCode: "+keyCode);
step_keyPressed();                                        // from main
}

//_______________________________________________
void keyReleased() { }

//________________________________________________ Pan Tilde Zoom
void PTZ() {
pushMatrix();
translate(width/2, height/2, Zaxis);
// get new mouse operation
if ( mode == 2 ) {                              // PAN ( right mouse button pressed)
xposd = (mouseX-float(width/2));
yposd = (mouseY-float(height/2));
}
newxpos = xposd;// xposd=0;
newypos = yposd;// yposd = 0;
translate(newxpos, newypos, 0);          // move object
if ( mode == 1 ) {  // ORBIT ( left mouse button pressed)
newXmag = mouseX/float(width) * TWO_PI;
newYmag = mouseY/float(height) * TWO_PI;

float diff = Xmag-newXmag;
if (abs(diff) >  0.01)   Xmag -= diff/4.0;
diff = Ymag-newYmag;
if (abs(diff) >  0.01)   Ymag -= diff/4.0;
}
rotateX(-Ymag);
rotateY(-Xmag);
scale(Zmag);
draw_object();                                // THE OBJECT
popMatrix();
}

//_______________________________________________ SETUP PRINT INFO
void info_print() {
println("PTZ info:");
println("key UP DOWN RIGHT LEFT -> rotate // key PAGE UP DOWN -> zoom");
println("mouse LEFT press drag up down right left -> rotate");
println("mouse RIGHT press -> move ");
println("mouse WHEEL turn -> zoom");
}
//_______________________________________________

``````
1 Like

Thanks a lot, that’s work nice, that’s exactly what I need. And I confirm when I write in poly it’s to know if the point is in the shape or not, it’s like a bonus track But the first thing I need, it was to know if a point is in any plane. My final idea is show all points are in a specific plane from a cloud 3D points. I try your solution and show the result when I implemented your soltion in my final sketch.

whaouuuuu you go very very far in the wild wild west that’s awesome, I don’t know yet how to use it… but that very nice !!!

OK so I have now added the in_poly code

``````PVector a, b, c, any;

void setup() {
size(125, 125, P3D);
// a, b , c define the plane
a = new PVector(35, 60, 4);
b = new PVector(40, 45, 9);
c = new PVector(10, 23, 45);
// The center of abc as it must be on the plane
any = getCenter(a, b, c);

println("Is in plane : " + in_plane(a, b, c, any));
println("Is in poly  : " + in_poly(a, b, c, any));
}

PVector getCenter(PVector a, PVector b, PVector c) {
PVector center = new PVector(a.x + b.x + c.x, a.y + b.y + c.y, a.z + b.z + c.z);
return center.div(3);
}

PVector getPlaneNormal(PVector a, PVector b, PVector c) {
return (PVector.sub(a, c).cross(PVector.sub(b, c))).normalize();
}

boolean in_plane(PVector a, PVector b, PVector c, PVector any) {
PVector n = getPlaneNormal(a, b, c);
// Calculate nearest distance between the plane represented by the vectors
// a,b and c, and the point any
float d = n.x*any.x + n.y*any.y + n.z*any.z - n.x*a.x - n.y*a.y - n.z*a.z;
// A perfect resuult would be d==0 but this will not hapen with realistic
// float data so the smaller d the closer the point. Here I have decided
// the point is on the plane if the distance is less than 1 uint.
return abs(d) < 1.0;
}

/**
If a point in inside a triangle then the sum of the 3 internal angles
will be 2Pi radians (360 degrees). This method calculates the sum of the
internal angles and compares this with 2Pi radians.
*/
boolean in_poly(PVector a, PVector b, PVector c, PVector any) {
// Since Processing uses floats rather than doubles the chance of
// getting Float.NaN (not-a-number) is high if we don't normalise
// the vectors before calculating the arc-cosine
PVector a_any = PVector.sub(a, any).normalize();
PVector b_any = PVector.sub(b, any).normalize();
PVector c_any = PVector.sub(c, any).normalize();
float s = abs(
acos(PVector.dot(a_any, b_any))
+ acos(PVector.dot(b_any, c_any))
+ acos(PVector.dot(c_any, a_any))
- TWO_PI);
// A perfect resuult would be s==0 but this will not hapen with realistic
// float data so the closer d is to zero the better. Here I have decided
// the point is in the triangle if s is less than 1 thousandth of a
return s < 1E-3;
}
``````
3 Likes

Thanks I feel i can code nice tool now !
here the result of any plane detection in any points of cloud !

what is it, it’s weird value, it’s like a very very very small value ?

This is the “scientific way” of writing 1*10^(-3 ) so 0.001

hmm interesting, so if I want write `0,00000000001` i can simply write `1E-12` ?
Claro, it’s just for my general knowledge, because i use often a very small value to multiply the `frameCount` and i have a lot `000000000` with your notation is clearer ! I learn a lot thing the 1st May… love this working day party !