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");
}
//_______________________________________________