Intersection between point and plane in 3D or more

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